The Onbookr widget communicates with the parent page via postMessage. You can listen for these events to build custom integrations, analytics, and user flows.
| Prop | Type | Default | Description |
|---|---|---|---|
| onbookr:ready | void | — | Fired when the widget iframe has loaded and the booking flow is ready. |
| onbookr:resize | { height: number } | — | Fired when the widget content height changes. Used for auto-resizing iframes. |
| onbookr:step-change | { step: string } | — | Fired when the user navigates to a different booking step. Steps: "team-member", "date", "time", "duration", "details". |
| onbookr:booking-success | { username: string } | — | Fired after the user completes checkout and the booking is confirmed. |
| onbookr:checkout | { checkoutUrl: string } | — | Fired when the widget needs to redirect to Stripe checkout. The embed script handles this automatically. |
| onbookr:error | { code: string, message: string } | — | Fired when an error occurs in the widget, such as a failed checkout or availability load failure. Codes: "checkout_failed", "availability_failed". |
Every message sent from the widget iframe has the following structure:
interface OnbookrMessage { source: 'onbookr-widget' // Always present — use to filter messages type: string // Event type (e.g., 'onbookr:ready') [key: string]: unknown // Event-specific payload}The embed script automatically dispatches CustomEvents on document for every widget message. Event data is available in event.detail:
1// Widget loaded2document.addEventListener('onbookr:ready', () => {3 console.log('Onbookr widget is ready')4})5 6// Booking completed7document.addEventListener('onbookr:booking-success', (event) => {8 console.log('Booking confirmed for:', event.detail.username)9 10 // Example: send to analytics11 gtag('event', 'booking_completed', {12 host: event.detail.username,13 })14 15 // Example: show a custom thank-you message16 document.getElementById('thank-you').style.display = 'block'17})18 19// Step navigation20document.addEventListener('onbookr:step-change', (event) => {21 console.log('User is on step:', event.detail.step)22 23 // Example: track funnel in analytics24 gtag('event', 'booking_step', {25 step: event.detail.step,26 })27})If you're managing the iframe yourself (not using the embed script or React components), listen for message events directly:
1window.addEventListener('message', (event) => {2 // Always check the source identifier3 if (!event.data || event.data.source !== 'onbookr-widget') return4 5 switch (event.data.type) {6 case 'onbookr:ready':7 console.log('Widget ready')8 break9 10 case 'onbookr:resize':11 // Resize the iframe to match content12 const iframe = document.getElementById('my-booking-iframe')13 if (iframe) iframe.style.height = event.data.height + 'px'14 break15 16 case 'onbookr:booking-success':17 console.log('Booked:', event.data.username)18 break19 20 case 'onbookr:error':21 console.error('Error:', event.data.code, event.data.message)22 break23 24 case 'onbookr:checkout':25 // Redirect to Stripe in the parent window26 window.location.href = event.data.checkoutUrl27 break28 }29})Security note
event.data.source === 'onbookr-widget' before processing messages. This prevents other iframes or scripts from injecting false events.With the @onbookr/react package, callbacks are passed as props — no manual event listener setup needed:
1'use client'2 3import { OnbookrEmbed } from '@onbookr/react'4 5export function BookingWidget() {6 return (7 <OnbookrEmbed8 username="janedoe"9 onReady={() => {10 console.log('Widget loaded and ready')11 }}12 onStepChange={(data) => {13 // Track funnel progression14 analytics.track('booking_step', { step: data.step })15 }}16 onBookingSuccess={(data) => {17 // Show confirmation, redirect, or trigger side effects18 console.log('Booking confirmed for:', data.username)19 router.push('/thank-you')20 }}21 onError={(data) => {22 // Handle widget errors23 console.error('Widget error:', data.code, data.message)24 // e.g., show a toast notification or log to error tracking25 }}26 />27 )28}When a user proceeds to checkout, the widget attempts to redirect the top-level window to Stripe. This is handled automatically by:
onbookr:checkout and redirects window.location.useOnbookrEvents hook handles the redirect automatically.window.top.location.assign(). If blocked by cross-origin restrictions, it falls back to sending an onbookr:checkout postMessage.