___TERMS_OF_SERVICE___ By creating or modifying this file you agree to Google Tag Manager's Community Template Gallery Developer Terms of Service available at https://developers.google.com/tag-manager/gallery-tos (or such other URL as Google may provide), as modified from time to time. ___INFO___ { "type": "MACRO", "id": "cvt_temp_public_id", "version": 1, "securityGroups": [], "displayName": "IP Address Redaction", "categories": [ "UTILITY", "ADVERTISING" ], "brand": { "id": "brand_dummy", "displayName": "Metric Owl", "thumbnail": "data:image/png;base64,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" }, "description": "Returns the visitor's IP address with the last part removed (IPv4 last octet, IPv6 last 80 bits), using Google's own getAnonymizedIpAddress API. Use it in an Augment event transformation to set ip_override for Google Ads and other tags. Can return the full IP address only when advertising consent is granted.", "containerContexts": [ "SERVER" ] } ___TEMPLATE_PARAMETERS___ [ { "type": "SELECT", "name": "mode", "displayName": "When to redact", "macrosInSelect": false, "simpleValueType": true, "selectItems": [ { "value": "always", "displayValue": "Always redact the IP address" }, { "value": "consent", "displayValue": "Redact unless advertising consent is granted" } ], "defaultValue": "always", "help": "Google has told advertisers that from 11 January 2027 its ad tags in a server container can receive the full IP address. Redacting it keeps the address shortened whatever the tags do." }, { "type": "TEXT", "name": "consentValue", "displayName": "Advertising consent", "simpleValueType": true, "help": "A variable that returns granted, true or 1 when the visitor has granted advertising consent. Anything else, including an empty value, redacts the address.", "enablingConditions": [ { "paramName": "mode", "paramValue": "consent", "type": "EQUALS" } ], "valueValidators": [ { "type": "NON_EMPTY" } ] } ] ___SANDBOXED_JS_FOR_SERVER___ const getAnonymizedIpAddress = require('getAnonymizedIpAddress'); const getEventData = require('getEventData'); const makeString = require('makeString'); // Full IP address only with advertising consent, and only if the client supplied one. if (data.mode === 'consent') { const consent = makeString(data.consentValue).toLowerCase(); if (consent === 'granted' || consent === 'true' || consent === '1') { const fullIp = getEventData('ip_override'); if (fullIp) return fullIp; } } // IPv4: last octet set to 0. IPv6: last 80 bits set to zero. '::' if the address can't be read. return getAnonymizedIpAddress(); ___SERVER_PERMISSIONS___ [ { "instance": { "key": { "publicId": "user_ip", "versionId": "1" }, "param": [] }, "clientAnnotations": { "isEditedByUser": true }, "isRequired": true }, { "instance": { "key": { "publicId": "read_event_data", "versionId": "1" }, "param": [ { "key": "eventDataAccess", "value": { "type": 1, "string": "specific" } }, { "key": "keyPatterns", "value": { "type": 2, "listItem": [ { "type": 1, "string": "ip_override" } ] } } ] }, "clientAnnotations": { "isEditedByUser": true }, "isRequired": true } ] ___TESTS___ scenarios: - name: Always redacts by default code: |- mock('getAnonymizedIpAddress', '198.51.100.0'); mock('getEventData', '198.51.100.42'); assertThat(runCode({mode: 'always'})).isEqualTo('198.51.100.0'); assertApi('getEventData').wasNotCalled(); - name: Full address when consent is granted code: |- mock('getAnonymizedIpAddress', '198.51.100.0'); mock('getEventData', '198.51.100.42'); assertThat(runCode({mode: 'consent', consentValue: 'granted'})).isEqualTo('198.51.100.42'); assertApi('getEventData').wasCalledWith('ip_override'); - name: Consent values are case-insensitive and accept true and 1 code: |- mock('getAnonymizedIpAddress', '198.51.100.0'); mock('getEventData', '198.51.100.42'); assertThat(runCode({mode: 'consent', consentValue: 'TRUE'})).isEqualTo('198.51.100.42'); assertThat(runCode({mode: 'consent', consentValue: 1})).isEqualTo('198.51.100.42'); - name: Redacts when consent is denied or missing code: |- mock('getAnonymizedIpAddress', '198.51.100.0'); mock('getEventData', '198.51.100.42'); assertThat(runCode({mode: 'consent', consentValue: 'denied'})).isEqualTo('198.51.100.0'); assertThat(runCode({mode: 'consent', consentValue: undefined})).isEqualTo('198.51.100.0'); - name: Redacts when consent is granted but there is no address to pass on code: |- mock('getAnonymizedIpAddress', '2001:db8:85a3::'); mock('getEventData', undefined); assertThat(runCode({mode: 'consent', consentValue: 'granted'})).isEqualTo('2001:db8:85a3::'); ___NOTES___ Built and maintained by Marc Alexander, Metric Owl Ltd (https://www.metricowl.co.uk). Licensed under the Apache License 2.0.