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 |