Search Documentation

Find sections across all documentation pages

Analytics Setup

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.

Events Fired

bookerkit_widget_opened

When: Widget loads or button is clicked

Use for: Tracking widget engagement, page views

Data included: accountId, sessionId, accountName

bookerkit_booking_started

When: User completes personal information (Step 1)

Use for: Lead generation tracking, measuring booking intent

Data included: accountId, sessionId, guestId, email

bookerkit_service_selected

When: 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_selected

When: 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_selected

When: User picks an appointment date

Use for: Micro-conversion tracking

Data included: accountId, sessionId, date (YYYY-MM-DD), serviceId

bookerkit_time_selected

When: User selects a time slot

Use for: Funnel optimization

Data included: accountId, sessionId, date, time, formattedTime, serviceId, duration

bookerkit_booking_completed

When: 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

Setting Up Conversion Tracking

  1. Open Google Ads and go to Tools → Conversions
  2. Click "+ New conversion action"
  3. Select "Website" as the conversion source
  4. Choose "Code the conversion action yourself"
  5. Set up conversion with event name: bookerkit_booking_completed
  6. Configure value tracking using the value parameter
  7. Save and verify events are being tracked

Pro Tip: The value parameter automatically includes the service price, allowing for accurate ROAS tracking.

Facebook Pixel

  1. Open Facebook Events Manager and select your pixel
  2. Go to "Custom Conversions" → "Create Custom Conversion"
  3. Name it "Booking Completed"
  4. For the rule, choose "URL equals" and enter your website domain
  5. Add an event parameter rule: "event equals bookerkit_booking_completed"
  6. Set the conversion value to use event value
  7. Save and use in your Facebook Ads campaigns

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.

Google Analytics 4

  1. Events automatically appear in GA4 if using GTM
  2. Go to GA4 → Configure → Events to see all BookerKit events
  3. Mark bookerkit_booking_completed as a conversion
  4. Use the value parameter for revenue tracking in reports
  5. Create audiences based on booking behavior for remarketing

Google Tag Manager

GTM receives every BookerKit event automatically. See Firing Your Own Tags below for the full trigger, variable, and tag walkthrough.

Firing Your Own Tags

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?

  • You already have GTM on the site: use Option A. GTM replaces dataLayer.push with its own version when it loads, so the Option B wrapper below can be bypassed on a GTM page.
  • You have no tag manager (hand-coded gtag.js, Meta pixel, a custom endpoint): use Option B.

Option A — Google Tag Manager trigger

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

  1. Go to GTM → Triggers → New → Trigger Configuration
  2. Choose trigger type Custom Event
  3. Event name: bookerkit_booking_completed
  4. Leave "This trigger fires on" set to All Custom Events
  5. Name it something like "CE - BookerKit Booking Completed" and save

One 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

  1. Go to GTM → Variables → User-Defined Variables → New
  2. Choose variable type Data Layer Variable
  3. Data Layer Variable Name: value (Version 2, no default)
  4. Name it "DLV - value" and save
  5. Repeat for any other key you need: bookingId, serviceId, sessionId, accountId, guestEmailSha256

3. Point a tag at the trigger

  1. Go to GTM → Tags → New and pick your tag type
  2. Google Ads Conversion Tracking: set Conversion Value to {{DLV - value}}, Transaction ID to {{DLV - bookingId}}, and type the currency in manually — see the note below
  3. GA4 Event: event name purchase (or your own), with event parameters mapped to the same variables
  4. Meta pixel via Custom HTML: call fbq('track', 'Schedule', ...) using the variables
  5. Under Triggering, select the Custom Event trigger from step 1, then save and submit

Currency: 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

  1. Click Preview and enter the URL of the page the widget is embedded on
  2. Complete a test booking in the widget
  3. The bookerkit_* events appear in the Tag Assistant timeline on the host page, not in the iframe — the widget relays them to the parent window
  4. Click the event and confirm your tag is listed under "Tags Fired"

Available DataLayer Variables

  • event (event name)
  • accountId, accountName
  • sessionId, guestId
  • bookingId, reservationId
  • value (service price)
  • serviceId
  • providerId, providerName
  • date, startTime, time, formattedTime, duration
  • addOnCount, prerequisiteCount
  • guestEmailSha256, guestNameSha256 (SHA-256 hashed)

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.

Option B — Vanilla JavaScript listener

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

  • Always check event.origin before reading a message. Any site can post to your window.
  • The dataLayer path is de-duplicated by the embed script (identical events within one second are dropped); the raw postMessage path is not.
  • Nothing fires when the booking flow is rendered outside an iframe, which is why the dashboard Demo preview emits no events. Test on a real embed.
  • Treat missing keys as normal — optional fields such as promoTitle only appear on the paths that set them.

Session Tracking & Attribution

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.

Ad Platform Click IDs

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.

UTM Parameters

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.

Device & Browser

Records device type (desktop/mobile/tablet), browser name and version, OS, screen resolution, and viewport size, captured on every load.

Referral Data

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.

Attribution Persistence

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.

Attribution Provenance

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.

Testing Analytics

Browser Console

Open your browser's developer console and type dataLayer to see all events. After completing a booking, you should see BookerKit events appear.

Google Tag Assistant

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.

Facebook Pixel Helper

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.