Events and callbacks
The editor tells your page when the customer saves a print job, uploads or changes a logo, adds a text or generates a proofreading. Use these events to put the print job GUID into your cart, refresh your UI or download files.
TIP
Example: Event handling · source
Choose how to listen
| Callback attributes | subscribeDesignerEvent() | |
|---|---|---|
| Where | data-td-*-callback attributes on the <script> tag | Your JavaScript |
| Handler | Name of a global function | Any function |
| Events | The seven listed below | All events, including logo selected |
| Remove later | unsubscribeDesignerEvent(window.name) or unsubscribeDesignerEvents() | unsubscribeDesignerEvent() or unsubscribeDesignerEvents() |
Both receive the same event object, a DesignerEntityEvent. The payload is in event.detail (there is no event.data).
Receive events with callback attributes
Add one attribute per event to the integration <script> tag. The value is the name of a global function:
| Attribute | Event (entityType / eventType) |
|---|---|
data-td-print-job-created-callback | printJob / created |
data-td-print-job-updated-callback | printJob / updated |
data-td-logo-created-callback | logo / created |
data-td-logo-updated-callback | logo / updated |
data-td-logo-deleted-callback | logo / deleted |
data-td-text-created-callback | text / created |
data-td-proofreading-created-callback | proofreading / created |
<script>
function onPrintJobCreated(event) {
console.log('Print job saved:', event.entityGuid, event.detail);
}
</script>
<script
async
src="https://app.trondesigner.com/js/website-integration.js"
referrerpolicy="origin"
data-td-api="https://app.trondesigner.com/api"
data-td-api-key="{API_KEY}"
data-td-print-job-created-callback="onPrintJobCreated"
></script>- Declare the handler as
function name() {}in a classic (non-module) script, so it becomes a property ofwindow. Functions declared withconst/letor inside<script type="module">are not found; the script logs… is not a functionand never calls them. - The script looks the names up once, while it initializes (after the page has loaded). A function defined later is ignored.
- There is no
data-td-text-updated-callback(the editor never firestextupdated) and no attribute forlogoselected. UsesubscribeDesignerEvent()forselected.
data-td-script-initialized-callback and data-td-script-init-failed-callback are not editor events; see Loading the integration script.
Subscribe from JavaScript
subscribeDesignerEvent(entityType, eventType, callback) registers a handler for one entity/event pair. Subscribe once window.tronDesigner exists, for example in the initialized callback:
<script>
function onTronDesignerReady() {
const td = window.tronDesigner;
td.subscribeDesignerEvent('printJob', 'created', onPrintJobSaved);
td.subscribeDesignerEvent('printJob', 'updated', onPrintJobSaved);
td.subscribeDesignerEvent('logo', 'selected', (event) => console.log('Logo:', event.entityGuid));
}
function onPrintJobSaved(event) {
console.log(event.eventType, event.detail.printJobGuid, event.detail.state);
}
</script>
<script async src="https://app.trondesigner.com/js/website-integration.js" referrerpolicy="origin"
data-td-api="https://app.trondesigner.com/api" data-td-api-key="{API_KEY}"
data-td-script-initialized-callback="onTronDesignerReady"></script>Subscriptions stay active for every editor you open on the page until you remove them, including subscriptions you add after opening the editor or a logo dialog. Subscribing the same function twice calls it twice. If a callback throws, the error is logged to the console and the other subscribers are still called.
Stop listening
There are two methods. Pick by what you still have a reference to:
| Call | Removes |
|---|---|
unsubscribeDesignerEvent(callback) | Every subscription of exactly this function object — if you subscribed it to several events, all of them |
unsubscribeDesignerEvents('logo', 'updated') | All handlers for this entity and event type |
unsubscribeDesignerEvents('logo') | All handlers for this entity type |
unsubscribeDesignerEvents(undefined, 'created') | All created handlers of any entity type |
unsubscribeDesignerEvents() | Every handler, including those registered by data-td-*-callback attributes |
const td = window.tronDesigner;
td.subscribeDesignerEvent('printJob', 'created', onPrintJobSaved);
td.subscribeDesignerEvent('printJob', 'updated', onPrintJobSaved);
// later, for example when your SPA component unmounts — removes both subscriptions:
td.unsubscribeDesignerEvent(onPrintJobSaved);- An inline arrow function can't be removed with
unsubscribeDesignerEvent(), because you have no reference to it. Keep the function in a variable. - Callback attributes subscribe the global function itself, so
unsubscribeDesignerEvent(window.onPrintJobCreated)removes them as well.
See unsubscribeDesignerEvent and unsubscribeDesignerEvents.
Know which events fire
entityType | eventType | Fires when |
|---|---|---|
printJob | created | The editor saves a new print job for the first time (see below). At most once per session. |
printJob | updated | The editor saves a print job that already exists — opened in Edit mode, or saved earlier in the same session. |
logo | created | The customer uploads a new logo in the editor and it is placed into a printing. |
logo | updated | The customer renames a logo or saves an edited logo to their gallery. |
logo | deleted | The customer removes a logo from their gallery. |
logo | selected | The customer picks, uploads or clears a logo in a dialog opened with openLogoGallery() / openLogoUpload(). See Logos. |
text | created | The customer adds a text or edits an existing one (each change creates new text data). |
proofreading | created | The editor generates a proofreading PDF: the default Get E-proof button, or a GenerateProofreading / DownloadProofreadingAndClose custom button. |
No other combination fires: there is no printJob deleted, text updated, proofreading updated or editor event. When the editor closes (confirmed, cancelled or after an error), you learn it from the onClose option, see Dialog and inline display.
The editor can save a print job more than once per session: when the customer generates a proofreading, when a Save or SaveAndClose custom button is used, and on the final confirmation. Which event fires depends on whether the print job already exists:
| Save | Create session, not saved yet | Create session, saved earlier in the session | Edit mode |
|---|---|---|---|
Generating a proofreading (Get E-proof, GenerateProofreading, DownloadProofreadingAndClose) | created | No print job event | No print job event |
Save / SaveAndClose button | created | created | updated |
| Final confirmation | created | updated | updated |
Every save is the same API call (it creates the print job or updates it if it exists), and all events of a session carry the same printJobGuid — so created can arrive more than once in a Create session (e.g. after each Save). Upsert by printJobGuid rather than adding a new entry for each event. The editor sends intermediate saves with the state PrepareDraft and the final confirmation with PrepareNew.
Read the event payload
Every event has entityType, eventType, entityGuid and an optional detail:
| Event | entityGuid | event.detail |
|---|---|---|
printJob created / updated | print job GUID | The saved print job, IPrintJobDto |
logo created | logo GUID | The logo, ILogoDTO |
logo updated / deleted | logo GUID | undefined — only the GUID is sent (typed DesignerEntityEvent<undefined>; call getLogo() if you need the logo data) |
logo selected | logo GUID, or null when cleared | { logoGuid, logoUploaded }, or {} when the customer cleared the logo |
text created | ID of the text object (a GUID; the same when the customer changes that text, and the id of its motive object in the saved print job) | The rendered text, ITextDTO (options, dimensions, data.svg) |
proofreading created | print job GUID | The proofreading PDF as a Blob |
Notes:
- Print job payloads are converted by the script before you get them: enum values are strings (
"PrepareNew","Pantone","MOCKUP_CLEAR"),languageis an upper-case ISO-2 code ("EN"),customer.customerGuidis camel-cased and every image has a ready-to-useprintJobFileUrl. This is the same shapegetPrintJob()returns.createdandupdatedare ISO 8601 strings (typedstring), and the customer's comments from the final verification are incommentof the print job and of each printing. - The logo payload is passed through unchanged, so its
typeandstateare numbers. - For
logoselected, the property islogoUploaded(truewhen the customer uploaded a new logo,falsewhen they picked one from the gallery).
Sample printJob created event (shortened)
{
"entityType": "printJob",
"eventType": "created",
"entityGuid": "3f6c2a8e-9b1d-4c47-a0e2-5d8f1b7c9e21",
"detail": {
"version": "1.0",
"printJobGuid": "3f6c2a8e-9b1d-4c47-a0e2-5d8f1b7c9e21",
"code": "PJ00000018",
"title": "Oregon 400 ml",
"state": "PrepareNew",
"language": "EN",
"created": "2026-09-30T10:15:42.117Z",
"comment": "Please match the logo color to the bottle.",
"supplier": "0f1e2d3c-4b5a-6978-8796-a5b4c3d2e1f0",
"supplierName": "PF Concept",
"printModelGuid": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"customer": {
"customerGuid": "b1e0c9d8-7f6a-4b5c-9d8e-7f6a5b4c3d2e",
"customerIdentity": "user-1234",
"customerPerson": "Jane Doe",
"customerCompany": "ACME Inc.",
"customerEmail": "jane@acme.example",
"orderTitle": "Oregon 400 ml - red",
"orderCode": "ORD-2026-0815",
"orderItemCode": "CART-LINE-3"
},
"customProperties": { "cartLineId": "CL-882" },
"product": {
"codeSupplier": "10086",
"title": "Oregon 400 ml sport bottle",
"variants": [
{
"guid": "5c4b3a29-1807-4f6e-8d5c-4b3a29180706",
"codeSupplier": "10086021",
"title": "Oregon 400 ml sport bottle - red",
"quantity": 100,
"previewImageUrl": "https://app.trondesigner.com/api/images/web-images/…?apiKey=…"
}
]
},
"printings": [
{
"printingGuid": "e7d6c5b4-a392-4817-9f6e-5d4c3b2a1908",
"printData": {
"positionCodePtn": "front",
"positionName": "Front",
"technologyCodePtn": "PAD03",
"technologyName": "Pad print",
"technologyColorMode": "Pantone",
"maxColors": 3,
"isFullColor": false,
"isNoColor": false
},
"printMotive": {
"motiveType": "VECTOR",
"widthMm": 50,
"heightMm": 25,
"motiveImage": {
"format": "PNG",
"printJobFileUrl": "https://app.trondesigner.com/api/print-jobs/3f6c…/printings/e7d6…/motive-image?apiKey=…"
},
"printAreaImages": [
{
"type": "MOCKUP_CLEAR",
"productVariants": ["5c4b3a29-1807-4f6e-8d5c-4b3a29180706"],
"printAreaImageFile": {
"format": "JPG",
"printJobFileUrl": "https://app.trondesigner.com/api/print-jobs/3f6c…/printings/e7d6…/print-area-image?variantCode=10086021&type=2&apiKey=…"
}
}
]
},
"validationMessages": []
}
]
}
}Save the print job to your cart
The most common use: store the printJobGuid with the cart line the customer is designing for. Because the editor can save several times and created can arrive more than once (e.g. after each Save; see the table in Know which events fire), listen to both created and updated, and upsert by printJobGuid instead of appending a new cart line for every event.
<script>
function onPrintJobSaved(event) {
const { printJobGuid, state, customProperties } = event.detail;
fetch('/cart/print-job', {
method: 'PUT', // idempotent: the same printJobGuid may arrive several times
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ printJobGuid, state, cartLineId: customProperties?.cartLineId }),
});
}
</script>
<script async src="https://app.trondesigner.com/js/website-integration.js" referrerpolicy="origin"
data-td-api="https://app.trondesigner.com/api" data-td-api-key="{API_KEY}"
data-td-print-job-created-callback="onPrintJobSaved"
data-td-print-job-updated-callback="onPrintJobSaved"></script>function onPrintJobSaved(event) {
const { printJobGuid, state, customProperties } = event.detail;
fetch('/cart/print-job', {
method: 'PUT', // idempotent: the same printJobGuid may arrive several times
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ printJobGuid, state, cartLineId: customProperties?.cartLineId }),
});
}
// once window.tronDesigner exists, e.g. in your data-td-script-initialized-callback
const td = window.tronDesigner;
td.subscribeDesignerEvent('printJob', 'created', onPrintJobSaved);
td.subscribeDesignerEvent('printJob', 'updated', onPrintJobSaved);Pass your cart line ID into the editor as a custom property or order item code, so that it comes back in the payload; see Customers and orders.
WARNING
Events run in the customer's browser. If the customer closes the tab right after confirming, your request may not finish. For guaranteed delivery, also receive print jobs on your server with Webhooks and load them with the REST API.
See also
- subscribeDesignerEvent and DesignerEntityEvent — API reference
- Retrieving print jobs and files — load images and PDFs for a saved print job
- Logos — the
logoselectedevent and the customer's current logo - Data attributes reference