Overview
Cross-domain tracking in Google Analytics 4 ensures user sessions persist when visitors navigate between domains you own. GA4 uses the _gl linker parameter to pass client identifiers across domain boundaries, preventing session fragmentation and preserving accurate attribution.
When Cross-Domain Tracking Is Required
- Separate checkout domains: Main site on
www.example.com, checkout oncheckout.example.com - Third-party payment processors: Redirects to payment gateways (Stripe, PayPal) that return users to confirmation pages
- Regional or brand domains:
example.com,example.co.uk,brand.example.com - Microsites and landing pages: Campaign-specific domains that funnel to conversion points
- App-to-web experiences: Mobile app links opening web views on different domains
Configuration Methods
Google Tag Manager Setup
- Navigate to your GA4 Configuration tag
- Expand Configure tag settings > More Settings > Cross-domain measurement
- Add all domains that should share sessions:
example.comcheckout.example.compayments.thirdparty.com
- Enable Enable cross-domain measurement
Alternatively, configure in the data stream settings:
- Go to Admin > Data Streams > [Your Stream] > Configure tag settings
- Click Configure your domains
- Add match conditions for each domain
gtag.js Direct Implementation
gtag('config', 'G-XXXXXXXXXX', {
linker: {
domains: ['example.com', 'checkout.example.com', 'partner.com'],
accept_incoming: true,
decorate_forms: true
}
});
Domain Configuration Options
| Option | Description |
|---|---|
domains |
Array of domains to include in cross-domain linking |
accept_incoming |
Accept linker parameters from other domains (default: true) |
decorate_forms |
Add linker to form submissions, not just links |
url_position |
Where to place the _gl parameter (query or fragment) |
Referral Exclusion Configuration
Prevent internal domains from appearing as referral traffic sources:
- Go to Admin > Data Streams > [Your Stream] > Configure tag settings
- Click List unwanted referrals
- Add match conditions:
- Match type:
Contains - Domain:
checkout.example.com
- Match type:
Without referral exclusions, users returning from checkout or payment domains will start new sessions, breaking attribution.
How the Linker Works
When a user clicks a cross-domain link:
- GA4 detects the link destination matches a configured domain
- The
_glparameter is appended with encoded client/session data - The destination domain reads the parameter and restores the session
Example decorated URL:
https://checkout.example.com/cart?_gl=1*abc123*_ga*MTIzNDU2Nzg5MA..*_ga_XXXXXXXX*MTY4...
The _gl parameter contains:
- Client ID (
_ga) - Session ID and timestamp
- Cross-domain linking metadata
Third-Party Checkout Integration
When using external payment providers:
Supported Flow
example.com → stripe.com → example.com/confirmation
- Pre-redirect: Store the GA client_id in a server session or URL parameter
- Payment callback: Include the
_glparameter in the return URL - Confirmation page: GA4 reads the linker and restores the session
Configuration for Payment Providers
Most payment providers support custom return URLs:
// Stripe checkout session
const session = await stripe.checkout.sessions.create({
success_url: 'https://example.com/success?session_id={CHECKOUT_SESSION_ID}&_gl=' + getGALinker(),
cancel_url: 'https://example.com/cart'
});
Retrieve the linker parameter:
function getGALinker() {
return new URLSearchParams(window.location.search).get('_gl') || '';
}
Edge Cases and Considerations
iFrame Embeds
When content is embedded via iframes across domains:
- Parent and child frames need separate GA4 instances
- Use
postMessageto pass client_id between frames - Consider whether iframe tracking genuinely adds value
Single Page Applications (SPAs)
Ensure the linker decorator attaches to dynamically rendered links:
// After SPA navigation or dynamic content load
gtag('event', 'page_view', {
page_location: window.location.href,
page_title: document.title
});
Link Decoration Blockers
Safari ITP and privacy extensions may strip URL parameters:
- Monitor cross-domain conversion rates for drops indicating blocking
- Implement server-side session stitching as a fallback
- Use first-party subdomains where possible
Consent Mode Integration
Cross-domain linking respects Consent Mode settings:
- With
analytics_storage: denied, the linker still works but uses cookieless pings - Client identity may be less persistent without cookies
- Ensure consent state is consistent across all domains
Validation and Testing
GTM Preview Mode
- Enable GTM Preview on the source domain
- Click a cross-domain link
- Verify the
_glparameter appears in the URL - Open GTM Preview on the destination domain
- Confirm the same client_id appears in both contexts
GA4 DebugView
- Enable DebugView in GA4 (Admin > DebugView)
- Install the GA Debugger browser extension
- Navigate through the cross-domain flow
- Verify
session_startonly fires once at the journey start - Confirm client_id remains consistent across domains
Network Tab Inspection
Check that the linker parameters persist:
- Open browser DevTools > Network
- Click a cross-domain link
- Inspect the request URL for
_glparameter - On the destination, verify the
collectrequest includes the restored client_id
Real-Time Reports
After implementing:
- Open GA4 Real-Time reports
- Navigate through the cross-domain journey
- Confirm a single user appears moving through pages on different domains
- Check that traffic source attribution is preserved
Troubleshooting
| Symptom | Likely Cause | Solution |
|---|---|---|
| Sessions split at domain boundary | Domain not in linker list | Add domain to cross-domain configuration |
| Internal domain shows as referral | Missing referral exclusion | Add domain to unwanted referrals list |
_gl parameter missing on links |
Linker not configured | Enable cross-domain measurement in GTM or gtag |
| Different client_id after redirect | accept_incoming disabled |
Ensure destination accepts linker parameters |
| Payment return loses session | Return URL missing _gl |
Pass linker parameter through payment flow |
| Safari users losing sessions | ITP blocking | Implement server-side fallback |
BigQuery Validation
For sites with BigQuery export enabled, validate cross-domain tracking with SQL:
SELECT
user_pseudo_id,
event_name,
(SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location') AS page_location,
event_timestamp
FROM `project.analytics_XXXXXX.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20240101' AND '20240131'
AND user_pseudo_id = 'your_test_client_id'
ORDER BY event_timestamp;
This query reveals the full journey with consistent user_pseudo_id across domains.