A Google Tag Manager Server-side variable template that decodes Google Consent Mode v2 strings from the gcd
parameter into a readable format.
This template automatically parses Google's encoded consent strings and returns the consent states for various categories (ad_storage, analytics_storage, ad_user_data, ad_personalization) in either object or string format.
- ✅ Parses Google Consent Mode v2
gcd
parameter - ✅ Supports all 4 consent categories
- ✅ Returns data in object or string format
- ✅ Works with server-side Google Tag Manager
- ✅ Handles missing consent parameters gracefully
- Download the template file
- In your GTM Server container, go to Templates
- Click New > Variable Template
- Import the template file
- Save and publish
- Go to Variables in your GTM Server container
- Click New > User-Defined Variables
- Select Google Consent Parser
- Configure the template parameters
Parameter | Description | Options |
---|---|---|
Consent Category | Which consent category to return | ad_storage , analytics_storage , ad_user_data , ad_personalization , all |
Output Format | How to format the response | object , string |
Consent Category: All
Output Format: Object
Returns:
{
ad_storage: { default: "denied", update: "granted" },
analytics_storage: { default: "denied", update: "granted" },
ad_user_data: { default: "denied", update: "granted" },
ad_personalization: { default: "denied", update: "granted" }
}
Consent Category: ad_storage
Output Format: String
Returns:
"default:denied|update:granted"
The template:
- Reads the
gcd
parameter from incoming requests - Parses the base64url-encoded consent string
- Extracts consent states using bitwise operations
- Returns formatted consent information
Based on your example: 13r3r3r3r5l1
┌───┬─────────┬─────────┬─────────┬─────────┬─────────────┬─────────────────────┐
│ 1 │( 3 | r )│( 3 | r )│( 3 | r )│( 3 | r )│ (5) │ ( 1 | l ) │
└───┴─────────┴─────────┴─────────┴─────────┴─────────────┴─────────────────────┘
Ver ad_storage analytics ad_user_data ad_personal Global Privacy Container Scoped
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ Controls Defaults
impl expl impl expl impl expl impl expl
Position: 1 2 3 4 5 6 7 8 9 10 11 12
String: 1 3 r 3 r 3 r 3 r 5 1 l
┌─┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌─────┐ ┌───────┐
│V│ │I│E│ │I│E│ │I│E│ │I│E│ │ GPC │ │ CSD │
└─┘ └───┘ └───┘ └───┘ └───┘ └─────┘ └───────┘
│ │ │ │ │ │ │ │ │ │ │ │
Version│ │ │ │ │ │ │ │ Global │ │
│ └─→ │ └─→ │ └─→ │ └─→ Privacy │ │
│ r │ r │ r │ r Controls │ l
│ │ │ │ │
ad_storage analytics ad_user Container
ad_personal Scoped
Defaults
consentString.substring(1, 3) → "3r" → pair[1] = 'r' // ad_storage
consentString.substring(3, 5) → "3r" → pair[1] = 'r' // analytics_storage
consentString.substring(5, 7) → "3r" → pair[1] = 'r' // ad_user_data
consentString.substring(7, 9) → "3r" → pair[1] = 'r' // ad_personalization
┌─────────────────┬─────────────────────────────────────────────┐
│ Component │ Description │
├─────────────────┼─────────────────────────────────────────────┤
│ 1 │ Version marker │
│ (3│r) │ Consent pair: Implicit│Explicit │
│ 5 │ Global Privacy Controls marker │
│ (1│l) │ Container Scoped Defaults (optional) │
└─────────────────┴─────────────────────────────────────────────┘
Value | Meaning |
---|---|
granted |
User has granted consent |
denied |
User has denied consent |
- |
Consent state not defined |
// Fire tag only if analytics consent granted
if ({{Consent Parser}}.analytics_storage.update === "granted") {
// Fire analytics tag
}
// Process data based on consent
const consent = {{Consent Parser}};
if (consent.ad_personalization.update === "granted") {
// Enable personalized features
}
// Log consent states for debugging
console.log("Current consent:", {{Consent Parser}});
Returns object with all consent categories:
{
ad_storage: { default: string, update: string },
analytics_storage: { default: string, update: string },
ad_user_data: { default: string, update: string },
ad_personalization: { default: string, update: string }
}
Returns single category data in chosen format:
Object format:
{ default: string, update: string }
String format:
"default:value|update:value"
- Returns
false
when nogcd
parameter exists - Returns
null
for invalid output format
The template includes comprehensive tests covering:
- ✅ Valid consent strings with all categories
- ✅ Single category extraction
- ✅ Missing parameter handling
- ✅ Object vs string format consistency
Run tests in GTM's template editor before deploying.
Returns false
- Check that
gcd
parameter exists in request - Verify Consent Mode v2 is properly implemented
Returns null
values
- Check
outputFormat
parameter is valid (object
orstring
) - Verify template configuration
Unexpected consent values
- Ensure Consent Mode v2 is correctly configured on client-side
- Check consent string format in browser network tab
- Check browser network requests for
gcd
parameter - Use GTM Preview mode to inspect variable values
- Enable debug logging in server container
The template uses a custom base64url (Safe) alphabet for decoding:
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_
For each consent category, the template:
- Extracts the second character from each 2-character pair
- Gets the base64url index value
- Uses bitwise operations to extract default and update values:
defaultVal = (value >> 2) & 3
(bits 2-3)updateVal = value & 3
(bits 0-1)
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Add tests for new features
- Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
For issues and questions:
- Open an issue on GitHub
- Contact Analytics Debugger S.L.U.
Created by Analytics Debugger S.L.U. - David Vallejo, 2025