Storefront JavaScript events
Use cart, form, AI sign designer, lightbox, and ShareLink events from inline storefront JavaScript.
Storefront JavaScript events let theme code respond to the customer customiser on the same page. They cover cart actions, forms, the AI sign designer, lightbox sizing, and ShareLinks.
These browser integrations use CustomEvent on document. They are not REST endpoints.
Browser scope
Listen on the same document as an inline customer customiser. These events do not support messaging across a cross-origin iframe.
Add listeners before the action that sends an event. Remove temporary listeners when your integration finishes.
Event list
| Event | Direction | When it occurs |
|---|---|---|
triggerUpdateCart | Customer customiser to theme | A product enters the Shopify cart and the Store uses a custom cart action. |
signCustomiserProductAddedToCart | Customer customiser to theme | A supported tracking plan adds a product to the Shopify cart. |
signCustomiserFormSubmitted | Customer customiser to theme | A custom design form submission succeeds. |
signCustomiserQuoteSubmitted | Customer customiser to theme | A quote form submission succeeds. |
signCustomiserAiLogoCompleted | Customer customiser to theme | The AI sign designer completes a design. |
signCustomiserAiLogoSuccess | Customer customiser to theme | The AI sign designer completes a design. This event fires with the completed event. |
signCustomiserAiLogoFailed | Customer customiser to theme | The AI sign designer cannot complete a design and uses its fallback. |
signCustomiserAiLogoInsufficientCredits | Customer customiser to theme | The Store has no AI sign designer credits. |
signCustomiserLightboxSizeMatched | Customer customiser to theme | A lightbox face image reaches automatic size matching. |
signCustomiserShareLinkRequested | Theme to customer customiser | Theme code requests a ShareLink for the current design. |
signCustomiserShareLinkCreated | Customer customiser to theme | ShareLink creation succeeds. |
signCustomiserShareLinkFailed | Customer customiser to theme | ShareLink creation fails. |
Listen for an event
Add a listener to document:
function handleProductAdded(event) { useCartResult(event.detail.cart);}
document.addEventListener( "signCustomiserProductAddedToCart", handleProductAdded,);Replace useCartResult with your integration code.
Cart events
Custom cart hand-off
triggerUpdateCart fires after an inline customer customiser adds a product to Shopify. It fires only when the Store uses the custom cart action.
The event detail is the Shopify cart response:
type TriggerUpdateCartDetail = Record<string, unknown>;Use this event to update a cart drawer or start another custom cart step.
Add-to-cart tracking
signCustomiserProductAddedToCart fires after a successful inline Shopify cart request. It fires before a cart redirect or custom cart hand-off.
type SignCustomiserProductAddedToCartDetail = { customiserId: string | number | null; domain: string | null; cart: Record<string, unknown>; adClickIds: Record<string, string> | null; utmParams: Record<string, string> | null;};This event is not available to Starter, Standard, or Pro plan families. This restriction includes yearly variants.
Form submission events
signCustomiserFormSubmitted fires after a custom design form submission succeeds. signCustomiserQuoteSubmitted fires after a quote form submission succeeds.
Both events use this detail:
type SignCustomiserFormSubmittedDetail = { customiserId: string | number | null; formId: string | number; domain: string | null; adClickIds: Record<string, string> | null; utmParams: Record<string, string> | null; data: Array<{ fieldId: string; label: string; value: string | File | Array<string | File>; urls?: string[]; }>;};Use formId and fieldId to map the submission to your system. Do not use label text as a stable field identifier.
These events are not available to Starter, Standard, or Pro plan families. This restriction includes yearly variants.
AI sign designer events
signCustomiserAiLogoCompleted and signCustomiserAiLogoSuccess fire together after the AI sign designer completes a design.
Both events use this detail:
type SignCustomiserAiLogoCompletedDetail = { svg: string | null; svgUrl: string | null; rawUrl: string | null;};signCustomiserAiLogoFailed fires when the AI sign designer uses its failure fallback. signCustomiserAiLogoInsufficientCredits fires when the Store has no credits. These events have no detail fields.
The URLs and SVG can contain customer design data. Send this data only to systems that need the design.
Lightbox size event
signCustomiserLightboxSizeMatched fires when a lightbox face image reaches automatic size matching.
type SignCustomiserLightboxSizeMatchedDetail = { outcome: | "matched" | "skipped-not-offered" | "skipped-no-image" | "skipped-empty-envelope";};matched means that the customer customiser applied an image-matched custom size. A skipped-* value identifies why the customer customiser kept the current size.
Request a ShareLink
Use signCustomiserShareLinkRequested when theme code needs a ShareLink for the current design.
Do not click the customer Share button from theme JavaScript. Do not read, close, or remove the Share modal. The customer customiser owns this interface.
The request does not open a modal, move focus, or change the current screen.
ShareLink event names
| Direction | Event name |
|---|---|
| Theme to customer customiser | signCustomiserShareLinkRequested |
| Customer customiser to theme, success | signCustomiserShareLinkCreated |
| Customer customiser to theme, failure | signCustomiserShareLinkFailed |
While the runtime remains mounted, each valid request receives one success or failure event.
Request detail
Dispatch signCustomiserShareLinkRequested with this detail:
type SignCustomiserShareLinkRequestedDetail = { requestId: string;};requestId must match this pattern:
[A-Za-z0-9._:-]{1,128}Create a new value for each pending request. Use it only to match the result to the request. It is not a server idempotency key.
The request does not accept callbacks, DOM nodes, cache data, customiser IDs, host URLs, or endpoint URLs. The mounted customer customiser supplies these values.
The customer customiser ignores invalid detail. Invalid detail does not create a ShareLink or change the design.
Success detail
Listen for signCustomiserShareLinkCreated:
type SignCustomiserShareLinkCreatedDetail = { requestId: string; customiserId: string; domain: string | null; url: string;};The customer customiser returns requestId without changes. Use it to match a result to a pending request.
url is the complete ShareLink. Its security value is in the URL fragment. Store the complete returned URL. Do not build a URL from token parts.
Failure detail
Listen for signCustomiserShareLinkFailed:
type SignCustomiserShareLinkFailedDetail = { requestId: string; customiserId: string | null; domain: string | null; code: "not_ready" | "sharing_unavailable" | "request_failed";};Use code to select the recovery action:
| Code | Meaning |
|---|---|
not_ready | The customer customiser is not ready to create a ShareLink. |
sharing_unavailable | The Store is not eligible to create ShareLinks. |
request_failed | A request or server problem stopped ShareLink creation. |
not_ready can occur before the runtime knows the customiser or domain. Therefore, customiserId and domain can be null.
Failure events do not contain response bodies, stack traces, cache data, URLs, or token fields.
Eligibility
The Store must be able to go live. Its plan must include sharing.
Settings such as shareLocation control the visible customer Share control. They do not block an eligible request after the runtime is ready.
Privacy and expiry
A ShareLink is a bearer link to a saved design. Anyone with the complete URL can open the design until it expires or you revoke it.
Each ShareLink expires 365 days after creation. Store the complete URL only in the workflow that needs the design.
To stop access before expiry, open Shares in the merchant admin, open the saved share, and select Revoke ShareLink. Revocation cannot be undone.
Do not log the ShareLink URL. Do not send it to analytics. Do not extract, build, or log token parts.
Complete ShareLink example
This example requests a ShareLink before a cart flow. It adds both terminal listeners before the request. It removes them after success, failure, or timeout.
function requestSignCustomiserShareLink(options = {}) { const timeoutMs = options.timeoutMs ?? 10000; const requestId = options.requestId ?? `cart-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
return new Promise((resolve, reject) => { let settled = false;
function cleanup() { document.removeEventListener( "signCustomiserShareLinkCreated", handleCreated, ); document.removeEventListener( "signCustomiserShareLinkFailed", handleFailed, ); window.clearTimeout(timeout); }
function settle(action, value) { if (settled) { return; }
settled = true; cleanup(); action(value); }
function handleCreated(event) { if (event.detail?.requestId !== requestId) { return; }
settle(resolve, event.detail.url); }
function handleFailed(event) { if (event.detail?.requestId !== requestId) { return; }
settle( reject, new Error(`ShareLink request failed: ${event.detail.code}`), ); }
const timeout = window.setTimeout(() => { settle(reject, new Error("ShareLink request timed out.")); }, timeoutMs);
document.addEventListener( "signCustomiserShareLinkCreated", handleCreated, ); document.addEventListener( "signCustomiserShareLinkFailed", handleFailed, );
document.dispatchEvent( new CustomEvent("signCustomiserShareLinkRequested", { detail: { requestId }, }), ); });}
async function continueCartFlow() { try { const shareLinkUrl = await requestSignCustomiserShareLink(); await saveShareLinkForCart(shareLinkUrl); } catch { // Continue without a ShareLink. }
await continueToCart();}Replace saveShareLinkForCart and continueToCart with your existing cart code.
Private implementation
Do not call private ShareLink routes from theme code. Storefront JavaScript events are the supported merchant integration.