Embedded Editor Events (postMessage)
The Templated embedded editor talks to your page with browser messages (window.postMessage). Your page can:
- Listen to events from the editor, for example when a template loads, is saved or is downloaded.
- Send commands to the editor, for example save, download or change the zoom.
This works without a backend. For server-side notifications, use the webhook URL in your embed configuration (see "Webhook Integration"). The create, save and download actions are sent both to your webhook and to your page.
Docs: https://templated.io/docs/embed/webhooks/ and https://templated.io/docs/embed/preview-mode/
Events the editor sends to your page
Event | When | Main fields |
|---|---|---|
| The editor started and can receive messages | none (no template ID) |
| The template finished loading |
|
action | A new template or clone was created (for example with |
|
action | The user saved |
|
action | A download finished |
|
| A save requested with the |
|
| A download requested with the |
|
| A requested download failed |
|
| Zoom changed with |
|
| The user selected a layer |
|
Important: there are two message styles.
- Events with a
typefield (likeEDITOR_READYandTEMPLATE_LOADED) arrive as JavaScript objects. - The
create,saveanddownloadactions arrive as a JSON string with anactionfield. Parse it withJSON.parse.
Example listener
window.addEventListener('message', (event) => {
if (event.origin !== 'https://app.templated.io') return;
let msg = event.data;
if (typeof msg === 'string') {
try { msg = JSON.parse(msg); } catch (e) { return; }
}
// Events with "type"
switch (msg.type) {
case 'EDITOR_READY':
console.log('Editor ready');
break;
case 'TEMPLATE_LOADED':
console.log('Template ID (clone ID when clone=true):', msg.template.id);
break;
case 'TEMPLATE_DOWNLOADED_SUCCESS':
console.log('Render URL:', msg.renderUrl);
break;
}
// Actions (create / save / download)
switch (msg.action) {
case 'create':
console.log('New template or clone:', msg.templateId, msg.metadata);
break;
case 'save':
console.log('Saved:', msg.templateId);
break;
case 'download':
console.log('Downloaded:', msg.renderId, msg.renderUrl);
break;
}
});
Getting the template or clone ID
- Use
TEMPLATE_LOADED:msg.template.idis the ID of the template that is open. Withclone=trueorrender=..., this is the new clone ID. - Or use the
createandsaveactions:msg.templateId. EDITOR_READYdoes not include any ID. It only tells you the editor is ready for messages.
Add your own data (user ID, order ID) with the metadata URL parameter (base64-encoded JSON). It comes back in create, save and download.
Commands your page can send to the editor
Get the iframe and send a message after EDITOR_READY:
const iframe = document.getElementById('templated-editor');
// Save the template
iframe.contentWindow.postMessage({ type: 'SAVE' }, '*');
// Download using the format selected in the editor
iframe.contentWindow.postMessage({ type: 'DOWNLOAD' }, '*');
// Download with a specific format and pages
iframe.contentWindow.postMessage({
type: 'DOWNLOAD',
format: 'png', // 'jpg', 'png', 'pdf' or 'mp4'
pages: 'all' // 'all' (default), page numbers like '1,3' or a range like '2-4' (first page = 1)
}, '*');
// Change the zoom (10 to 100, 50 = 100% scale)
iframe.contentWindow.postMessage({ type: 'SET_ZOOM', zoom: 60 }, '*');
// Change layer values without reloading
iframe.contentWindow.postMessage({
type: 'UPDATE_LAYERS',
data: { 'title': { text: 'New title' } }
}, '*');
// Open another template without reloading
iframe.contentWindow.postMessage({ type: 'LOAD_TEMPLATE', templateId: 'TEMPLATE_ID', clone: false }, '*');
Notes:
SAVEworks only when saving is allowed in your embed configuration.DOWNLOADworks only when download is allowed and uses credits from your account, like a download from the button. With your own buttons you can hide the editor's Save button with&hide-save-button=true.- The full list of messages (add or remove layers, change permissions, show one page, get layers) is in the Preview Mode docs: https://templated.io/docs/embed/preview-mode/
FAQ
Q: How do I know when the user saved?
A: Listen for the save action (frontend) or use the webhook. Both include templateId.
Q: How do I get the clone ID in my frontend?
A: Listen for TEMPLATE_LOADED and read template.id. With clone=true you also receive a create action with templateId.
Q: EDITOR_READY has no template ID. Is that a bug?
A: No. EDITOR_READY only means the editor is ready. The ID comes in TEMPLATE_LOADED.
Q: My listener gets the save event but event.data.action is undefined. Why?
A: The create, save and download actions are sent as a JSON string. Run JSON.parse(event.data) first.
Q: Can I trigger the download from my own button?
A: Yes. Send { type: 'DOWNLOAD', format: 'png' } to the iframe. You receive TEMPLATE_DOWNLOADED_SUCCESS with the renderUrl.
Q: Can I change the zoom after the editor loads?
A: Yes. Send { type: 'SET_ZOOM', zoom: 60 }.
Updated on: 01/10/2026
Thank you!