Integrations

Conversion tracking & attribution

Your ad attribution survives the embed — conversions fire in your own analytics, and the click data is saved on the booking.

Why this matters

Embedded schedulers normally break ad attribution. The booking happens inside an iframe served from another domain, so the conversion lands in the scheduler's analytics session — not yours — and your ad platforms report the booking as "direct" traffic. The campaign that actually drove the appointment never gets credit.

Cartoply solves this two ways, and both are automatic when you use the embed script: conversion events fire on your page in your analytics session, and the visitor's ad-click attribution is captured and stored on the booking itself.

Conversions fire in your analytics

The embed script runs on your own page, inside your visitor's normal analytics session. When a booking completes inside the embed, the script automatically forwards the conversion to whatever tracking you already have installed:

  • Google Tag Manager — pushes a cartoply_booking_confirmed event to dataLayer.
  • GA4 (gtag) — fires a cartoply_booking_confirmed custom event and the standard generate_lead event.
  • Meta Pixel — fires a CartoplyBookingConfirmed custom event and the standard Schedule event.
  • Everything else — a DOM cartoply:booking-confirmed CustomEvent is always dispatched on window for custom setups (see below).

Because these events fire in the visitor's session on your domain, the ad click that brought them to your site stays attached to the conversion natively — no cross-domain measurement setup, no linker parameters, nothing to configure.

GA4 & Google Ads how-to

In GA4, go to Admin → Events and mark generate_lead (or cartoply_booking_confirmed, if you want a Cartoply-only signal) as a Key Event. Google Ads can then import it as a conversion action. Since the event fires in the visitor's own session on your domain, the original ad click (gclid) is preserved automatically — campaigns get full credit for the bookings they generate.

Google Tag Manager how-to

Create a Custom Event trigger with the event name cartoply_booking_confirmed and attach it to whatever tags you want to fire on a booking. These extra dataLayer keys are available for use in variables:

  • cartoply_event_name — the name of the booked event type.
  • cartoply_start_time — the appointment start time.
  • cartoply_requestedtrue if the booking was held for host approval (see below).

Custom integrations

For anything else — your own analytics, a CRM tag, closing the popup yourself — listen for the DOM event the embed always dispatches. The booking details are on e.detail:

window.addEventListener('cartoply:booking-confirmed', (e) => {
  // e.detail = { type, event, start, requested }
  console.log('Booked:', e.detail.event, 'at', e.detail.start);
});

Attribution is saved on the booking

Separately from firing conversions, the embed script reads campaign parameters from your page's URL (where the ad landed) and forwards them into the booking flow. On each booking, Cartoply stores:

  • utmSource, utmMedium, utmCampaign, utmTerm, utmContent — from the standard utm_* parameters.
  • gclid (Google Ads), fbclid (Meta), msclkid (Microsoft Ads) — ad click IDs.
  • referrer — the referring page, and page — the URL of the page the embed was on.

Attribution persists across your site: the parameters are captured on the page the visitor lands on and remembered for the rest of their browser session, so someone who arrives from an ad, browses to your contact page, and books there is still attributed to the ad. It's last-touch — if they later land on another page carrying utm_* or a click ID, that newer campaign replaces the stored one. Direct visits to a Cartoply booking page (no embed) with those parameters on the URL are captured too.

The stored attribution rides along as an attribution object in Zapier webhook payloads (booking.created, booking.requested, and the rest) — use it to sync lead source into your CRM, or to upload offline conversions to Google Ads by gclid when a booking later turns into revenue.

Bookings held for approval

If the event type uses manual approval (pre-qualification), the conversion events still fire when the guest submits — but with cartoply_requested: true (and requested: true on the DOM event payload), meaning the booking is held for host approval and not yet confirmed. Decide whether to count these as conversions in your setup: count them if you optimize for lead volume, or filter on cartoply_requested being false if you only want confirmed appointments.

If conversions aren't firing

Nothing errors when this breaks — bookings still work, the events just never arrive. Check these in order:

  • Your embed snippet is current. Snippets copied before September 2026 carry a domain check that fails when the booking URL is the bare cartoply.com rather than www.cartoply.com. Because cartoply.com redirects to the www version, the frame's real origin never matched what the script expected, and every event was discarded — no dataLayer push, no gtag, no fbq. Re-copy the snippet from the Embed panel and replace what's on your page. Current snippets accept either form.
  • Your CMS kept the script. Some rich-text editors strip <script> tags on save. View the saved source; if the script is gone, move it to a footer or custom-code area for that page.
  • The tag you expect is actually on the page. The embed forwards to GTM, gtag and fbq only when it finds them. If your analytics loads after the booking completes, or is blocked by a consent banner the visitor hasn't accepted, there's nothing to forward to. The DOM cartoply:booking-confirmed event always fires regardless — listen for that to confirm the embed side is working.
  • You're testing a held booking. Event types using manual approval fire with cartoply_requested: true. If your GA4 Key Event or GTM trigger filters those out, a test booking on an approval event type looks like a failure when it isn't.

Direct links to a Cartoply booking page — not embedded — never fire events in your analytics, by design. There's no page of yours for them to fire on. Attribution is still saved on the booking and reaches you through Zapier.