How to generate PDF event tickets
In this blog post, you’ll create an e-ticket from scratch. The example will be a ticket for a music event, but you can follow the example for a variety of situations, such as flight boarding passes, conference tickets, and even lottery tickets!
The example will use Document Engine and introduce the PDF Generation feature, which allows you to describe your content in HTML, style the content with CSS, and describe the page layout in JSON.
Defining the content
You’ll start with a basic layout for the e-ticket. There’ll be no data yet — just the style and content:
<!DOCTYPE html> <html> <head> <style> body { font-size: 16px; font-family: 'Helvetica', Arial, sans-serif; margin: 0; } .container { width: 602px; height: 200px; margin: 0 auto; border-radius: 4px; background-color: #4537de; box-shadow: 0 8px 16px rgba(35, 51, 64, 0.25); } .column-1 { float: left; width: 400px; height: 200px; border-right: 2px dashed #fff; } .column-2 { float: right; width: 200px; height: 200px; } .text-frame { padding: 40px; height: 120px; } .qr-holder { position: relative; width: 160px; height: 160px; margin: 20px; background-color: #fff; text-align: center; line-height: 30px; z-index: 1; } .qr-holder > img { margin-top: 20px; } .event { font-size: 24px; color: #fff; letter-spacing: 1px; } .date { font-size: 18px; line-height: 30px; color: #a8bbf8; } .name, .ticket-id { font-size: 16px; line-height: 22px; color: #fff; } </style> </head> <body> <div class="container"> <div class="column-1"> <div class="text-frame"> <div class="event">PSPDFKit TALENT SHOW</div> <div class="date">26 August, 2021</div> <br /> <div class="name">John Smith</div> <div class="ticket-id">#123456</div> </div> </div> <div class="column-2"> <div class="qr-holder"> <img src="qr-code.png" width="120px" height="120px" /> </div> </div> </div> </body> </html>
When previewed in a browser such as Chrome, you’ll see a page like the following.
Variable data
You may have noticed there’s lots of data in the ticket that needs to be generated at runtime. Examples of this are the ticket number, the name of the guest, and even the QR code.
That’s where you can use a template. In place of the hardcoded data, you can add placeholders. And at runtime, you can replace the placeholders with the correct data:
... </head> <body> <div class="container"> <section> <div class="qr-holder"> <img src="{{QR_CODE_IMAGE_PATH}}" width="100px" height="100px"> </div> <div class="event">PSPDFKit Talent Show</div> <div class="date">26 August, 2021</div> <hr> <div class="name">{{NAME}}</div> <div class="ticket-id">#{{TICKET_NUMBER}}</div> </section> </div> </body> </html>
Now that you’ve added placeholders for the data generated at runtime, you can replace it.
For this example, you’ll use Mustache.js, a templating library that will take the HTML above and replace the placeholders in double curly braces with the data you provide.
Note that this example will be using JavaScript and Node.js. If you’re looking for other language examples, you can find them in the Document Engine guides.
Define your data, which in theory could be pulled from any desired source (database, REST API, local file), and apply that to the template:
const mustache = require('mustache'); const fs = require('fs'); const page = fs.readFileSync('page.mustache').toString(); const ticketData = { name: 'John Smith', ticket_id: '123456', qr_code_image_path: 'qr-code.png', }; const outputHTML = mustache.render(page, ticketData);
Run the script with Node.js:
node mustache-example.js
You now have your custom e-ticket created in HTML. Next, you’ll pass this to the PDF Generation feature to create a PDF.
PDF generation
The first part is simple. Pass the created HTML to Document Engine’s /api/build
endpoint for generation:
curl -X POST http://localhost:5000/api/build \ -F '[email protected];type=text/html' \ -F '[email protected];type=image/png' \ -F instructions='{ "parts": [ { "html": "page.html", "assets": [ "qr-code.png" ] } ], "output": { "type": "pdf" } }' \ -o result.pdf
Along with the HTML, you can see that you passed the qr-code.png
image (you can download the QR code from here if you’re following along). This allows the generator to reference the image when generating the PDF.
From the above, you’ll receive the following resulting PDF. But the page is A4 size, which is probably not what you want.
Page size
You can resize the page with the size
property in the PDF Generation schema.
Because you’ve already defined your ticket size in HTML as 600px
by 200px
, you’ll want a similar page size. The PDF Generation schema page size takes values in millimeters, so you’ll have to do the conversion. (More information on conversions can be found in the PDF Generation guides):
(600 / 96) * 25.4 = 158.75 mm (200 / 96) * 25.4 = 52.91 mm
The page size expects integer value types, so round the results and use a width of 159 and a height of 53 in the PDF Generation schema:
curl -X POST http://localhost:5000/api/build \ -F '[email protected];type=text/html' \ -F '[email protected];type=image/png' \ -F instructions='{ "parts": [ { "html": "page.html", "assets": [ "qr-code.png" ], "layout": { "size": { "width": 159, "height": 53 } } } ], "output": { "type": "pdf" } }' \ -o result.pdf
This is perfect. But to make things a little cleaner, you can add some white space with page margins — let’s say 5 mm all around.
Page margins
To define margins, add the margin
object in the PDF Generation schema with the values required. Then, expand the width and height to account for the margins:
curl -X POST http://localhost:5000/api/build \ -F '[email protected];type=text/html' \ -F '[email protected];type=image/png' \ -F instructions='{ "parts": [ { "html": "page.html", "assets": [ "qr-code.png" ], "layout": { "size": { "width": 169, "height": 63 }, "margin": { "top": 5, "left": 5, "right": 5, "bottom": 5 } } } ], "output": { "type": "pdf" } }' \ -o result.pdf
And now you end up with a nicely sized e-ticket in a PDF, ready to send to your customer!
Conclusion
In this post, you created an event e-ticket from scratch. As you can see from this example, it’s possible to create expressive designs and convert these designs to PDFs.
All the areas of the PDF Generation feature discussed in this blog post can be found in our guides. There, you’ll also find more information describing how to further customize your PDFs and edit them after they’re generated.
When Nick started tinkering with guitar effects pedals, he didn’t realize it’d take him all the way to a career in software. He has worked on products that communicate with space, blast Metallica to packed stadiums, and enable millions to use documents through Nutrient, but in his personal life, he enjoys the simplicity of running in the mountains.