iFrame events (postMessage)
The embedded white-label UI talks to the page that hosts it using postMessage. This works the same way whether you embed with v2 or with v1 — the events below apply to both.
There are three: a keepalive signal, a height report, and flow commands.
Always check the sender
The embedded application posts every outgoing message with a wildcard target origin, so your host page must check both event.origin and event.source before acting on anything. The origin check rejects other sites; the source check distinguishes the intended frame from another Worklio frame on the same page.
// The origin of the Worklio application — derive it from the appUrl you were given.
const worklioOrigin = new URL(appUrl).origin;
window.addEventListener('message', (event) => {
if (event.origin !== worklioOrigin) return;
if (event.source !== iframe.contentWindow) return;
// Keepalive: a plain string.
if (event.data === 'activity') {
resetYourSessionTimeout();
return;
}
// Everything else is an object with a `type`.
switch (event.data?.type) {
case 'resize':
iframe.style.height = `${event.data.height}px`;
break;
case 'command':
handleCommand(event.data.commandName, event.data);
break;
}
});What the application sends
| Message | When | Sent by |
|---|---|---|
"activity" (plain string) | Mouse or keyboard activity inside the iframe, at most once a minute | Every embed — pages and named flows |
{ type: "resize", height } | The content height changes | Named flows only |
{ type: "command", commandName, …data } | Flow-specific, see below | Named flows only |
activity — keeping your session alive
activity — keeping your session aliveThe application reports that the user is still working, so your host page can keep its own session open while they are busy inside the frame.
window.parent.postMessage('activity', '*');- It is a plain string, not an object — check
event.data === 'activity'. - Emitted on mouse movement or key presses inside the frame.
- Rate-limited to at most one message per minute, however continuously the user interacts. Treat each one as "still active", not as a count of anything.
- Sent by page embeds and named flows alike, but only in iFrame mode — an embed opened in browser mode does not send it.
window.addEventListener('message', (event) => {
if (event.origin !== worklioOrigin) return;
if (event.source !== iframe.contentWindow) return;
if (event.data === 'activity') {
// Reset your host timeout, or mark the session as active.
}
});resize — sizing the frame to its content
resize — sizing the frame to its contentNamed flows are content-sized and report their height whenever it changes, so you can grow the <iframe> instead of scrolling inside it.
{ type: 'resize', height: 412 }heightis the measured content height in pixels, plus a two-pixel allowance.- Sent whenever the height changes, including once on first render.
- Named flows only. Page embeds never send it — give those a height of your own.
if (event.data?.type === 'resize') {
iframe.style.height = `${event.data.height}px`;
}command — what the user did
command — what the user didNamed flows report user actions as command messages. Every one carries type: 'command' and a commandName; some carry extra data alongside.
{ type: 'command', commandName: 'submit' }commandName | Extra data | Sent by | What it means |
|---|---|---|---|
submit | – | custom-fields-employee-edit, custom-fields-employee-onboarding-phase1, custom-fields-employee-onboarding-phase2 | The user saved successfully. Refresh your own view; advance your wizard. |
close | – | custom-fields-employee-edit | The modal finished closing. If no submit arrived first, it was dismissed without saving. Remove the frame or overlay. |
back | – | custom-fields-employee-onboarding-phase2 | The user asked to go back a step. Move your own wizard back. |
editable | – | custom-fields-employee-view, premium-ats | The embedded content switched into an editable or entered state. |
After a successful save, custom-fields-employee-edit sends submit first and then close. Act on submit for the result and treat close as "the frame is finished".
Sending commands to the application
The channel works in both directions. Post the same shape to the frame and the flow reacts — this lets your own buttons drive an embedded form:
iframe.contentWindow.postMessage(
{ type: 'command', commandName: 'submit' },
worklioOrigin
);commandName | Accepted by | Effect |
|---|---|---|
submit | custom-fields-employee-onboarding-phase1 | Submits the embedded form, exactly as if the user had clicked its own save button. The flow then answers with a submit command of its own once the save succeeds. |
Always pass the Worklio origin as the second argument rather than '*', so the message is delivered only while the target window is on that origin.
Updated about 3 hours ago
