The hosted iframe is the lowest-code way to place a responsive SeatLayer picker
on a page. It loads the published event at https://app.seatlayer.io/e/:eventKey
and needs no browser credential.
When to use it
Use the iframe for:
- no-payment registration or reservation;
- internal event allocation;
- previews and rapid prototypes; or
- a direct-booking experience where the hosted behavior is intentional.
For paid ticketing, use the hosted script form of SeatPicker.
It also works without a bundler and provides the server checkout handoff.
Responsive embed
<iframe
id="seatlayer"
title="Choose your seats"
src="https://app.seatlayer.io/e/ev_9f3a"
style="
width: 100%;
aspect-ratio: 4 / 3;
max-height: min(85vh, 760px);
border: 0;
border-radius: 12px;
"
allow="fullscreen"
></iframe>
<script>
const frame = document.getElementById("seatlayer");
const seatLayerOrigin = new URL(frame.src).origin;
addEventListener("message", (event) => {
if (event.origin !== seatLayerOrigin) return;
if (event.source !== frame.contentWindow) return;
if (event.data?.type === "seatlayer:height") {
frame.style.height = `${event.data.px}px`;
frame.style.aspectRatio = "auto";
}
if (event.data?.type === "seatlayer:fullscreen") {
const on = event.data.on === true;
frame.style.position = on ? "fixed" : "";
frame.style.inset = on ? "0" : "";
frame.style.zIndex = on ? "9999" : "";
frame.style.maxHeight = on ? "none" : "";
document.documentElement.style.overflow = on ? "hidden" : "";
}
});
</script>Replace ev_9f3a with a published event key. aspect-ratio reserves stable
space before the first measurement arrives; the height message then tracks
content changes.
Message contract
| Message | Payload | Host action |
|---|---|---|
seatlayer:height |
{ type: "seatlayer:height", px: number } |
Set the frame height |
seatlayer:fullscreen |
{ type: "seatlayer:fullscreen", on: boolean } |
Pin or restore the frame |
The picker sends these messages because a framed document cannot resize its own iframe or escape it for fullscreen. There is currently no public checkout, selection, hold, or booking-result message.
Use the frame helper
@seatlayer/js exports attachPickerFrame() for the same protocol. It validates
the frame source, locks and restores document scrolling, preserves prior styles,
handles height changes received during fullscreen, and exits fullscreen on
Escape.
npm i @seatlayer/jsyarn add @seatlayer/jspnpm add @seatlayer/jsbun add @seatlayer/jsimport { attachPickerFrame } from "@seatlayer/js";
const iframe = document.querySelector<HTMLIFrameElement>("#seatlayer");
if (!iframe) throw new Error("SeatLayer iframe was not found");
const detach = attachPickerFrame(iframe);
// Call when the iframe is removed or the host view unmounts.
detach();By default the helper accepts the origin parsed from iframe.src. To pin it
explicitly:
const detach = attachPickerFrame(iframe, {
origin: "https://app.seatlayer.io",
});Security requirements
- Compare
event.originwith the iframe URL’s origin. - Compare
event.sourcewithiframe.contentWindow. - Accept only known message types and expected primitive fields.
- Never put a SeatLayer secret key in the iframe URL or host JavaScript.
- Give the iframe an accessible
title.
Iframe versus SDK
| Requirement | Iframe | SeatPicker |
|---|---|---|
| No bundler | Yes | Yes, through hosted script |
| Direct booking | Yes | Optional host-controlled flow |
| Your payment/order step before booking | No | Yes |
onCheckout and hold callbacks |
No | Yes |
| Host pricing overrides | No | Yes |
| Host theme overrides | No | Yes |
| Responsive/fullscreen helper | Required in host | Built into same-document widget |
Verification checklist
- Direct booking is the intended product behavior.
- The event is published in the expected mode.
- The listener verifies both origin and window source.
- The frame has a useful title and keyboard focus is visible.
- Height changes do not create horizontal page overflow.
- Fullscreen locks scrolling and restores all prior styles on exit.
- Mobile Safari and an Android browser have been tested.
- Paid flows use an SDK surface instead.
Continue with choose an integration or
install SeatPicker.