Skip to content

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 attributessubscribeDesignerEvent()
Wheredata-td-*-callback attributes on the <script> tagYour JavaScript
HandlerName of a global functionAny function
EventsThe seven listed belowAll events, including logo selected
Remove laterunsubscribeDesignerEvent(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:

AttributeEvent (entityType / eventType)
data-td-print-job-created-callbackprintJob / created
data-td-print-job-updated-callbackprintJob / updated
data-td-logo-created-callbacklogo / created
data-td-logo-updated-callbacklogo / updated
data-td-logo-deleted-callbacklogo / deleted
data-td-text-created-callbacktext / created
data-td-proofreading-created-callbackproofreading / created
html
<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 of window. Functions declared with const/let or inside <script type="module"> are not found; the script logs … is not a function and 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 fires text updated) and no attribute for logo selected. Use subscribeDesignerEvent() for selected.

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:

html
<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:

CallRemoves
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
js
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 ​

entityTypeeventTypeFires when
printJobcreatedThe editor saves a new print job for the first time (see below). At most once per session.
printJobupdatedThe editor saves a print job that already exists — opened in Edit mode, or saved earlier in the same session.
logocreatedThe customer uploads a new logo in the editor and it is placed into a printing.
logoupdatedThe customer renames a logo or saves an edited logo to their gallery.
logodeletedThe customer removes a logo from their gallery.
logoselectedThe customer picks, uploads or clears a logo in a dialog opened with openLogoGallery() / openLogoUpload(). See Logos.
textcreatedThe customer adds a text or edits an existing one (each change creates new text data).
proofreadingcreatedThe 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:

SaveCreate session, not saved yetCreate session, saved earlier in the sessionEdit mode
Generating a proofreading (Get E-proof, GenerateProofreading, DownloadProofreadingAndClose)createdNo print job eventNo print job event
Save / SaveAndClose buttoncreatedcreatedupdated
Final confirmationcreatedupdatedupdated

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:

EvententityGuidevent.detail
printJob created / updatedprint job GUIDThe saved print job, IPrintJobDto
logo createdlogo GUIDThe logo, ILogoDTO
logo updated / deletedlogo GUIDundefined — only the GUID is sent (typed DesignerEntityEvent<undefined>; call getLogo() if you need the logo data)
logo selectedlogo GUID, or null when cleared{ logoGuid, logoUploaded }, or {} when the customer cleared the logo
text createdID 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 createdprint job GUIDThe 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"), language is an upper-case ISO-2 code ("EN"), customer.customerGuid is camel-cased and every image has a ready-to-use printJobFileUrl. This is the same shape getPrintJob() returns. created and updated are ISO 8601 strings (typed string), and the customer's comments from the final verification are in comment of the print job and of each printing.
  • The logo payload is passed through unchanged, so its type and state are numbers.
  • For logo selected, the property is logoUploaded (true when the customer uploaded a new logo, false when they picked one from the gallery).
Sample printJob created event (shortened)
json
{
  "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.

html
<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>
js
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 ​

Czech Republic – The Country for the FutureFunded by the European Union – NextGenerationEUThe project was implemented within the The Country for the Future programme of the Ministry of Industry and Trade and co-financed by the European Union under NextGenerationEU.Support · Examples

Czech Republic – The Country for the FutureFunded by the European Union – NextGenerationEUThe project was implemented within the The Country for the Future programme of the Ministry of Industry and Trade and co-financed by the European Union under NextGenerationEU.Support · Examples