Pełna Referencja JavaScript API
Kompletny kontrakt window.CookieZen. Podstawowe snippety znajdziesz w Integracji JavaScript API - szybki start. Wszystkie recepty integracyjne (React, AbortController, Multi-tab, GTM, iframe) opisuje plik cookiezen-docs-api.md.
Korzystasz z Agentów AI typu Cursor, Claude Code lub Codex? Pobierz paczkę cookiezen-docs-api.md, która zawiera kompletną referencję API w jednym miejscu. Plik został dostosowany w celu przyspieszenia pracy z narzędziami LLM.
Kategorie zgód
| Kategoria | Opis | Domyślnie |
|---|---|---|
essential | Niezbędne do działania strony | Zawsze true |
preferences | Czat, personalizacja, systemy opinii | false |
analytics | Google Analytics, Hotjar, Clarity | false |
marketing | Facebook Pixel, Google Ads, TikTok | false |
require() przyjmuje tylko trzy non-essential. essential jest read-only.
Metody window.CookieZen
| Metoda | Sygnatura | Opis |
|---|---|---|
ready() | () => Promise<api> | Resolve gdy banner załadowany (bot/failsafe: natychmiast). |
getConsent() | () => Snapshot | Zawsze zwraca obiekt. Sprawdzaj .finalized. |
hasConsent(cat) | (cat) => boolean | Synchroniczne sprawdzenie kategorii. |
hasResponse() | () => boolean | true po decyzji usera (accept/reject/customize/withdraw). |
require(cat, opts?) | (cat, {timeout?, signal?}) => Promise<true> | Czeka na zgodę. Reject z error code. |
on(event, cb) | (evt, cb) => api | Subscribe (chainable). 8 eventów (poniżej). |
off(event, cb) | (evt, cb) => api | Unsubscribe. Zawsze wywołuj w cleanup SPA / React. |
once(event, cb) | (evt, cb) => api | Subscribe-once z auto-off. |
accept() | () => Promise<Snapshot> | Programatyczna akceptacja wszystkiego (action='accept'). Zamyka otwarty baner pierwszej wizyty. |
decline() | () => Promise<Snapshot> | Programatyczna odmowa (action='reject' lub 'withdraw'). Zamyka otwarty baner pierwszej wizyty. |
submitConsent(partial) | (Partial<Cats>) => Promise<Snapshot> | Partial merge, action='customize'. Zamyka otwarty baner pierwszej wizyty. |
show(opts?) | ({view?: 'main'|'details'}) => void | Otwiera centrum zgód. |
showSettings() | () => void | Alias show({view:'details'}). Dla integracji bez własnego JS użyj deep linku #cookiezen-settings (sekcja niżej). |
onMarketingConsent(cb) | sugar | Alias on('marketing', cb). |
onAnalyticsConsent(cb) | sugar | Alias on('analytics', cb). |
onPreferencesConsent(cb) | sugar | Alias on('preferences', cb). |
debug() | () => DebugSnapshot | Diagnostyka: listy zablokowanych skryptów. |
Deep link #cookiezen-settings: otwarcie ustawień przez link
Rekomendowane dla każdego klienta, który nie chce / nie może wkleić własnego JavaScriptu na stronie (CMS-y bez custom JS: Shoper, Wix, prosty WordPress przez edytor treści).
Wystarczy odnośnik z hashem #cookiezen-settings. Banner sam wykryje go i otworzy widok szczegółów (kategorie + przełączniki + ID zgody, jeśli już zapisana).
<!-- Najprostsze: względny hash, działa na każdej podstronie -->
<a href="#cookiezen-settings">Ustawienia cookies</a>
<!-- Pełny URL, wklej w pole "URL" przycisku w CMS (Shoper menu, Wix link, itp.) -->
https://twoja-domena.pl/#cookiezen-settingsJak to działa (routing zależy od stanu zgody usera):
| Stan usera | Co się otwiera | Po co |
|---|---|---|
| Powracający (zgoda już zapisana) | Floating popup: DOKŁADNIE to samo co kliknięcie przycisku float (summary kategorii + „Pokaż szczegóły" z ID zgody i datą + Anuluj/Zmień zgodę) | Deep link zastępuje przycisk float gdy klient go ukryje. UX musi być 1:1, żeby user dalej miał dostęp do ID i opcji zmiany/wycofania. |
| Pierwsza wizyta (brak zgody) | Standardowy baner pierwszej wizyty (accept / reject / customize). Hash jest cicho konsumowany, więc refresh po consent nie wyświetla niespodziewanego popupa. | Główny baner ma już wszystkie toggle potrzebne nowemu userowi; otwieranie dedykowanego centrum byłoby duplikatem. |
Mechanika:
- Wejście na stronę z hashem + zapisana zgoda → floating popup od razu.
- Wejście z hashem + brak zgody → główny baner pierwszej wizyty, hash skonsumowany.
- Kliknięcie w link w trakcie sesji uruchamia trzy ścieżki (bez przeładowania):
- hashchange: klasyczna nawigacja hashem,
- capture click na <a href*="#cookiezen-settings">: fallback dla SPA (Shoper Storefront itp.), z preventDefault w tej samej karcie,
- popstate: wstecz/naprzód z hashem w URL.
- Krótkie okno deduplikacji (~100 ms) chroni przed podwójnym otwarciem gdy
clickihashchangeodpalą się razem (inaczej popup by się zamknął przez toggle). target="_blank": banner nie przechwytuje kliknięcia; nowa karta otwiera się z hashem i obsługuje go przy load.- Na wielostronicowych sklepach preferuj względny hash
#cookiezen-settingszamiast absolutnego URL do strony głównej. - Hash jest konsumowany po obsłużeniu (banner usuwa go via
history.replaceState), więc refresh nie zostawia śmieci w pasku adresu. - Skanery i boty: pominięte (banner w tych trybach w ogóle się nie pokazuje).
Kiedy preferować showSettings() w JS:
- Reaktywny UI we własnym SPA (React/Vue):
onClick={() => window.CookieZen.showSettings()}. - Centrum klienta z własną logiką (np. otwierane modale).
Gotowe snippety (link absolutny dla Twojej domeny + HTML + relativny hash) znajdziesz w panelu CookieZen: Wygląd baneru → Pozycja przycisku ustawień cookies → Ukryty.
Snapshot
getConsent() zwraca obiekt o tym kształcie:
type Snapshot = {
categories: { essential: true; preferences: boolean; analytics: boolean; marketing: boolean; };
consentId: string | null; // UUID po finalizacji
timestamp: number | null; // ms epoch
policyVersion: string | null;
action: 'accept' | 'reject' | 'customize' | 'withdraw' | null;
finalized: boolean; // false gdy user nie zatwierdził decyzji
};getConsent() nigdy nie zwraca null. Pre-finalize → finalized: false i null w metadanych. Sprawdzaj if (CookieZen.getConsent().finalized).
policyVersion
Wersja polityki skonfigurowana w panelu CMP (np. "v1.2"). Podbicie wersji unieważnia zapisaną zgodę przy następnym pełnym załadowaniu strony: cookie zgody i powiązany storage są czyszczone, finalized wraca do false, a wiszące require() nie resolve'ują się ze starej decyzji.
Reset jest load-time: w SPA bez przeładowania bump wersji na serwerze nie wymusi ponownego promptu. Użyj location.reload() lub show(), jeśli potrzebujesz re-promptu w tej samej sesji.
Automatyczne usuwanie artefaktów first-party
Po decline(), wycofaniu (withdraw) lub submitConsent() z kategorią denied, a także przy starcie strony dla powracającego usera z odmową, CookieZen automatycznie usuwa first-party cookies, localStorage, sessionStorage i IndexedDB sklasyfikowane przez skaner w tej kategorii.
- Sterowane klasyfikacją skanera; chronione są własne artefakty zgody CMP i krytyczne nazwy (koszyk, sesja).
- W innych kartach: sync przez
storageczyści też per-tabsessionStoragedla denied. - Brak opt-out, to część kontraktu zgody. Ręczny cleanup w
unloadSdk()to opcjonalne zabezpieczenie dla SDK third-party.
Integracja przez iframe (placeholder)
Przy manual blocking zablokowany <iframe> (np. widget opinii Trustmate) jest ukryty i zastąpiony placeholderem (Shadow DOM) z przyciskiem zgody:
- Iframe nie ładuje się do czasu przyznania wymaganej kategorii.
- Klik w placeholder nadaje całą wymaganą kategorię i zamyka otwarty baner pierwszej wizyty (jeśli był widoczny).
- Po zgodzie placeholder znika, iframe się pokazuje; usunięcie iframe z DOM czyści placeholder.
- Współgra z
on('change')i nie wymaga własnego markupu od integratora.
Szczegóły i snippet: cookiezen-docs-api.md §10.10a.
Eventy
8 typów eventów. Każdy ma odpowiadający DOM CustomEvent na window (zob. niżej).
| Event | Fire-on-subscribe | Future transitions |
|---|---|---|
consent | Tak, z aktualnym Snapshot | Tak (każda zmiana, informacyjny) |
ready | Tak, natychmiast | brak |
change | Nie | Tak (diff niepusty) |
accept | Nie | Tak (finalized + any granted) |
decline | Nie | Tak (finalized + all denied) |
marketing / analytics / preferences | Tak, jeśli granted | Tak (przy tranzycji false → true) |
Kolejność emisji przy zmianie stanu: change → accept lub decline → per-category → consent.
Returning user (brak spurious eventów): przy reload strony consent odpala się (informacyjny), ale change/accept/decline NIE, bo nie było tranzycji w bieżącej sesji. Rozwiązuje klasyczny problem CMP-ów (Cookiebot OnAccept spamuje przy każdym page load).
Payload change
type ChangePayload = Snapshot & {
previousCategories: ConsentCategories;
changedCategories: ('marketing' | 'analytics' | 'preferences')[];
};DOM Events
Każdy event registry ma odpowiadający CustomEvent na window (dla addEventListener pattern).
| Event | event.detail |
|---|---|
cookiezen:ready | {categories, finalized}, emitowany na każdy page load po init |
cookiezen:consent | ChangePayload, informacyjny |
cookiezen:change | ChangePayload, realna tranzycja |
cookiezen:accept | Snapshot |
cookiezen:decline | Snapshot |
window.addEventListener('cookiezen:accept', function(e) {
if (e.detail.categories.marketing) initPixel();
});Error codes: require() reject contract
require() rzuca Error z polem code. Stabilny kontrakt:
| Code | Kiedy | err.category |
|---|---|---|
CONSENT_DECLINED | hasResponse() && !hasConsent(cat) | Tak |
CONSENT_TIMEOUT | Minął opts.timeout ms | Tak |
CONSENT_ABORTED | opts.signal.abort() | Tak |
INVALID_CATEGORY | cat ∉ {marketing, analytics, preferences} | Nie |
Timeout policy
- Bez
opts.timeout→console.warn+ hard cap 30 minut (fail-safe). opts.timeout: 30000→ reject po 30 sekundach.opts.timeout: 0lubInfinity→ świadomie bez cap. Bez warna.
Wzorce inicjalizacji
Command Queue (Twój skrypt po naszym loaderze)
API jest dostępne jako stub od razu po załadowaniu loadera, a wywołania są kolejkowane i drenowane po inicjalizacji bannera. Wszystkie metody Promise (require, accept, decline, submitConsent, ready) są Promise-aware w stubie.
<script src="https://cz-cdn.com/api/cmp/loader?site_key=TWOJ_KEY"></script>
<script>
CookieZen.on('change', function ({ categories }) {
console.log('marketing:', categories.marketing);
});
</script>CookieZenCallback_OnReady (Twój skrypt może załadować się PRZED naszym loaderem)
Na platformach z asynchronicznym ładowaniem (Shoper Storefront, IdoSell, Magento) nie ma gwarancji, że nasz loader wykona się jako pierwszy. Wtedy zdefiniuj globalną funkcję, a CookieZen wywoła ją po inicjalizacji niezależnie od kolejności. Wzorzec analogiczny do CookiebotCallback_OnLoad z Cookiebot.
<script>
window.CookieZenCallback_OnReady = function (CookieZen) {
CookieZen.require('marketing', { timeout: 30000 }).then(initWidget).catch(function () {});
CookieZen.on('change', function (p) {
if (p.categories.marketing) initWidget();
else destroyWidget();
});
};
</script>Late registration: jeśli zarejestrujesz CookieZenCallback_OnReady PO inicjalizacji CookieZen, nie odpali się. Wtedy użyj CookieZen.on('ready', cb); ready ma fire-on-subscribe.
Bot / failsafe
Gdy banner nie załaduje się (bot detection lub failsafe timeout 7s), window.CookieZen jest podmieniany na mini-API:
require()rejecta natychmiast zCONSENT_DECLINED.accept()/decline()/submitConsent()zwracają pre-finalize Snapshot (no-op).- DOM event
cookiezen:readyemitowany.
Kod z try/catch na require() działa identycznie w normal mode i bot/failsafe.
Server-side cookie
Cookie cmp_consent_<siteKey> (np. cmp_consent_site_abc123) na root domain, SameSite=Lax. Nazwa jest kluczowana Twoim site_key, dzięki czemu zgoda jest izolowana między stronami współdzielącymi tę samą domenę nadrzędną:
{
"finalized": true,
"consentId": "c_xyz...",
"categories": {"essential": true, "preferences": false, "analytics": true, "marketing": false},
"policyVersion": "v1.2",
"timestamp": 1715000000000,
"action": "customize"
}// Zastąp <siteKey> swoim site_key (lub przeskanuj cookies po prefiksie cmp_consent_).
$raw = $_COOKIE['cmp_consent_<siteKey>'] ?? null;
if ($raw) {
$c = json_decode(urldecode($raw), true);
if ($c && !empty($c['finalized'])) {
$marketing = !empty($c['categories']['marketing']);
$action = $c['action'] ?? null;
}
}const raw = req.cookies?.['cmp_consent_<siteKey>'];
if (raw) {
const c = JSON.parse(decodeURIComponent(raw));
if (c?.finalized) {
const marketing = c.categories?.marketing === true;
}
}Stare cookies bez action → action: null, reszta pól wczytuje się normalnie.
TypeScript types
interface ConsentCategories {
essential: true;
preferences: boolean;
analytics: boolean;
marketing: boolean;
}
interface Snapshot {
categories: ConsentCategories;
consentId: string | null;
timestamp: number | null;
policyVersion: string | null;
action: 'accept' | 'reject' | 'customize' | 'withdraw' | null;
finalized: boolean;
}
interface ChangePayload extends Snapshot {
previousCategories: ConsentCategories;
changedCategories: ('marketing' | 'analytics' | 'preferences')[];
}
interface RequireOptions {
timeout?: number; // ms; 0/Infinity = bez cap
signal?: AbortSignal;
}
type ConsentEvent =
| 'consent' | 'ready' | 'change' | 'accept' | 'decline'
| 'marketing' | 'analytics' | 'preferences';
interface ConsentError extends Error {
code: 'CONSENT_DECLINED' | 'CONSENT_TIMEOUT' | 'CONSENT_ABORTED' | 'INVALID_CATEGORY';
category?: 'marketing' | 'analytics' | 'preferences';
}
interface CookieZenAPI {
ready(): Promise<CookieZenAPI>;
getConsent(): Snapshot;
hasConsent(category: string): boolean;
hasResponse(): boolean;
require(category: 'marketing' | 'analytics' | 'preferences', opts?: RequireOptions): Promise<true>;
on(event: ConsentEvent, cb: (payload: Snapshot | ChangePayload) => void): CookieZenAPI;
off(event: ConsentEvent, cb: Function): CookieZenAPI;
once(event: ConsentEvent, cb: (payload: Snapshot | ChangePayload) => void): CookieZenAPI;
accept(): Promise<Snapshot>;
decline(): Promise<Snapshot>;
submitConsent(partial: Partial<{ marketing: boolean; analytics: boolean; preferences: boolean; }>): Promise<Snapshot>;
show(opts?: { view?: 'main' | 'details' }): void;
showSettings(): void;
onMarketingConsent(cb: (snap: Snapshot) => void): CookieZenAPI;
onAnalyticsConsent(cb: (snap: Snapshot) => void): CookieZenAPI;
onPreferencesConsent(cb: (snap: Snapshot) => void): CookieZenAPI;
debug(): unknown;
}
declare global {
interface Window {
CookieZen: CookieZenAPI;
CookieZenCallback_OnReady?: (api: CookieZenAPI) => void;
}
interface WindowEventMap {
'cookiezen:ready': CustomEvent<{ categories: ConsentCategories; finalized: boolean }>;
'cookiezen:consent': CustomEvent<ChangePayload>;
'cookiezen:change': CustomEvent<ChangePayload>;
'cookiezen:accept': CustomEvent<Snapshot>;
'cookiezen:decline': CustomEvent<Snapshot>;
}
}Consent Mode → kategorie
Jeśli budujesz integrację, która ma działać z dowolnym CMP na rynku (Cookiebot, OneTrust, CookieYes, CookieZen, wbudowane CMP na IdoSell / Shoper / WordPress), nasłuchuj sygnałów Google Consent Mode na dataLayer zamiast wiązać kod z jednym dostawcą. Każdy certyfikowany przez Google CMP emituje gtag('consent', 'update', ...), a wynik trafia do window.dataLayer.
Mapowanie kluczy Consent Mode na kategorie CookieZen:
| Klucz Consent Mode | Kategoria CookieZen |
|---|---|
ad_storage | marketing |
ad_user_data | marketing |
ad_personalization | marketing |
analytics_storage | analytics |
functionality_storage | preferences |
personalization_storage | preferences |
Kształt debug() (DebugSnapshot)
debug() zwraca migawkę stanu wyłącznie do diagnostyki. Nie buduj na niej kodu produkcyjnego: kształt nie jest częścią stabilnego kontraktu i służy tylko do ręcznego troubleshootingu.
type DebugSnapshot = {
version: string;
siteKey: string;
policyVersion: string | null;
mode: 'normal' | 'bot' | 'failsafe' | 'preview';
snapshot: Snapshot;
blockedScripts: number; // liczba <script type="text/plain" data-cmp-category>
blockedIframes: number;
requirePending: number; // liczba wiszących promisów require()
listeners: Record<ConsentEvent, number>;
};Recepty integracyjne
Recepty (React z cleanup, once('accept'), AbortController, programatyczne accept / decline, kontekstowa zgoda, GTM Custom HTML, iframe sync, multi-tab sync, integracja SDK plugin z load + unload + graceful fallback, cross-CMP via Consent Mode) znajdziesz w cookiezen-docs-api.md, sekcja §10 Recipes.