Building a GDPR-Compliant Server-Side Data Collection Stack

Standard

As GDPR and other data protection laws become stricter and enforcement rises, companies need more than consent bannersโ€”they need privacy-by-design infrastructure. A Server-Side Data Collection Stack, built with Google Tag Manager Server-Side (ssGTM) and privacy-compliant practices, empowers organizations to collect data lawfully, securely, and transparently.

โœ… Key GDPR Principles to Implement

Principle Implementation
Lawfulness, fairness & transparency Enforce valid consent before tracking
Purpose limitation Collect only data for declared purposes
Data minimization Strip unnecessary identifiers
Storage limitation Anonymize or expire personal data
Integrity & confidentiality Use secure channels and prevent leaks
Accountability Log consents and tag executions


๐Ÿงฐ Stack Components Required

  • Web GTM and GA4 setup
  • Server-Side GTM hosted at https://gtm.yourdomain.com
  • Consent Management Platform (e.g., Cookiebot, OneTrust)
  • HTTPS and secure cookie configuration
  • GDPR-aware tagging logic in GTM (Web + Server)
  • Optional: BigQuery or Cloud Logging for audit trails


๐Ÿš€ Step-by-Step Setup


๐Ÿ”น Step 1: Obtain & Store Valid Consent (Client-Side)

Use a CMP that supports TCF v2.2 or custom JSON-based consent.

Example (Cookiebot):

<script>
window.addEventListener('CookieConsentDeclaration', function() {
const consent = {
analytics_storage: Cookiebot.consents.statistics ? 'granted' : 'denied',
ad_storage: Cookiebot.consents.marketing ? 'granted' : 'denied'
};

document.cookie = "user_consent=" + btoa(JSON.stringify(consent)) + "; path=/; max-age=31536000; Secure; SameSite=Lax";
});
</script>

โœ… This cookie will be parsed by Server-Side GTM to decide whether tracking is allowed.


๐Ÿ”น Step 2: Route All Events to Server-Side GTM

In your Web GTM container:

  • Update GA4 Configuration Tag
  • Add Transport URL:

https://gtm.yourdomain.com

โœ… This proxies all data through your server before reaching GA4 or vendors.


๐Ÿ”น Step 3: Parse Consent Cookie in Server-Side GTM

Variable Type: Request Header

  • Name: Header - Cookie

function() {
const cookie = {{Header - Cookie}} || '';
const match = cookie.match(/user_consent=([^;]+)/);
if (!match) return { analytics_storage: 'denied', ad_storage: 'denied' };

try {
return JSON.parse(atob(match[1]));
} catch (e) {
return { analytics_storage: 'denied', ad_storage: 'denied' };
}
}

โœ… This allows server-side logic to act based on the userโ€™s preference.


๐Ÿ”น Step 4: Enforce Consent via Tag Triggers

Create Consent-Aware Triggers in ssGTM:

Trigger: GA4 Event Tag

Condition: Parsed Consent.analytics_storage equals granted

Trigger: Facebook CAPI Tag

Condition: Parsed Consent.ad_storage equals granted

โœ… No tag will fire unless the proper consent has been granted.


๐Ÿ”น Step 5: Apply Data Minimization

Remove or anonymize sensitive PII when not needed or not allowed.

Custom Variable: Sanitized Event Data

function() {
const data = event.data;
const consent = {{Parsed Consent}};

if (consent.analytics_storage !== 'granted') {
delete data.email;
delete data.user_id;
}

return data;
}

โœ… This ensures even server-logged data follows GDPR minimization rules.


๐Ÿ”น Step 6: Use First-Party Cookies with Secure Flags

In Server-Side GTM, ensure any Set-Cookie header follows:

Set-Cookie: _ga=GA1.1.XXXXXX; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=63072000

โœ… Prevents cross-site misuse or hijacking.


๐Ÿ”น Step 7: Hash Emails and Identifiers for CAPI

If sending emails or phone numbers for advertising APIs (Meta, Google):

Custom Template: SHA-256 Email Hash

function() {
const email = {{Event Data - email}};
if (!email) return null;

return crypto.subtle.digest('SHA-256', new TextEncoder().encode(email.toLowerCase().trim()))
.then(buffer => {
return [...new Uint8Array(buffer)].map(b => b.toString(16).padStart(2, '0')).join('');
});
}

โœ… This prevents sending raw identifiers to third parties.


๐Ÿ”น Step 8: Log Consent and Data Use for Auditing

Create a Webhook Tag in ssGTM to send logs to your internal backend or BigQuery:

{
"event": "{{Event Name}}",
"timestamp": "{{Timestamp}}",
"user_id": "{{Event Data - user_id}}",
"consent": "{{Parsed Consent}}",
"tags_fired": "{{Tag Name}}",
"ip": "{{Header - x-forwarded-for}}"
}

โœ… Logs provide traceability for every action taken, per GDPR Article 30 (Record of Processing Activities).


๐Ÿ”น Step 9: Geo-based Consent Enforcement

Use x-forwarded-for and accept-language to geolocate users.

Custom Variable: Is EU User

const ip = {{Header - x-forwarded-for}};
const response = fetch(`https://geoapi.com/lookup?ip=${ip}`);
const country = response.country_code;

return ['DE', 'FR', 'NL', 'IT', 'SE'].includes(country);

Use this in Trigger Conditions:

  • Block non-consented GA4 only for EU users


๐Ÿ”น Step 10: Periodic Anonymization and Expiry

Use a Cloud Scheduler or CRON job to:

  • Delete user-level data from internal logs
  • Replace event-level IDs with anonymized keys
  • Retain only aggregated values

โœ… Enables Article 5(1)(e) compliance (data retention limitation).


๐Ÿง  Bonus: Privacy-First Tag Strategy

Tag Type Consent Required Notes
GA4 (analytics) analytics_storage = granted Optional data minimization
Google Ads ad_storage = granted Pass consent mode flags
Meta CAPI ad_storage = granted Hash email + conditionally send
Internal CRM Webhook depends Encrypt PII and respect user_id TTLs


๐Ÿ“ฆ Summary Table

Step Action
1 Capture consent and store as secure cookie
2 Route all GA4 and marketing tags via ssGTM
3 Parse and decode consent on server
4 Use consent in server tag triggers
5 Strip or hash PII where needed
6 Secure all cookies and tokens
7 Forward only hashed identifiers
8 Log all actions for auditability
9 Enforce geo-sensitive consent logic
10 Anonymize and expire old data periodically


Leave a Reply

Your email address will not be published. Required fields are marked *