Plausible Cross-Domain Tracking | OpsBlu Docs

Plausible Cross-Domain Tracking

How to track users across multiple domains and subdomains with Plausible Analytics.

Overview

Cross-domain tracking in Plausible allows you to monitor user journeys that span multiple domains or subdomains as a single continuous session. This is essential for businesses that operate across multiple web properties, such as a marketing site on www.example.com and a checkout flow on shop.example.com.

Unlike traditional analytics platforms that rely on third-party cookies, Plausible uses a first-party cookie approach that requires specific configuration when tracking across domains. Without proper setup, each domain transition will be counted as a new session, leading to inflated visitor counts and broken conversion funnels.

Key Concepts

Session Continuity: Ensuring that a visitor moving from Domain A to Domain B is recognized as the same session, not two separate visits.

Referrer Attribution: Maintaining accurate referral source information when users navigate between your domains, preventing internal cross-domain navigation from being counted as external referrals.

Privacy Compliance: Plausible's cross-domain tracking maintains its privacy-first approach by not sharing personally identifiable information between domains.

Configuration

Single Domain with Multiple Subdomains

If you're tracking across subdomains of the same parent domain (e.g., blog.example.com, shop.example.com, www.example.com), you can use wildcard domain tracking:

<script defer data-domain="example.com" src="https://plausible.io/js/script.js"></script>

This configuration automatically tracks all subdomains under example.com as a single property.

Multiple Distinct Domains

For tracking across completely different domains (e.g., example.com and example.org), use a comma-separated list:

<script defer data-domain="example.com,example.org" src="https://plausible.io/js/script.js"></script>

Rollup Reporting

If you want to track domains individually but also see aggregate data, use rollup reporting:

<!-- On example.com -->
<script defer data-domain="example.com,rollup.example.com" src="https://plausible.io/js/script.js"></script>

<!-- On example.org -->
<script defer data-domain="example.org,rollup.example.com" src="https://plausible.io/js/script.js"></script>

This sends data to both the individual domain property and a combined rollup property.

For accurate cross-domain session tracking, configure your links to include session parameters:

// Automatically handled by Plausible when using data-domain attribute
// Manual configuration if needed:
const plausibleConfig = {
  trackOutboundLinks: true,
  hashMode: false
};

Code Examples

Basic Multi-Domain Setup

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Multi-Domain Tracking Example</title>

  <!-- Plausible script for multiple domains -->
  <script defer data-domain="shop.example.com,www.example.com" src="https://plausible.io/js/script.js"></script>
</head>
<body>
  <a href="https://www.example.com/products">View Products</a>
  <a href="https://shop.example.com/checkout">Checkout</a>
</body>
</html>

Dynamic Domain Configuration

For sites with dynamic domain requirements:

// Determine domains based on environment
const domains = window.location.hostname.includes('staging')
  ? 'staging.example.com,staging.shop.example.com'
  : 'example.com,shop.example.com';

// Create script element dynamically
const script = document.createElement('script');
script.defer = true;
script.setAttribute('data-domain', domains);
script.src = 'https://plausible.io/js/script.js';
document.head.appendChild(script);

Cross-Domain Event Tracking

Tracking events that occur during cross-domain transitions:

// Track when user clicks cross-domain checkout link
document.querySelector('#checkout-button').addEventListener('click', function() {
  plausible('Checkout Started', {
    props: {
      source_domain: window.location.hostname,
      destination: 'shop.example.com'
    }
  });
});

Excluding Internal Cross-Domain Traffic

Filter out internal referrals between your domains:

// In your Plausible dashboard settings, add these to "Exclude Pages":
// /internal-transfer/*
// Or configure in script if using custom proxy

window.plausible = window.plausible || function() {
  (window.plausible.q = window.plausible.q || []).push(arguments);
};

// Filter internal cross-domain referrals
const internalDomains = ['example.com', 'shop.example.com', 'blog.example.com'];
const referrer = document.referrer;
const isInternalReferral = internalDomains.some(domain => referrer.includes(domain));

if (isInternalReferral) {
  // Pageview will still be tracked, but referrer won't be counted as external
  console.log('Internal cross-domain navigation detected');
}

Proxy Configuration for Cross-Domain Tracking

When using a custom proxy to avoid ad blockers:

<!-- Using custom proxy endpoint -->
<script defer
  data-domain="example.com,shop.example.com"
  data-api="/analytics/api/event"
  src="/analytics/js/script.js">
</script>

Corresponding nginx configuration:

location /analytics/ {
  proxy_pass https://plausible.io/;
  proxy_set_header Host plausible.io;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;

  # Critical: Forward Referer header for cross-domain attribution
  proxy_set_header Referer $http_referer;

  # Enable CORS for cross-domain requests
  add_header Access-Control-Allow-Origin *;
  add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
}

Validation Steps

1. Verify Script Installation

Check that the Plausible script is installed on all domains with matching configuration:

# Test script presence on each domain
curl -I https://www.example.com | grep -i plausible
curl -I https://shop.example.com | grep -i plausible

2. Real-Time Dashboard Verification

  1. Open Plausible dashboard in one browser window
  2. Navigate to your primary domain in another window
  3. Verify the pageview appears in real-time with correct domain label
  4. Click a link to your secondary domain
  5. Confirm the session continues without creating a new visitor

3. Session Continuity Test

Create a test journey across domains:

// Test script to verify session continuity
// Run in browser console on Domain A
console.log('Session test started on', window.location.hostname);
plausible('Cross-Domain Test Start');

// Navigate to Domain B and run:
console.log('Session test continued on', window.location.hostname);
plausible('Cross-Domain Test Continue');

// Check Plausible dashboard to verify both events belong to same session

4. Referrer Attribution Check

Verify that internal cross-domain navigation doesn't create false referrals:

  1. Navigate from Domain A to Domain B
  2. Check Plausible Sources report
  3. Confirm Domain A doesn't appear as a referral source for Domain B traffic
  4. Verify original external referrer is maintained

5. Network Request Inspection

Use browser DevTools to inspect event requests:

// In browser console, monitor network tab
// Filter for: plausible.io/api/event or your custom proxy endpoint

// Verify request payload includes:
{
  "n": "pageview",
  "u": "https://shop.example.com/checkout",
  "d": "example.com,shop.example.com",
  "r": "https://www.google.com/", // Original external referrer, not internal domain
  "w": 1920
}

6. Goal Conversion Tracking

Test that goals spanning multiple domains are properly attributed:

  1. Set up a goal in Plausible dashboard (e.g., "Purchase Complete")
  2. Start journey on Domain A
  3. Complete conversion on Domain B
  4. Verify goal conversion appears in dashboard with complete funnel attribution

Edge Cases

Proxy Referrer Header Forwarding

If using a proxy, ensure it forwards the Referer header so Plausible can attribute traffic accurately across domains:

# Apache configuration
<Location /analytics/>
  ProxyPass https://plausible.io/
  ProxyPassReverse https://plausible.io/

  # Preserve Referer header
  ProxyPreserveHost Off
  RequestHeader set Referer %{HTTP_REFERER}e
</Location>

Mixed HTTP/HTTPS Environments

Cross-domain tracking may fail if mixing HTTP and HTTPS:

<!-- Ensure all domains use HTTPS for consistent cookie behavior -->
<script>
  if (window.location.protocol === 'http:') {
    window.location.href = window.location.href.replace('http:', 'https:');
  }
</script>

Single-Page Applications (SPA)

For SPAs with client-side routing across domains:

// React Router example
import { useLocation } from 'react-router-dom';
import { useEffect } from 'react';

function AnalyticsTracker() {
  const location = useLocation();

  useEffect(() => {
    // Track pageview on route change, including cross-domain navigation
    window.plausible('pageview', {
      props: {
        domain: window.location.hostname
      }
    });
  }, [location]);

  return null;
}

Troubleshooting

Issue Possible Cause Solution
Sessions split across domains data-domain not configured on all domains Verify identical data-domain attribute on all tracked domains
Internal domains appear as referrers Referrer filtering not configured Add internal domains to exclusion list in Plausible settings
Events not appearing for secondary domain Script not loaded on secondary domain Check network tab for script load errors; verify CORS headers
Cross-domain links don't preserve session Browser blocking third-party cookies Ensure all domains use HTTPS; consider using same root domain
Proxy blocks cross-domain requests Missing CORS headers Add appropriate Access-Control-Allow-Origin headers to proxy
Goals not attributing to original source Session tracking broken Test session continuity; verify cookie domain settings
Duplicate pageviews Script loaded multiple times Check for duplicate script tags; ensure SPA only calls pageview once per route
Ad blockers preventing tracking Default Plausible domain blocked Implement custom proxy with first-party domain path
Rollup data missing Incorrect rollup domain syntax Verify comma-separated domain list includes rollup domain
Subdomain tracking not working Cookie domain too restrictive Use wildcard domain or configure cookie domain properly
Real-time dashboard shows multiple visitors Session cookies not shared Ensure cookie domain allows subdomain sharing (e.g., .example.com)
Revenue tracking lost on domain transition Event props not preserved Send revenue data at point of transaction, not during navigation
Cross-domain forms losing attribution Form hosted on different domain Include hidden fields to pass attribution data; track form submission as event
Mobile app to web transitions not tracked Different tracking mechanisms Implement deep linking with UTM parameters to maintain attribution
Iframe cross-domain tracking fails Cookie restrictions in iframe context Avoid iframe tracking; use postMessage API to communicate events to parent

Best Practices

  1. Consistent Configuration: Use identical data-domain values across all tracked properties
  2. Testing in Staging: Always test cross-domain flows in staging environment before production
  3. Documentation: Maintain a list of all tracked domains and their purposes
  4. Regular Audits: Periodically verify cross-domain tracking is functioning correctly
  5. Performance Monitoring: Monitor script load times across all domains
  6. Privacy Compliance: Ensure cross-domain tracking complies with GDPR, CCPA, and other privacy regulations
  7. Fallback Strategy: Have a plan for when cross-domain tracking fails (e.g., UTM parameter fallback)
  8. Version Consistency: Keep Plausible script versions consistent across all domains