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.
Cross-Domain Link Decoration
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
- Open Plausible dashboard in one browser window
- Navigate to your primary domain in another window
- Verify the pageview appears in real-time with correct domain label
- Click a link to your secondary domain
- 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:
- Navigate from Domain A to Domain B
- Check Plausible Sources report
- Confirm Domain A doesn't appear as a referral source for Domain B traffic
- 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:
- Set up a goal in Plausible dashboard (e.g., "Purchase Complete")
- Start journey on Domain A
- Complete conversion on Domain B
- 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
- Consistent Configuration: Use identical
data-domainvalues across all tracked properties - Testing in Staging: Always test cross-domain flows in staging environment before production
- Documentation: Maintain a list of all tracked domains and their purposes
- Regular Audits: Periodically verify cross-domain tracking is functioning correctly
- Performance Monitoring: Monitor script load times across all domains
- Privacy Compliance: Ensure cross-domain tracking complies with GDPR, CCPA, and other privacy regulations
- Fallback Strategy: Have a plan for when cross-domain tracking fails (e.g., UTM parameter fallback)
- Version Consistency: Keep Plausible script versions consistent across all domains