Find sections across all documentation pages
BookerKit automatically sends analytics events to your website's tracking infrastructure for complete conversion tracking and campaign attribution.
How It Works
The widget sends events via postMessage to your page, which automatically pushes them to window.dataLayer. No configuration required—if you have GTM or analytics installed, events will flow automatically.
bookerkit_widget_openedWhen: Widget loads or button is clicked
Use for: Tracking widget engagement, page views
Data included: accountId, sessionId, accountName
bookerkit_booking_startedWhen: User completes personal information (Step 1)
Use for: Lead generation tracking, measuring booking intent
Data included: accountId, sessionId, guestId, email
bookerkit_service_selectedWhen: User selects a service (Step 2)
Use for: Understanding which services drive bookings
Data included: accountId, sessionId, serviceId, price, addOnCount. On a pre-selected or promo link, also preSelected and promoTitle.
bookerkit_provider_selectedWhen: User selects a provider/therapist (Step 3, if provider selection is enabled)
Use for: Tracking provider preferences, funnel analysis
Data included: accountId, sessionId, providerId, providerName, serviceId
bookerkit_date_selectedWhen: User picks an appointment date
Use for: Micro-conversion tracking
Data included: accountId, sessionId, date (YYYY-MM-DD), serviceId
bookerkit_time_selectedWhen: User selects a time slot
Use for: Funnel optimization
Data included: accountId, sessionId, date, time, formattedTime, serviceId, duration
bookerkit_booking_completedWhen: Booking successfully completed
Use for: PRIMARY CONVERSION EVENT for Google Ads, Facebook, GA4
Data included: accountId, sessionId, bookingId, reservationId, value (service price, a number), serviceId, date, startTime, addOnCount, prerequisiteCount, guestNameSha256, guestEmailSha256
bookerkit_booking_completedvalue parameterPro Tip: The value parameter automatically includes the service price, allowing for accurate ROAS tracking.
bookerkit_booking_completed"Alternative Method: If you have GTM set up with Facebook Pixel, create a trigger using the bookerkit_booking_completed event and fire a Facebook Standard Event.
bookerkit_booking_completed as a conversionvalue parameter for revenue tracking in reportsGTM receives every BookerKit event automatically. See Firing Your Own Tags below for the full trigger, variable, and tag walkthrough.
There are two ways to act on a BookerKit event: build a trigger in Google Tag Manager, or listen for the event in plain JavaScript and fire your tag yourself. Both run on the page that hosts the widget — never inside the widget iframe.
Which one should I use?
dataLayer.push with its own version when it loads, so the Option B wrapper below can be bypassed on a GTM page.The embed script pushes every event onto window.dataLayer with the event name in the event key, which is exactly what a GTM Custom Event trigger listens for. No cross-domain or iframe configuration is needed — install your GTM container on the host page as usual.
1. Create the trigger
bookerkit_booking_completedOne trigger for every event: tick Use regex matching and set the event name to ^bookerkit_. Pair it with a {{Event}} variable in your tag to tell the funnel steps apart.
2. Create Data Layer Variables for the fields you need
value (Version 2, no default)bookingId, serviceId, sessionId, accountId, guestEmailSha2563. Point a tag at the trigger
{{DLV - value}}, Transaction ID to {{DLV - bookingId}}, and type the currency in manually — see the note belowpurchase (or your own), with event parameters mapped to the same variablesfbq('track', 'Schedule', ...) using the variablesCurrency: value is a bare number (the service price) — there is no currency key in the event. Hard-code the currency in your tag.
4. Verify in Preview
bookerkit_* events appear in the Tag Assistant timeline on the host page, not in the iframe — the widget relays them to the parent windowAvailable DataLayer Variables
For privacy, service names and raw guest identifiers are not exposed in the dataLayer. Email and name are provided only as SHA-256 hashes, suitable for Google Enhanced Conversions and Meta Advanced Matching.
With no tag manager, wrap dataLayer.push and call your tag from the wrapper. Place this script before the BookerKit embed script so the wrapper is installed before the first event fires.
Listen and fire a tag
<script>
window.dataLayer = window.dataLayer || []
// Wrap push so every BookerKit event runs through your handler.
var originalPush = window.dataLayer.push.bind(window.dataLayer)
window.dataLayer.push = function () {
for (var i = 0; i < arguments.length; i++) {
var entry = arguments[i]
if (entry && typeof entry.event === 'string' &&
entry.event.indexOf('bookerkit_') === 0) {
handleBookerkitEvent(entry)
}
}
return originalPush.apply(null, arguments)
}
function handleBookerkitEvent(payload) {
if (payload.event !== 'bookerkit_booking_completed') return
// Google Ads conversion via gtag.js
gtag('event', 'conversion', {
send_to: 'AW-XXXXXXXXX/AbC-D_efGh12_34-567',
value: payload.value,
currency: 'USD',
transaction_id: payload.bookingId
})
// Meta pixel — eventID lets Meta dedupe against the CAPI event
fbq('track', 'Schedule', {
value: payload.value,
currency: 'USD'
}, { eventID: payload.bookingId })
}
</script>
<!-- BookerKit embed goes after the script above -->
<div data-bookerkit-widget="your-account"></div>
<script src="https://www.bookerkit.com/embed.js" async></script>If you would rather not touch dataLayer at all, read the raw message the widget posts to the parent window. This is the same stream the embed script consumes, so it works even on a page with no analytics installed.
Alternative: listen to the postMessage directly
<script>
var seen = {}
window.addEventListener('message', function (event) {
// Required: only trust messages from the BookerKit origin.
if (event.origin !== 'https://www.bookerkit.com') return
var msg = event.data
if (!msg || msg.type !== 'bookerkit_analytics') return
// The raw stream is not de-duplicated — guard it yourself.
var key = msg.event + '|' + (msg.data.sessionId || '')
if (seen[key]) return
seen[key] = true
if (msg.event === 'bookerkit_booking_completed') {
// msg.data holds the same keys listed under Events Fired
fbq('track', 'Schedule', {
value: msg.data.value,
currency: 'USD'
}, { eventID: msg.data.bookingId })
}
})
</script>Rules for a custom listener
event.origin before reading a message. Any site can post to your window.dataLayer path is de-duplicated by the embed script (identical events within one second are dropped); the raw postMessage path is not.promoTitle only appear on the paths that set them.BookerKit automatically captures detailed session data for every booking. This data is stored with the booking session and included in webhook payloads for full attribution. When a page URL carries no UTMs, BookerKit infers the traffic source from click IDs or the referring site, and every session records how its attribution was determined.
Automatically captures: gclid (Google), fbclid (Facebook), fbc / fbp (Facebook cookies), msclkid (Microsoft), ttclid (TikTok), and li_fat_id (LinkedIn). When a session has no UTMs, these fill utm_source and utm_medium: gclid → google / cpc, msclkid → bing / cpc, ttclid → tiktok / paid_social, li_fat_id → linkedin / paid_social, and the Meta ad ids (campaign_id, ad_set_id, ad_id) → facebook / paid_social. fbclid on its own → facebook / social, since Facebook adds fbclid to organic shares too, so on its own it is never counted as paid.
Captures utm_source, utm_medium, utm_campaign, utm_term, and utm_content from the page URL, along with the Meta ad hierarchy ids campaign_id, ad_set_id, and ad_id. UTMs you set always win; inference never overwrites them.
Records device type (desktop/mobile/tablet), browser name and version, OS, screen resolution, and viewport size, captured on every load.
The referrer is the page the visitor came from before reaching your site (a link from another page of your own site, or the widget frame itself, counts as direct), plus the page where the widget loaded. With the tracking script installed, the stored referrer and landing page can be those of the most recent attributed visit within the last 30 days rather than this visit's, and both are always recorded as the page address without its query string or hash (the campaign tags live in the dedicated UTM fields). With no UTMs or click IDs, an external referrer sets source / medium: Facebook and Instagram → social, Google / Bing / Yahoo / DuckDuckGo → organic, any other site → its hostname / referral.
The optional tracking script (bookerkit.min.js, from Widget Settings → Code) stores the most recent visit that carried UTMs or click IDs in the browser for 30 days, so a booking made in another tab or on a later visit is still attributed to that campaign; a visit with only a referrer never replaces a stored campaign. The widget itself keeps attribution for return visits to the page it is on; installing the tracking script extends that to every page. Multi-location (organization) embeds are attributed exactly like single-location ones. This record is written to localStorage in the browser, at the clinic site's own origin, and expires after 30 days; it does not trigger a consent prompt of its own. It holds only campaign tags, ad click IDs, and the page URLs it stores — never a guest's name, email, phone number, or health information — so site owners should list it in their privacy policy and, where they run a consent banner, categorize it under marketing or analytics.
Each session records how its source was determined: declared (UTMs on the URL), inferred_click_id, inferred_referrer, or none, in the session record's metadata as attribution_source. The source value in webhook payloads and the dashboard traffic breakdown is the utm_source when one exists, so traffic that is now inferred reports lowercase names such as facebook or google where it previously showed the referring domain's label.
Open your browser's developer console and type dataLayer to see all events. After completing a booking, you should see BookerKit events appear.
Install the Google Tag Assistant browser extension. It will show you all GTM and GA4 events firing in real-time as you test the widget.
Install the Facebook Pixel Helper extension to verify Facebook events are firing correctly.
Testing Recommendation
Complete a test booking on your live site before running any paid ads. Verify that the bookerkit_booking_completed event appears in your analytics platform with the correct value.