Checkout Events & Callbacks
Listen to booking lifecycle events — track conversions, redirect after checkout, and integrate analytics.
ResytechClient emits events at each stage of the booking flow. Use on() and off() to subscribe.
Events
| Event | Payload | When |
|---|---|---|
checkout:open | CheckoutRequest | The booking modal has opened |
checkout:ready | undefined | The iframe has loaded and is ready to interact |
checkout:complete | { confirmationCode, price, ... } | The customer completed a booking |
checkout:close | undefined | The modal has been closed |
checkout:open
Fires immediately when showUI() is called. The payload is the CheckoutRequest object passed to showUI(), including any pre-fill options and the location from config.
client.on('checkout:open', (data) => {
console.log('Booking started for activity:', data.activity);
console.log('Pre-selected date:', data.date);
});Payload
{
location: string; // Location UUID (always present)
activity?: string; // Activity UUID (if pre-selected)
equipment?: string; // Equipment UUID (if pre-selected)
date?: string; // Date (if pre-selected)
durationMins?: number; // Duration in minutes (if pre-selected)
timeSlotStart?: string; // Time slot start (if pre-selected)
timeSlotEnd?: string; // Time slot end (if pre-selected)
timeSlotPrice?: number; // Price (if pre-selected)
}checkout:ready
Fires when the iframe has loaded and the booking UI is visible. This event has no payload.
The iframe sends a checkout-ready PostMessage when it is fully initialized. If no message is received within 3 seconds, the iframe is shown anyway (timeout fallback).
client.on('checkout:ready', () => {
console.log('Booking UI is loaded and visible');
});checkout:complete
Fires when the customer successfully completes a booking. The payload includes the confirmation code and price, along with any additional data sent by the booking iframe.
client.on('checkout:complete', (data) => {
console.log('Confirmation:', data.confirmationCode);
console.log('Total price:', data.price);
});Payload
{
confirmationCode: string; // Booking confirmation code
price: number; // Total price charged
// ...additional fields from the booking iframe
}checkout:close
Fires when the modal is closed, either by the user or by calling client.close(). This event has no payload. Fires regardless of whether a booking was completed.
client.on('checkout:close', () => {
console.log('Modal closed');
});Registering and Removing Listeners
// Register
client.on('checkout:complete', handleComplete);
// Remove (must use the same function reference)
client.off('checkout:complete', handleComplete);You can register multiple listeners for the same event:
client.on('checkout:complete', trackConversion);
client.on('checkout:complete', showConfirmationBanner);
client.on('checkout:complete', sendAnalyticsEvent);PostMessage Communication
The booking iframe communicates with the parent window using window.postMessage. The library handles this internally -- you do not need to work with PostMessage directly.
The iframe sends these message types:
| Message Type | Maps To Event | Description |
|---|---|---|
checkout-ready | checkout:ready | Iframe is loaded and ready |
checkout-close | checkout:close | User closed the booking from inside the iframe |
checkout-complete | checkout:complete | Booking was successfully completed |
Messages are parsed as JSON. Non-JSON messages and messages without a type field are silently ignored. When debug mode is enabled, all received messages are logged to the console.
Practical Examples
Conversion Tracking with Google Analytics
client.on('checkout:complete', (data) => {
gtag('event', 'purchase', {
transaction_id: data.confirmationCode,
value: data.price,
currency: 'USD'
});
});Facebook Pixel
client.on('checkout:open', () => {
fbq('track', 'InitiateCheckout');
});
client.on('checkout:complete', (data) => {
fbq('track', 'Purchase', {
value: data.price,
currency: 'USD'
});
});Redirect After Booking
client.on('checkout:complete', (data) => {
window.location.href = `/confirmation?code=${data.confirmationCode}`;
});Show a Confirmation Banner
client.on('checkout:complete', (data) => {
const banner = document.createElement('div');
banner.className = 'success-banner';
banner.textContent = `Booking confirmed! Your code: ${data.confirmationCode}`;
document.body.prepend(banner);
});
client.on('checkout:close', () => {
// Refresh availability after the modal closes
refreshCalendar();
});Log All Events (Debugging)
['checkout:open', 'checkout:ready', 'checkout:complete', 'checkout:close'].forEach(event => {
client.on(event, (data) => {
console.log(`[Resytech] ${event}`, data || '');
});
});Error Handling
If the iframe fails to load or an error occurs during PostMessage handling:
- With
debug: true, errors are logged toconsole.error - With
debug: false(default), errors are silently caught - The
checkout:readyevent fires after a 3-second timeout even if the iframe does not send a ready message, so the user is never stuck on a spinner indefinitely - There is no dedicated error event. If you need to detect load failures, use the
checkout:readyevent timing combined with your own timeout logic.
