Domain Migration for Tracker Mergers

When a tracking domain needs to merge with or migrate to a different domain (e.g., due to company acquisition, rebranding, or infrastructure consolidation), cookie migration presents unique challenges. Unlike simple redirects, tracker migrations require careful planning to preserve user identity, maintain attribution accuracy, and minimize disruption to ongoing campaigns.

The Migration Challenge

Scenario: A tracker operating on tracker-old.com needs to migrate to tracker-new.com (or merge with another tracker's domain). This migration must:

  1. Preserve User Identity: Existing cookies containing user IDs, session data, or tracking identifiers must be accessible on the new domain
  2. Maintain Attribution: Campaign tracking links, pixel fires, and conversion attribution must continue to work
  3. Minimize Data Loss: Historical tracking data should remain accessible
  4. Support Parallel Operations: During transition, both domains may need to function simultaneously
  5. Comply with Privacy Regulations: GDPR, CCPA, and other regulations may require explicit user consent for domain changes

Critical Constraint: Browsers enforce strict domain isolation for cookies. A cookie set on tracker-old.com cannot be directly accessed by tracker-new.com, even if:

Why This Matters:

sequenceDiagram participant Browser participant OldDomain as tracker-old.com participant NewDomain as tracker-new.com Browser->>OldDomain: GET /pixel.gif
Cookie: user_id=abc123
Domain=tracker-old.com OldDomain->>Browser: HTTP 200 OK
Set-Cookie: user_id=abc123
Domain=tracker-old.com Note over Browser: Migration: tracker-old.com
redirects to tracker-new.com Browser->>OldDomain: GET /pixel.gif OldDomain->>Browser: HTTP 301 Moved Permanently
Location: https://tracker-new.com/pixel.gif Browser->>Browser: Check cookies for tracker-new.com Browser->>Browser: No cookies found (different domain) Browser->>NewDomain: GET /pixel.gif
Cookie: (none) Note over Browser,NewDomain: Cookie NOT sent because
Domain=tracker-old.com doesn't
match tracker-new.com

Approach: Use HTTP redirects to forward requests, and have the target domain read cookies from the source domain via redirect flow, then set new cookies on the target domain.

Implementation Flow:

  1. User visits tracker-old.com/pixel.gif
  2. Server at tracker-old.com reads cookie: Cookie: user_id=abc123; Domain=tracker-old.com
  3. Server responds with 301 redirect to tracker-new.com/pixel.gif?user_id=abc123
  4. Browser follows redirect (cookie may be sent if SameSite allows)
  5. Server at tracker-new.com receives request with user_id in query parameter
  6. Server sets new cookie: Set-Cookie: user_id=abc123; Domain=tracker-new.com

Sequence Diagram:

sequenceDiagram participant Browser participant OldDomain as tracker-old.com participant NewDomain as tracker-new.com Browser->>OldDomain: GET /pixel.gif
Cookie: user_id=abc123
Domain=tracker-old.com OldDomain->>OldDomain: Read cookie: user_id=abc123 OldDomain->>Browser: HTTP 301 Moved Permanently
Location: https://tracker-new.com/pixel.gif?user_id=abc123&t=1704067200 Browser->>Browser: Follow redirect Browser->>NewDomain: GET /pixel.gif?user_id=abc123&t=1704067200
Cookie: (none from old domain) NewDomain->>NewDomain: Extract user_id from query param NewDomain->>NewDomain: Validate timestamp (t=1704067200) NewDomain->>Browser: HTTP 200 OK
Set-Cookie: user_id=abc123
Domain=tracker-new.com
SameSite=None#59; Secure Note over Browser,NewDomain: New cookie set on target domain
User identity preserved

Advantages:

Disadvantages:

Security Considerations:

Example Implementation:

// tracker-old.com handler
app.get('/pixel.gif', (req, res) => {
  const userId = req.cookies.user_id;
  const timestamp = Math.floor(Date.now() / 1000);
  const signature = createHMAC(userId + timestamp, SECRET_KEY);
  
  const redirectUrl = `https://tracker-new.com/pixel.gif?uid=${userId}&t=${timestamp}&sig=${signature}`;
  res.redirect(301, redirectUrl);
});

// tracker-new.com handler
app.get('/pixel.gif', (req, res) => {
  const { uid, t, sig } = req.query;
  
  // Validate signature
  if (!validateHMAC(uid + t, sig, SECRET_KEY)) {
    return res.status(400).send('Invalid signature');
  }
  
  // Validate timestamp (5 minute window)
  const timestamp = parseInt(t);
  if (Math.abs(Date.now() / 1000 - timestamp) > 300) {
    return res.status(400).send('Expired');
  }
  
  // Set cookie on new domain
  res.cookie('user_id', uid, {
    domain: 'tracker-new.com',
    sameSite: 'None',
    secure: true,
    maxAge: 365 * 24 * 60 * 60 * 1000 // 1 year
  });
  
  res.send(gifPixel());
});

Approach: During the transition period, set cookies on both domains simultaneously. This ensures users who visit either domain have their identity preserved.

Implementation Flow:

  1. User visits tracker-new.com/pixel.gif (no cookie yet)
  2. Server checks if user has cookie on tracker-old.com via server-side lookup (using shared database)
  3. If found, server sets cookie on tracker-new.com
  4. Server also sets cookie on tracker-old.com via redirect or CORS request
  5. Both domains now have the cookie

Sequence Diagram:

sequenceDiagram participant Browser participant OldDomain as tracker-old.com participant NewDomain as tracker-new.com participant Database as Shared Database Browser->>NewDomain: GET /pixel.gif
Cookie: (none) NewDomain->>Database: Lookup user by IP/fingerprint Database-->>NewDomain: Found: user_id=abc123
originally from tracker-old.com NewDomain->>NewDomain: Set cookie on tracker-new.com NewDomain->>Browser: HTTP 200 OK
Set-Cookie: user_id=abc123
Domain=tracker-new.com
SameSite=None#59; Secure Note over Browser: Later: User visits old domain Browser->>OldDomain: GET /pixel.gif
Cookie: user_id=abc123
Domain=tracker-new.com (not sent) OldDomain->>Database: Lookup user Database-->>OldDomain: Found: user_id=abc123 OldDomain->>Browser: HTTP 200 OK
Set-Cookie: user_id=abc123
Domain=tracker-old.com
SameSite=None#59; Secure Note over Browser: Now both domains have cookies

Advantages:

Disadvantages:

Privacy Considerations:

Approach: Use JavaScript and postMessage API to coordinate cookie migration between domains via iframe or popup communication.

Implementation Flow:

  1. User visits tracker-new.com (embedded in publisher site)
  2. Page loads iframe pointing to tracker-old.com/migrate.html
  3. Iframe reads cookie from tracker-old.com
  4. Iframe sends cookie value to parent via postMessage
  5. Parent page receives cookie value and sets it on tracker-new.com

Sequence Diagram:

sequenceDiagram participant Browser participant Publisher as publisher.com participant OldDomain as tracker-old.com participant NewDomain as tracker-new.com Browser->>Publisher: Load page with tracker-new.com pixel Publisher->>NewDomain: Load pixel script NewDomain->>Browser: Return JavaScript that creates iframe Browser->>Browser: Create iframe: tracker-old.com/migrate.html Browser->>OldDomain: GET /migrate.html
Cookie: user_id=abc123
Domain=tracker-old.com OldDomain->>Browser: Return HTML with postMessage script OldDomain->>Browser: JavaScript reads cookie: user_id=abc123 OldDomain->>Browser: postMessage({userId: 'abc123'}, 'https://tracker-new.com') Browser->>Browser: Receive message in tracker-new.com context Browser->>Browser: Set cookie: user_id=abc123
Domain=tracker-new.com Browser->>NewDomain: GET /pixel.gif
Cookie: user_id=abc123
Domain=tracker-new.com

Advantages:

Disadvantages:

Implementation Example:

<!-- tracker-new.com pixel script -->
<script>
(function() {
  // Check if cookie already exists on new domain
  if (getCookie('user_id')) {
    return; // Already migrated
  }
  
  // Create hidden iframe to old domain
  const iframe = document.createElement('iframe');
  iframe.src = 'https://tracker-old.com/migrate.html';
  iframe.style.display = 'none';
  document.body.appendChild(iframe);
  
  // Listen for postMessage from old domain
  window.addEventListener('message', function(event) {
    // Verify origin
    if (event.origin !== 'https://tracker-old.com') {
      return;
    }
    
    // Set cookie on new domain
    if (event.data.userId) {
      document.cookie = `user_id=${event.data.userId}; Domain=tracker-new.com; SameSite=None#59; Secure; Max-Age=31536000`;
      
      // Fire pixel with migrated cookie
      const img = new Image();
      img.src = 'https://tracker-new.com/pixel.gif';
    }
  });
})();
</script>

<!-- tracker-old.com/migrate.html -->
<script>
const userId = getCookie('user_id');
if (userId) {
  // Send cookie to parent window (tracker-new.com)
  window.parent.postMessage({ userId: userId }, 'https://tracker-new.com');
}
</script>

Strategy 4: Server-Side Session Migration

Approach: Use server-side session storage (Redis, database) instead of cookies for user identity. Cookies store only a session ID, which can be migrated easily.

Implementation Flow:

  1. User visits tracker-old.com
  2. Server creates session in shared Redis/database
  3. Server sets cookie: Set-Cookie: session_id=xyz789; Domain=tracker-old.com
  4. Session data stored server-side: {session_id: 'xyz789', user_id: 'abc123', ...}
  5. During migration, tracker-new.com checks session ID against same database
  6. Server sets new cookie: Set-Cookie: session_id=xyz789; Domain=tracker-new.com
  7. Both domains can access same session data

Advantages:

Disadvantages:

Hybrid Approach:

Combine server-side sessions with redirect-based migration:

// tracker-old.com
app.get('/pixel.gif', (req, res) => {
  const sessionId = req.cookies.session_id || generateSessionId();
  const userId = getUserIdFromSession(sessionId);
  
  // Store session data server-side
  redis.set(`session:${sessionId}`, JSON.stringify({
    user_id: userId,
    created_at: Date.now(),
    migrated: false
  }));
  
  // Redirect with session ID (small, can be signed)
  const signature = createHMAC(sessionId, SECRET_KEY);
  res.redirect(301, `https://tracker-new.com/pixel.gif?sid=${sessionId}&sig=${signature}`);
});

// tracker-new.com
app.get('/pixel.gif', (req, res) => {
  const { sid, sig } = req.query;
  
  // Validate signature
  if (!validateHMAC(sid, sig, SECRET_KEY)) {
    return res.status(400).send('Invalid');
  }
  
  // Check session in shared storage
  const sessionData = JSON.parse(redis.get(`session:${sid}`));
  if (!sessionData) {
    return res.status(404).send('Session not found');
  }
  
  // Set cookie on new domain
  res.cookie('session_id', sid, {
    domain: 'tracker-new.com',
    sameSite: 'None',
    secure: true,
    maxAge: 30 * 24 * 60 * 60 * 1000 // 30 days
  });
  
  // Mark as migrated
  sessionData.migrated = true;
  redis.set(`session:${sid}`, JSON.stringify(sessionData));
  
  res.send(gifPixel());
});

Best Practice: Multi-Phase Approach

For a tracker domain migration, use a phased approach combining multiple strategies:

Phase 1: Preparation (Weeks 1-2)

  1. Set Up Dual Infrastructure:

    • Deploy tracker-new.com infrastructure
    • Set up shared database/Redis for session storage
    • Configure DNS for new domain
  2. Implement Cookie Migration Logic:

    • Add redirect handlers on tracker-old.com
    • Implement cookie copying on tracker-new.com
    • Add server-side session storage
  3. Testing:

    • Test redirect flow
    • Test cookie migration
    • Test both domains simultaneously
    • Verify attribution accuracy

Phase 2: Parallel Operation (Weeks 3-8)

  1. Enable Dual-Domain Support:

    • Both domains accept pixel requests
    • Both domains set cookies
    • Both domains read from shared session storage
  2. Gradual Migration:

    • Start redirecting a small percentage of traffic (5-10%)
    • Monitor cookie migration success rate
    • Gradually increase percentage
    • Monitor for attribution gaps
  3. Update Partner Integrations:

    • Notify partners of new domain
    • Provide migration timeline
    • Update pixel URLs in ad platforms
    • Update tracking links

Sequence Diagram - Parallel Operation:

sequenceDiagram participant Partner as Ad Partner participant OldDomain as tracker-old.com participant NewDomain as tracker-new.com participant Database as Shared Session DB Partner->>OldDomain: GET /pixel.gif
Cookie: user_id=abc123
Domain=tracker-old.com alt Old domain still active OldDomain->>Database: Store/update session OldDomain->>Browser: HTTP 200 OK
Set-Cookie: user_id=abc123
Domain=tracker-old.com else Redirect enabled (gradual migration) OldDomain->>Browser: HTTP 301
Location: tracker-new.com/pixel.gif?uid=abc123&t=...&sig=... Browser->>NewDomain: GET /pixel.gif?uid=abc123&t=...&sig=... NewDomain->>Database: Store/update session NewDomain->>Browser: HTTP 200 OK
Set-Cookie: user_id=abc123
Domain=tracker-new.com end Note over Database: Both domains write to
same session storage

Phase 3: Full Migration (Weeks 9-12)

  1. Complete Redirect:

    • 100% of traffic redirected to tracker-new.com
    • tracker-old.com only handles redirects
    • Monitor migration success rate
  2. Cookie Migration:

    • All cookies migrated via redirect flow
    • Both domains maintain cookies (for backward compatibility)
    • Monitor for users still on old domain cookies
  3. Validation:

    • Verify attribution accuracy
    • Check for data gaps
    • Monitor error rates
    • Validate campaign performance

Phase 4: Sunset (Weeks 13-16)

  1. Maintain Redirects:

    • Keep redirects active for extended period (6-12 months)
    • Handle edge cases and late migrations
  2. Monitor Old Domain:

    • Track redirect volume
    • Identify when traffic drops to near zero
    • Plan domain decommissioning
  3. Final Cleanup:

    • After sufficient time (6-12 months), redirect can be removed
    • Old domain can be decommissioned
    • Update documentation

Migration Timeline Considerations

Short Timeline (1-2 months):

Medium Timeline (3-4 months):

Long Timeline (6+ months):

Critical Settings for Migration:

  1. Domain Attribute:

    • Old domain: Domain=tracker-old.com
    • New domain: Domain=tracker-new.com
    • Cannot use parent domain if domains are unrelated
  2. SameSite Attribute:

    • Use SameSite=None#59; Secure for cross-domain scenarios
    • Required for redirect-based migration
    • Allows cookies to be sent with redirects
  3. Secure Flag:

    • Always use Secure flag (HTTPS only)
    • Required when SameSite=None
    • Protects cookies in transit
  4. Path Attribute:

    • Use Path=/ for maximum compatibility
    • Ensures cookies work across all paths

Example Configuration:

Set-Cookie: user_id=abc123; Domain=tracker-new.com; Path=/; SameSite=None#59; Secure; Max-Age=31536000

Privacy and Compliance

GDPR Considerations:

CCPA Considerations:

Best Practices:

  1. Update Privacy Policy:

    • Document domain migration
    • Explain cookie migration process
    • Provide opt-out mechanisms
  2. User Notification:

    • Consider notifying users of domain change
    • Provide clear explanation
    • Offer opt-out if required
  3. Consent Management:

    • Migrate consent signals
    • Ensure consent applies to new domain
    • Re-obtain consent if necessary

Testing Strategy

Pre-Migration Testing:

  1. Cookie Migration Tests:

    • Test redirect flow
    • Verify cookie copying
    • Test parameter validation
    • Test signature verification
  2. Cross-Browser Testing:

    • Chrome/Edge (Chromium)
    • Firefox
    • Safari (especially ITP behavior)
    • Mobile browsers
  3. Privacy Tool Testing:

    • Test with ad blockers enabled
    • Test with privacy extensions
    • Test with ITP enabled (Safari)
  4. Attribution Testing:

    • Verify campaign tracking
    • Test conversion attribution
    • Validate pixel fires
    • Check for data gaps

During Migration Testing:

  1. Monitor Migration Success Rate:

    • Track percentage of successful migrations
    • Identify failure patterns
    • Monitor error rates
  2. Attribution Validation:

    • Compare attribution before/after migration
    • Identify discrepancies
    • Validate conversion tracking
  3. Performance Monitoring:

    • Monitor redirect latency
    • Check cookie migration time
    • Validate server response times

Common Pitfalls and Solutions

Pitfall 1: Cookie Not Migrated

Symptoms:

Solutions:

Pitfall 2: Duplicate Users

Symptoms:

Solutions:

Pitfall 3: Attribution Gaps

Symptoms:

Solutions:

Pitfall 4: Privacy Tool Blocking

Symptoms:

Solutions:

Migration Success Metrics

Key Metrics to Monitor:

  1. Migration Success Rate:

    • Percentage of cookies successfully migrated
    • Target: >95% migration rate
  2. Attribution Accuracy:

    • Conversion attribution maintained
    • Campaign performance consistent
    • No significant data gaps
  3. User Experience:

    • No user-visible errors
    • Minimal latency impact
    • Seamless transition
  4. Technical Performance:

    • Redirect latency <200ms
    • Cookie migration time <500ms
    • Error rate <1%

Conclusion

Domain migration for trackers requires careful planning and execution. The recommended approach combines:

  1. HTTP Redirects for immediate migration
  2. Server-Side Session Storage for data persistence
  3. Dual-Domain Support during transition
  4. Gradual Migration to minimize risk
  5. Extended Parallel Operation for compatibility

By following a phased approach and testing thoroughly, tracker migrations can be executed with minimal data loss and maximum attribution accuracy.

Key Takeaways:

Additional Resources