Reddit Ads Cross-Domain Tracking | OpsBlu Docs

Reddit Ads Cross-Domain Tracking

Implementing cross-domain tracking for multi-site user journeys with Reddit Pixel.

Overview

Cross-domain tracking enables Reddit Pixel to maintain user session continuity when visitors navigate between multiple domains in your ecosystem. Without proper cross-domain configuration, each domain transition creates a new session, breaking attribution and underreporting conversions.

When You Need Cross-Domain Tracking

  • Separate checkout domain: Main site on example.com, checkout on checkout.example.com
  • Multiple brand domains: Navigate between brand1.com and brand2.com
  • Third-party payment: Redirect to payment processor then back to confirmation page
  • Subdomain structure: Move between www.example.com, shop.example.com, blog.example.com
  • Partner referrals: Track users referred from partner domains

How Cross-Domain Tracking Works

Reddit Pixel uses first-party cookies to identify users. When navigating between domains:

  1. Same domain: Cookie persists automatically
  2. Different domain: Cookie doesn't transfer by default
  3. Cross-domain solution: Pass click ID in URL parameter to maintain identity

Implementation Methods

Method 1: URL Parameter Passing (Linker)

The most common approach is to append Reddit click ID (rdt_cid) to cross-domain links.

How it works:

  1. Reddit Pixel sets rdt_cid cookie on first domain
  2. Click ID appended to links pointing to second domain
  3. Reddit Pixel on second domain reads rdt_cid from URL
  4. Second domain sets its own cookie with same click ID
  5. User session continues across domains

For more advanced scenarios, manually sync cookie values between domains via JavaScript.

Method 3: Server-Side Session Passing

Use server-side session management to pass user identity between domains, then sync with Reddit Pixel.

Basic Cross-Domain Setup

Step 1: Install Pixel on All Domains

Ensure Reddit Pixel is installed with the same Pixel ID on all domains:

Domain A (example.com):

<script>
!function(w,d){if(!w.rdt){var p=w.rdt=function(){p.sendEvent?p.sendEvent.apply(p,arguments):p.callQueue.push(arguments)};p.callQueue=[];var t=d.createElement("script");t.src="https://www.redditstatic.com/ads/pixel.js",t.async=!0;var s=d.getElementsByTagName("script")[0];s.parentNode.insertBefore(t,s)}}(window,document);

rdt('init', 'a2_XXXXXXXXXX');
rdt('track', 'PageView');
</script>

Domain B (checkout.example.com):

<script>
!function(w,d){if(!w.rdt){var p=w.rdt=function(){p.sendEvent?p.sendEvent.apply(p,arguments):p.callQueue.push(arguments)};p.callQueue=[];var t=d.createElement("script");t.src="https://www.redditstatic.com/ads/pixel.js",t.async=!0;var s=d.getElementsByTagName("script")[0];s.parentNode.insertBefore(t,s)}}(window,document);

rdt('init', 'a2_XXXXXXXXXX');  // Same Pixel ID
rdt('track', 'PageView');
</script>

Modify links that navigate to the second domain to include the Reddit click ID.

Manual Linker Implementation:

// Get Reddit click ID from cookie
function getRedditClickId() {
  const cookies = document.cookie.split(';');
  for (let cookie of cookies) {
    const [name, value] = cookie.trim().split('=');
    if (name === 'rdt_cid') {
      return value;
    }
  }
  return null;
}

// Add click ID to URL
function addRedditClickId(url) {
  const clickId = getRedditClickId();
  if (!clickId) return url;

  const separator = url.includes('?') ? '&' : '?';
  return `${url}${separator}rdt_cid=${clickId}`;
}

// Update all cross-domain links
document.querySelectorAll('a[href*="checkout.example.com"]').forEach(link => {
  link.href = addRedditClickId(link.href);
});

// Or handle on click
document.querySelectorAll('a[href*="checkout.example.com"]').forEach(link => {
  link.addEventListener('click', function(e) {
    e.preventDefault();
    window.location.href = addRedditClickId(this.href);
  });
});

Step 3: Read Parameter on Destination Domain

Reddit Pixel automatically reads rdt_cid from URL parameters. No additional code needed if pixel is properly installed.

Verification:

// Check if rdt_cid in URL
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('rdt_cid')) {
  console.log('Reddit Click ID received:', urlParams.get('rdt_cid'));
}

Automated Cross-Domain Linking

Automatically decorate all cross-domain links on page load:

(function() {
  const crossDomains = [
    'checkout.example.com',
    'shop.example.com',
    'secure.example.com'
  ];

  function decorateLink(link) {
    const clickId = getRedditClickId();
    if (!clickId) return;

    const url = new URL(link.href);

    // Check if link goes to cross-domain
    const isCrossDomain = crossDomains.some(domain =>
      url.hostname.includes(domain)
    );

    if (isCrossDomain && !url.searchParams.has('rdt_cid')) {
      url.searchParams.set('rdt_cid', clickId);
      link.href = url.toString();
    }
  }

  function getRedditClickId() {
    const match = document.cookie.match(/rdt_cid=([^;]+)/);
    return match ? match[1] : null;
  }

  // Decorate links on page load
  document.addEventListener('DOMContentLoaded', function() {
    document.querySelectorAll('a[href]').forEach(decorateLink);
  });

  // Decorate dynamically added links
  const observer = new MutationObserver(mutations => {
    mutations.forEach(mutation => {
      mutation.addedNodes.forEach(node => {
        if (node.tagName === 'A') {
          decorateLink(node);
        } else if (node.querySelectorAll) {
          node.querySelectorAll('a[href]').forEach(decorateLink);
        }
      });
    });
  });

  observer.observe(document.body, {
    childList: true,
    subtree: true
  });
})();

Form Submission Cross-Domain

Add click ID to form submissions that redirect to another domain:

document.querySelectorAll('form[action*="checkout.example.com"]').forEach(form => {
  form.addEventListener('submit', function(e) {
    const clickId = getRedditClickId();
    if (clickId) {
      const input = document.createElement('input');
      input.type = 'hidden';
      input.name = 'rdt_cid';
      input.value = clickId;
      this.appendChild(input);
    }
  });
});

function getRedditClickId() {
  const match = document.cookie.match(/rdt_cid=([^;]+)/);
  return match ? match[1] : null;
}

Google Tag Manager Cross-Domain Setup

GTM Configuration

Step 1: Create Reddit Click ID Variable

  • Variable Type: 1st-Party Cookie
  • Cookie Name: rdt_cid
  • Variable Name: Cookie - Reddit Click ID

Step 2: Create Cross-Domain Linker Tag

Tag Type: Custom HTML Tag Name: Reddit - Cross Domain Linker

<script>
(function() {
  const crossDomains = ['checkout.example.com', 'shop.example.com'];
  const clickId = {{Cookie - Reddit Click ID}};

  if (!clickId) return;

  function decorateLink(link) {
    const url = new URL(link.href);
    const isCrossDomain = crossDomains.some(d => url.hostname.includes(d));

    if (isCrossDomain && !url.searchParams.has('rdt_cid')) {
      url.searchParams.set('rdt_cid', clickId);
      link.href = url.toString();
    }
  }

  document.querySelectorAll('a[href]').forEach(decorateLink);
})();
</script>

Trigger: DOM Ready (All Pages)

Step 3: URL Parameter Variable

  • Variable Type: URL
  • Component Type: Query
  • Query Key: rdt_cid
  • Variable Name: URL - Reddit Click ID

Step 4: Set Cookie on Destination Domain

If Reddit Pixel doesn't automatically pick up the parameter, manually set cookie:

Tag Type: Custom HTML Tag Name: Reddit - Set Click ID Cookie

<script>
(function() {
  const clickIdFromUrl = {{URL - Reddit Click ID}};

  if (clickIdFromUrl) {
    document.cookie = 'rdt_cid=' + clickIdFromUrl +
      '; path=/; domain=.' + location.hostname.split('.').slice(-2).join('.') +
      '; max-age=604800';  // 7 days
  }
})();
</script>

Trigger: All Pages (with condition: URL - Reddit Click ID is not undefined)

Subdomain Tracking

For subdomains under the same root domain (e.g., www.example.com, shop.example.com), set cookie at root domain level.

// Set cookie for all subdomains
document.cookie = 'rdt_cid=' + clickId +
  '; path=/' +
  '; domain=.example.com' +  // Note the leading dot
  '; max-age=604800';
rdt('init', 'a2_XXXXXXXXXX', {
  optOut: false,
  useDecimalCurrencyValues: true,
  // Cookie will be set at subdomain level by default
  // For custom cookie domain handling, manage manually
});

Third-Party Payment Processor Flow

Scenario

User flow: example.compaymentprocessor.comexample.com/confirmation

Implementation

Step 1: Pass Click ID to Payment Processor

// On example.com checkout page
const checkoutForm = document.getElementById('checkout-form');
checkoutForm.addEventListener('submit', function(e) {
  const clickId = getRedditClickId();

  // Add as hidden field
  if (clickId) {
    const input = document.createElement('input');
    input.type = 'hidden';
    input.name = 'rdt_cid';
    input.value = clickId;
    this.appendChild(input);
  }
});

Step 2: Include in Return URL

Configure payment processor to include rdt_cid in return URL:

https://example.com/confirmation?order_id=12345&rdt_cid={{rdt_cid}}

Step 3: Set Cookie on Return

// On example.com/confirmation page
const urlParams = new URLSearchParams(window.location.search);
const clickId = urlParams.get('rdt_cid');

if (clickId) {
  document.cookie = 'rdt_cid=' + clickId +
    '; path=/; max-age=604800';
}

// Reddit Pixel will now use restored click ID for Purchase event
rdt('track', 'Purchase', {
  value: orderTotal,
  currency: 'USD',
  transactionId: orderId
});

Server-Side Session Passing

Node.js/Express Example

Domain A (example.com):

app.get('/checkout', (req, res) => {
  const clickId = req.cookies.rdt_cid;

  // Store in session
  req.session.redditClickId = clickId;

  // Redirect to checkout domain with session ID
  const checkoutUrl = `https://checkout.example.com/cart?session=${req.sessionID}`;
  res.redirect(checkoutUrl);
});

Domain B (checkout.example.com):

app.get('/cart', (req, res) => {
  const sessionId = req.query.session;

  // Retrieve session from shared session store (Redis, database)
  const session = await getSession(sessionId);
  const clickId = session.redditClickId;

  // Set cookie on checkout domain
  res.cookie('rdt_cid', clickId, {
    maxAge: 604800000,  // 7 days
    httpOnly: false,
    domain: '.example.com'
  });

  res.render('checkout');
});

Testing Cross-Domain Tracking

Manual Testing

  1. Start on Domain A (e.g., www.example.com)
  2. Inspect cookies: Open DevTools > Application > Cookies
  3. Find rdt_cid cookie and note the value
  4. Click link to Domain B (e.g., checkout.example.com)
  5. Check URL includes ?rdt_cid=... parameter
  6. Inspect cookies on Domain B and verify rdt_cid matches
  7. Complete conversion and verify attribution in Reddit Ads

Console Testing

// On Domain A
console.log('Domain A Click ID:', getRedditClickId());

// Click cross-domain link, then on Domain B
console.log('Domain B Click ID:', getRedditClickId());
console.log('URL Parameter:', new URLSearchParams(window.location.search).get('rdt_cid'));

// Both should match

function getRedditClickId() {
  const match = document.cookie.match(/rdt_cid=([^;]+)/);
  return match ? match[1] : null;
}

GTM Preview Mode

  1. Enable GTM Preview on Domain A
  2. Navigate to Domain B (new browser tab opens for preview)
  3. Verify cross-domain linker tag fired
  4. Check that rdt_cid variable populated
  5. Confirm Reddit Pixel events fire with correct attribution

Troubleshooting

Click ID Not Passing

Symptoms:

  • No rdt_cid parameter in URL when navigating to second domain
  • Cookie not set on destination domain

Solutions:

  • Verify linker JavaScript executes before link click
  • Check cross-domain array includes all target domains
  • Ensure links use full URL (not relative paths)
  • Test with console.log to verify click ID exists before linking

Symptoms:

  • Cookie exists on Domain A but not Domain B
  • Cookie value different between domains

Solutions:

  • Verify same Pixel ID used on both domains
  • Check cookie domain setting (use .example.com for subdomains)
  • Ensure cookie max-age sufficient (7+ days)
  • Test in incognito to rule out old cookies

Attribution Lost

Symptoms:

  • User journey starts on Reddit ad but conversion not attributed
  • Cross-domain clicks break session continuity

Solutions:

  • Verify click ID successfully transferred between domains
  • Check Reddit Events Manager for session continuity
  • Ensure conversion event fires with valid pixel initialization
  • Test full user journey end-to-end

Third-Party Redirect Issues

Symptoms:

  • Click ID lost during payment processor redirect
  • Conversion fires but no attribution

Solutions:

  • Confirm payment processor includes rdt_cid in return URL
  • Set cookie immediately upon return before pixel fires
  • Use server-side session storage as backup
  • Test with payment processor sandbox/test mode

Best Practices

  1. Use Same Pixel ID: Always use identical Pixel ID across all domains
  2. Consistent Naming: Use rdt_cid parameter name consistently
  3. Cookie Duration: Set cookie max-age to at least 7 days (attribution window)
  4. Domain Coverage: Decorate all cross-domain links, not just primary CTAs
  5. Test Thoroughly: Test complete user journeys across all domain combinations
  6. Monitor Attribution: Check Events Manager for cross-domain session continuity
  7. Document Domains: Maintain list of all domains requiring cross-domain tracking
  8. Privacy Compliance: Update privacy policy to disclose cross-domain tracking
  9. Fallback Methods: Consider server-side session passing as backup
  10. Regular Audits: Quarterly review of cross-domain link decoration

Advanced Patterns

Multiple Domain Hops

User navigates: Domain A → Domain B → Domain C

// Persist click ID through entire chain
const crossDomains = [
  'checkout.example.com',  // Domain B
  'secure.example.com'      // Domain C
];

// On all domains, decorate outbound links
// Implementation same as single cross-domain

Iframe Cross-Domain

When using iframes with different domains:

// Parent domain posts message to iframe
const clickId = getRedditClickId();
iframe.contentWindow.postMessage({
  type: 'reddit_click_id',
  clickId: clickId
}, 'https://checkout.example.com');

// Iframe receives and sets cookie
window.addEventListener('message', function(e) {
  if (e.data.type === 'reddit_click_id') {
    document.cookie = 'rdt_cid=' + e.data.clickId + '; path=/; max-age=604800';
  }
});

Dynamic Subdomain Generation

For sites that generate dynamic subdomains (e.g., user123.example.com):

// Set cookie at root domain level
function setRedditCookie(clickId) {
  const rootDomain = location.hostname.split('.').slice(-2).join('.');
  document.cookie = 'rdt_cid=' + clickId +
    '; path=/' +
    '; domain=.' + rootDomain +
    '; max-age=604800';
}