FullStory Cross-Domain Tracking | OpsBlu Docs

FullStory Cross-Domain Tracking

Configure FullStory to track users seamlessly across multiple domains and subdomains.

Overview

Cross-domain tracking allows FullStory to maintain a continuous session as users navigate between different domains or subdomains. Without proper configuration, each domain transition creates a new session, breaking the user journey and making it difficult to analyze multi-domain flows.

This is essential for businesses that operate across multiple domains, such as:

  • Marketing site (example.com) → App (app.example.com)
  • E-commerce store (shop.example.com) → Checkout (checkout.example.com)
  • Main site (example.com) → Support portal (support.example.com)

How Cross-Domain Tracking Works

FullStory uses first-party cookies to identify users. By default, cookies are scoped to a single domain. Cross-domain tracking works by:

  1. Preserving the user identifier as users navigate between domains
  2. Passing session context via URL parameters or shared cookie domains
  3. Linking sessions together in FullStory's backend

Same-Domain vs Cross-Domain Scenarios

Same Domain (No Configuration Needed)

These scenarios work automatically without additional setup:

Subdomain to Subdomain (Same Root Domain):

  • www.example.comapp.example.com
  • shop.example.comcheckout.example.com

FullStory's cookies are set at the root domain level (.example.com), so they're accessible across all subdomains.

Path to Path (Same Hostname):

  • example.com/pricingexample.com/signup
  • app.example.com/dashboardapp.example.com/settings

These are the same domain, so sessions continue seamlessly.

Cross-Domain (Requires Configuration)

These scenarios require cross-domain tracking setup:

Different Root Domains:

  • example.comexampleapp.io
  • shop-example.comcheckout-example.com

Different Top-Level Domains (TLDs):

  • example.comexample.co.uk
  • example.ioexample.net

Configuration Methods

FullStory offers two methods for cross-domain tracking:

If all your domains share a common root domain, configure FullStory to set cookies at that level.

Example Scenario:

  • Main site: example.com
  • App: app.example.com
  • Shop: shop.example.com

Configuration:

When initializing FullStory, specify the shared cookie domain:

window['_fs_host'] = 'fullstory.com';
window['_fs_script'] = 'edge.fullstory.com/s/fs.js';
window['_fs_org'] = 'YOUR_ORG_ID';
window['_fs_namespace'] = 'FS';

// Set shared cookie domain
window['_fs_cookie_domain'] = '.example.com';  // Note the leading dot

// Rest of FullStory snippet...

This sets FullStory cookies on .example.com, making them accessible to www.example.com, app.example.com, shop.example.com, etc.

When to Use:

  • All domains share a common root (*.example.com)
  • You control all subdomains
  • Users frequently move between subdomains

Limitations:

  • Doesn't work for completely different domains (example.comdifferentdomain.com)
  • Requires all domains to have FullStory installed

Method 2: URL Parameter Passing (For Different Root Domains)

For completely different domains, FullStory can pass session context via URL parameters.

Example Scenario:

  • Marketing site: example.com
  • App: myapp.io

Configuration:

Step 1: Enable URL Parameter Passing

In FullStory dashboard:

  1. Go to Settings > Cross-Domain Tracking
  2. Enable "Pass session ID via URL parameters"
  3. Add trusted domains: example.com, myapp.io

Step 2: Link Between Domains

When linking from one domain to another, append FullStory's session parameter:

// Automatically append session ID to cross-domain links
document.querySelectorAll('a[href*="myapp.io"]').forEach(link => {
  link.addEventListener('click', function(e) {
    const sessionURL = FS.getCurrentSessionURL();
    if (sessionURL) {
      const sessionID = sessionURL.split('/').pop();
      const separator = this.href.includes('?') ? '&' : '?';
      this.href = this.href + separator + '_fs_session=' + sessionID;
    }
  });
});

Step 3: Install FullStory on Both Domains

Ensure FullStory is installed with the same Org ID on all domains.

When to Use:

  • Domains have completely different root domains
  • Users navigate between domains via links
  • You need to maintain session continuity across unrelated domains

Limitations:

  • Requires JavaScript to append parameters to links
  • URL parameter must be preserved during navigation
  • Session context can be lost if users manually edit URLs

Implementation Examples

Example 1: E-Commerce with Separate Checkout Domain

Scenario:

  • Store: shop.example.com
  • Checkout: checkout.example.com

Solution: Shared Cookie Domain

// On both shop.example.com and checkout.example.com
window['_fs_cookie_domain'] = '.example.com';

Users can now navigate from browsing products to checkout without breaking the session.

Example 2: Marketing Site to SaaS App

Scenario:

  • Marketing: example.com
  • App: app.exampleapp.io

Solution: URL Parameter Passing

On example.com:

// Add session ID to "Sign In" and "Get Started" links
document.querySelectorAll('a[href*="app.exampleapp.io"]').forEach(link => {
  link.addEventListener('click', function(e) {
    const sessionURL = FS.getCurrentSessionURL();
    if (sessionURL) {
      const sessionID = sessionURL.split('/').pop();
      const separator = this.href.includes('?') ? '&' : '?';
      this.href = this.href + separator + '_fs_session=' + sessionID;
    }
  });
});

On app.exampleapp.io:

Ensure FullStory is installed with the same Org ID. FullStory will automatically detect the _fs_session parameter and continue the session.

Example 3: Multi-Region Sites

Scenario:

  • US site: example.com
  • UK site: example.co.uk
  • EU site: example.eu

Solution: URL Parameter Passing + Conditional Cookie Domain

Configure per-region:

// Dynamically set cookie domain based on hostname
const hostname = window.location.hostname;

if (hostname.endsWith('.com')) {
  window['_fs_cookie_domain'] = '.example.com';
} else if (hostname.endsWith('.co.uk')) {
  window['_fs_cookie_domain'] = '.example.co.uk';
} else if (hostname.endsWith('.eu')) {
  window['_fs_cookie_domain'] = '.example.eu';
}

For cross-region navigation:

Use URL parameter passing when users switch between .com.co.uk.

Testing Cross-Domain Tracking

Verification Steps

  1. Start a session on Domain A:

    • Visit example.com
    • Open DevTools Console
    • Run: FS.getCurrentSessionURL()
    • Copy the session URL (e.g., https://app.fullstory.com/ui/o-XYZ-na1/session/12345)
  2. Navigate to Domain B:

    • Click a link to app.example.com (or different domain)
    • Open DevTools Console on the new domain
    • Run: FS.getCurrentSessionURL()
  3. Compare session IDs:

    • If session IDs match → Cross-domain tracking is working
    • If session IDs differ → Cross-domain tracking failed

Common Issues

Session breaks despite shared cookie domain:

Possible causes:

  • Cookie domain configured incorrectly (missing leading dot)
  • Different FullStory Org IDs on each domain
  • FullStory not installed on one of the domains

Solution:

// Correct
window['_fs_cookie_domain'] = '.example.com';  // Leading dot

// Incorrect
window['_fs_cookie_domain'] = 'example.com';  // No leading dot

URL parameters not working:

Possible causes:

  • Parameters stripped by redirects or server-side routing
  • JavaScript not appending parameters correctly
  • Session parameter name incorrect

Solution:

// Verify parameter is appended
console.log(link.href);  // Should include ?_fs_session=12345

Advanced Configuration

Excluding Specific Subdomains

If you have subdomains that shouldn't share sessions (e.g., admin panels), use different Org IDs:

// On www.example.com and app.example.com
window['_fs_org'] = 'o-PROD-na1';
window['_fs_cookie_domain'] = '.example.com';

// On admin.example.com (separate Org ID)
window['_fs_org'] = 'o-ADMIN-na1';
window['_fs_cookie_domain'] = 'admin.example.com';  // No leading dot

Tracking Across iframes

For tracking users within iframes (same domain):

// Parent page
window['_fs_cookie_domain'] = '.example.com';

// Iframe (on iframe.example.com)
window['_fs_cookie_domain'] = '.example.com';

FullStory will automatically link activity in the iframe to the parent session.

Note: Cross-origin iframes (different domains) are not recorded by FullStory due to browser security restrictions.

For sites with dynamically generated links:

// Automatically append session ID to all external cross-domain links
function injectFullStorySession() {
  const sessionURL = FS.getCurrentSessionURL();
  if (!sessionURL) return;

  const sessionID = sessionURL.split('/').pop();
  const targetDomains = ['app.exampleapp.io', 'checkout.example.net'];

  document.querySelectorAll('a').forEach(link => {
    const href = link.getAttribute('href');
    if (!href) return;

    targetDomains.forEach(domain => {
      if (href.includes(domain) && !href.includes('_fs_session=')) {
        const separator = href.includes('?') ? '&' : '?';
        link.href = href + separator + '_fs_session=' + sessionID;
      }
    });
  });
}

// Run on page load and after dynamic content is added
window.addEventListener('load', injectFullStorySession);

// For SPAs, run after route changes
// Example for React Router:
// useEffect(() => { injectFullStorySession(); }, [location]);

Privacy Considerations

If your site requires cookie consent (GDPR, CCPA):

// Only set shared cookie domain after consent
function onConsentGranted() {
  window['_fs_cookie_domain'] = '.example.com';
  FS.restart();  // Restart recording with new cookie domain
}

// On consent denial
function onConsentDenied() {
  FS.shutdown();
}

Data Sharing Between Domains

Ensure your privacy policy discloses cross-domain tracking:

"We use FullStory to track user behavior across our website and app (example.com and app.example.com). FullStory uses cookies to maintain session continuity as you navigate between these domains."

Best Practices

If all your domains are subdomains of a common root, always use shared cookie domain method. It's simpler and more reliable than URL parameters.

Document Your Domain Structure

Maintain documentation of:

  • All domains using FullStory
  • Which domains share sessions
  • Which Org ID each domain uses
  • Cross-domain link mapping

Test Cross-Domain Flows Regularly

Create test scenarios:

  • Navigate from marketing site to app
  • Complete checkout flow across domains
  • Verify session continuity in FullStory dashboard

Monitor Session Continuity

Use FullStory's Omnisearch to verify cross-domain sessions:

Search: user.email = "test@example.com"
Filter by: Multiple page views across different domains

If sessions are splitting, investigate cross-domain configuration.

Troubleshooting

Common Cross-Domain Issues

Issue Symptoms Possible Causes Solutions
Sessions splitting across domains New session starts when navigating to different domain - Different Org IDs on each domain
- Cookie domain not configured
- URL parameter not passed
- Browser blocking third-party cookies
- Use same Org ID on all domains
- Set _fs_cookie_domain to shared root
- Append _fs_session parameter to links
- Use first-party cookies only
Cookie domain not working Shared cookie domain set but sessions still split - Missing leading dot in cookie domain
- Domains don't share root
- Browser security settings
- Incorrect cookie domain value
- Add leading dot: ._fs_cookie_domain = '.example.com'
- Verify domains share root (e.g., *.example.com)
- Test in incognito mode
- Check cookie domain in DevTools
URL parameters stripped _fs_session parameter removed during navigation - Server-side redirect removing params
- Client-side router stripping params
- Form POST losing parameters
- Preserve URL parameters in redirects
- Manually re-append parameters after route change
- Use hidden form fields for POST requests
Different root domains not linking Sessions don't connect across .com and .co.uk - Cannot share cookies across TLDs
- URL parameter not passed
- FullStory not installed on both
- Use URL parameter method
- Append _fs_session to cross-domain links
- Install FullStory with same Org ID on both
User identification not persisting User identified on one domain but not another - FS.identify() not called on second domain
- Different user IDs used
- Identify called after navigation
- Call FS.identify() on all domains
- Use consistent user ID format
- Identify immediately on page load
Session URL parameter not recognized Parameter in URL but session still splits - Parameter name misspelled
- FullStory version doesn't support feature
- Parameter value corrupted
- Use exact name: _fs_session
- Update to latest FullStory version
- Validate parameter value is session ID
Cross-origin iframe issues Parent and iframe sessions not linking - Cross-origin security restrictions
- FullStory not on both pages
- Different Org IDs
- Same-origin iframes work automatically
- Cross-origin iframes cannot share sessions (browser limitation)
- Install FullStory with same Org ID
Cookie consent blocking tracking GDPR consent preventing cross-domain cookies - Consent not granted before navigation
- Cookie banner blocking FullStory
- Consent state not shared across domains
- Get consent before cross-domain navigation
- Share consent state via URL or backend
- Initialize FullStory after consent
Performance degradation Page load slow after adding cross-domain setup - Synchronous link modification
- Too many links being processed
- Heavy DOM manipulation
- Use async link processing
- Target specific links only
- Optimize selector performance
Testing shows success but production fails Works in staging but not production - Different domain configuration
- Production firewall/CDN interference
- Environment-specific cookie settings
- Verify production domain config matches staging
- Check CDN/firewall settings
- Test in production-like environment

Debugging Cross-Domain Tracking

Step 1: Verify Session ID on First Domain

// On domain A (e.g., example.com)
const sessionURL = FS.getCurrentSessionURL();
console.log('Session URL:', sessionURL);

// Extract session ID
const sessionID = sessionURL ? sessionURL.split('/').pop() : null;
console.log('Session ID:', sessionID);

Step 2: Check Link Parameter Injection

// Verify links have session parameter
document.querySelectorAll('a[href*="app.example.io"]').forEach(link => {
  console.log('Link href:', link.href);
  // Should include ?_fs_session=SESSION_ID or &_fs_session=SESSION_ID
});

Step 3: Verify Session on Second Domain

// On domain B (e.g., app.example.io)
// Check for session parameter in URL
const urlParams = new URLSearchParams(window.location.search);
const passedSessionID = urlParams.get('_fs_session');
console.log('Passed session ID:', passedSessionID);

// Get current session
const currentSessionURL = FS.getCurrentSessionURL();
const currentSessionID = currentSessionURL ? currentSessionURL.split('/').pop() : null;
console.log('Current session ID:', currentSessionID);

// Compare - should match
if (passedSessionID === currentSessionID) {
  console.log('Cross-domain tracking working!');
} else {
  console.error('Session IDs do not match');
}

Step 4: Check Cookie Domain

// View FullStory cookies
document.cookie.split(';').forEach(cookie => {
  if (cookie.includes('fs_')) {
    console.log('FullStory cookie:', cookie.trim());
  }
});

// Check cookie domain in DevTools:
// 1. Open DevTools > Application tab
// 2. Go to Cookies section
// 3. Look for cookies starting with `fs_`
// 4. Check "Domain" column - should show `.example.com` (with leading dot)

Validation Steps

Test Subdomain Tracking:

  1. Set cookie domain to .example.com
  2. Visit www.example.com
  3. Get session URL
  4. Navigate to app.example.com
  5. Get session URL again
  6. Verify: Session IDs match

Test Cross-Domain (Different Roots):

  1. Visit example.com
  2. Get session URL and ID
  3. Click link to exampleapp.io (with _fs_session parameter)
  4. On exampleapp.io, check URL for _fs_session parameter
  5. Get current session URL
  6. Verify: Session IDs match

Test User Identification:

  1. Login on domain A
  2. FS.identify() is called
  3. Navigate to domain B
  4. Check if user still identified
  5. Verify: User properties persist

Check cookie domain setting:

// Should be set before FullStory loads
console.log('Cookie domain:', window._fs_cookie_domain);

// For subdomains of example.com, should be:
// ".example.com" (with leading dot)

Verify cookie is set correctly:

# In browser DevTools Console
document.cookie.split(';').forEach(c => console.log(c.trim()));

# Look for:
# fs_uid=... (user identifier)
# Domain should show .example.com

Common Configuration Mistakes

Missing leading dot:

// Wrong
window['_fs_cookie_domain'] = 'example.com';

// Correct
window['_fs_cookie_domain'] = '.example.com';

Incorrect session parameter name:

// Wrong
const url = `${targetUrl}?fs_session=${sessionID}`;

// Correct
const url = `${targetUrl}?_fs_session=${sessionID}`;
// Note the underscore prefix: _fs_session

Not preserving parameters during navigation:

// Wrong - Parameter gets stripped
window.location.href = '/new-page';  // Loses _fs_session

// Correct - Preserve parameter
const sessionParam = new URLSearchParams(window.location.search).get('_fs_session');
if (sessionParam) {
  window.location.href = `/new-page?_fs_session=${sessionParam}`;
}

Using different Org IDs:

// Wrong - Different Org IDs won't link sessions
// On example.com
window['_fs_org'] = 'o-ABC-na1';

// On app.example.com
window['_fs_org'] = 'o-XYZ-na1';  // Different!

// Correct - Same Org ID everywhere
window['_fs_org'] = 'o-ABC-na1';

Advanced Debugging

Monitor cookie changes:

// Track cookie changes
let lastCookies = document.cookie;

setInterval(() => {
  if (document.cookie !== lastCookies) {
    console.log('Cookies changed!');
    console.log('Old:', lastCookies);
    console.log('New:', document.cookie);
    lastCookies = document.cookie;
  }
}, 1000);

Log cross-domain navigation:

// Add to links for debugging
document.querySelectorAll('a[href*="different-domain.com"]').forEach(link => {
  link.addEventListener('click', function(e) {
    const sessionURL = FS.getCurrentSessionURL();
    const sessionID = sessionURL ? sessionURL.split('/').pop() : null;

    console.log('[Cross-Domain Nav]', {
      from: window.location.href,
      to: this.href,
      sessionID: sessionID,
      hasParameter: this.href.includes('_fs_session')
    });
  });
});

Getting Help

If cross-domain tracking still not working:

  1. Verify basic FullStory setup works on each domain individually
  2. Check FullStory Status: status.fullstory.com
  3. Review Help Center: help.fullstory.com
  4. Contact Support: Include:
    • Both domain names
    • Cookie domain setting
    • Session URLs from both domains
    • Screenshots of cookies in DevTools
    • Network tab showing FullStory requests

Next Steps:

Additional Resources: