Cross-Domain Tracking Issues | Blue Frog Docs

Cross-Domain Tracking Issues

Diagnose and fix cross-domain tracking problems to maintain user sessions across multiple domains

Cross-Domain Tracking Issues

What This Means

Cross-domain tracking allows analytics platforms to recognize the same user as they navigate between different domains (e.g., from example.com to checkout.example.net). When cross-domain tracking fails, each domain appears as a separate session, causing:

  • Inflated user counts
  • Lost referral data
  • Broken conversion attribution
  • Inaccurate customer journeys

Impact on Your Business

Analytics Accuracy:

  • Users counted multiple times - One visitor appears as 2+ users
  • Self-referrals - Your own domains show as traffic sources
  • Lost attribution - Marketing source data breaks at domain boundary
  • Incorrect funnels - User journey appears fragmented

Marketing ROI:

  • Conversions attributed to wrong source
  • Campaign performance looks worse than reality
  • Retargeting audiences become inaccurate
  • Customer lifetime value calculations fail

Business Decisions:

  • Misleading data leads to wrong decisions
  • Marketing spend misallocated
  • User experience issues go undetected

How to Diagnose

Method 1: Check for Self-Referrals in GA4

  1. Open Google Analytics 4
  2. Navigate to Reports → Acquisition → Traffic acquisition
  3. Look for your own domains in the "Session source/medium" report
  4. If you see yourdomain.com / referral - cross-domain is broken

Method 2: Inspect Client ID Across Domains

On domain A, run in console:

// Get GA4 client ID
gtag('get', 'G-XXXXXXXXXX', 'client_id', (clientId) => {
  console.log('Domain A Client ID:', clientId);
});

Click a link to domain B, then run the same code.

If client IDs differ, cross-domain tracking isn't working.

Method 3: Check URL Parameters

When clicking a link to another domain:

  1. Hover over a cross-domain link
  2. Check if URL contains _gl parameter (GA4) or _ga parameter (UA)
  3. Click the link and inspect the landing URL

Working cross-domain URL:

https://checkout.example.com/cart?_gl=1*1abc123*_ga*MTIzNDU2Nzg5*_ga_XXXXXXXXXX*MTY0MDAwMDAwMC4x

If no _gl parameter, cross-domain isn't configured.

Method 4: GA4 DebugView

  1. Enable debug mode on both domains
  2. Navigate across domains
  3. In GA4 DebugView, check if session_start fires on each domain
  4. Multiple session_start events = cross-domain broken

Method 5: GTM Preview Mode

  1. Start GTM Preview on domain A
  2. Click cross-domain link
  3. Check if Preview mode continues on domain B
  4. If preview breaks, linker isn't working

Common Causes

1. Missing Cross-Domain Configuration

GA4 needs explicit cross-domain setup for each domain pair.

The linker script isn't adding parameters to outbound links.

3. Wrong Domain Format

Using www.example.com vs example.com inconsistently.

4. JavaScript Errors Blocking Linker

Errors before the linker runs prevent decoration.

Some configurations don't handle target="_blank" links.

6. Form Submissions Crossing Domains

Forms need special handling for cross-domain tracking.

7. Redirects Stripping Parameters

Server redirects removing the _gl parameter.

CMP blocking cookies before linker runs.

General Fixes

Fix 1: Configure GA4 Cross-Domain Tracking

In GA4 Admin:

  1. Navigate to Admin → Data Streams
  2. Click on your web stream
  3. Click Configure tag settings
  4. Click Configure your domains
  5. Add all domains that need cross-domain tracking:
    • example.com
    • checkout.example.net
    • shop.example.com

Match types:

  • Contains - Matches any URL containing the domain
  • Equals - Exact match only
  • Starts with - URL prefix match

Fix 2: Configure GTM Linker

If using Google Tag Manager:

  1. Open your GTM container
  2. Edit your GA4 Configuration tag
  3. Add Fields to Set:
    • Field Name: linker
    • Value: {"domains": ["example.com", "checkout.example.net"]}

Or use separate Linker tag:

{
  "domains": ["example.com", "checkout.example.net", "shop.example.com"],
  "accept_incoming": true,
  "url_position": "query"
}

Fix 3: Manual gtag.js Configuration

If implementing directly:

<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-XXXXXXXXXX', {
    'linker': {
      'domains': ['example.com', 'checkout.example.net', 'shop.example.com'],
      'accept_incoming': true
    }
  });
</script>

Fix 4: Handle Forms Crossing Domains

Forms need special treatment:

// Decorate form action URLs
gtag('config', 'G-XXXXXXXXXX', {
  'linker': {
    'domains': ['checkout.example.com'],
    'decorate_forms': true
  }
});

Or manual form decoration:

document.querySelectorAll('form[action*="checkout.example.com"]').forEach(form => {
  form.addEventListener('submit', function() {
    gtag('get', 'G-XXXXXXXXXX', 'client_id', function(clientId) {
      const url = new URL(form.action);
      url.searchParams.set('_gl', generateLinkerParam(clientId));
      form.action = url.toString();
    });
  });
});

Fix 5: Exclude Referrals from Your Domains

In GA4:

  1. Navigate to Admin → Data Streams
  2. Click on your web stream
  3. Click Configure tag settings
  4. Click List unwanted referrals
  5. Add all your domains:
    • example.com
    • checkout.example.net

Fix 6: Handle Subdomain Tracking

For subdomains of the same root domain:

gtag('config', 'G-XXXXXXXXXX', {
  'cookie_domain': '.example.com', // Note the leading dot
  'linker': {
    'domains': ['www.example.com', 'shop.example.com', 'blog.example.com']
  }
});

Fix 7: Debug and Verify Linker

Add debug logging:

// Check if linker is decorating links
document.querySelectorAll('a[href*="checkout.example"]').forEach(link => {
  link.addEventListener('click', function(e) {
    console.log('Link href:', this.href);
    // Should contain _gl parameter
  });
});

// Check incoming linker parameter
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('_gl')) {
  console.log('Incoming linker:', urlParams.get('_gl'));
}

Fix 8: Handle Redirects

Ensure server redirects preserve query parameters:

Apache (.htaccess):

# Preserve query string in redirects
RewriteRule ^old-page$ /new-page [R=301,L,QSA]

Nginx:

# Preserve query string
rewrite ^/old-page$ /new-page permanent;

Meta Pixel Cross-Domain

Configure fbq for Multiple Domains

fbq('init', 'YOUR_PIXEL_ID', {}, {
  agent: 'your-agent-string'
});

// Enable cross-domain with external_id
fbq('init', 'YOUR_PIXEL_ID', {
  external_id: getCrossDomainUserId() // Your user identifier
});

Use First-Party Cookies

// Set consistent user ID across domains using server-side
fbq('init', 'YOUR_PIXEL_ID', {
  external_id: 'USER_123', // Server-provided consistent ID
  em: 'hashed_email' // Hashed user email for matching
});

Platform-Specific Guides

Platform Troubleshooting Guide
Shopify Shopify Cross-Domain Guide
WordPress WordPress Cross-Domain Guide
Magento Magento Cross-Domain Guide

Verification

After implementing cross-domain tracking:

  1. Test the link decoration:

    • Click a link to another domain
    • Verify _gl parameter appears in URL
    • Check parameter persists after page load
  2. Verify Client ID consistency:

    // Run on both domains after navigation
    gtag('get', 'G-XXXXXXXXXX', 'client_id', console.log);
    // Should show same ID
    
  3. Check GA4 reports:

    • Wait 24-48 hours for data
    • Verify self-referrals are gone
    • Check user count is realistic
  4. Test user journey:

    • Start on domain A
    • Navigate to domain B
    • Complete conversion
    • Verify single session in GA4

Common Mistakes

  1. Forgetting www vs non-www - Treat as separate domains
  2. Not including all domains - Missing one breaks the chain
  3. Incorrect match conditions - "Contains" vs "Equals"
  4. Not testing forms - Only testing regular links
  5. Ignoring new tabs - target="_blank" needs handling
  6. Redirect stripping params - Server config issues
  7. Cookie consent timing - Linker runs before consent
  8. Subdomain cookie scope - Need root domain cookie
  9. Multiple GA4 properties - Each needs configuration
  10. Testing in same browser session - Use incognito for clean tests

Cross-Domain Checklist

Pre-Implementation:
[ ] List all domains involved
[ ] Identify domain transition points (links, forms, redirects)
[ ] Document current user/session counts for comparison

Configuration:
[ ] Add all domains to GA4 cross-domain settings
[ ] Configure referral exclusions
[ ] Set up GTM linker (if using GTM)
[ ] Enable form decoration if needed

Testing:
[ ] Test in incognito/private browsing
[ ] Verify _gl parameter appears on outbound links
[ ] Confirm client ID matches across domains
[ ] Check forms work correctly
[ ] Test new tab/window links

Verification:
[ ] Monitor for self-referrals in GA4
[ ] Compare user counts before/after
[ ] Verify conversion attribution works
[ ] Check campaign tracking maintains source

Additional Resources

// SYS.FOOTER