Skip to main content
Google Consent Mode v2 lets you communicate your visitors’ consent choices to Google tags (Analytics, Ads, etc.). When integrated with Katla, consent decisions automatically update Google’s consent parameters - no manual gtag calls needed.

How it works

Katla maps its cookie categories to Google Consent Mode parameters: When a visitor grants or denies a category, the corresponding Google parameters are set to 'granted' or 'denied'. Categories without a Google equivalent (e.g. functional, personalization) are ignored. Consent Mode is two configurations, and this is the decision that matters most. Katla supports both; only one of them sends anything to Google before a visitor has answered. In advanced mode your Google tag loads for everyone and Consent Mode carries the decision. No cookie is written while consent is denied - Katla’s cookie guard sees to that, and the client id in the ping is minted fresh on each page load rather than stored - but a page_view still reaches Google carrying the visitor’s IP address, the full page URL and the page title. It keeps going on every page after the visitor clicks Reject, because rejecting denies storage and does not stop the tag that is already running. In basic mode the tag is not loaded at all until the category is granted. Google receives nothing, including nothing from visitors who decline.

Which one to pick

The distinction people expect to matter here - ePrivacy Article 5(3), the cookie rule - is not what separates them. That article governs storing information on a device or reading what is stored there, and a cookieless ping does neither. Article 6 is the question. An IP address plus every URL a person visits is personal data, so the transmission needs a lawful basis. You are not asking for consent, which leaves legitimate interest, and that balance is hard to sustain once the visitor has actively refused: Recital 47 makes their reasonable expectations part of the test, and nobody who has just clicked Reject All expects their browsing to keep reaching Google. Naming the transmission in your privacy policy answers Article 13. It does not answer Article 6 - disclosure is not a lawful basis. We run basic mode on katla.app, and recommend it if you have EU/EEA visitors. It costs conversion modelling and the pre-consent traffic estimate. Advanced mode is a defensible choice where those numbers matter to you and you have taken your own view on the Article 6 question - it is a choice, not a default.

Basic mode: gate your own tag

Katla signals consent either way. Basic mode is about your tag, so it is your embed that changes: load it from the consent state rather than on page load.
Leave Google Consent Mode enabled in your widget settings alongside this. The default is still declared before your tag can initialise, so a returning visitor who accepted gets granted from the first paint, and the update calls keep working for tags you load later. onConsentChange is a single callback slot rather than an event emitter, which is why the snippet keeps whatever was there and calls it first.

Basic mode in React

Do not declare a Consent Mode default of your own in either case. The widget declares it before your tag loads, and a second default arriving after Google’s tags have read the first can clobber it and re-deny a visitor who had already accepted.
Withdrawing consent stops further events, but it cannot unload a tag that is already running in the current page - nothing can. The next page load starts clean.

Widget setup

If you use the Katla widget (the <script> tag embed), enable Google Consent Mode in your site’s widget settings:
  1. Go to your site’s Widget Settings page
  2. Set Google Consent Mode to Enabled
  3. Save changes
The loader then declares the default consent state, and the widget calls gtag('consent', 'update', ...) when the visitor accepts or rejects categories.

Use the loader, not the single-language script

The consent default is declared by the loader at {siteId}.js, not by the engine it pulls in:
This matters more than it looks. The loader is a few hundred bytes and runs the moment it is parsed, so the default is declared before your Google tag initialises. The script it pulls in is around a hundred kilobytes and is deferred - on a real connection gtag.js routinely finishes first. Declaring consent from inside that script means Google has already initialised with its own implicit defaults, which it records as wasSetLate and which makes the first hits of a page view count as consented. You can verify either way with the free Consent Mode checker.

Inline it to win the race outright

Linking the loader still costs a connection to another origin before it can run, and on a cold connection that is enough to lose to a gtag.js that was preloaded or already cached. Pasting the loader into <head> removes the request, so the default is declared during parsing and nothing can get in front of it. Copy it from Install → Widget → Inline in your dashboard. This is the only install where the ordering is guaranteed rather than merely likely. Re-copy after changing your Consent Mode setting - a pasted copy is frozen.
This is the URL you already have in your page - {siteId}.js became the loader so that existing installs pick this up without being edited. The engine it pulls in still declares a default of its own when the loader has not already, so nothing regresses if you reach it directly.

Forcing a language

Pass locale to the loader to skip language detection:
Useful when you serve one market, or when your own routing already knows the visitor. An unrecognised value resolves to the closest language we publish, and to English if there is no such language.

What the default contains

All four Consent Mode v2 signals, plus a wait window:
For a returning visitor the loader reads their stored choice from the consent cookie and declares that as the default, so their first page view is measured with the consent they already gave rather than a blanket deny they have to re-answer. region is deliberately not set: the default applies everywhere, which is stricter than scoping it to the EEA and never less compliant. If you measure outside the EEA and want the looser behaviour there, set it yourself on your own tag.

React setup

If you use the @katla.app/sdk React integration, add the <GoogleConsentMode /> component alongside your existing setup:
The component:
  • Sets gtag('consent', 'default', ...) on mount with all parameters denied (or granted if consent already exists)
  • Listens for katla:consent events and calls gtag('consent', 'update', ...) automatically
  • Cleans up the event listener on unmount

Vanilla JavaScript setup

For non-React apps using the SDK directly:
setupGoogleConsentMode() returns a cleanup function that removes the consent change listener. Every gtag('consent', 'update', ...) Katla sends is followed by a plain dataLayer event carrying the same state:
Google’s own tags follow a consent update by themselves. Other tags in a tag manager do not: a consent command has no event name, so no trigger can fire on it, and a tag that was held back while consent was denied waits for the next page view. The page it misses is the one your visitor landed on. In Google Tag Manager, create a Custom Event trigger named consent_update and a Data Layer Variable for the signal a tag depends on, such as consent_state.ad_storage. Fire the tag when that variable equals granted. The event is sent whenever an update is:
  • On a choice. When a visitor accepts, rejects or changes their categories. A refusal sends it too, with every value denied.
  • On page load, with the Google Tag Manager template. That install declares a denied default and replays a returning visitor’s stored choice as an update, so the event follows on every page view.
  • Not on page load with the widget script tag. The loader makes the stored choice the default, so there is no update to follow.
The widget sends the event from guard script version 4 (KatlaConsent.version).

CCPA mode behavior

When the widget operates in CCPA mode and a visitor opts out of the sale/sharing of personal information, the following Google Consent Mode parameters are set: This differs from a GDPR “Reject All” which denies all parameters including analytics.

Verification

Use Google Tag Assistant to verify that consent signals are being sent correctly:
  1. Install the Tag Assistant browser extension
  2. Load your page with Katla and Google Analytics/Ads
  3. Check the Consent tab - you should see a default event with all parameters set to denied
  4. Accept cookies in the Katla widget
  5. Verify an update event appears with the appropriate parameters set to granted