Cross-Domain Tracking Overview
Cross-domain tracking enables you to track users as they move between different domains (e.g., from shop.example.com to checkout.example.com) while maintaining attribution to your Snapchat ads.
When You Need Cross-Domain Tracking
Common Scenarios
| Scenario | Example | Solution |
|---|---|---|
| Subdomain checkout | www.example.com → checkout.example.com |
Shared cookie domain |
| Separate checkout domain | example.com → secure-checkout.com |
URL parameter passing |
| Multiple brand sites | brand1.com → brand2.com |
URL parameter passing |
| Third-party payment | shop.com → paypal.com → shop.com |
Session restoration |
| Landing page service | lp.example.com → example.com |
Subdomain tracking |
Without Cross-Domain Tracking
User clicks Snapchat ad → Lands on shop.example.com
↓ (Cookie: _scid=abc123)
|
User clicks checkout → checkout.example.com
↓ (Cookie: LOST - different domain)
|
Purchase complete → NO ATTRIBUTION ❌
With Cross-Domain Tracking
User clicks Snapchat ad → Lands on shop.example.com
↓ (Cookie: _scid=abc123)
|
User clicks checkout → checkout.example.com?_scid=abc123
↓ (Cookie: Restored)
|
Purchase complete → ATTRIBUTION SUCCESS ✅
Subdomain Tracking
Same Root Domain
For subdomains under the same root domain (e.g., www.example.com, shop.example.com, checkout.example.com):
Implementation
// Set cookie_domain to share cookies across subdomains
snaptr('init', 'YOUR_PIXEL_ID', {
'cookie_domain': '.example.com' // Note the leading dot
});
snaptr('track', 'PAGE_VIEW');
Complete Setup Example
<!-- On www.example.com -->
<script type='text/javascript'>
(function(e,t,n){if(e.snaptr)return;var a=e.snaptr=function()
{a.handleRequest?a.handleRequest.apply(a,arguments):a.queue.push(arguments)};
a.queue=[];var s='script';var r=t.createElement(s);r.async=!0;
r.src=n;var u=t.getElementsByTagName(s)[0];
u.parentNode.insertBefore(r,u);})(window,document,
'https://sc-static.net/scevent.min.js');
// Share cookies across all subdomains
snaptr('init', 'YOUR_PIXEL_ID', {
'cookie_domain': '.example.com' // Works for shop.example.com, checkout.example.com, etc.
});
snaptr('track', 'PAGE_VIEW');
</script>
<!-- On shop.example.com - SAME pixel configuration -->
<script type='text/javascript'>
// ... same pixel code with same cookie_domain setting
snaptr('init', 'YOUR_PIXEL_ID', {
'cookie_domain': '.example.com'
});
</script>
<!-- On checkout.example.com - SAME pixel configuration -->
<script type='text/javascript'>
// ... same pixel code with same cookie_domain setting
snaptr('init', 'YOUR_PIXEL_ID', {
'cookie_domain': '.example.com'
});
</script>
Verification
// Check cookie domain in browser console
// On any subdomain, run:
document.cookie.split(';').forEach(cookie => {
if (cookie.includes('_scid')) {
console.log('Snap Cookie:', cookie);
}
});
// Should show: _scid=abc123; domain=.example.com
Configuration Options
// Option 1: Share across all subdomains (recommended)
snaptr('init', 'YOUR_PIXEL_ID', {
'cookie_domain': '.example.com'
});
// Option 2: Specific subdomain only (not recommended for cross-subdomain)
snaptr('init', 'YOUR_PIXEL_ID', {
'cookie_domain': 'shop.example.com'
});
// Option 3: Auto-detect (default - may not work across subdomains)
snaptr('init', 'YOUR_PIXEL_ID');
Cross-Domain Tracking (Different Root Domains)
URL Parameter Method
For completely different domains (e.g., example.com → checkout-provider.com):
Step 1: Capture Snap Click ID
// On source domain (example.com)
function getSnapClickId() {
const cookies = document.cookie.split(';');
for (let cookie of cookies) {
const [name, value] = cookie.trim().split('=');
if (name === '_scid') {
return value;
}
}
return null;
}
// Store click ID for later use
const snapClickId = getSnapClickId();
if (snapClickId) {
sessionStorage.setItem('snap_click_id', snapClickId);
}
Step 2: Pass Click ID in URL
// When linking to external domain
function appendSnapParams(url) {
const snapClickId = getSnapClickId() || sessionStorage.getItem('snap_click_id');
if (snapClickId) {
const separator = url.includes('?') ? '&' : '?';
return `${url}${separator}_scid=${snapClickId}`;
}
return url;
}
// Usage: Update links
document.querySelectorAll('a[href*="checkout-provider.com"]').forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const newUrl = appendSnapParams(this.href);
window.location.href = newUrl;
});
});
// Or for form submissions
document.querySelector('#checkout-form').addEventListener('submit', function(e) {
e.preventDefault();
const actionUrl = appendSnapParams(this.action);
this.action = actionUrl;
this.submit();
});
Step 3: Restore Click ID on Destination Domain
// On destination domain (checkout-provider.com)
function restoreSnapClickId() {
// Get _scid from URL parameter
const urlParams = new URLSearchParams(window.location.search);
const scidFromUrl = urlParams.get('_scid');
if (scidFromUrl) {
// Set cookie to restore tracking
document.cookie = `_scid=${scidFromUrl}; path=/; domain=.checkout-provider.com; max-age=604800`; // 7 days
console.log('Snap click ID restored:', scidFromUrl);
// Clean URL (optional - removes parameter from address bar)
const cleanUrl = window.location.pathname + window.location.hash;
window.history.replaceState({}, document.title, cleanUrl);
}
}
// Run on page load
restoreSnapClickId();
// Initialize pixel (cookie should now be available)
snaptr('init', 'YOUR_PIXEL_ID');
snaptr('track', 'PAGE_VIEW');
Complete Cross-Domain Example
// ===== SOURCE DOMAIN (shop.example.com) =====
// Get Snap click ID from cookie
function getSnapClickId() {
const match = document.cookie.match(/_scid=([^;]+)/);
return match ? match[1] : null;
}
// Append to all external links
function setupCrossDomainTracking() {
const externalDomains = ['checkout.partner.com', 'payment.gateway.com'];
document.querySelectorAll('a').forEach(link => {
const url = new URL(link.href, window.location.origin);
// Check if link goes to external domain
if (externalDomains.some(domain => url.hostname.includes(domain))) {
link.addEventListener('click', function(e) {
e.preventDefault();
const scid = getSnapClickId();
if (scid) {
const separator = url.search ? '&' : '?';
const newUrl = `${url.href}${separator}_scid=${scid}`;
window.location.href = newUrl;
} else {
window.location.href = url.href;
}
});
}
});
}
// Run on page load
document.addEventListener('DOMContentLoaded', setupCrossDomainTracking);
// ===== DESTINATION DOMAIN (checkout.partner.com) =====
// Restore Snap click ID from URL
(function() {
const urlParams = new URLSearchParams(window.location.search);
const scid = urlParams.get('_scid');
if (scid) {
// Set cookie
const domain = window.location.hostname.split('.').slice(-2).join('.');
document.cookie = `_scid=${scid}; path=/; domain=.${domain}; max-age=604800; SameSite=Lax`;
console.log('Snap tracking restored');
}
})();
// Initialize pixel
snaptr('init', 'YOUR_PIXEL_ID');
snaptr('track', 'PAGE_VIEW');
Return Path Tracking
Handling Third-Party Redirects
When users leave your domain (e.g., PayPal) and return:
// Before redirect to payment provider
function handlePaymentRedirect(paymentUrl) {
const scid = getSnapClickId();
const returnUrl = encodeURIComponent(window.location.origin + '/payment-complete');
// Add Snap ID and return URL
const fullUrl = `${paymentUrl}?return=${returnUrl}&_scid=${scid}`;
window.location.href = fullUrl;
}
// On return page (/payment-complete)
function handlePaymentReturn() {
const urlParams = new URLSearchParams(window.location.search);
const scid = urlParams.get('_scid');
if (scid) {
// Restore cookie
document.cookie = `_scid=${scid}; path=/; max-age=604800`;
// Track purchase
snaptr('track', 'PURCHASE', {
'price': urlParams.get('amount'),
'currency': urlParams.get('currency'),
'transaction_id': urlParams.get('order_id')
});
}
}
Advanced Cross-Domain Patterns
Automatic Link Decoration
// Automatically decorate all outbound links
(function() {
const targetDomains = [
'checkout.example.com',
'secure-payment.com',
'partner-site.com'
];
function decorateLink(link) {
const scid = getSnapClickId();
if (!scid) return;
try {
const url = new URL(link.href);
// Check if domain should be decorated
if (targetDomains.some(domain => url.hostname.includes(domain))) {
url.searchParams.set('_scid', scid);
link.href = url.toString();
}
} catch (e) {
console.error('Invalid URL:', link.href);
}
}
// Decorate existing links
document.querySelectorAll('a').forEach(decorateLink);
// Decorate dynamically added links
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.tagName === 'A') {
decorateLink(node);
}
if (node.querySelectorAll) {
node.querySelectorAll('a').forEach(decorateLink);
}
});
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
})();
Form Auto-Submit with Parameters
// Automatically add Snap ID to form submissions
function decorateForm(form) {
const scid = getSnapClickId();
if (!scid) return;
form.addEventListener('submit', function() {
// Add hidden input with Snap click ID
const input = document.createElement('input');
input.type = 'hidden';
input.name = '_scid';
input.value = scid;
form.appendChild(input);
});
}
// Apply to all forms going to external domains
document.querySelectorAll('form[action*="external-domain.com"]').forEach(decorateForm);
Session Storage Fallback
// Store Snap ID in sessionStorage as backup
function preserveSnapId() {
const scid = getSnapClickId();
if (scid) {
sessionStorage.setItem('snap_click_id', scid);
sessionStorage.setItem('snap_click_timestamp', Date.now());
}
}
// Restore from sessionStorage if cookie lost
function restoreSnapId() {
const cookieScid = getSnapClickId();
if (!cookieScid) {
const storedScid = sessionStorage.getItem('snap_click_id');
const timestamp = sessionStorage.getItem('snap_click_timestamp');
const maxAge = 7 * 24 * 60 * 60 * 1000; // 7 days
if (storedScid && (Date.now() - timestamp < maxAge)) {
document.cookie = `_scid=${storedScid}; path=/; max-age=604800`;
console.log('Snap ID restored from sessionStorage');
}
}
}
// Run on every page
preserveSnapId();
restoreSnapId();
Testing Cross-Domain Tracking
Manual Testing Steps
- Clear cookies in browser
- Click a Snapchat ad (or simulate with
?_scid=test123) - Verify cookie set on landing domain
- Navigate to second domain (checkout, etc.)
- Verify cookie persists or URL parameter passed
- Complete conversion event
- Check Events Manager for attribution
Verification Checklist
## Cross-Domain Tracking Checklist
### Subdomain Setup
- [ ] cookie_domain set to root domain (e.g., .example.com)
- [ ] Same pixel ID on all subdomains
- [ ] Same pixel configuration on all subdomains
- [ ] Cookie accessible on all subdomains
### Cross-Domain Setup
- [ ] Snap click ID captured from cookie
- [ ] URL parameters appended to external links
- [ ] Click ID restored on destination domain
- [ ] Cookie set on destination domain
- [ ] Events fire correctly on destination
### Testing
- [ ] Cookie persists across subdomains
- [ ] URL parameter passed to external domain
- [ ] Cookie restored on external domain
- [ ] Purchase event attributes correctly
- [ ] No duplicate events
Console Debugging
// Debug cross-domain tracking in console
function debugCrossDomain() {
console.group('Snap Cross-Domain Debug');
// Check cookie
const scid = getSnapClickId();
console.log('Snap Click ID (cookie):', scid || 'NOT FOUND');
// Check URL parameter
const urlParams = new URLSearchParams(window.location.search);
const scidParam = urlParams.get('_scid');
console.log('Snap Click ID (URL):', scidParam || 'NOT FOUND');
// Check sessionStorage
const storedScid = sessionStorage.getItem('snap_click_id');
console.log('Snap Click ID (storage):', storedScid || 'NOT FOUND');
// Check cookie domain
document.cookie.split(';').forEach(cookie => {
if (cookie.includes('_scid')) {
console.log('Cookie details:', cookie.trim());
}
});
console.groupEnd();
}
// Run debug
debugCrossDomain();
Common Issues and Solutions
Issue: Cookie Not Shared Across Subdomains
Problem: Cookie set on www.example.com not available on shop.example.com
Solution:
// Ensure cookie_domain includes leading dot
snaptr('init', 'YOUR_PIXEL_ID', {
'cookie_domain': '.example.com' // ✅ Correct - note the dot
});
// Not:
snaptr('init', 'YOUR_PIXEL_ID', {
'cookie_domain': 'example.com' // ❌ May not work across subdomains
});
Issue: URL Parameter Lost
Problem: _scid parameter not preserved through redirects
Solution:
// Preserve parameter through multiple redirects
function preserveSnapParam(url) {
const currentScid = new URLSearchParams(window.location.search).get('_scid')
|| getSnapClickId();
if (currentScid) {
const urlObj = new URL(url, window.location.origin);
urlObj.searchParams.set('_scid', currentScid);
return urlObj.toString();
}
return url;
}
Issue: Third-Party Cookies Blocked
Problem: Safari or other browsers block third-party cookies
Solution:
// Use URL parameters as primary method
// Implement server-side Conversions API as backup
// See: Server-Side vs Client-Side guide
Privacy Considerations
GDPR Compliance
// Only track cross-domain with consent
if (userHasConsented()) {
snaptr('init', 'YOUR_PIXEL_ID', {
'cookie_domain': '.example.com'
});
} else {
// Don't set cookies
console.log('Cross-domain tracking disabled - no consent');
}
Cookie Disclosure
Update privacy policy to disclose:
- Cookies shared across subdomains/domains
- Purpose of cross-domain tracking
- How users can opt out
Best Practices
- Use consistent pixel configuration across all domains
- Test thoroughly before deploying to production
- Document domains in your tracking setup
- Monitor attribution in Events Manager
- Implement CAPI as backup for cookie restrictions
- Validate parameters before passing between domains
- Clean URLs (optional) to remove tracking parameters from address bar
Next Steps
- Implement Conversions API - See Server-Side vs Client-Side
- Set up GTM - See Install Pixel or SDK
- Configure events - See Event Tracking