Wprowadzenie
CookiePilot to platforma do zarządzania zgodami cookies (CMP), zgodna z RODO, PKE i Google Consent Mode v2.
Dla kogo
- Właściciele stron: wdrożenie bez programowania.
- Developerzy: API, eventy, integracje z GTM.
- Agencje: white-label, zarządzanie wieloma domenami.
Szybki start
Krok 1: Rejestracja
- Załóż konto na app.cookiepilot.io/register.
- Dodaj domenę w panelu i skopiuj klucz API (format
cp_live_...).
Krok 2: Instalacja kodu
Wklej jako pierwszy skrypt w sekcji <head>, przed GTM, GA i resztą trackerów:
<script src="https://cdn.cookiepilot.io/cookiepilot.js" data-cpkey="TWOJ_KLUCZ"></script>
Kolejność ma znaczenie: stub w bundlu ustawia synchronicznie domyślne zgody (denied) dla Google Consent Mode v2, zanim cokolwiek innego się załaduje.
Krok 3: Konfiguracja banera
W panelu: Domena → Konfiguracja → Wygląd:
- pozycja banera (góra, dół, modal),
- kolory i teksty,
- pływający przycisk "Ustawienia cookies" dla powracających użytkowników.
Integracja z Google Tag Manager
Jeśli używasz GTM, zamiast jednego skryptu w <head> potrzebujesz dwóch tagów: stub inline z zewnętrznego pliku oraz tag ładujący baner.
Krok 1: Stub w <head>, przed GTM
To musi być fizycznie w HTML, nie w GTM (GTM ładuje się asynchronicznie i jego "Consent Initialization" trigger może odpalić się już po pierwszym pageview innych skryptów):
<script src="https://cdn.cookiepilot.io/stub.js"></script>
Krok 2: Tag CookiePilot Banner w GTM
Tagi → Nowy → Niestandardowy kod HTML:
<script src="https://cdn.cookiepilot.io/cookiepilot.js" data-cpkey="TWOJ_KLUCZ"></script>
- Trigger: All Pages
- Opcje uruchamiania: Raz na stronę
Kolejność tagów
| Kolejność | Tag | Trigger |
|---|---|---|
| 1 | stub.js w HTML | (poza GTM, inline w <head>) |
| 2 | CookiePilot Banner | All Pages, raz na stronę |
| 3 | GA4, Google Ads, inne Google | według potrzeb (Consent Mode obsłuży zgody) |
| 4 | Facebook Pixel, TikTok, LinkedIn itd. | Custom Event cookiepilot_consent_update (patrz niżej) |
Tagi spoza Google (Facebook Pixel, TikTok, LinkedIn)
Google Consent Mode obsługuje tylko tagi Google. Dla pozostałych skryptów widget przy każdej zmianie zgody pushuje do dataLayer event:
dataLayer.push({
event: 'cookiepilot_consent_update',
cookiepilot_consent: {
necessary: true,
analytics: true,
marketing: true,
preferences: false
}
});
Event leci również przy każdym wejściu powracającego użytkownika (gdy widget odczyta cookie ze zgodą), więc trigger w GTM zadziała na każdej wizycie, nie tylko przy pierwszej decyzji.
Wspólny pattern (wykonaj raz)
Te trzy elementy konfigurujesz raz, potem używasz dla wszystkich tagów spoza Google.
- Trigger (Triggers → New → Custom Event): Event name
cookiepilot_consent_update. Bez warunków, bez "Once per page" (tag musi móc odpalić się ponownie po zmianie decyzji). - Data Layer Variable dla każdej kategorii której używasz:
- Name
cookiepilot_consent.marketing→ zmienna np.dlv.cp_marketing - Name
cookiepilot_consent.analytics→ zmienna np.dlv.cp_analytics - Name
cookiepilot_consent.preferences→ zmienna np.dlv.cp_preferences
- Name
- Trigger Group lub warunek w triggerze:
dlv.cp_marketing equals true(dla tagów marketingowych) albo odpowiednie pole.
W każdym z poniższych przykładów Trigger to ten sam Custom Event z dorzuconym warunkiem na właściwą zmienną.
Facebook Pixel
Tag w GTM: Tags → New → Custom HTML.
<script>
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', 'YOUR_PIXEL_ID');
fbq('track', 'PageView');
</script>
- Trigger:
cookiepilot_consent_update+ warunekdlv.cp_marketing equals true. - Tag firing options: Once per page.
Opcjonalnie, dla pełnej zgodności z Facebook Limited Data Use, dodaj drugi tag wywołujący fbq('consent','revoke') z triggerem dlv.cp_marketing equals false.
TikTok Pixel
Tag w GTM: Tags → New → Custom HTML.
<script>
!function (w, d, t) {
w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie","holdConsent","revokeConsent","grantConsent"],ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);ttq.instance=function(t){for(var e=ttq._i[t]||[],n=0;n<ttq.methods.length;n++)ttq.setAndDefer(e,ttq.methods[n]);return e},ttq.load=function(e,n){var r="https://analytics.tiktok.com/i18n/pixel/events.js",o=n&&n.partner;ttq._i=ttq._i||{},ttq._i[e]=[],ttq._i[e]._u=r,ttq._t=ttq._t||{},ttq._t[e]=+new Date,ttq._o=ttq._o||{},ttq._o[e]=n||{};n=document.createElement("script");n.type="text/javascript",n.async=!0,n.src=r+"?sdkid="+e+"&lib="+t;e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(n,e)};
ttq.load('YOUR_TIKTOK_PIXEL_ID');
ttq.grantConsent();
ttq.page();
}(window, document, 'ttq');
</script>
- Trigger:
cookiepilot_consent_update+ warunekdlv.cp_marketing equals true. - Tag firing options: Once per page.
ttq.grantConsent() to nowe API TikTok (od 2024). Bez tego TikTok dostaje hashowane dane bez zgody, co łamie warunki.
LinkedIn Insight Tag
<script type="text/javascript">
_linkedin_partner_id = "YOUR_LINKEDIN_PARTNER_ID";
window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];
window._linkedin_data_partner_ids.push(_linkedin_partner_id);
</script>
<script type="text/javascript">
(function(l) {
if (!l){window.lintrk = function(a,b){window.lintrk.q.push([a,b])};
window.lintrk.q=[]}
var s = document.getElementsByTagName("script")[0];
var b = document.createElement("script");
b.type = "text/javascript";b.async = true;
b.src = "https://snap.licdn.com/li.lms-analytics/insight.min.js";
s.parentNode.insertBefore(b, s);})(window.lintrk);
</script>
- Trigger:
cookiepilot_consent_update+ warunekdlv.cp_marketing equals true. - Tag firing options: Once per page.
Hotjar
<script>
(function(h,o,t,j,a,r){
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
h._hjSettings={hjid:YOUR_HOTJAR_ID,hjsv:6};
a=o.getElementsByTagName('head')[0];
r=o.createElement('script');r.async=1;
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
a.appendChild(r);
})(window,document,'https://static.hotjar.com/c/hotjar-',".js?sv=");
</script>
- Trigger:
cookiepilot_consent_update+ warunekdlv.cp_analytics equals true. - Tag firing options: Once per page.
Hotjar idzie pod analytics, nie marketing (mierzy zachowanie, nie reklamy). Sprawdź własną politykę cookies, niektóre firmy klasyfikują Hotjar inaczej.
Microsoft Clarity
<script type="text/javascript">
(function(c,l,a,r,i,t,y){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "YOUR_CLARITY_PROJECT_ID");
</script>
- Trigger:
cookiepilot_consent_update+ warunekdlv.cp_analytics equals true. - Tag firing options: Once per page.
Pinterest Tag
<script>
!function(e){if(!window.pintrk){window.pintrk = function () {
window.pintrk.queue.push(Array.prototype.slice.call(arguments))};var
n=window.pintrk;n.queue=[],n.version="3.0";var
t=document.createElement("script");t.async=!0,t.src=e;var
r=document.getElementsByTagName("script")[0];
r.parentNode.insertBefore(t,r)}}("https://s.pinimg.com/ct/core.js");
pintrk('load', 'YOUR_PINTEREST_TAG_ID');
pintrk('page');
</script>
- Trigger:
cookiepilot_consent_update+ warunekdlv.cp_marketing equals true. - Tag firing options: Once per page.
Microsoft Ads (UET)
UET wspiera Google Consent Mode od końca 2023, więc nie potrzebujesz Custom Event triggera. Wstaw tag standardowo (All Pages, Once per page), a UET sam czyta ad_storage z GCM, które ustawia widget.
Mapowanie kategorii (skrót)
| Tag | Kategoria | Pole w cookiepilot_consent |
|---|---|---|
| Facebook Pixel | marketing | marketing |
| TikTok Pixel | marketing | marketing |
| LinkedIn Insight | marketing | marketing |
| marketing | marketing | |
| Hotjar | analytics | analytics |
| Microsoft Clarity | analytics | analytics |
| Mixpanel, Amplitude | analytics | analytics |
| Intercom, Drift, Crisp | preferences | preferences |
| GA4, Google Ads, UET | (GCM, bez triggera) | obsługiwane przez gtag('consent','update') |
API Reference
CookiePilot udostępnia obiekt window.CookiePilot:
| Metoda | Opis |
|---|---|
CookiePilot.getConsent() | Aktualny stan zgód lub null jeśli nie ma decyzji. |
CookiePilot.acceptAll() | Zgoda na wszystkie kategorie. |
CookiePilot.rejectAll() | Odrzuca wszystko poza necessary. |
CookiePilot.updateConsent(partial) | Aktualizuje wybrane kategorie, np. { analytics: true }. |
CookiePilot.showSettings() | Otwiera modal preferencji. |
CookiePilot.hideSettings() | Zamyka modal preferencji. |
CookiePilot.showMyConsent() / hideMyConsent() | Pokazuje/ukrywa pływający przycisk. |
Przykład
const consent = CookiePilot.getConsent();
// { necessary: true, analytics: true, marketing: false, preferences: false }
CookiePilot.updateConsent({ analytics: true });
document.getElementById('cookie-settings').addEventListener('click', () => {
CookiePilot.showSettings();
});
Link "Zarządzaj cookies" w stopce
<a href="#" onclick="CookiePilot.showSettings(); return false;">Zarządzaj cookies</a>
Eventy JavaScript
Widget dispatcuje natywny event cookiepilot:consent na window. Listener musi być zarejestrowany przed załadowaniem widgetu, jeśli chcesz złapać event dla powracającego użytkownika (dispatch leci natychmiast po starcie widgetu):
<script>
window.addEventListener('cookiepilot:consent', (e) => {
if (e.detail.marketing) {
fbq('init', 'YOUR_PIXEL_ID');
}
});
</script>
<script src="https://cdn.cookiepilot.io/cookiepilot.js" data-cpkey="TWOJ_KLUCZ"></script>
e.detail zawiera ten sam payload co getConsent(). Dla integracji przez GTM użyj dataLayer eventu opisanego wyżej zamiast tego, bo dataLayer jest persistent array i GTM łyka eventy historyczne.
Kategorie zgód
| Kategoria | Opis | Domyślnie |
|---|---|---|
necessary | Niezbędne do działania strony | Zawsze aktywne |
analytics | Statystyki i analityka | Wymagana zgoda |
marketing | Reklamy i remarketing | Wymagana zgoda |
preferences | Personalizacja, język | Wymagana zgoda |
Mapowanie na Google Consent Mode
| Kategoria CookiePilot | Pola Consent Mode |
|---|---|
analytics | analytics_storage |
marketing | ad_storage, ad_user_data, ad_personalization |
preferences | functionality_storage, personalization_storage |
| (zawsze) | security_storage: granted |
Google Consent Mode v2
Wersja 2 dodała ad_user_data i ad_personalization (wymagane od marca 2024 dla EU/EEA przy reklamach Google).
| Parametr | Opis |
|---|---|
ad_storage | Cookies reklamowe |
analytics_storage | Cookies analityczne |
ad_user_data | Wysyłka danych użytkownika do Google |
ad_personalization | Personalizacja reklam |
functionality_storage | Cookies funkcjonalne |
personalization_storage | Cookies personalizacyjne |
security_storage | Zawsze granted |
Mechanizm:
- Stub ustawia wszystkie pola na
deniedsynchronicznie, zwait_for_update: 500. - Po decyzji użytkownika widget puszcza
gtag('consent', 'update', {...})z mapowaniem powyżej. - Dla powracającego użytkownika punkt 2 leci natychmiast po starcie widgetu, na podstawie cookie.
Konfiguracja wyglądu
W panelu: Domena → Konfiguracja:
- Wygląd: pozycja, kolory, układ (BAR / BOX / MODAL).
- Teksty: nagłówek, opis, etykiety przycisków, opisy kategorii. 13 języków (EN, PL, DE, FR, ES, IT, NL, PT, SV, CS, RO, EL, HU).
- Przycisk zgód: pływający przycisk "Ustawienia cookies" widoczny po pierwszej decyzji (lewy/prawy dół).
- Custom CSS: pole na własne style. Widget renderuje się w Shadow DOM, więc selektory CSS z głównego dokumentu nie zadziałają. Tylko przez to pole.
Dostępność (WCAG 2.1 AA)
- ✅ Nawigacja klawiaturą (Tab, Shift+Tab, Enter, Escape).
- ✅ ARIA labels, role="dialog", aria-modal.
- ✅ Focus trap w modalu.
- ✅ Screen reader (live regions na zmianę stanu).
- ✅ Responsywność.
Integracje
WordPress
Mamy oficjalną wtyczkę: CookiePilot na WordPress.org.
- WordPress admin → Wtyczki → Dodaj nową → szukaj "CookiePilot".
- Zainstaluj i aktywuj.
- Ustawienia → CookiePilot → wklej klucz API z panelu.
Wtyczka sama wstawia stub i tag w <head> (z poprawną kolejnością przed innymi skryptami) i wystawia shortcode [cookiepilot_settings] do linku "Zarządzaj cookies" w stopce.
Jeśli wolisz bez wtyczki: użyj "Insert Headers and Footers" i wklej snippet z kroku 2 Szybkiego startu w sekcję Header.
Shopify
- Sklep → Motywy → Edytuj kod.
- W
theme.liquidwklej snippet przed</head>.
Next.js
// app/layout.tsx
import Script from 'next/script';
export default function RootLayout({ children }) {
return (
<html>
<head>
<Script
src="https://cdn.cookiepilot.io/cookiepilot.js"
data-cpkey="TWOJ_KLUCZ"
strategy="beforeInteractive"
/>
</head>
<body>{children}</body>
</html>
);
}
strategy="beforeInteractive" jest istotny: stub w bundlu musi się wykonać przed innymi skryptami.
FAQ
Czy skrypt spowalnia stronę?
Bundle to ok. 12 KB gzip, ładowany asynchronicznie. Bez wpływu na Core Web Vitals.
Jak długo trzymane są zgody?
Cookie z decyzją użytkownika: domyślnie 365 dni (konfigurowalne w panelu). Zdarzenia w analityce: 2 lata (TTL ClickHouse).
Czy event cookiepilot_consent_update leci dla powracającego użytkownika?
Tak. Widget odczytuje cookie przy starcie i pushuje event do dataLayer. Trigger Custom Event w GTM odpali się przy każdej wizycie, nie tylko przy pierwszej decyzji.
Gdzie zgłosić problem?
kontakt@cookiepilot.io lub chat w panelu.