Server-Side Tracking Compliance | Blue Frog Docs

Server-Side Tracking Compliance

Implementing server-side tracking while maintaining privacy compliance and user trust.

Server-Side Tracking Compliance

What This Means

Server-side tracking sends data from your server rather than the user's browser. While it provides more accurate data and bypasses ad blockers, it creates new privacy compliance challenges.

Server-Side Tracking Methods:

Impact Assessment

Benefits

  • Ad Blocker Bypass: Data collection isn't blocked
  • Data Accuracy: More reliable than client-side
  • Data Control: Greater control over what's sent
  • Performance: Reduces client-side script load

Privacy Considerations

  • Consent Still Required: Server-side doesn't bypass consent requirements
  • Data Transparency: Harder for users to see what's collected
  • First-Party Disguise: Can mask third-party tracking
  • Regulatory Scrutiny: Increasing attention from privacy authorities

How to Diagnose

Current Server-Side Implementation

Check for sGTM:

// Look for server-side GTM container
// Client-side tag sends to first-party domain
const isServerSide =
  document.querySelector('script[src*="gtm.js"]')
    ?.src.includes('your-domain.com');

Audit Data Flow:

  1. Map all data collection points
  2. Identify server-side endpoints
  3. Document what data is forwarded to third parties
  4. Review consent signal handling

Compliance Checklist

  • Consent signals sent to server
  • User consent respected in server-side forwarding
  • Privacy policy updated to reflect server-side tracking
  • Data processing agreements in place
  • Data minimization applied

General Fixes

GTM Server Container:

// Read consent from incoming request
const consentState = eventData.consent;

// Only forward to vendors if consent granted
if (consentState.analytics_storage === 'granted') {
  // Forward to GA4
  sendToGoogleAnalytics(eventData);
}

if (consentState.ad_storage === 'granted') {
  // Forward to advertising platforms
  sendToMeta(eventData);
  sendToGoogle(eventData);
}
// Server-side: Set first-party cookie
response.setHeader('Set-Cookie', [
  `_ga=GA1.1.${clientId}; ` +
  'Path=/; ' +
  'SameSite=Lax; ' +
  'Secure; ' +
  'HttpOnly; ' +
  'Max-Age=63072000'  // 2 years
]);

3. Data Minimization in Transit

// Minimize data sent server-side
const minimizedEvent = {
  event_name: eventData.event_name,
  // Include only necessary parameters
  page_location: eventData.page_location,
  user_id: hasConsent ? eventData.user_id : undefined,
  // Exclude unnecessary PII
  // NO: full IP address
  // NO: precise geolocation
  // NO: device fingerprints
};

4. Transparent Data Forwarding

// Log all third-party data forwarding
const forwardingLog = {
  timestamp: Date.now(),
  destination: 'Meta Conversions API',
  data_types: ['event_name', 'event_time', 'hashed_email'],
  consent_basis: 'explicit_consent',
  user_id_hash: hashUserId(userId)
};

await logToAuditSystem(forwardingLog);

5. Respect Do-Not-Track

// Check for DNT signal
const dntEnabled =
  req.headers['dnt'] === '1' ||
  req.headers['sec-gpc'] === '1';

if (dntEnabled) {
  // Respect user preference
  return sendMinimalAnalytics(req);
}

Server-Side GTM Best Practices

// In sGTM template
const consentState = getRequestHeader('X-Consent-State');

if (consentState) {
  const consent = JSON.parse(consentState);

  // Apply consent to all vendors
  setConsentState(consent);
}

Privacy-Compliant IP Handling

// Anonymize IP before forwarding
const clientIP = getRequestHeader('X-Forwarded-For');
const anonymizedIP = clientIP.split('.').slice(0, 2).join('.') + '.0.0';

// Or don't forward IP at all
delete eventData.ip_override;

User Identifier Hashing

// Hash PII before sending to vendors
const crypto = require('crypto');

function hashEmail(email) {
  return crypto
    .createHash('sha256')
    .update(email.toLowerCase().trim())
    .digest('hex');
}

// Send hashed values
eventData.em = hashEmail(eventData.email);
delete eventData.email;

Conversions API Compliance

Meta Conversions API

// Privacy-compliant CAPI implementation
const event = {
  event_name: 'Purchase',
  event_time: Math.floor(Date.now() / 1000),
  action_source: 'website',
  user_data: {
    // Hashed PII only
    em: hasConsent ? [hashEmail(email)] : [],
    ph: hasConsent ? [hashPhone(phone)] : [],
    // Respect consent for identifiers
    fbc: hasConsent ? getCookie('_fbc') : undefined,
    fbp: hasConsent ? getCookie('_fbp') : undefined
  },
  custom_data: {
    value: order.total,
    currency: order.currency
  }
};
// Privacy-compliant Google conversion
const conversion = {
  conversionAction: 'customers/123/conversionActions/456',
  conversionDateTime: formatDateTime(new Date()),
  conversionValue: order.total,
  currencyCode: 'USD',
  // Only include user identifiers with consent
  userIdentifiers: hasConsent ? [
    { hashedEmail: hashEmail(email) },
    { hashedPhoneNumber: hashPhone(phone) }
  ] : []
};

Privacy Policy Updates

Include in your privacy policy:

## Server-Side Data Processing

We process certain analytics and advertising data on our servers before
sharing with service providers. This may include:

- Page views and interactions
- Purchase and conversion events
- Hashed email addresses (for advertising matching)

Server-side processing allows us to:
- Improve data quality
- Apply data minimization
- Better control what data is shared

Your consent preferences are respected in all server-side processing.

Monitoring and Auditing

Data Flow Logging

// Log all outbound data transfers
const auditLog = {
  timestamp: new Date().toISOString(),
  source: 'server-gtm',
  destination: vendor,
  eventType: event.event_name,
  dataCategories: categorizeData(event),
  consentBasis: consent.basis,
  retentionPeriod: vendor.retentionDays
};

Regular Audits

  1. Quarterly review of server-side data flows
  2. Vendor data retention verification
  3. Consent mechanism testing
  4. Privacy policy accuracy check

Further Reading

// SYS.FOOTER