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:
- Server-side GTM (sGTM)
- Conversions API (Meta, TikTok)
- Measurement Protocol (Google Analytics)
- Server-side pixels
- First-party data collection
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:
- Map all data collection points
- Identify server-side endpoints
- Document what data is forwarded to third parties
- 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
1. Implement Consent-Aware Server-Side Tracking
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);
}
2. First-Party Cookie Handling
// 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
Consent Mode with sGTM
// 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
}
};
Google Ads Conversion API
// 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
- Quarterly review of server-side data flows
- Vendor data retention verification
- Consent mechanism testing
- Privacy policy accuracy check