Iframe embed
The hosted URL works inside an <iframe> — drop it into any page that allows iframes and your agent appears, fully isolated from the host page.
Minimal embed
<iframe
src="https://livelayer.app/a/your-agent-slug"
width="100%"
height="720"
allow="microphone; camera; autoplay"
style="border: none; border-radius: 12px;">
</iframe>
The allow="microphone; camera" attribute is required — without it the browser blocks the agent from accessing the mic and the visitor sees a permission error.
Floating-bubble pattern
To get a corner-docked widget instead of an inline frame, position the iframe with position: fixed:
<iframe
src="https://livelayer.app/a/your-agent-slug?mode=widget"
allow="microphone; camera; autoplay"
style="
position: fixed;
bottom: 16px;
right: 16px;
width: 400px;
height: 600px;
border: none;
border-radius: 16px;
box-shadow: 0 12px 40px rgba(0,0,0,0.15);
z-index: 999999;
">
</iframe>
For most floating-widget use cases, the Script tag is better — it's a single line, handles open/close, and remembers state. Use an iframe when you need full isolation (the agent can't see anything in your page).
What an iframe can't do
The hosted URL inside an iframe is sandboxed by browser cross-origin policies. The agent inside cannot:
- Read text, headings, or form fields on your host page.
- Fill or submit your forms.
- Navigate your host page (the iframe can navigate its own contents only).
- Click elements outside the iframe.
If you need any of that, reach for the NPM package — it embeds in the same DOM as your app and gets full page-context awareness.
Cross-frame messaging (advanced)
The hosted page posts a small set of events to the parent window via postMessage. Listen for them on your page:
window.addEventListener("message", (e) => {
if (e.origin !== "https://livelayer.app") return;
if (typeof e.data !== "object" || e.data === null) return;
switch (e.data.type) {
case "livelayer:loaded":
console.log("Agent ready");
break;
case "livelayer:conversation:started":
analytics.track("agent_conversation_started", { id: e.data.id });
break;
case "livelayer:conversation:ended":
analytics.track("agent_conversation_ended", { duration: e.data.duration });
break;
}
});
Always validate e.origin before trusting message contents.
Read next
- URL customization — query params for
mode, theme, greeting. - Script tag — drop-in widget without iframe limitations.