Blog
Strip the last octet, hash the whole address, or replace it with a coarse geo lookup. Pick one and apply it once.
In most EU jurisdictions, IP addresses are personal data, which means how you handle them is a regulatory choice as much as a technical one. The good news: you can do the anonymisation once at your tagging server and trust that downstream destinations receive only the redacted version.
Strip the last octet of an IPv4 address (the last 80 bits of an IPv6). Cheap and reversible-ish: a /24 network identifies your ISP and rough city but not you specifically. Acceptable under most GDPR interpretations.
const ip = getRequestHeader('x-forwarded-for') || '';
const truncated = ip.includes('.')
? ip.split('.').slice(0, 3).join('.') + '.0'
: ip.replace(/(:[^:]*){5}$/, ':0:0:0:0:0');
return truncated;
Replace the IP with its hash. Loses geographic information but preserves the ability to count distinct users per session. Useful when you need a stable per-user signal but cannot retain the IP.
const sha256 = require('sha256');
const ip = getRequestHeader('x-forwarded-for') || '';
return ip ? sha256(ip + '|' + SALT, {outputEncoding: 'hex'}) : '';
The salt is a per-container secret you store in a Custom Template variable. Without the salt, hashed IPs are still de-anonymisable by anyone who can hash all 4 billion IPv4 addresses (which is fast).
Replace the IP entirely with country and region codes. Use a built-in geo enrichment client (Stape, MaxMind via Custom Template) to do the lookup, then drop the IP from the outgoing payload.
This is the strictest option and the one most likely to satisfy a strict reading of GDPR. The trade-off is that you lose the ability to forward IP to destinations that legitimately need it (Meta CAPI uses it for matching, for example).
If you do not need IP for any destination, geo-only replacement. If you need it for CAPI matching but want to minimise exposure, last-octet truncation. If you need to deduplicate users without storing IP, hashing.
Apply the transformation as early as possible in your container, ideally in a variable that every tag references. The longer the raw IP travels, the more places it can leak. For the related step of forwarding headers correctly, see the separate post.