Widget Script Reference
Every script attribute, iframe parameter, and query-string override for the embed widget.
Script embed
<script
src="https://your-mozo-domain.com/embed/widget.js"
data-agent-id="YOUR_AGENT_ID"
data-position="right"
async
></script>The script is served from /embed/widget.js. On load, it injects a fixed-position <iframe>
pointing at /widget/{agentId} into document.body. The iframe resizes dynamically based on
widget state and the host page viewport width.
Script attributes
| Attribute | Required | Description |
|---|---|---|
data-agent-id | Yes, unless data-embed-url is set | The agent to load |
data-embed-url | No | Full iframe URL override, replacing the default /widget/{agentId} URL |
data-position | No | "left" or "right" (default "right") — which corner the widget docks to |
Dynamic iframe sizing
| State | Mobile (≤768px) | Desktop (>768px) |
|---|---|---|
| Closed | 80×80px bubble in corner | 80×80px bubble in corner |
| Open | Full viewport (100vw × 100dvh) | 384×600px panel in corner |
When the chat is open on mobile, the host page scroll is locked until the user closes the widget.
The iframe uses z-index: 2147483647 so it stays above your page's other content. It's sandboxed with
allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-same-origin.
Use the script embed (not a manual iframe) for full-screen mobile behavior. A direct iframe embed fills its own container only and cannot overlay the host page.
Iframe embed
If you'd rather control placement yourself instead of a floating widget, embed the iframe directly:
<iframe
src="https://your-mozo-domain.com/widget/YOUR_AGENT_ID?embed=floating"
style="width:360px;height:600px;border:none;"
></iframe>On viewports ≤768px wide, the widget UI expands to fill the iframe container. For full-screen overlay on mobile (covering the host page), use the script embed above.
PostMessage protocol
The embed script and widget iframe communicate via bidirectional postMessage. This is handled
automatically by /embed/widget.js and does not require custom integration.
Iframe to host (mozo-widget-resize)
Sent when the user opens or closes the chat:
{
"type": "mozo-widget-resize",
"state": "open"
}| Field | Type | Description |
|---|---|---|
type | "mozo-widget-resize" | Message identifier |
state | "open" | "closed" | Current widget open state |
The embed script validates event.source === iframe.contentWindow before applying layout changes.
Mobile vs desktop sizing is determined by the host page viewport width, not the iframe.
Host to iframe (mozo-host-viewport)
Sent on iframe load and when the host window is resized:
{
"type": "mozo-host-viewport",
"isMobile": false
}| Field | Type | Description |
|---|---|---|
type | "mozo-host-viewport" | Message identifier |
isMobile | boolean | Whether the host viewport is ≤768px wide |
The widget uses this to choose its internal layout (full-screen vs panel) without reading the iframe's own dimensions, which shrink to 80×80px when the bubble is closed.
Query parameter overrides
Both the default widget iframe and a manually embedded iframe accept query parameters that override the agent's saved widget configuration for that specific embed:
| Parameter | Description |
|---|---|
primary | Primary color (hex, URL-encoded, e.g. %236366F1) |
accent | Accent color |
background | Background color |
text | Text color |
brand | Brand name override |
logo | Logo URL override |
profilePicture | Profile picture URL override |
welcome | Welcome message override |
alignment | Chat bubble alignment: left or right |
embed | Set to floating for the floating widget layout |
Example:
https://your-mozo-domain.com/widget/YOUR_AGENT_ID?primary=%236366F1&alignment=right&embed=floating
Anything not overridden by a query parameter falls back to the agent's saved configuration from the Embed Widget settings page.
Security
Widget and hosted-page chat requests are authenticated with a short-lived signed session
token (header x-widget-session) and checked against the agent's origin allowlist. See
Security & Access Control for how to configure allowed origins,
since embeds on domains not in the allowlist will be blocked.