JavaScript reference
https://api.idealfactory.com/embed/v1/customiser.js is the whole client
integration. Loading it mounts the Customiser into every element carrying
data-idealfactory-customiser — including elements added later, so modals and
SPA navigation need no re-initialisation — and reports back through
bubbling DOM events. It owns the session lifecycle end to end: you never
handle tokens, URLs, or expiry.
Attributes
There is no JavaScript initialisation — everything is configured with attributes on the mount element:
| Attribute | Required | Meaning |
|---|---|---|
data-idealfactory-customiser |
yes | Marks the element the Customiser fills. Give it real size — fullscreen is best. |
data-embed-key |
yes | Your public embed key. Only works from your registered domains. |
data-sku |
no | Your product SKU or reference — resolved to our product through the mapping on your storefront page (supplier SKUs need no mapping). |
data-product |
no | Our product id, if you'd rather name it directly. |
data-design-version |
no | A design id you stored earlier — opens it for re-editing. |
Give at most one of data-sku, data-product, data-design-version. Give
none and the Customiser opens on a product selection page — customers
pick from your mapped products (or everything you sell, if nothing is
mapped) and go straight into designing it. This needs "customers choose the
product inside" enabled in your storefront settings; otherwise a snippet
without a product is refused.
| data-customer-token | no | Identity claim for your logged-in customer — see Customer identity. |
| data-api-base | no | Defaults to the origin the script was loaded from. Only for staging setups. |
| data-debug | no | Console-logs the message traffic. |
Mounting & unmounting
There is no lifecycle to manage. An element mounts when it appears — on page load, or added later by a modal or SPA navigation — and tears itself down when it leaves the DOM: the iframe and every listener are released automatically. So an "edit design" modal is exactly two operations: insert the element to open, remove it to close. Nothing to initialise, nothing to destroy, nothing leaks.
Events
All events bubble, so one document.addEventListener covers every Customiser
on the page; listen on the element itself if you mount several and need to
tell them apart.
customiser:design-ready
Fires after every successful finish. This is your integration point.
document.addEventListener('customiser:design-ready', function (e) {
e.detail.design_id // stable across re-edits of one design
e.detail.design_version_id // THIS saved version — store it on your cart line
e.detail.thumbnails // raw base64 JPEG previews, in view order
});
Always keep the latest design_version_id you receive — a customer
can finish, keep editing, and finish again; each finish returns a new id
and your cart line should point at the newest one. (The script already
chains versions correctly internally; you only ever store the latest.)
Thumbnails carry no data: prefix — add one to display them:
'data:image/jpeg;base64,' + e.detail.thumbnails[0].
customiser:back
The customer clicked the Customiser's back/exit control. Close your overlay or navigate back to the product page.
customiser:error
document.addEventListener('customiser:error', function (e) {
e.detail.stage; // 'session' | 'mount' | 'save'
e.detail.detail; // Error or string for your logs
});
| stage | Meaning | Sensible handling |
|---|---|---|
session |
The session could not be created (bad key, unregistered domain, unavailable product) | Hide the Customiser, show a generic error; check key / domain / product id |
mount |
The mount element was unusable | Fix the markup |
save |
A finish could not be saved after retrying | Ask the customer to try finishing again — their work is still in the Customiser |
Errors are never silently swallowed: everything lands on this event.
Session lifecycle (what the script does for you)
- A session is created when the element mounts, and lives 12 hours.
- Saves are valid for 7 days — a customer who leaves the tab open overnight (or hibernates a laptop) and finishes tomorrow saves normally.
- If a save ever outlives that, the script silently creates a fresh session and retries once; the design is preserved. You implement nothing for any of this.
Versioning & caching
The v1 in the URL is the compatibility contract: everything documented
here holds for as long as /embed/v1/customiser.js exists.
- Fixes and improvements ship in place — browsers revalidate the file and pick them up automatically. You never edit your snippet for an update.
- Breaking changes never ship to v1. If one is ever needed, it becomes
/embed/v2/customiser.js; your embed keeps working on v1 untouched, and you upgrade by editing the snippet on your own schedule.
Don't self-host or copy the file — you'd freeze yourself out of fixes.
Advanced: programmatic mounting
Everything above needs no JavaScript API, and dynamically inserted
data-idealfactory-customiser elements mount automatically — so most shops
never need this section. The exception is a server-created session
(your backend called POST /v1/shop/sessions itself with the API token,
for example to attach external_ref directly):
IdealFactory.customiser({
container: 'customiser-container', // element or id
session: sessionFromYourServer, // the response's `data` object
onDesignReady: function (design) { /* same payload as the event */ },
onBack: function () {},
onError: function (stage, detail) {},
});
Callbacks fire in addition to the DOM events. In this mode the script does not self-renew (it holds no embed key): an expired save surfaces as an error and your code fetches a fresh session. Prefer the declarative embed key plus, for identity, a customer token — renewal then stays automatic.