Server-Side PII Redaction: Building a Privacy Firewall in ssGTM

Contents
- 1. Why PII Leakage in URLs is a Critical Compliance Risk
- 2. Server-Side GTM as an Intermediary Privacy Firewall
- 3. Developing Sandboxed JavaScript Variables for PII Detection
- 4. Applying Redaction Across GA4 and Meta Conversions API Tags
- 5. Setting Up the Rule as a Transformation
- Questions and answers
- Sources
Accidental leakage of Personally Identifiable Information (PII) within HTTP query parameters represents one of the most critical regulatory and technical risks in digital analytics. When forms submit data via GET requests or marketing automation tools append unencrypted email addresses, phone numbers, or national identification numbers (such as Polish PESEL numbers) to URL parameters, client-side tags transmit this PII directly to third-party endpoints. Modern analytics architectures mitigate this risk by utilizing Server-Side Google Tag Manager (ssGTM) as an intermediary privacy firewall, scrubbing sensitive strings before outgoing network payloads are dispatched to Google Analytics 4 or the Meta Conversions API.
1. Why PII Leakage in URLs is a Critical Compliance Risk
Transmitting PII to external vendors without explicit cryptographic hashing violates both strict data privacy regulations (such as GDPR) and the mandatory terms of service of major advertising platforms. The Google Analytics 4 terms prohibit unhashed PII in standard dimensions like page_location or custom event parameters as well, and values already collected can only be removed with a data deletion request in the property. Traditional client-side redaction is often fragile, as scripts can be bypassed or fail to catch dynamically decorated query strings.
2. Server-Side GTM as an Intermediary Privacy Firewall
In a server-side tagging topology, incoming analytics requests from the browser terminate first at a first-party tagging server. Because the incoming HTTP request is held inside the server environment before any third-party dispatch occurs, developers can inspect, transform, and redact the event data model completely within a trusted boundary:
- Decoupled Ingestion and Dispatch: Client-side browsers send raw event streams solely to the ssGTM container. Third-party vendors never communicate directly with the end-user browser.
- Centralized Transformation: A single redaction rule applied in the server container protects all outbound downstream tags simultaneously, preventing accidental data leaks across multiple marketing platforms.
3. Developing Sandboxed JavaScript Variables for PII Detection
Implementing an automated scrubbing engine in ssGTM requires creating a custom Sandboxed JavaScript Variable that evaluates URL strings and replaces matching regular expression patterns with safe placeholders. Within the server container, regular expression logic must adhere to Sandboxed JavaScript APIs (utilizing native regex evaluation patterns available in the environment):
- Email Address Redaction: A regex pattern matches standard email formats (
[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+) and replaces the detected sequence with a static string such as[REDACTED_EMAIL]. - Phone Number Masking: Numerical sequences containing 9 to 15 digits, frequently preceded by country codes or formatting characters (e.g.,
+48or hyphens), are identified and stripped from query parameters to prevent accidental transmission of contact numbers. - National Identification (PESEL) Filtering: For Central European deployments, specialized regex expressions identify 11-digit numeric sequences matching PESEL checksum algorithms or date-of-birth structures, substituting them with
[REDACTED_PESEL].
4. Applying Redaction Across GA4 and Meta Conversions API Tags
Once the custom scrubbing variable is defined, it must be mapped to the primary URL parameters inside the server container. For Google Analytics 4 tags, overriding the page_location, page_referrer, and any custom URL event parameters with the sanitized variable output ensures that no plaintext PII ever leaves the server infrastructure. Similarly, Meta Conversions API tags can safely process sanitized event URLs while reserving user identification strictly for properly SHA-256-hashed user data parameters.
5. Setting Up the Rule as a Transformation
The variable does the cleaning; a transformation decides where the cleaned value ends up. In the server container, transformations run after the client has created the event data object and before the tags read it. Of the three types, Allow parameters, Augment event and Exclude parameters, Augment event is the one that changes the value of an existing event parameter. Without further settings a transformation applies to all tags, so a tag added later receives the cleaned value without any mapping of its own.
The setup has three parts:
- A custom variable template in Sandboxed JavaScript reads one parameter from the event data and returns it cleaned. The parameter name comes from a text field of the template, so the same template serves every field.
- One variable per field is created from the template, for example for
page_location,page_referrerandsearch_term. - An Augment event transformation sets each of these parameters to its own variable. Affected Tags and Matching Conditions stay at their defaults, which cover all tags and all events.
A reduced version of the template:
const getEventData = require('getEventData');
const createRegex = require('createRegex');
const getType = require('getType');
const value = getEventData(data.parameter);
if (getType(value) !== 'string') {
return value;
}
// query parameters that must not leave the server, case-insensitive
const params = ['email', 'e-mail', 'user_email', 'phone', 'token', 'reset_key'];
let out = value;
for (let i = 0; i < params.length; i++) {
const re = createRegex('\\b' + params[i] + '=[^&#]*', 'gi');
out = out.replace(re, params[i] + '=[REDACTED_PARAM]');
}
// addresses elsewhere in the value, also with a percent-encoded @
const mail = createRegex('[a-zA-Z0-9_.+-]+(@|%40)[a-zA-Z0-9-]+\\.[a-zA-Z0-9.-]+', 'gi');
return out.replace(mail, '[REDACTED_EMAIL]');
createRegex requires server image 2.0.0 or later and returns null where RE2 is unavailable, so the image version belongs on the checklist before the container is published. The phone pattern from section 3 is deliberately left out: any run of 9 to 15 digits also matches order numbers, timestamps in seconds or milliseconds and long product IDs. Applied to a URL, it replaces an order number in the path; applied to every field of an event, it can overwrite a transaction_id. Digit patterns therefore belong only on free-text fields such as search terms, while fields with a known meaning stay excluded.
Before publishing, three test requests show whether the rule holds: one with ?email=test@example.com, one with the percent-encoded test%40example.com and one with the parameter name written as Email=. In the preview the incoming request still shows the raw values, which is expected; the outgoing requests of the GA4 and Meta tags have to carry the placeholders. A test event with real order numbers alongside shows whether anything was overwritten that should have stayed.
Questions and answers
Does the redaction also protect tags that are added to the server container later?
Only if it applies before the tags. If the cleaned variable is entered into page_location and page_referrer in each tag individually, a tag created later without that mapping sends the raw URL again. The rule only works centrally as a transformation in the server container that overrides the event data before the tags read it.
Where does the privacy firewall in the server container reach its limits?
The firewall only acts on what passes through the server container and, there, through the variable. Four gaps are easily left open:
- Tags that still run in the browser. A pixel in the web container sends the URL straight to the vendor, bypassing the server. The firewall only holds if the browser really talks to the ssGTM container alone.
- The incoming request itself. The data reaches the tagging server unfiltered, and the request logs of the server or the hosting platform often record the URL including the query string. Those logs belong in the same assessment.
- Encoded values. In a URL, the @ of an email address often appears as
%40, and a pattern looking for @ will not find it. The variable should therefore decode the value before checking it. - Fields outside the URL. Page titles, search terms and custom parameters that carry no URL, such as form fields, can hold the same data even when page_location and page_referrer are clean.
The firewall is therefore the second line of defense. The first remains keeping personal data out of the URL in the first place, for example by having forms submit via POST rather than GET.