Installing ConsentChecks
How to put the consent banner on a site, how consent reaches GTM and every common tracking pixel — Meta, TikTok, LinkedIn, Hotjar and more — and the checklist that proves it works before launch.
1 · Install — 5 minutes
Copy the embed code. Dashboard → Sites → your site → Embed code:
<!-- Place above your GTM snippet --> <script src="https://app.consentchecks.com/cc.js" data-site="YOUR_SITE_KEY"></script>Paste it in the page
<head>, above the GTM snippet. The order is load-bearing: ConsentChecks must set consent defaults before GTM boots. Don't addasyncordefer.Register every hostname under Dashboard → site → Domains.
www.example.comandexample.comare separate entries. Consent logging is rejected (HTTP 400) from unregistered hostnames.#1 cause of "I accepted but see no logs."If the www variant isn't registered, every consent click is dropped by design.Remove any other consent tool (iubenda, CookieYes, OneTrust…). Two CMPs fight over the same Google signals.
Purge page caches (WP Engine, LiteSpeed, Cloudflare APO…). Cached HTML won't contain the snippet.
2 · How consent reaches GTM
Three mechanisms run at once. Use whichever fits each tag.
A — Google Consent Mode v2 (automatic)
Before GTM loads, ConsentChecks sets consent defaults: denied in opt-in regions (EU/UK/CH), granted under the US opt-out model until the visitor objects. When a visitor chooses, category keys map to Google's signals:
| Category key | Google signals |
|---|---|
| analytics | analytics_storage |
| marketing | ad_storage · ad_user_data · ad_personalization |
| preferences | personalization_storage |
| always granted | functionality_storage · security_storage |
GA4, Google Ads and Floodlight obey these natively — no GTM changes needed. Denied analytics_storage means GA4 runs cookieless; granted means full tracking.
analytics, marketing or preferences drive Google signals. Custom categories still work with B and C.B — dataLayer events (for everything else)
On every consent decision ConsentChecks pushes cc_consent_update (with cc_granted / cc_denied arrays) plus one cc_<category>_granted event per granted category.
Recipe — gate a Meta pixel on marketing consent:
GTM → Triggers → New → Custom Event → event name
cc_marketing_granted→ fires on All Custom Events.Open the pixel's tag → Triggering → replace All Pages with this trigger.
Done — the tag cannot fire until marketing is granted. The event re-fires on every page load for returning visitors, so page-view pixels keep working.
Want GA4 fully silent on reject (not even cookieless pings)? Tag → Consent Settings → Require additional consent → analytics_storage, or use the trigger recipe.
C — outside GTM entirely
- Custom scripts (Dashboard → site → Custom scripts): JS that runs when its category is granted, once per page load.
- Gated markup:
<div data-cc-show="marketing" hidden>…</div>shows only with consent;data-cc-hideis the inverse. Ship thehiddenattribute so nothing flashes.
3 · Platform recipes
The pattern is always the same: pick the category, then gate the tag through GTM (custom-event trigger) or through ConsentChecks itself (Custom scripts).
| Platform | Category | How to gate it |
|---|---|---|
| GA4 · Google Ads · Floodlight | analytics / marketing | Nothing to do — Consent Mode v2 governs them automatically (GTM or direct gtag.js, kept below the ConsentChecks script). For full silence on reject, gate with cc_analytics_granted or the tag's Require additional consent. |
| Meta (Facebook) Pixel | marketing | In GTM: Custom Event trigger cc_marketing_granted on the pixel tags. Hardcoded: move the base pixel into Dashboard → Custom scripts under marketing. Advanced: fbq('consent','revoke') at load + 'grant' from a gated script, only if you need Meta's limited-data mode. |
| TikTok Pixel | marketing | GTM trigger on cc_marketing_granted, or base snippet as a Custom script. |
| LinkedIn Insight | marketing | Same: GTM trigger or Custom script. |
| Pinterest · X · Snap | marketing | Same pattern. |
| Hotjar · MS Clarity | analytics | Session recording counts as analytics: cc_analytics_granted trigger, or Custom script under analytics. |
| Chat widgets (Intercom, Drift, Tawk…) | preferences / custom | Custom script under preferences, or a dedicated category (e.g. chat). Custom keys don't drive Google signals but gate scripts, events and markup the same. |
Anything else: decide the category (advertises → marketing, measures → analytics, personalizes → preferences); in GTM use a cc_<category>_granted trigger; hardcoded snippets move into Custom scripts; visible UI can be wrapped in <div data-cc-show="…" hidden>.
4 · US specifics
- GPC is automatic: visitors with Global Privacy Control are opted out of all non-required categories and logged as
gpc_optout. Nothing to configure. - "Do Not Sell or Share": enable Show floating preferences badge in site settings, or add a footer link:
<a href="#" onclick="window.ConsentChecks.open();return false"> Do Not Sell or Share My Personal Information</a>window.ConsentCheck(no "s") keeps working as a permanent compatibility alias.
5 · Verify before launch — 10 minutes
Snippet placement. View source:
cc.jsabove GTM, no async/defer. Missing → page cache or publish state.Banner shows. Fresh incognito window → banner appears (US visitors see it too).
Consent round-trip. DevTools → Network → filter
cc/log→ Accept all → POST returns 204. A 400 means the hostname isn't registered. Thendocument.cookiecontainscc_consent_<sitekey>; reload → no banner.Log recorded. Dashboard → Logs: the accept appears within seconds.
Google signals. Connect tagassistant.google.com → Consent tab: denied before the choice, granted after Accept; gated tags fire;
cc_*events visible in the stream.Reject path. Fresh incognito → Reject all: signals stay denied, gated tags silent,
reject_allrow in Logs.GPC. Firefox →
about:config→privacy.globalprivacycontrol.enabled= true → visit: agpc_optoutrow appears with no click.Re-open. Console:
window.ConsentChecks.open()shows preferences; a changed choice logs anupdateaction.getConsent()prints granted keys.Pixels. Install the platform's helper extension (Meta Pixel Helper, TikTok Pixel Helper): the pixel is absent before consent and fires after Accept.
6 · Troubleshooting
| Symptom | Cause → fix |
|---|---|
| No banner | Snippet not in served HTML (cache / unpublished), visitor already has a consent cookie (use incognito), or geo mode none |
| Accepts but Logs stay empty | 400 origin not allowed — register the exact hostname (www and apex separately) under site → Domains |
| Tags fire before any choice | Snippet below GTM, or tag lacks a consent check / cc_* trigger |
| Banner reappears every visit | Cookies blocked in that browser, or policy_version was bumped (that re-prompt is intentional) |
| New banner settings not live | Cloudflare still caching cc.js (purge it) and/or the site's own page cache |
| GA4 shows traffic from rejecters | Consent Mode's cookieless pings (by design, no cookies). For full silence, gate GA4 with cc_analytics_granted |