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.
Basic or advanced: whether the tag loads before consent
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.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
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:
- Go to your site’s Widget Settings page
- Set Google Consent Mode to Enabled
- Save changes
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:
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 agtag.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
Passlocale to the loader to skip language detection:
What the default contains
All four Consent Mode v2 signals, plus a wait window: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:
- Sets
gtag('consent', 'default', ...)on mount with all parameters denied (or granted if consent already exists) - Listens for
katla:consentevents and callsgtag('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.
The consent_update event
Everygtag('consent', 'update', ...) Katla sends is followed by a plain dataLayer event
carrying the same state:
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.
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:- Install the Tag Assistant browser extension
- Load your page with Katla and Google Analytics/Ads
- Check the Consent tab - you should see a
defaultevent with all parameters set todenied - Accept cookies in the Katla widget
- Verify an
updateevent appears with the appropriate parameters set togranted