Documentation · Consent API
Consent API on Admaxxer
GDPR / CCPA / state-privacy laws require explicit user consent before tracking. The Admaxxer pixel exposes a JS API for cookie-banner integration: admaxxer.optIn() after the user accepts, admaxxer.optOut() after they decline, and admaxxer.hasOptedIn() for any custom analytics layer that needs to gate its own behaviour. The requireConsent: true init flag puts the pixel in buffer mode at startup — events queue in memory but don't transmit until consent is granted. Drop-in compatible with OneTrust, Cookiebot, and custom banners.
The 3-method API
Three functions, all synchronous, all callable at any point in the page lifecycle — even before the pixel has finished booting (calls queue and replay).
// The 3-method JS API. Available on window.admaxxer once the pixel boots.
admaxxer.optIn();
// Clears the opt-out cookie.
// Drains the in-memory event buffer (when requireConsent: true was set).
// Future events transmit normally.
admaxxer.optOut();
// Sets the opt-out cookie with Max-Age 31536000 (1 year).
// Clears localStorage (visitor_id, click-IDs, first-touch UTMs).
// Drops any in-memory buffer.
// Future events are no-ops client-side.
admaxxer.hasOptedIn();
// Returns true when the opt-out cookie is absent (default).
// Returns false when the opt-out cookie is set.
// Synchronous; safe to call before the pixel has finished booting.
The requireConsent: true flag
Without this flag, the pixel transmits events the moment they fire. With requireConsent: true, the pixel is in buffer mode at startup:
- Bootstrap mints
visitor_idlocally but does NOT transmit any event. - Events queue in an in-memory buffer (cap: 50; oldest dropped on overflow).
- When
admaxxer.optIn()is called, the buffer drains in order — each event is re-stamped with the current timestamp and posted to/api/event. - When
admaxxer.optOut()is called, the buffer is dropped — the queued events never transmit.
<script
defer
src="https://admaxxer.com/script.js"
data-website-id="admx_a1b2c3d4e5"
data-require-consent="true">
</script>
<!-- Or via the JS init API: -->
<script>
admaxxer('init', {
websiteId: 'admx_a1b2c3d4e5',
requireConsent: true, // Buffer mode at startup
respectDNT: true, // Default — implicit opt-out via navigator.doNotTrack
});
</script>
The buffer cap of 50 is a safety mechanism — if a user lingers for an hour without responding to your cookie banner, you don't want the pixel to consume unbounded memory. In practice, most accept/decline decisions happen within a few page-views.
Cookie banner integrations
Three concrete examples. Pick the one that matches your CMP, or adapt the custom banner pattern to whatever framework your team already uses.
OneTrust
// OneTrust fires OneTrust.OnConsentChanged when the user accepts/declines.
window.OneTrust = window.OneTrust || {};
OneTrust.OnConsentChanged(function (groups) {
// 'C0002' is OneTrust's Performance/Analytics consent group.
// Adjust to match your published categorization.
if (groups.indexOf('C0002') !== -1) {
admaxxer('optIn');
} else {
admaxxer('optOut');
}
});
Cookiebot
// Cookiebot dispatches a custom 'CookiebotOnAccept' event on document.
window.addEventListener('CookiebotOnAccept', function () {
if (window.Cookiebot && window.Cookiebot.consent.statistics) {
admaxxer('optIn');
}
});
window.addEventListener('CookiebotOnDecline', function () {
admaxxer('optOut');
});
Custom banner
<!-- Minimal banner — call admaxxer() on accept/decline button click. -->
<div id="cookie-banner">
<p>We use analytics to improve your experience.</p>
<button id="accept">Accept</button>
<button id="decline">Decline</button>
</div>
<script>
document.getElementById('accept').addEventListener('click', function () {
admaxxer('optIn');
document.getElementById('cookie-banner').style.display = 'none';
});
document.getElementById('decline').addEventListener('click', function () {
admaxxer('optOut');
document.getElementById('cookie-banner').style.display = 'none';
});
</script>
JS API vs /opt-out page
Admaxxer ships two opt-out surfaces. The /opt-out page (introduced in GL#363) is a STATIC URL that merchants link from cookie banners as a footer link — "Click here to opt out of all tracking." Visiting it sets a long-lived opt-out cookie and clears localStorage.
The JS API on this page is the dynamic equivalent for cookie-banner integrations where the user makes an in-flow choice (accept / decline buttons inside the banner) instead of navigating away. Both surfaces set the SAME opt-out cookie name, so they're interchangeable from the server's perspective — you can use either, both, or different ones on different pages.
Server-side respects opt-out
The opt-out cookie is read on the server too, not just the client (per GL#363). Every event handler at /api/event runs an isOptedOut(req) check before writing to Tinybird — if the visitor's opt-out cookie is set, the row is dropped before it lands. This is a belt-and-braces guarantee: even a misconfigured client (e.g. a stale pixel deployed to a customer's site that doesn't yet read the consent state) can't accidentally track an opted-out user.
The same check applies to the server-side webhook ingest paths (Stripe, Paddle, Polar, Lemon, Dodo, Shopify admin). When an opted-out visitor's visitor_id appears on a server-side payment event, the row still lands in revenue_events (revenue is a financial transaction, not a tracking event), but no UTM / click-ID stitching is performed. The dashboard counts the dollars without attributing them.
Frequently asked
- What happens to events captured before opt-in when `requireConsent: true` is set?
- They sit in an in-memory buffer (cap: 50 events; oldest dropped on overflow). The visitor_id is minted locally so it's available to attribution code, but no network requests fire. When `admaxxer.optIn()` is called, the buffer drains in order — each event is re-stamped with the current timestamp and posted to `/api/event`. If `admaxxer.optOut()` is called instead, the buffer is dropped on the floor and never transmits.
- Does this work with the Shopify Custom Pixel?
- Partially. Shopify's Customer Privacy API is the canonical consent surface for Shopify storefronts — the Custom Pixel automatically respects merchant-configured consent banners. The Admaxxer Custom Pixel snippet ships pre-wired to read Shopify's consent state, so you typically don't need a separate JS API call. The standalone JS consent API on this page applies to non-Shopify installs (direct script-tag, custom storefronts).
- How does this interact with the `Do Not Track` (DNT) header?
- By default, the pixel honours `navigator.doNotTrack === '1'` as an implicit opt-out — events are dropped client-side. You can disable this behaviour via the init flag `respectDNT: false` if your jurisdiction requires explicit consent regardless of DNT, or if you've validated that your cookie banner already gates tracking. DNT is widely deprecated by browsers (Apple removed it from Safari, Mozilla deprecated it in Firefox), so most operators leave the default on as a belt-and-braces signal.
- Can I require explicit opt-in for EU visitors only?
- Yes. Pass `requireConsent: 'eu'` instead of `true`. The pixel does a synchronous check against `navigator.language`, `Intl.DateTimeFormat().resolvedOptions().timeZone`, and the `Sec-CH-Geo` client hint (where supported) to determine whether the visitor is plausibly EU/EEA/UK. EU visitors enter buffer mode; everyone else tracks immediately. This is a heuristic — for stricter geofencing, run your own IP-based check server-side and toggle the flag at HTML render time.
- What's the difference between this JS API and the existing /opt-out page?
- The /opt-out page (GL#363) is a static URL merchants link from cookie banners — 'Click here to opt out of all tracking.' Visiting it sets a long-lived opt-out cookie and clears localStorage. The JS API on this page is the dynamic equivalent for cookie-banner integrations where the user makes an in-flow choice instead of navigating away. Both routes set the same opt-out cookie, so they're interchangeable from the server's perspective.
- Is the opt-out cookie scoped per-domain or workspace-wide?
- Per-pixel-domain. The cookie is set on the merchant's first-party domain, not on `admaxxer.com`. If a visitor opts out on `brand.com`, they're still trackable on `another-merchant.com` (which is correct — consent is per-merchant). For multi-domain merchants, propagate the opt-out via cross-domain handoff (`_admx_v` carries an opt-out flag if set on the origin) — see /documentation/integrations/cross-domain-tracking.
- How do I check opt-in status in my own analytics code?
- Call `admaxxer.hasOptedIn()`. It returns `true` if the opt-out cookie is absent (the default), `false` if it's set. Use it to gate any custom tracking layered on top of Admaxxer — for example, calling Klaviyo's `_learnq.push(['identify', ...])` only when the pixel is allowed to track. The function is synchronous and safe to call before the pixel has finished booting.
Next steps
- Cross-domain tracking — how the visitor_id propagates to allow-listed domains.
- Safari ITP mitigation — the HTTP-only cookie mirror that bypasses the 7-day localStorage cap.
- /opt-out page — the static opt-out URL for cookie-banner footer links.
- Privacy policy — the merchant-facing statement on data handling.