How-To: Integrate Shelf Ticketing
We presume you've already authenticated your application before reading this document.
Overview
Shelf ticketing in Shopfront is designed to be highly flexible, allowing for automatic queueing of tickets based on item changes, customisable templates, and direct browser-based printing.
Currently Shopfront supports ticketing Products, Promotions and Future Prices
This guide explores how Shopfront's internal ticketing system works and provides recommendations for developers looking to integrate their own ticketing solutions or extend Shopfront's existing functionality.
How Ticketing Works
Shopfront maintains a Ticket Queue which stores items that need to be printed. Items are typically added to this queue automatically based on the context of changes and the templates currently existing and connected in their store.
These changes can include:
- Price changes (both manual and scheduled)
- Product name or detail updates
- Manual additions by users from the product list or ticket management screens
Once items are in the queue, users can select a Ticket Template and a Page Layout to print them. Printing is handled directly in the browser using Shopfront's custom template system, which renders tickets as HTML/CSS before sending them to the printer.
If you have a ticketing system that supports HTML/CSS rendering, you can use Shopfront's Ticket Templates directly and allow the user to retain control over styling and layout without having to implement your own system.
Page Layouts
Page layouts define the physical characteristics of the surface you are displaying templates on and how tickets are
arranged on that surface. In the GraphQL API, these are represented by the
TicketTemplatePage type.
Key properties include:
- Dimensions:
pageWidthandpageHeight(in millimeters), - Grid Layout:
horizontalPanelsandverticalPanelsdefine how many tickets fit on a single page, - Margins & Spacing:
pageMargin,horizontalPanelSpacing, andverticalPanelSpacingcontrol the positioning of the ticket grid, - Cutting Lines:
cuttingWidthcan be used to display guides for manual cutting
Ticket Templates
Ticket templates define the visual appearance and data transformation for individual tickets. They are represented by
the TicketTemplate type.
A template consists of:
- Dimensions:
widthandheightof the individual ticket panel, - Fonts: A list of custom fonts required by the template
- Styles: Custom CSS used to style the ticket,
- Transformation Script: A JavaScript snippet that takes raw product data and transforms it into fields usable by the template,
To render these in the browser we create a custom HTML element which transforms the raw object (e.g. the product or
promotion) into a usable ticket by using the user-provided transformation script. We then render this transformed data
by placing each key into its own div. The styles are then injected via CSS to position the content.
Integrating Your Own System
If you are building an integration that provides its own ticketing system (such as electronic shelf labels), we suggest one of the following two routes depending on where you want the "source of truth" for the print queue to reside.
There are other ways to integrate your own system with Shopfront, but these two routes are the most common.
Managing Your Own Queue
This route is best if you're already managing your own queue or if you want full control over the ticketing process. This has the downside that you can't leverage Shopfront's contextual knowledge of tickets without reimplementing it yourself.
To build your integration this way, you'll typically want to do the following:
- Perform an Initial Sync: Similar to an eCommerce integration, perform a full sync of products to your system, you'll also want to make this possible to call at other times in case your system becomes out of date with Shopfront,
- Stay Up-to-Date: Listen to standard product webhooks like
PRODUCT_UPDATEDto determine when a ticket update is needed, - Handle Printing: Manage the queue and printing process entirely within your own application
Using Shopfront's Queue
This route allows you to leverage Shopfront's built-in logic for queueing tickets while using your own system for the actual printing or display of tickets.
- Query the Queue: Use the
ticketQueuequery to retrieve items currently waiting to be printed,- We also suggest keeping this available to use manually in case a change is missed
- Monitor Changes: Listen to ticket-specific webhooks to get real-time updates:
THIN_TICKET_QUEUED: Triggered when an item is added to the queue,THIN_TICKET_PRINTED: Triggered when an item is marked as printed,THIN_TICKET_DELETED: Triggered when an item is removed from the queue
- Mark as Printed: After your system has successfully printed / displayed the tickets, use the
markTicketsAsPrintedmutation to remove them from Shopfront's active queue- this also enables the queue to provide functionality like automatically activating future prices after they're marked as printed
Querying the Ticket Queue
const response = await shopfront.graphql(`
query GetTicketQueue($cursor: Cursor, $outlets: [ID!]) {
ticketQueue(after: $cursor, outlets: $outlets) {
edges {
node {
id,
user {
name,
},
queuedAt,
item {
id,
__typename,
},
},
},
pageInfo {
endCursor,
hasNextPage,
},
}
}
`, {
outlets: [ "11e6..." ]
});
const tickets = response.ticketQueue.edges.map(edge => edge.node);
<?php
global $shopfront;
$data = $shopfront->graphql('
query GetTicketQueue($cursor: Cursor, $outlets: [ID!]) {
ticketQueue(after: $cursor, outlets: $outlets) {
edges {
node {
id,
user {
name,
},
queuedAt,
item {
id,
__typename,
},
},
},
pageInfo {
endCursor,
hasNextPage,
},
}
}
', [
'outlets' => [ '11e6...' ],
]);
$tickets = array_map(fn($edge) => $edge->node, $data->ticketQueue->edges);
Marking Tickets as Printed
await shopfront.graphql(`
mutation MarkTicketsAsPrinted($tickets: [ID!]!) {
markTicketsAsPrinted(tickets: $tickets)
}
`, {
tickets: [ "11e6..." ],
});
<?php
global $shopfront;
$shopfront->graphql('
mutation MarkTicketsAsPrinted($tickets: [ID!]!) {
markTicketsAsPrinted(tickets: $tickets)
}
', [
'tickets' => [ '11e6...' ],
]);