Skip to content
pixelary Docs

Consent & banners

Consent Mode v2 IAB TCF 2.2 GPC

Pixelary sends nothing a visitor has declined. It reads the answer from your cookie banner before any pixel loads or any event leaves the page.

Visitors from Europe need a consent banner

In the EEA, the UK and Switzerland, Pixelary waits for the visitor’s yes. Without a banner nobody answers, so those visitors are not tracked: no pixels, no server events. This applies to new sites and to sites moved from the Framer plugin alike.

What each consent type controls

Pixelary uses the four types of Google Consent Mode, whichever banner the answer comes from.

TypeWithout it
ad_storagePlatform pixels don’t load, and the ad cookies (_fbp, _fbc, _ttp, ttclid, __oppref, __obref) are neither written nor read.
ad_user_dataNo customer data or hashes go anywhere, and no server copy is sent.
ad_personalizationPassed on to the platforms. For ChatGPT Ads a denial sets opt_out.
analytics_storageNo Pixelary session summary on free sites.

Before the visitor answers

Events that happen before the visitor answers wait on the page. If the visitor accepts, they go out with the time they happened. If the visitor declines or leaves, they are dropped.

  • EEA, UK and Switzerland: nothing is granted until the visitor says yes. The script counts a visitor as there when their IP country (which Cloudflare reports when it delivers the script) or the browser’s time zone is in that region, and our server checks the country again: a server event from there without consent is dropped.
  • Elsewhere: consent counts as granted unless your banner, your Google Consent Mode defaults, your settings in the dashboard or the visitor’s Global Privacy Control say otherwise.

The defaults per region can be changed in the dashboard, on the Consent screen.

Where Pixelary reads consent

For each consent type, the strongest source that has an answer wins:

  1. Your own code, pixelary("consent", …), and the GTM template. Once one of these sets a type, banners no longer change it on that page.
  2. IAB TCF 2.2 (__tcfapi).
  3. Google Consent Mode updates in dataLayer.
  4. Supported banners, read directly (table below), then the Framer cookie banner.
  5. Global Privacy Control (navigator.globalPrivacyControl), as a decline until the visitor answers your banner.
  6. Google Consent Mode defaults set before anyone answered.
  7. Your site’s defaults from the dashboard, then the region rule above.

Supported banners

BannerHow Pixelary reads it
CookiebotMarketing → ads, statistics → analytics. Follows changes.
OneTrustTargeting and Performance groups: C0004 and C0002 by default, 4 and 2 on older accounts. Groups with other IDs are found by name. Follows changes.
CookieYesAdvertisement and analytics categories. Follows changes.
UsercentricsBrowser UI v2 directly. CMP v3 through the Consent Mode it sets.
ComplianzMarketing and statistics. Follows changes.
iubendaThe saved preference when the page loads. For changes during the visit, enable Consent Mode in iubenda.
TermlyAdvertising and analytics categories.
OsanoMarketing and analytics. Follows changes.
CookieFirstAdvertising and performance categories. Follows changes.
Framer cookie bannerMarketing and analytics, read from the banner directly. Works with or without a GTM ID.
DidomiThrough IAB TCF 2.2.
Any banner with Google Consent Mode v2 or IAB TCF 2.2Read through Consent Mode or TCF.

Klaro, Axeptio and others that ask per service rather than per category are not read directly. If they set Google Consent Mode, that works; otherwise pass the answer from code as below.

Any other banner

Call pixelary("consent", …) from your banner’s accept and reject callbacks:

JavaScript
// Your banner's callbacks; the names depend on the banner.
banner.onAccept(() => {
  pixelary("consent", {
    ad_storage: "granted",
    ad_user_data: "granted",
    ad_personalization: "granted",
    analytics_storage: "granted",
  });
});

banner.onReject(() => {
  pixelary("consent", {
    ad_storage: "denied",
    ad_user_data: "denied",
    ad_personalization: "denied",
    analytics_storage: "denied",
  });
});

Pass only the types you know; the others stay as they were. Repeating the same answer does nothing. If your code may run before the Pixelary script, add the queue stub from the HTML snippet guide.

Sites that used the Framer plugin’s window.ft.setConsent(true) keep working: it sets all four types at once.

If your banner supports Google Consent Mode, set the defaults before any tag runs, usually in the banner’s own snippet. Pixelary reads them and then follows each update:

HTML
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag() { dataLayer.push(arguments); }
  gtag("consent", "default", {
    ad_storage: "denied",
    ad_user_data: "denied",
    ad_personalization: "denied",
    analytics_storage: "denied",
  });
</script>

With Google Tag Manager

The Pixelary template passes GTM’s consent state by default. If your site doesn’t use Consent Mode, GTM reports everything as granted, so uncheck Pass Google Consent Mode state on the Pixelary tags and let Pixelary read the banner itself. Consent in Tag Manager

Check it on your site

Open your site with ?pixelary_debug=1 added to the address. The browser console logs every command and event Pixelary handles, and whether an event went out or is waiting for consent. Try accepting and declining in a private window: after a decline, no requests to the pixel domains should appear in the Network tab.

Something here doesn’t match what you see? Write to hello@pixelary.app.