Snapchat Ads Cross-Domain Tracking | Blue Frog Docs

Snapchat Ads Cross-Domain Tracking

Track users seamlessly across multiple domains and subdomains for accurate attribution.

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.comcheckout.example.com Shared cookie domain
Separate checkout domain example.comsecure-checkout.com URL parameter passing
Multiple brand sites brand1.combrand2.com URL parameter passing
Third-party payment shop.compaypal.comshop.com Session restoration
Landing page service lp.example.comexample.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.comcheckout-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

// 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

  1. Clear cookies in browser
  2. Click a Snapchat ad (or simulate with ?_scid=test123)
  3. Verify cookie set on landing domain
  4. Navigate to second domain (checkout, etc.)
  5. Verify cookie persists or URL parameter passed
  6. Complete conversion event
  7. 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

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');
}

Update privacy policy to disclose:

  • Cookies shared across subdomains/domains
  • Purpose of cross-domain tracking
  • How users can opt out

Best Practices

  1. Use consistent pixel configuration across all domains
  2. Test thoroughly before deploying to production
  3. Document domains in your tracking setup
  4. Monitor attribution in Events Manager
  5. Implement CAPI as backup for cookie restrictions
  6. Validate parameters before passing between domains
  7. Clean URLs (optional) to remove tracking parameters from address bar

Next Steps

Resources

// SYS.FOOTER