The moment a user crosses from your main site to a separate checkout, booking, or partner domain, GA4 treats them as two different people on two different sessions – unless you have told it otherwise. That split is what quietly turns one clean conversion journey into a self-referral and a broken funnel. Here is how to configure cross-domain tracking properly.

When you actually need it

You need cross-domain tracking when a single user journey spans two or more domains that share the same GA4 property: yoursite.com to checkout-provider.com, or a marketing site to a separate app domain. You do not need it for subdirectories or for a subdomain that already shares the main domain's cookies in the same property, since first-party cookies carry across those on their own.

Both sites must use the same property

The non-negotiable prerequisite: every domain in the journey must have the same GA4 property installed, whether through gtag or GTM. Cross-domain tracking links sessions within one property; it cannot stitch two separate properties together. Confirm the same measurement ID is live on each domain before you touch any settings.

Set it up in the GA4 admin

The configuration is entirely in the interface, no code required for the standard case:

  • In Admin, open Data Streams and select your primary web stream.
  • Click Configure tag settings under the Google tag section.
  • Choose “Configure your domains.”
  • Add each domain with a “contains” or “equals” rule.

Enter domains without the protocol and without trailing slashes – use example.com, not https://example.com/. GA4 will not assume www and non-www are the same, so list each variation you use, along with any distinct subdomains like checkout.example.com.

How the linker works under the hood

Once configured, GA4 decorates outbound links to your listed domains with a _gl parameter in the URL. That parameter carries the client ID across the boundary so the second domain continues the same session instead of starting a new one. You normally do not write any code for this, but for edge cases – a form POST, a button that builds a URL in JavaScript – you may need to pass the linker manually:

// Edge case: manually decorate a URL with the linker parameter
gtag('get', 'G-XXXXXXXXXX', 'client_id', function(id) {
  // append/forward the client_id or use gtag linker config for custom flows
  console.log('client_id to carry across domains:', id);
});

Exclude the referral, then verify

Two final steps make the data clean:

  • Add the other domains to your unwanted-referrals list so the second domain does not show up as a referral source, which would otherwise overwrite the original campaign.
  • Test the journey end to end: click from domain A to domain B and confirm the _gl parameter appears in the destination URL.

In DebugView or Realtime, walk the full path and check it stays one session with the original source intact. If the second domain still starts a fresh session_start with (direct), the _gl parameter is not being passed, which points back to the domain list or a link the linker did not decorate.

A user crossing to your checkout domain should stay one person on one journey, not fracture into two sessions and a self-referral. Install the same property everywhere, list every domain and variation, let the _gl linker carry the client ID, exclude the cross-referrals, and verify the parameter in the URL. Do that and the conversion journey that spans your domains reports as the single path it really is.

Want a stronger data analyst role or a raise? Grab the FREE Product Analyst Playbook and get the exact roadmap to your next offer.