ServicesAboutNotesContact Get in touch →
EN FR
Note

Consent Mode Server-Side GTM Propagation

How consent signals travel from the web container to server-side GTM via gcs and gcd parameters, and why non-Google vendor tags require manual consent enforcement.

Planted
ga4google adsanalyticsdata quality

Server-side GTM has no built-in Consent Mode. The web container handles consent natively. The server container receives consent state as encoded HTTP parameters and must be configured to respect them — automatic for Google tags, manual for all other vendors.

When the web container sends a request to your server-side GTM endpoint, it encodes the current consent state into HTTP request parameters. Two parameters carry this information:

gcs (Google Consent State) encodes the v1 consent parameters. The format is G1xy where:

  • x = ad_storage consent (1 = granted, 0 = denied)
  • y = analytics_storage consent (1 = granted, 0 = denied)

So gcs=G111 means both ad_storage and analytics_storage are granted. gcs=G100 means both are denied.

gcd (Google Consent Default) encodes all four v2 parameters along with their consent journey. Each parameter position gets a letter indicating how the consent state was reached:

  • l = default denied, no update received (user hasn’t interacted with the banner)
  • q = default denied, then updated to granted (user accepted)
  • t = default granted, no update received (region where consent isn’t required, or defaults misconfigured)
  • p and r = intermediate states

These parameters are part of the HTTP request payload — they travel alongside the event data in the /g/collect request from the browser to your server container endpoint.

Google Tags: Automatic Handling

The GA4 Client in your server container reads gcs and gcd parameters automatically from incoming requests. It decodes the consent state and makes it available to server-side tags.

Google product tags (GA4, Google Ads, Floodlight) in the server container then adjust their behavior based on the decoded consent state. If ad_user_data is denied, the Google Ads Conversion Tracking tag won’t include personal data in the request it forwards to Google. If analytics_storage is denied, the GA4 tag adjusts its cookie behavior.

This automatic chain works without any additional configuration, as long as:

  1. The web container is correctly setting consent defaults and processing CMP updates (see Consent Mode Implementation Mechanics)
  2. The web container’s HTTP requests to the server container aren’t being modified by intermediate proxies, CDNs, or load balancers that strip query parameters
  3. The GA4 Client in the server container is the one claiming the incoming requests

Non-Google Tags: The Manual Gap

Here’s where most server-side consent implementations break. Non-Google vendor tags in the server container — Meta Conversions API, TikTok Events API, LinkedIn CAPI, Pinterest API, and any custom HTTP request tags — have zero awareness of Google’s consent parameters. They don’t read gcs or gcd. They fire unconditionally unless you build explicit consent checks.

This creates a compliance gap. A user in France denies consent. The web container respects this: it sends cookieless pings with gcs=G100. The GA4 Client receives the request and correctly marks consent as denied. The GA4 server-side tag adjusts its behavior. But the Meta CAPI tag, sitting in the same server container, fires its event to Meta’s servers with whatever data it has — potentially including the user’s IP address, user agent, and any other event data that arrived in the request.

The user denied consent. Your Google tags respected it. Your Meta tag ignored it.

To enforce consent for non-Google vendor tags, you need trigger conditions that evaluate consent state before the tag fires.

In server-side GTM, you can access the decoded consent state through event data. The GA4 Client parses gcs and gcd and exposes consent information. Create a Variable of type “Event Data” that reads the consent state, then use it as a trigger condition:

Trigger: Custom Event
Condition: x-ga-gcs matches RegEx G1[1][1]

This ensures the tag only fires when both ad_storage and analytics_storage are granted. For v2 parameters, you’ll need to parse the gcd parameter for the specific parameter positions.

A More Robust Approach

A cleaner pattern is to create a custom variable template or use a community template that parses the full consent state and returns individual parameter values. Then your trigger conditions become explicit:

Tag: Meta CAPI - Purchase Event
Trigger conditions:
- Event Name equals "purchase"
- ad_user_data equals "granted"
- ad_storage equals "granted"

This makes consent enforcement visible and auditable. Each non-Google tag has explicit trigger conditions documenting which consent signals it requires.

Some server-side tag templates (particularly newer ones built with consent awareness) accept consent state as input parameters. If your Meta CAPI template supports it, pass the consent state from the parsed event data directly into the tag configuration. The tag can then make its own decisions about what data to include or suppress.

Stripped parameters. If your server container is behind a CDN or reverse proxy that modifies query strings, gcs and gcd might get stripped or truncated. Verify by inspecting the incoming request in server-side GTM’s Preview mode — look for both parameters in the event data.

Wrong Client claiming the request. If you have multiple Clients in your server container and the wrong one claims the incoming request, consent parameters may not be parsed correctly. The GA4 Client specifically knows how to decode Google’s consent encoding. A generic HTTP Client won’t.

Assuming server-side means consent is handled. Some teams implement server-side GTM partly for privacy reasons and assume the server container inherently handles consent. It doesn’t. Moving tags server-side changes where they execute, not whether they respect consent. Without explicit configuration, server-side tags are less consent-aware than client-side tags, not more.

Case sensitivity in trigger conditions. Server-side GTM trigger conditions are case-sensitive. If your GA4 Client is named ga4 but a trigger condition checks for GA4 in the Client Name field, nothing fires. This breaks your entire server-side setup, consent and all.

The Compliance Posture

For a complete compliance infrastructure, every server-side tag should have documented consent requirements. Build a mapping:

Server-Side TagRequired Consent SignalsBehavior When Denied
GA4analytics_storageAutomatic (via GA4 Client)
Google Adsad_storage, ad_user_dataAutomatic (via GA4 Client)
Meta CAPIad_storage, ad_user_dataManual trigger condition required
TikTok Events APIad_storage, ad_user_dataManual trigger condition required
LinkedIn CAPIad_storage, ad_user_dataManual trigger condition required

This mapping becomes your audit artifact. When a privacy review asks “how do you enforce consent for Meta server-side events?”, the answer is documented in your server container configuration, not in a policy document that may not reflect reality.