Server-side GTM
Bridge the CookieLint consent state into your server-side Google Tag Manager container via the cl_consent_state cookie.
How it works
The CookieLint banner writes a first-party cookie called cl_consent_stateon the visitor's browser, scoped to the registrable apex of the page. Every subdomain of that apex sees the cookie on every request, including a server-side Google Tag Manager container running on a sibling subdomain (eg tags.acme.com).
The cookie format is a single URL-encoded line:
v=1&site=<publicKey>&cfg=<bannerConfigVersion>&grants=<COMMA-SEPARATED-CATEGORIES>A sGTM Variable template parses that line, maps the granted categories to Google Consent Mode v2 signals, and exposes the result to your downstream tags. You write no code; you import the template, point a Variable at it, and reference the Variable from any tag that should respect consent.
Prerequisites
Two preconditions for the cookie to cross subdomain boundaries:
- Same registrable apex. The banner page and the sGTM container must share an apex.
www.acme.com+tags.acme.comworks.www.acme.com+tags.gtm-server-abc.appspot.comdoes not. The cookie'sDomainattribute is set to the registrable apex; the browser will not send it to a foreign apex. - Banner 0.2 or later. Older builds wrote the cookie host-scoped (no
Domainattribute). A sibling subdomain liketags.acme.comnever received the cookie. Update the banner.
If you use Stape or Addingwell, point your custom domain (eg tags.acme.com) at their provided server. The Variable template works identically; the host has to be on your apex.
Install the Variable template
The repo ships three Custom Templates that work together:
- Web GTM Tag: CookieLint Banner —
CookieLint-plugins/gtm/banner-tag/template.tpl. Loads the banner from inside web-side GTM and (optionally) pushes the Consent Mode v2 default-deny state before the banner script reaches the browser. - Web GTM Variable: CookieLint Consent State —
CookieLint-plugins/gtm/consent-variable/template.tpl. Reads the cookie in the page-side GTM container. - Server GTM Variable: CookieLint Consent State (Server) —
CookieLint-plugins/sgtm/consent-variable/template.tpl. The one this page is about. Reads the cookie on incoming sGTM requests.
Server-side install:
- In the sGTM Server container go to Templates in the left sidebar.
- Under Variable Templates, click New.
- From the three-dot menu in the top right, choose Import.
- Select
sgtm/consent-variable/template.tpl. - Save the template.
- Create a Variable that uses it. Pick the output mode you need: most customers want
gcmStatefor the GA4 tag's consent settings,isGrantedfor per-tag Trigger conditions.
Wire it into GA4
The standard pattern: gate the GA4 Server tag's firing on a Trigger that checks for granted ANALYTICS consent.
- Create a Variable using the template. Set Output mode to
isGranted, Category toANALYTICS. Name itCL Analytics Granted. - Create a Trigger of type Custom with condition
CL Analytics Granted equals true. Name itCL Consent — Analytics. - Edit the existing GA4 (Server) tag. Change its Firing Trigger to
CL Consent — Analytics. The tag now only fires when the visitor has consented to ANALYTICS.
For Google Consent Mode v2 native flow, also add a Variable in gcmState output mode and reference it from the GA4 tag's Event data map under the key consent. Google's edge will respect the signal even on tags that fire.
Wire it into Meta Conversions API
Meta does not have a Google-style Consent Mode equivalent. The right pattern is do not fire the tag when MARKETING consent is denied.
- Create a Variable with Output mode
isGranted, CategoryMARKETING. Name itCL Marketing Granted. - Trigger your Meta CAPI tag only when
CL Marketing Granted equals true.
The same pattern works for TikTok Events API, LinkedIn Insight, and Microsoft UET.
Failure modes
When the cookie is missing or malformed the Variable returns a configurable fallback. Two modes:
- denyAll (default) —
isGrantedreturnsfalsefor every category exceptNECESSARY;grantedListis empty;gcmStatematches the default-deny shape (security_storagegranted, everything else denied). - allowNecessary — same as denyAll but treats
NECESSARYas granted. Same result in practice because NECESSARY is always granted regardless.
Both modes return the same conservative state in steady operation. The selector exists so future failure modes (allow-analytics, gate-on-region) can land without breaking existing customers.
Verify the integration
In sGTM Preview, send a request from a browser where the banner has been answered:
- Open the banner page; accept or reject in the banner.
- Open browser devtools, inspect cookies. Confirm
cl_consent_stateexists with aDomainattribute matching your registrable apex (eg.acme.com). - Fire any tracked event that hits sGTM. Open sGTM Preview — the request inspector should show the cookie among the incoming headers, and the CookieLint Consent State (Server) Variable should resolve to a non-empty siteId plus the expected grant list.
- Flip a category in the banner. Refresh. The next sGTM request shows the updated grant list.
If the Variable always resolves to the failure fallback the cookie is not reaching the container. The cause is almost always one of the two prerequisites above: wrong apex or banner version.

