Embedding the Growth Lab GUI
The GUI is designed to run inside an <iframe> in your application. Embedding is governed
by a Content-Security-Policy frame-ancestors allowlist configured for your
tenant; your host origin must be registered before the GUI will render inside it.
Available
- The iframe bridge (v1):
lab-ready, origin allow-listing, theinithandshake, token exchange throughPOST /v1/auth/session
Planned
select-sourcesandresizemessages
1. Add the iframe
<iframe
id="growth-lab"
src="https://lab.example.com/"
allow="clipboard-write"
style="width:100%;height:100%;border:0"
></iframe>2. Wait for lab-ready, then send init
The GUI posts lab-ready to your origin as soon as it has loaded. Reply with an init
message carrying a session token your backend minted for the current user
(POST /v1/users/{id}/session-tokens, see Authentication). The GUI
never trusts identity claims from the host; it exchanges the token with the Engine, which
issues the session cookie.
const frame = document.getElementById("growth-lab");
const GUI_ORIGIN = "https://lab.example.com";
window.addEventListener("message", (event) => {
if (event.origin !== GUI_ORIGIN) return; // always check the origin
const msg = event.data;
if (msg?.source !== "growth-lab-gui" || msg.v !== 1) return;
if (msg.type === "lab-ready") {
frame.contentWindow.postMessage(
{
source: "growth-lab-host",
v: 1,
type: "init",
credential: { kind: "session-token", token: "<token minted by your backend>" },
theme: "light", // optional UI hints: theme, locale
},
GUI_ORIGIN // never "*"
);
}
if (msg.type === "session-state") console.log("authenticated:", msg.authenticated);
});Message reference (v1)
GUI → host
type | Payload | Meaning |
|---|---|---|
lab-ready | (none) | GUI loaded and listening |
session-state | { authenticated: boolean } | Result of the init handshake / later changes |
resize | { height } | Content height changed (planned) |
error | { code, message } | Handshake or runtime error |
host → GUI
type | Payload | Meaning |
|---|---|---|
init | { credential: { kind: "session-token", token }, theme?, locale? } | Start a session (token is single-use, expires in minutes) |
select-sources | { sourceIds: string[] } | Focus sources in the UI (planned) |
Every message includes source (growth-lab-gui / growth-lab-host) and v: 1.
Cookies in third-party context
The Engine session cookie is set Secure; HttpOnly; SameSite=None; Partitioned so it works
when the GUI is embedded cross-site. Safari users may be prompted via the Storage Access API
the first time.