See what I see — flip the site into its own live test environment: dataLayer, event schemas, measurement grid.
Server-side GTM consent forwarding patterns
last verified · against Google Tag Platform consent and sGTM docs as of 2026-07
Reference for server-side GTM consent forwarding: gcs and gcd HTTP parameters, x-ga event-data keys, native versus custom tag gating, and denied-state behavior.
What this is
Server-side consent forwarding is the mechanism by which a website’s Consent Mode state travels from the browser to a server-side Tag Manager container as HTTP request parameters, where it becomes event-data keys that tags read to adjust or suppress the data they send. Native Google server tags honor the forwarded state automatically; custom and non-Google server tags must be gated manually, because the server-side sandbox exposes no consent API.
Reference tables
Consent types
Every type carries a state of granted or denied. The cited sources describe four of the seven in detail.
Consent type
Purpose (per cited docs)
ad_storage
Advertising storage such as cookies
ad_user_data
Consent to send user data to Google for online advertising
ad_personalization
Consent for personalized advertising
analytics_storage
Analytics storage
functionality_storage
Not described in the cited sources
personalization_storage
Not described in the cited sources
security_storage
Not described in the cited sources
Consent flow to the server container (3 steps)
Step
Where
What happens
1
Browser
Consent banner sends the user’s choices to the Google tag
2
Browser to server
Google tag adds consent parameters to the HTTP request to the server container
3
Server container
Google product tags are consent-aware and adjust the amount and kind of data they send
Outgoing HTTP consent parameters
Parameter
Carries
Always sent?
gcs
ad_storage plus analytics_storage consent
Only with consent mode active
gcd
Detailed consent across all consent types
Always, even without consent mode
dma
Consent HTTP parameter; not described in the cited sources
Mapping: the outgoing gcs reads as x-ga-gcs in event data; gcd as x-ga-gcd; dma as x-ga-dma; dma_cps as x-ga-dma_cps. The internal-parameters reference publishes only Name, Type, and Products (no value decoding) and warns that names, types, and products are subject to change.
Value-decoding note: Google does not publish the bit-level structure of gcs (the community G1XY scheme) or the base64 layout of gcd. Any value-to-category mapping is community reverse-engineering and may change without notice; treat it as unofficial.
Per-product behavior when consent denied (server-side)
Server tag
Denied signal
Behavior
GA4
analytics_storage
Cookieless measurement (advanced mode) or fully blocked (basic mode)
Google Ads Conversions
ad_storage
No Ads cookies read or written; cookieless conversion pixel sent to a domain without third-party cookies
Notes: read APIs require the access_consent permission with read access; setDefaultConsentState and updateConsentState require access_consent write access. isConsentGranted returns true when the type is granted OR unset. setDefaultConsentState optional fields are region (array of ISO 3166-2 codes) and wait_for_update (milliseconds). The listener in addConsentListener is invoked with (consentType, granted).
Web-side knobs that shape the payload before it leaves the browser
Setting
Effect when ad_storage denied
Scope
ads_data_redaction=true
Redacts ad-click identifiers (GCLID / DCLID) in pings and drops third-party cookies
Web / client (gtag)
url_passthrough=true
Passes ad-click info (e.g. gclid) via URL parameters across pages
Web / client
Server-side consent design must assume the incoming payload was already shaped by these; they are not server-container settings.
Tag-level consent controls (web container UI)
Control
Meaning
Built-in consent checks
Template is itself consent-aware; Google tags check analytics_storage, ad_storage, ad_user_data, ad_personalization
Additional consent checks
Tag fires only if all listed consent types are granted
Gotchas
Server tags send full data despite on-site denial. Cause: the consent state never reached the server, either because the web Google tag is not forwarding gcs/gcd, or, for custom tags, because nothing in the container reads it. Fix: confirm the web Google tag forwards gcs/gcd to the container URL; for non-Google tags, read consent from event data and gate manually.
A server variable referencing gcs returns undefined or empty. Cause: in event data the key is namespaced x-ga-gcs; the raw gcs name exists only as the outgoing HTTP parameter. Fix: reference x-ga-gcs (and x-ga-gcd) as the event-data key.
Calling isConsentGranted() or addConsentListener() in a server template fails. Cause: those consent APIs exist only in web and client templates; the server sandbox exposes none. Fix: derive consent from request or event data (parse x-ga-gcs, or read a custom header or cookie) and implement gating manually.
Some events arrive with no gcs or consent signal at all. Cause: the source is not running Google consent mode (custom clients, Measurement Protocol, non-consent-mode sites), or the site is on basic mode where nothing is sent pre-interaction. Fix: handle the missing case explicitly with a deliberate fallback, treating it as denied for safety or as configured.
isConsentGranted() returns true although consent was never set. Cause: it returns true when the type is granted OR unset. Fix: always call setDefaultConsentState with explicit denied defaults before the user interacts, so an unset type does not read as granted.
Reporting or attribution looks degraded or modeled after enabling consent mode. Cause: denied storage means cookieless pings, and Google fills gaps via modeling that requires data thresholds. Fix: this is expected behavior, not a bug; ensure advanced mode is configured, confirm traffic meets thresholds, and communicate the modeled nature of the numbers to stakeholders.
Quick recipes
read-forwarded-consent.js
constgetAllEventData=require('getAllEventData');
constevent=getAllEventData();
constgcs= event['x-ga-gcs']; // outgoing gcs, namespaced in event data