Cross-Domain Tracking
Pendo provides robust cross-domain tracking capabilities by using consistent visitor and account identifiers across multiple domains. This enables you to track user journeys seamlessly across different properties, subdomains, and top-level domains.
How Pendo Handles Cross-Domain Tracking
Unlike cookie-based tracking systems, Pendo relies primarily on visitor IDs that you provide during initialization. This approach offers several advantages:
- No cookie sharing complexities: Each domain runs its own Pendo instance with the same visitor ID
- Complete session continuity: User sessions remain intact across domain transitions
- Unified analytics: All user behavior aggregates under a single visitor profile
- Account-level tracking: Track users across domains at both visitor and account levels
Implementation Requirements
Consistent Visitor IDs
The most critical requirement for cross-domain tracking is maintaining consistent visitor IDs across all domains where Pendo is installed.
// Domain 1: app.example.com
pendo.initialize({
visitor: {
id: 'user-12345', // Must be identical across domains
email: 'user@example.com',
role: 'admin'
},
account: {
id: 'acct-789', // Must be identical across domains
name: 'Acme Corp'
}
});
// Domain 2: billing.example.com
pendo.initialize({
visitor: {
id: 'user-12345', // Same ID as Domain 1
email: 'user@example.com',
role: 'admin'
},
account: {
id: 'acct-789', // Same ID as Domain 1
name: 'Acme Corp'
}
});
Authentication State Sharing
For applications with separate authentication systems across domains, ensure visitor IDs are synchronized:
// Example: Shared authentication service
async function initializePendo() {
const userData = await fetchUserFromAuthService();
pendo.initialize({
visitor: {
id: userData.userId, // Consistent ID from central auth
email: userData.email,
full_name: userData.fullName
},
account: {
id: userData.accountId,
name: userData.accountName
}
});
}
Cross-Subdomain Tracking
Tracking users across subdomains (e.g., app.example.com, admin.example.com, api.example.com):
// Shared configuration across all subdomains
const pendoConfig = {
visitor: {
id: window.currentUser.id,
email: window.currentUser.email
},
account: {
id: window.currentAccount.id,
name: window.currentAccount.name
}
};
pendo.initialize(pendoConfig);
Best Practices for Subdomains
- Centralized user data: Store user identification data in a location accessible by all subdomains (localStorage, sessionStorage, or cookies with appropriate domain settings)
- Consistent initialization: Use the same initialization code across all subdomains
- Verify visitor ID availability: Ensure visitor IDs are available before initializing Pendo
Cross-Top-Level Domain Tracking
Tracking across completely different domains (e.g., example.com and example.org):
// Both domains need access to the same user identity
// Option 1: URL parameter passing
const urlParams = new URLSearchParams(window.location.search);
const visitorId = urlParams.get('userId') || getUserIdFromSession();
pendo.initialize({
visitor: {
id: visitorId,
source: 'cross-domain'
}
});
// Option 2: Shared backend API
async function initializePendoFromAPI() {
const response = await fetch('https://auth.example.com/api/user/current', {
credentials: 'include'
});
const userData = await response.json();
pendo.initialize({
visitor: {
id: userData.userId,
email: userData.email
},
account: {
id: userData.accountId
}
});
}
Single Sign-On (SSO) Integration
For applications using SSO, leverage the SSO system's user identifiers:
// After SSO authentication
saml.on('authenticated', (samlResponse) => {
pendo.initialize({
visitor: {
id: samlResponse.nameId, // Use SAML NameID
email: samlResponse.email,
sso_provider: 'okta'
},
account: {
id: samlResponse.organizationId
}
});
});
Visitor ID Strategies
Using Database IDs
// Most reliable: Use your database's user ID
pendo.initialize({
visitor: {
id: user.databaseId.toString(),
id_type: 'database'
}
});
Using Email Addresses
// Alternative: Use email as visitor ID
pendo.initialize({
visitor: {
id: user.email.toLowerCase(),
id_type: 'email'
}
});
Using External System IDs
// For integrated systems: Use external ID
pendo.initialize({
visitor: {
id: user.salesforceId,
id_type: 'salesforce',
internal_id: user.databaseId
}
});
Troubleshooting Cross-Domain Tracking
Verifying Visitor ID Consistency
Check the Pendo debugger to ensure visitor IDs match across domains:
// Add to browser console on each domain
console.log('Pendo Visitor ID:', pendo.getVisitorId());
console.log('Pendo Account ID:', pendo.getAccountId());
Common Issues
Issue: Different visitor IDs across domains
- Cause: Initialization using different ID sources
- Solution: Centralize user identification logic
Issue: Session data not appearing
- Cause: Delayed Pendo initialization or missing IDs
- Solution: Ensure IDs are available before calling
pendo.initialize()
Issue: Guides not showing consistently
- Cause: Different account IDs or feature tagging
- Solution: Verify account IDs match and guides are published to all domains
Analytics and Reporting
With proper cross-domain tracking, Pendo provides unified analytics:
- Complete user journeys: See the full path users take across all domains
- Feature usage: Track feature adoption across different applications
- Account-level insights: Aggregate all user activity within an account
- Guide effectiveness: Measure guide performance across the entire ecosystem
Testing Cross-Domain Implementation
- Open multiple domains in the same browser session
- Log in with the same user credentials on each domain
- Open browser console and verify visitor IDs match
- Trigger events on one domain and verify they appear in Pendo
- Navigate between domains and confirm session continuity
// Test script to verify cross-domain setup
function testPendoCrossDomain() {
const domains = [
'https://app.example.com',
'https://billing.example.com',
'https://admin.example.com'
];
domains.forEach(domain => {
console.log(`Testing ${domain}...`);
// Manual verification: Open each domain and check console
});
}