By default, browsers isolate cookies by domain, which means the moment a user moves from one domain to another, the analytics on each side has no idea it is the same person. They show up as two separate users with two separate sessions, the funnel breaks in the middle, and your attribution is split between two halves of a single journey. Cross-domain tracking stitches that journey back together. In GA4 it works by passing the user’s identifiers across the domain boundary in the URL, so the second domain recognises the visitor as the same person continuing the same session. This article covers why it is needed, exactly how it works, how to set it up in GTM, and how to confirm it is actually working.
The problem it solves
Picture a user who starts on one domain, gets assigned a client ID and a session, then clicks through to a different domain. Because cookies do not cross that boundary, the second domain assigns a brand-new client ID and starts a fresh session, and GA4 counts two users where there is one. The fix is a URL parameter, GA4’s linker, written as _gl, which carries the client ID and session ID across the boundary so the destination domain writes the same client ID into its own cookie and the session continues unbroken. One user, one session, a complete funnel.
When you need it, and when you do not
The single rule that decides this is the registrable domain, the part you would actually buy from a registrar. If two addresses share the same registrable domain, cookies are already shared and you need nothing. If the registrable domain differs, you need cross-domain tracking. So moving between shop.example.com and blog.example.com needs no configuration, because they are subdomains of one registrable domain that GA4 handles automatically. But moving from example.com to example.co.uk, to an external checkout like checkout.partner.com, to a separate marketing blog, or to an app on a different registered domain all require it, because each is a different cookie scope. Subdomains of the same registrable domain are free; anything else needs the linker.
How it actually works
The mechanism is worth understanding because it explains every troubleshooting step later. When a user clicks a link from the first domain, GA4, running through GTM, intercepts the click and checks whether the destination is in its list of linker domains. If it is, GA4 reads the current client ID from the _ga cookie and the session information from the _ga_<MEASUREMENT_ID> cookie, encodes both into a _gl parameter, and rewrites the link so the destination URL carries it.
https://domain2.com/page?_gl=1*abc123*_ga*1234.5678*_ga_XYZ*abcdef
The browser navigates with that parameter in the URL, GA4 loads on the second domain, detects and decodes _gl, and writes the same client ID into the second domain’s _ga cookie. From that point the visitor is the same user in the same session. The reason this uses a URL parameter rather than a shared cookie is decisive: browsers actively block third-party cookies, but a URL parameter becomes first-party for the destination domain, which makes it resilient to tracking-prevention features that would otherwise sever the link.
Setting it up in GTM
A few prerequisites must all hold, and they are the most common cause of a setup that silently fails. Every domain must use the same GA4 property and, critically, the same Measurement ID, because the _gl linking only works between domains sharing that ID. GTM must be deployed on every domain, since the linker logic runs from the GA4 Configuration tag and the second domain needs GA4 present to read the incoming parameter. The domains do not all need the same GTM container, though using one across them is simpler.
The configuration itself lives in the GA4 Configuration tag. Inside it you open the domains configuration and add each registrable domain involved, one per line, with no scheme and no path.
example.compartner-domain.comcheckout-provider.com
Bare domains only, so example.com rather than https://example.com/, and you do not list subdomains separately because adding the registrable domain covers them all. It is also worth confirming the cookie domain is set to detect the highest-level domain automatically, which is the default and ensures the cookie is shared across subdomains.
cookie_domain: auto
You only need to set that explicitly if you previously overrode it. With the domains configured, preview the container starting on the first domain, click through to a configured destination, and you are ready to verify.
Confirming it works
Verification has four checks, and doing all of them saves a lot of guesswork. First, look at the outbound link. After clicking from the first domain to a configured destination, the destination URL should carry a _gl parameter. If it is missing, the linker is not configured or the destination is not in the domains list. Second, compare the _ga cookie values in DevTools under Application and Cookies. The value on the first domain and the value on the second after the click should be identical, because a matching value means the same user, and different values mean the linker is not working. Third, open GA4 DebugView, where a journey across domains should appear as a single session with a consistent client ID rather than two users starting fresh. Fourth, in reports add Hostname as a secondary dimension, where after test traffic you should see one user appearing under multiple hostnames within the same session.
Subdomains are a different problem
This is the most common point of confusion, so it is worth stating plainly. Subdomains and cross-domain are different problems with different solutions. Two subdomains of one registrable domain, like www.example.com and shop.example.com, need nothing at all, because GA4 handles them natively through the auto cookie domain. Two different registrable domains, like example.com and partner.com, or even the same brand on different country domains like example.com and example.co.uk, need the linker. The technical reason is that browsers scope cookies by registrable domain: a cookie set at .example.com is readable from any of its subdomains, but is not readable from partner.com.
Common multi-domain shapes
Most real setups fall into one of three patterns. The hub-and-spoke is the most common, a main site with a third-party checkout and a vendor-hosted help centre, where all three go in the linker list. The multi-region pattern has the same brand on several country domains, all four in the linker, often paired with a lookup table that selects the right Measurement ID per region. And the application split, common in SaaS, has a marketing site on one registrable domain and the product app on another, both listed so the journey from marketing to product stays intact.
Edge cases worth knowing
A few situations behave differently from a plain link. Iframes embedded from another domain do not automatically share the client ID, and your options are to pass _gl through the iframe’s source URL, to share the ID with postMessage through custom development, or often simplest, not to track the iframe separately. Cross-domain forms that post from one domain to another need the linker to decorate the form action, which GA4 does by default through form decoration, and you only touch it if you have explicitly disabled it.
gtag('set', 'linker', { decorate_forms: true, domains: ['example.com', 'partner.com'] });
Programmatic navigation is the trap, because setting window.location directly does not get _gl appended automatically, so you would have to fetch the session ID and build the URL yourself, though in practice most navigation goes through anchor tags that the linker handles for you. And server-side redirects usually preserve the _gl parameter through a 301, but some redirect configurations strip query parameters, so this is worth verifying rather than assuming.
Mistakes can happen
The failures cluster around a handful of causes. Different Measurement IDs across domains is the classic one: the _glparameter is sent but the destination ignores it, so the IDs must match everywhere. Typos in the domain list, or adding a scheme or trailing slash, stop links being decorated, because the linker needs bare domains. Deploying GTM on only one domain means the linker fires on the first but the second has no GA4 to read it, so users still appear new. Tracking-prevention features like Safari’s intelligent tracking prevention can shorten the _ga cookie’s life even when _gl works, which is one of the strongest arguments for server-side GTM where resilience matters. Consent denied for analytics means no cookies, no client ID, and no linking at all, which is the expected behaviour under Consent Mode v2. And URL shorteners can strip the _gl parameter, so avoid them on cross-domain critical paths or add UTMs as a backup signal.
Practices that keep it healthy
A few habits make cross-domain setups maintainable. Use one GTM container across all domains where you can, and store the Measurement ID and the domain list in constant variables so there is a single source of truth that is easy to update when domains change. Document the intent in the tag’s notes for whoever maintains it next. Test every direction rather than just one, because A to B working does not prove B to A works. Audit periodically, since partners, regions, and dev environments rotate. And coordinate with any partner domain that runs its own GA4, to avoid double-counting.
A checklist before you publish
When planning an implementation, work through a simple sequence: list every domain involved, including staging and partners; identify which share a registrable domain and therefore need nothing; confirm the same Measurement ID will be used everywhere; verify GTM is deployed on every domain; add all the distinct registrable domains to the linker; confirm the cookie domain is auto; then test every direction, check that _gl appears on outbound links, that the _ga cookie matches across domains, and that DebugView shows a single continuous session. Document it, and publish. Follow that order and cross-domain tracking stops being mysterious and becomes a reliable, verifiable part of your measurement setup.
See you soon.
[…] Cross-Domain Tracking in Google Tag Manager […]