AnswersAnalytics

How do I track across several sites or booking platforms?

9 min read|Updated June 19, 2026
Analyst reviewing cross-site conversion data on two monitors while reconciling booking-platform reports
Short answer

Send every site and booking tool into one analytics destination — usually a single GA4 property — using consistent IDs and UTM tags. Where a platform like Calendly or OpenTable won't take your tracking script, capture the conversion on your side at the click or via the platform's webhook, then stitch sessions with a shared ID.

Key facts
  • The reliable pattern is one analytics destination (usually a single GA4 property) fed by every site and tool, not a separate GA4 property per site that you try to merge later.
  • Cross-domain tracking in GA4 is configured under Admin → Data Streams → Configure tag settings → Configure your domains; without it, a visitor moving from your site to your booking domain is counted as two people in two sessions.
  • GA4 stitches domains by passing a _gl linker parameter in the URL between configured domains — if the booking platform strips query parameters, that handoff breaks and the session splits.
  • Third-party booking platforms (Calendly, OpenTable, Square, Acuity) often won't let you install your own GA4 or gtag code on the final confirmation step, so the booking itself can't be tracked there directly.
  • When you can't put a tag on the booking page, the two fallbacks are tracking the click/redirect on your own site as the conversion, or receiving the platform's webhook server-side and sending a Measurement Protocol event into GA4.

Start With One Destination, Not Many

The mistake that creates most cross-site tracking pain is installing a separate analytics property on each site and trying to reconcile them afterward. Don't. Choose one destination — for almost every SMB that's a single GA4 property — and route every property, subdomain, microsite, and landing page into it with the same Measurement ID. One property, many data streams. That single decision removes most of the reconciliation work before it starts.

Why a shared property rather than per-site properties you stitch together later? Because GA4 can only de-duplicate users, attribute conversions, and build a single customer journey inside one property. The moment a visitor's path lives across two properties, there is no first-class way to join those sessions — you're exporting CSVs and matching by hand, and the numbers never quite agree. Keeping everything in one property means a person who lands on your blog, clicks to your main site, and then hits your booking subdomain is one user on one journey, not three strangers.

Use data streams to keep the sources distinguishable. Each web stream has its own stream ID, and you can add a hostname dimension to any report so you always know which site an event came from. If you genuinely need separate reporting for, say, two distinct brands, GA4 sub-properties or filtered explorations handle that without splitting the underlying data.

The practical setup: deploy the same gtag or Google Tag Manager container across all the web properties you control, point them at one GA4 Measurement ID, and confirm in real-time reports that events from each hostname are arriving. Get this foundation right and the harder cases — cross-domain handoffs and third-party booking tools — become contained problems rather than a tangle across five disconnected accounts.

Cross-Domain Tracking: Don't Lose the Visitor at the Handoff

When a single visit spans more than one domain — your marketing site on one domain and your booking or store on another — you must enable cross-domain tracking, or GA4 counts one person as two. In GA4 this lives under Admin → Data Streams → your web stream → Configure tag settings → Configure your domains. List every domain involved (your-site.com, book.your-site.com if it's a true separate domain, shop.your-site.com, the checkout host). Subdomains on the same root domain usually share cookies and don't need this; genuinely different domains do.

Here's the mechanism, because knowing it tells you when it'll break. GA4 carries the user's identity between domains by appending a _gl linker parameter to the outbound link. The destination domain reads that parameter and adopts the same client ID, so the journey stays continuous. If the platform you're sending people to strips query parameters from the URL — and some booking and payment platforms do — the _gl value never arrives, and the session splits anyway. Test the actual handoff: click through from site A to site B and confirm the _gl parameter survives in the landing URL.

Two failure modes to watch. First, redirects: if your link bounces through a redirect service or a shortener before reaching the booking domain, the linker parameter is often lost in transit. Second, iframes versus full redirects: a booking widget embedded as an iframe on your own page (Calendly's inline embed, for example) behaves differently from a full redirect to the booking domain, and each needs its own verification.

Whatever your stack, verify empirically rather than trusting the config screen. Walk the real path a customer walks, watch GA4 real-time, and confirm it reads as one session across both domains. The settings being saved is not the same as the handoff working.

Booking Platforms You Can't Put a Tag On

The genuinely hard part is the third-party booking platform — Calendly, OpenTable, Square Appointments, Acuity, Mindbody, an OTA — where the confirmation happens on their domain and they won't let you drop your own GA4 or gtag code on the final step. You can't tag the conversion where it occurs, so you capture it somewhere you can. There are two reliable fallbacks.

The first is client-side: track the intent on your own site. Fire a GA4 conversion event the instant the visitor clicks the 'Book now' button or opens the booking widget — before they leave your domain. This is a proxy: it measures booking starts, not confirmed bookings, so it will overcount by the share of people who begin and abandon. It's imperfect but it's free, immediate, and good enough to compare which campaigns and pages drive booking intent.

The second is server-side and far more accurate: use the platform's webhook. Most serious booking tools (Calendly, Acuity, Square, Stripe-backed checkouts) can POST a notification to your server when a booking is actually confirmed. Catch that webhook and forward a server-side event into GA4 using the Measurement Protocol, or into Google Ads as an offline conversion import. Now you're recording confirmed bookings, not just clicks — and if the webhook payload includes a UTM value or a click identifier you passed into the booking flow, you can attribute the confirmed booking back to its original source.

The linchpin for the server-side method is identity. Pass your GA4 client ID (or a click ID like GCLID for Google Ads) into the booking platform as a hidden field or URL parameter at the start, so when the webhook fires you can stitch the confirmed booking to the original session. Without a shared key, you have a conversion count with no source — useful for totals, useless for attribution. Decide up front which identifier travels through the whole flow.

UTMs, Shared IDs, and Avoiding Double-Counting

Consistent UTM tagging and one shared identifier are what hold a multi-site, multi-platform setup together. Tag every inbound link — ads, email, social, partner sites, QR codes — with a disciplined UTM scheme, and document it so utm_source, utm_medium, and utm_campaign mean the same thing everywhere. The most common reason cross-site numbers don't reconcile isn't broken code; it's three people spelling the same campaign three different ways, fragmenting it across reports.

Guard against double-counting, which is the flip side of cross-domain tracking. If both your booking-intent click event and the platform's webhook fire for the same booking, you'll count it twice. Pick one source of truth per conversion — usually the server-side webhook for confirmed revenue — and either don't mark the click event as a conversion, or label them distinctly ('booking_started' versus 'booking_confirmed') so a report never sums them as one number. Self-referrals are the other classic inflator: add your own domains to GA4's unwanted-referrals list so a hop to your booking subdomain and back doesn't register as a brand-new session from 'your-site.com'.

For true end-to-end measurement — first ad click to final paid sale across separate systems — the durable key is an order ID or customer ID that travels with the record. Carry it from the booking platform into your CRM or POS, and when the sale closes, import that outcome back against the original click. This is exactly the offline-conversion stitching that lets you see which channel produced revenue, not just form fills.

A quick word on tools: a single tag-management container (GTM) across your owned sites, plus server-side tagging for the webhook events, covers most SMB setups without exotic software. You don't need a customer data platform to do this well — you need one destination, consistent IDs, and the discipline to verify the handoffs. If your stack spans many platforms and the stitching is eating your week, that's the point to bring in help rather than guess.

Related questions

Send all three into one GA4 property. Shopify supports GA4 natively, so connect it and confirm purchase events arrive. Calendly and Typeform are third-party domains you usually can't fully tag, so use their webhooks (or Typeform's built-in tracking and Calendly's redirect/event hooks) to fire server-side conversions, and pass your GA4 client ID or a campaign parameter into each at the start so the booking or response stitches back to its original source. Add all your domains to cross-domain settings and the self-referral exclusion list so a visitor moving between them stays one session.

Usually no. Subdomains on the same root domain (shop.your-site.com and your-site.com) share cookies by default, so GA4 already treats them as one site. You only need to configure cross-domain tracking when the journey spans genuinely different root domains — for example your-site.com sending visitors to a booking platform on its own domain. When in doubt, walk the path in GA4 real-time and check whether it reads as one session or two.

Because the session split at a domain handoff. GA4 carries identity between domains using a _gl linker parameter in the URL; if the second domain isn't listed in your cross-domain config, or it strips query parameters, or a redirect drops the parameter, the visitor arrives as a brand-new user. Add every domain to the cross-domain list, exclude your own domains as referrals, and test the actual click-through to confirm the parameter survives.

Yes, with a workaround. You have two options: fire a conversion event on your own site when the visitor clicks through to book (this measures intent and slightly overcounts), or catch the platform's webhook when a booking is confirmed and send a server-side event into GA4 via the Measurement Protocol or into Google Ads as an offline conversion. The webhook method is more accurate because it records confirmed bookings, not just clicks.

No, in almost every case. Separate properties can't be merged into one customer journey, so a visitor crossing between your sites becomes multiple disconnected users and your conversion attribution falls apart. Use one GA4 property with a data stream per site, and add a hostname dimension to your reports to tell the sites apart. Reserve separate properties for genuinely separate businesses that never share traffic.

Want a second opinion on your situation?

Get a free, no-obligation proposal. We’ll look at your site and your market and tell you honestly what we’d do — and what we wouldn’t.

Get Free Proposal →

No upfront fees. No long contracts. If you’re not satisfied after the first 30 days, you don’t pay.

Get Free Proposal
Get Free ProposalCall