Server-Side Tagging Does Not Remove Consent: The gcs and gcd Signals That Carry It

The pitch is seductive: move your tags server-side and the consent problem goes away, because nothing runs in the browser anymore. It does not go away. The browser still sends the data to your server, your server still forwards it to Meta and TikTok, and the law cares about who receives personal data and what they do with it, not about where your code runs. Server-side tagging changes where tags execute. It does not change whether they need consent.

What server-side actually changes

Server-side tagging moves tag execution off the device. The browser sends a single request to your server container, usually on a first-party subdomain like sgtm.yourdomain.com, and your server fans the data out to the vendors. The browser only ever talks to your own domain, which defeats ad blockers that filter third party requests and keeps the page lighter. That is a real benefit, and it is the only benefit that is automatic. What does not change is the data flow: you are still sending a user behavioural data to Meta, to Google, to TikTok, for advertising and analytics purposes. Consent law cares about that, about who receives personal data and what they do with it, not about where your code runs. The ePrivacy Directive Article 5(3) requires consent before storing information on, or gaining access to information already stored on, a user terminal, and the EDPB Guidelines 2/2023 on the technical scope of Article 5(3) apply it to pixels, tracking links, and identifiers as well. Moving the tag to a server you control does not touch that requirement.

The consent state travels to the server container inside each request, as two encoded parameters on the Google hit. gcs, the Google Consent State, format G1xy, where x is ad_storage and y is analytics_storage, 1 granted and 0 denied: G100 is both denied, G101 is analytics granted, G110 is ads granted, G111 is both granted. gcd, the Google Consent Default, encodes all four v2 parameters and the journey each took, with letters describing how the state was reached: l means defaulted to denied and never updated, the user never touched the banner; q means defaulted denied then updated to granted, the user accepted; t means defaulted granted with no update, a region where consent is not required. Both parameters travel inside the /g/collect request from the browser to your server endpoint, and the GA4 Client in the server container decodes them and exposes the consent state to your tags as event data.

The part that is less consent aware by default

In the browser container, Google tags have consent checks built in. Consent Mode is native there: you configure defaults, your CMP updates them, and Google tags respect the state automatically. Move to the server container and that built-in awareness only partially carries over. The GA4 Client in the server container can read Google consent signals automatically, and Google server-side tags will respect them. But every non-Google tag in that server container, Meta Conversions API, TikTok Events API, LinkedIn Conversions API, Pinterest, any custom HTTP tag, has zero awareness of consent unless you build it in. They do not read Google consent parameters. They fire unconditionally. A server container with Meta CAPI and no consent gating is forwarding behavioural data for every visitor, including the ones who rejected, and the CMP on the site has no idea it is happening, because the CMP lives in the browser and the forwarding happens on your server. That is the failure that ships most often, and it is invisible from the browser: the network tab shows one request to your own subdomain, and the forwarding to Meta happens where no browser tool can see it.

The gate belongs in the browser, not the server. Your CMP captures the choice, Consent Mode records it, and the browser gates behaviour accordingly. The server container only ever receives what the browser already sent. If the browser sends an event for a visitor who rejected, the server has to decide per destination whether to forward, strip, or drop, and a container receiving no consent signal defaults to forwarding. Build the consent aware trigger for every non-Google tag, test all four consent states, and test the withdrawal path: Article 7(3) requires withdrawing consent to be as easy as giving it, so a withdrawal has to reach the container and stop the forwarding, not just hide the banner.

The fine that sets the stakes

France's CNIL fined Google 325 million euros and SHEIN 150 million euros in September 2025 for placing cookies before consent, and that is the scale of the refusal path. Server-side tagging does not reduce that exposure, because the exposure was never about where the tag runs. It was about whether the data moved before the visitor chose. Audit the server container the way you audit the browser: list every destination, check each one for a consent gate, and prove the gate works by rejecting everything and watching what still arrives. If Meta still receives the purchase event after a rejection, the gate is missing, and the server-side migration made the problem harder to see, not smaller.

Keep reading: Consent Banners on the Checkout: The Conversion Hit Nobody Attributes, Consent Nudging: The Dark Patterns Regulators Are Now Fining, How long to keep consent records: retention without hoarding.

Frequently asked questions

What are the gcs and gcd parameters?

gcs is the Google Consent State, format G1xy, where x is ad_storage and y is analytics_storage, 1 for granted and 0 for denied. G100 means both denied, G111 means both granted. gcd is the Google Consent Default, which encodes all four v2 parameters and the journey each took, with letters like l for defaulted denied and never updated, and q for defaulted denied then updated to granted.

Do non-Google tags in a server container respect consent automatically?

No. Google tags in the server container, GA4, Google Ads, Floodlight, read the consent signals automatically. Every non-Google tag, Meta Conversions API, TikTok Events API, LinkedIn Conversions API, Pinterest, or any custom HTTP tag, has zero awareness of consent unless you build it in. They do not read Google consent parameters, and they fire unconditionally.

Does moving tracking server-side remove the need for consent?

No. Server-side tagging changes where data is processed, not what needs consent. Consent law cares about who receives personal data and what they do with it, not about where your code runs. The ePrivacy Directive Article 5(3) requires consent before storing or accessing information on a visitor device, and the GDPR Article 6 requires a legal basis for processing. Moving the tag to your server satisfies neither.

Where should the consent gate live, browser or server?

In the browser. Your CMP captures the choice, Consent Mode records it, and the browser gates behaviour accordingly. The server container only ever receives what the browser already sent, and it has no independent way to know the consent state. A container receiving no consent signal defaults to forwarding, which is the failure that ships most often.