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

KategoriaOpisDomyślnie
essentialNiezbędne do działania stronyZawsze true
preferencesCzat, personalizacja, systemy opiniifalse
analyticsGoogle Analytics, Hotjar, Clarityfalse
marketingFacebook Pixel, Google Ads, TikTokfalse

require() przyjmuje tylko trzy non-essential. essential jest read-only.

Metody window.CookieZen

MetodaSygnaturaOpis
ready()() => Promise<api>Resolve gdy banner załadowany (bot/failsafe: natychmiast).
getConsent()() => SnapshotZawsze zwraca obiekt. Sprawdzaj .finalized.
hasConsent(cat)(cat) => booleanSynchroniczne sprawdzenie kategorii.
hasResponse()() => booleantrue 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) => apiSubscribe (chainable). 8 eventów (poniżej).
off(event, cb)(evt, cb) => apiUnsubscribe. Zawsze wywołuj w cleanup SPA / React.
once(event, cb)(evt, cb) => apiSubscribe-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'}) => voidOtwiera centrum zgód.
showSettings()() => voidAlias show({view:'details'}). Dla integracji bez własnego JS użyj deep linku #cookiezen-settings (sekcja niżej).
onMarketingConsent(cb)sugarAlias on('marketing', cb).
onAnalyticsConsent(cb)sugarAlias on('analytics', cb).
onPreferencesConsent(cb)sugarAlias on('preferences', cb).
debug()() => DebugSnapshotDiagnostyka: listy zablokowanych skryptów.

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).

Kod
<!-- 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-settings

Jak to działa (routing zależy od stanu zgody usera):

Stan useraCo się otwieraPo 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 click i hashchange odpalą 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-settings zamiast 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:

Kod
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 storage czyści też per-tab sessionStorage dla 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:

  1. Iframe nie ładuje się do czasu przyznania wymaganej kategorii.
  2. Klik w placeholder nadaje całą wymaganą kategorię i zamyka otwarty baner pierwszej wizyty (jeśli był widoczny).
  3. Po zgodzie placeholder znika, iframe się pokazuje; usunięcie iframe z DOM czyści placeholder.
  4. 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).

EventFire-on-subscribeFuture transitions
consentTak, z aktualnym SnapshotTak (każda zmiana, informacyjny)
readyTak, natychmiastbrak
changeNieTak (diff niepusty)
acceptNieTak (finalized + any granted)
declineNieTak (finalized + all denied)
marketing / analytics / preferencesTak, jeśli grantedTak (przy tranzycji false → true)

Kolejność emisji przy zmianie stanu: changeaccept 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

Kod
type ChangePayload = Snapshot & {
  previousCategories: ConsentCategories;
  changedCategories: ('marketing' | 'analytics' | 'preferences')[];
};

DOM Events

Każdy event registry ma odpowiadający CustomEvent na window (dla addEventListener pattern).

Eventevent.detail
cookiezen:ready{categories, finalized}, emitowany na każdy page load po init
cookiezen:consentChangePayload, informacyjny
cookiezen:changeChangePayload, realna tranzycja
cookiezen:acceptSnapshot
cookiezen:declineSnapshot
Kod
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:

CodeKiedyerr.category
CONSENT_DECLINEDhasResponse() && !hasConsent(cat)Tak
CONSENT_TIMEOUTMinął opts.timeout msTak
CONSENT_ABORTEDopts.signal.abort()Tak
INVALID_CATEGORYcat ∉ {marketing, analytics, preferences}Nie

Timeout policy

  • Bez opts.timeoutconsole.warn + hard cap 30 minut (fail-safe).
  • opts.timeout: 30000 → reject po 30 sekundach.
  • opts.timeout: 0 lub Infinity → ś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.

Kod
<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.

Kod
<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 z CONSENT_DECLINED.
  • accept() / decline() / submitConsent() zwracają pre-finalize Snapshot (no-op).
  • DOM event cookiezen:ready emitowany.

Kod z try/catch na require() działa identycznie w normal mode i bot/failsafe.

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ą:

Kod
{
  "finalized": true,
  "consentId": "c_xyz...",
  "categories": {"essential": true, "preferences": false, "analytics": true, "marketing": false},
  "policyVersion": "v1.2",
  "timestamp": 1715000000000,
  "action": "customize"
}
Kod
// 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;
    }
}
Kod
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 actionaction: null, reszta pól wczytuje się normalnie.

TypeScript types

Kod
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>;
  }
}

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 ModeKategoria CookieZen
ad_storagemarketing
ad_user_datamarketing
ad_personalizationmarketing
analytics_storageanalytics
functionality_storagepreferences
personalization_storagepreferences

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.

Kod
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.