The booking widget, live on this page
This is the widget a business pastes into its own site. Not a copy kept for the demo: the production build, loaded from the production origin when you click it. Make a test booking against Aria Hair & Beauty (Demo) and watch what it hands back to the page.
Inline. The widget rendered inside the page column, exactly as it sits in a venue's own layout.
Modal. The floating launcher button, opening the same flow over the page.
The widget loads on click, not on page load. That's the facade pattern we recommend on venue sites too, so this page demonstrates real load behaviour rather than a pre-warmed one. It runs in its own iframe with its own styles: your theme can't restyle it, it can't leak into your page, and it survives Elementor and the rest of the page-builder world it was built for. If the connection drops mid-booking, the retry reuses the same idempotency key, so a recovered submission can't create a second booking.
Nothing loads from bookmyvenue.com.au until you click.
Events seen by the host page
Waiting for a booking. Make one above and watch this panel.
Put it on your site
Inline or modal container, one script:
<div data-bookmyvenue
data-venue="your-venue"
data-api="https://bookmyvenue.com.au"></div>
<script src="https://bookmyvenue.com.au/widget/loader.js?v=13" defer></script>Floating launcher: one script tag, no container needed.
<div data-bookmyvenue
data-venue="your-venue"
data-api="https://bookmyvenue.com.au"
data-mode="modal"></div>
<script src="https://bookmyvenue.com.au/widget/loader.js?v=13" defer></script>Events seen by the host page
When a booking completes, the widget fires a bookmyvenue:booked CustomEvent on the page and pushes the same payload to dataLayer when one exists. The panel above prints each event as it arrives.
This panel is the point of the whole page. The booking happens inside an iframe, and iframes normally swallow the conversion: your analytics see a visit and no outcome. The bridge hands the outcome back to your page, so your own GTM tags and ad pixels count the booking on your own site, attributed to the traffic that earned it.
The layout shift that doesn't happen
Watch the page while the widget loads: nothing below it moves. The loader reserves the widget's height before anything renders, then adjusts it over postMessage as the flow steps through. No layout jump, which shows up in Core Web Vitals and in how the page feels under your thumb.
