Full Screen Embedding
Embed the Customizer anywhere on your website using an iframe.
Important: the Customizer uses its own embed session handshake. Your page replies to ALTER_CHILD_HELLO, then responds to ALTER_CUSTOMIZER_INIT_SESSION with ALTER_CUSTOMIZER_SESSION_READY.
Flow:
- Your page loads the iframe with the Customizer URL.
- The iframe sends
ALTER_CHILD_HELLOand your page replies withALTER_PARENT_ACKusing the same nonce. - The iframe requests a Customizer session with
ALTER_CUSTOMIZER_INIT_SESSION. - Your backend creates a session through Alter Product Public API and returns
token,cartKey, andmode. - Your page sends
ALTER_CUSTOMIZER_SESSION_READY. After save, the Customizer emitsALTER_CUSTOMIZER_ADD_TO_CARTorALTER_CUSTOMIZER_UPDATE_DESIGN.
<!DOCTYPE html>
<html>
<head>
<title>Customizer - Full Screen (Token + postMessage)</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
* { box-sizing: border-box; }
html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
#wrapper { width: 100%; height: 100%; }
iframe { width: 100%; height: 100%; border: 0; display: block; }
</style>
</head>
<body>
<div id="wrapper">
<iframe
id="alter-iframe"
title="Alter Product Customizer"
src="https://alterproduct.com/app/customizer/11"
allowfullscreen
></iframe>
</div>
<script>
const IFRAME_ORIGIN = "https://alterproduct.com";
const ALTER_PRODUCT_ID = 11;
const DEFAULT_MODE = "view";
const iframe = document.getElementById("alter-iframe");
let handshakeOk = false;
function postToIframe(payload) {
iframe.contentWindow.postMessage(payload, IFRAME_ORIGIN);
}
/**
* Your backend owns this endpoint. It should create or reserve a cartKey
* and call Alter Product Public API using server-side credentials.
* Expected response: { token: "...", cartKey: "...", mode: "view" | "edit" }
*/
async function createCustomizerSessionFromYourBackend(payload) {
const res = await fetch("/api/alter/customizer-session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload || {})
});
if (!res.ok) throw new Error("Failed to create customizer session");
const data = await res.json();
if (!data || !data.token || !data.cartKey) {
throw new Error("Missing token or cartKey");
}
return data;
}
window.addEventListener("message", async (event) => {
// ✅ 1) Always validate origin
if (event.origin !== IFRAME_ORIGIN) return;
// ✅ 2) Always validate source
if (event.source !== iframe.contentWindow) return;
const msg = event.data || {};
if (!msg.type || typeof msg.type !== "string") return;
// -----------------------
// A) HANDSHAKE
// iframe -> parent: ALTER_CHILD_HELLO { nonce }
// parent -> iframe: ALTER_PARENT_ACK { nonce }
// -----------------------
if (msg.type === "ALTER_CHILD_HELLO") {
const nonce = msg.nonce;
if (!nonce || typeof nonce !== "string") return;
handshakeOk = true;
postToIframe({ type: "ALTER_PARENT_ACK", nonce });
return;
}
// Ignore everything until handshake is done
if (!handshakeOk) return;
// -----------------------
// B) CUSTOMIZER SESSION REQUEST (on-demand)
// iframe -> parent: ALTER_CUSTOMIZER_INIT_SESSION
// payload: { alterProductId, uiDesignId, mode }
//
// parent -> iframe: ALTER_CUSTOMIZER_SESSION_READY
// { token, cartKey, mode }
// -----------------------
if (msg.type === "ALTER_CUSTOMIZER_INIT_SESSION") {
try {
const payload = msg.payload || {};
const alterProductId = Number(payload.alterProductId || ALTER_PRODUCT_ID);
const uiDesignId = Number(payload.uiDesignId || 0);
const mode = payload.mode === "edit" ? "edit" : DEFAULT_MODE;
const session = await createCustomizerSessionFromYourBackend({
alterProductId,
mode,
uiDesignId,
origin: window.location.origin
});
postToIframe({
type: "ALTER_CUSTOMIZER_SESSION_READY",
token: session.token,
cartKey: session.cartKey,
mode: session.mode || mode
});
} catch (e) {
postToIframe({
type: "ALTER_CUSTOMIZER_SESSION_ERROR",
message: String(e && e.message ? e.message : e)
});
}
return;
}
// -----------------------
// C) OPTIONAL: listen to Customizer events
// -----------------------
if (msg.type === "ALTER_CUSTOMIZER_ADD_TO_CART") {
console.log("[Alter] Customizer add to cart:", msg.payload);
return;
}
if (msg.type === "ALTER_CUSTOMIZER_UPDATE_DESIGN") {
console.log("[Alter] Customizer update design:", msg.payload);
return;
}
});
</script>
</body>
</html>