Embed the widget
Embed the Bookitive seat map and checkout on your own site — the loader, every mount option, the events it emits, the controller API, and the captcha-safe checkout.
The widget is Bookitive's seat-map UI — seat picking, live availability, and checkout — as a drop-in you host on your own page. Buyers never leave your domain, while payments, captcha, and phone verification run safely on Bookitive's side.
The quick embed
The copy-paste snippet from Share & embed:
<div id="bookitive-tickets"></div>
<script src="https://events.bookitive.com/widget/v1.js"></script>
<script>
Bookitive.mount(document.getElementById('bookitive-tickets'), {
baseUrl: 'https://api.bookitive.com',
org: 'your-org',
event: 'your-event',
});
</script>The typed loader (recommended)
For a real app, use @bookitive/widget-js — the @stripe/stripe-js
pattern: don't bundle the runtime, inject it and get a typed mount().
import { loadBookitive, type BookitiveCustomEvent } from '@bookitive/widget-js';
const bk = await loadBookitive(); // injects events.bookitive.com/widget/v1.js
const el = document.getElementById('seatmap')!;
const controller = bk.mount(el, {
org: 'city-theatre',
event: 'spring-gala-2027',
legend: true,
});
el.addEventListener('bookitive:selectionchanged', (e) => {
const { selection, totalCents } = (
e as BookitiveCustomEvent<'bookitive:selectionchanged'>
).detail;
// update your cart…
});loadBookitive() is idempotent (repeated calls reuse the in-flight
promise or the already-loaded global) and rejects during SSR — call
it from onMount / useEffect.
Mount options
Prop
Type
Events
The host page owns tabs, cart, and the checkout button; the widget
reports everything through bubbling CustomEvents on the mount
element, each typed via BookitiveCustomEvent<'…'>:
bookitive:ready—{ event }, the full public event payload (floors, ticket types, protection flags).bookitive:selectionchanged—{ selection, totalCents }, your cart hook.bookitive:seatselected/bookitive:seatdeselected—{ seatId, code? }(deselect can carryreason: 'taken'when live availability revokes a seat).bookitive:limitreached—{ ticketTypeId, ticketTypeName?, max }, so you can show "max N per order".bookitive:error—{ message }.
The controller
mount() returns a controller to drive the widget:
setFloor(floorId),getSelection(),clearSelection(),selectAvailableByType(ticketTypeId)— bulk-select all free seats of a type,mountCaptcha(el),verifyStart(phone),verifyCheck(phone, code),checkout(input)→ the created order,destroy().
Captcha-safe checkout
controller.checkout() routes the order submission through a mounted
captcha bridge on Bookitive's origin — so Turnstile and phone
verification are solved and verified on Bookitive's side, and your
host domain never configures captcha at all. This is what lets you
wrap a completely custom checkout UI around the widget without taking on
bot-protection yourself.
The published type definitions can trail the live runtime by a release. If an
option or method here isn't in your installed .d.ts yet, it's a type lag,
not a missing feature — upgrade @bookitive/widget-js, or consult the
interactive reference at api.bookitive.com/public/v1/docs.
Related
Developers
Bookitive's integration surfaces — the embeddable widget, the typed JS client, the partner API, and webhooks — and which to reach for.
JS client
The @bookitive/js typed client for building your own checkout — reads, placing orders, phone verification, waitlist, live seat updates, and typed errors.

