Uvod
CookiePilot je platforma za upravljanje privolama za kolačiće (CMP), usklađena s GDPR-om (Opća uredba o zaštiti podataka, OUZP), hrvatskim Zakonom o elektroničkim komunikacijama (ePrivacy) te Google Consent Modeom v2. Usklađenost s ovim propisima u Hrvatskoj nadzire Agencija za zaštitu osobnih podataka (AZOP).
Za koga
- Vlasnici stranica: implementacija bez programiranja.
- Programeri: API, eventi, integracije s GTM-om.
- Agencije: white-label, upravljanje većim brojem domena.
Brzi početak
Korak 1: Registracija
- Otvorite račun na app.cookiepilot.io/register.
- Dodajte domenu u nadzornoj ploči i kopirajte API ključ (format
cp_live_...).
Korak 2: Instalacija koda
Izravna instalacija znači dvije skripte u sekciji <head>, ovim redoslijedom.
Korak 2a: Zadane privole (inline stub). Zalijepite kao prvu, prije bilo koje druge skripte (cookiepilot.js, GA, GTM, oglasne i tragačke tagove):
<script>"use strict";(function(){window.dataLayer=window.dataLayer||[];var d={ad_storage:"denied",ad_user_data:"denied",ad_personalization:"denied",analytics_storage:"denied",functionality_storage:"denied",personalization_storage:"denied",security_storage:"granted",wait_for_update:500},h=false;try{for(var i=0;i<window.dataLayer.length;i++){var x=window.dataLayer[i];if(x&&x[0]==="consent"&&x[1]==="default"){h=true;break}}}catch(err){}if(!h&&window.dataLayer.length)window.dataLayer.unshift(["consent","default",d]);window.gtag=function(){window.dataLayer.push(arguments)};if(!h)window.gtag("consent","default",d);var a=document.cookie.match(/(^|)cookiepilot_consent=([^;]+)/);if(a){try{var e=JSON.parse(decodeURIComponent(a[2]));window.gtag("consent","update",{analytics_storage:e.analytics?"granted":"denied",ad_storage:e.marketing?"granted":"denied",ad_user_data:e.marketing?"granted":"denied",ad_personalization:e.marketing?"granted":"denied",functionality_storage:e.preferences?"granted":"denied",personalization_storage:e.preferences?"granted":"denied",security_storage:"granted"})}catch(err){}}})();</script>
Ovaj inline isječak odmah postavlja sve kategorije na denied (uz wait_for_update: 500), pa je zadano stanje Google Consent Modea v2 spremno prije nego što se išta drugo učita. Za korisnika koji se vraća odmah iščitava spremljenu privolu iz kolačića i šalje consent update.
Korak 2b: Skripta bannera. Dodajte odmah nakon inline stuba:
<!-- CookiePilot -->
<script async src="https://cdn.cookiepilot.io/cookiepilot.js" data-cpkey="TWOJ_KLUCZ"></script>
Korak 3: Konfiguracija bannera
U nadzornoj ploči: Domena → Konfiguracija → Izgled:
- pozicija bannera (gore, dolje, modal),
- boje i tekstovi,
- plutajući gumb „Postavke kolačića” za korisnike koji se vraćaju.
Integracija s Google Tag Managerom
Putem GTM-a instalirate CookiePilot jednim Custom HTML tagom koji odmah postavlja zadane privole i učitava banner u najranijoj fazi GTM-a. Ne trebate zasebnu stub datoteku ni drugi tag.
Tag: CookiePilot - Consent Init + Banner
U GTM-u izradite Custom HTML tag (Tagovi → Novi → Prilagođeni HTML kod) i zalijepite:
<script>"use strict";
(function() {
window.dataLayer=window.dataLayer||[];var d={ad_storage:"denied",ad_user_data:"denied",ad_personalization:"denied",analytics_storage:"denied",functionality_storage:"denied",personalization_storage:"denied",security_storage:"granted",wait_for_update:500},h=false;try{for(var i=0;i<window.dataLayer.length;i++){var x=window.dataLayer[i];if(x&&x[0]==="consent"&&x[1]==="default"){h=true;break}}}catch(err){}if(!h&&window.dataLayer.length)window.dataLayer.unshift(["consent","default",d]);window.gtag=function(){window.dataLayer.push(arguments)};if(!h)window.gtag("consent","default",d);var a=document.cookie.match(/(^|)cookiepilot_consent=([^;]+)/);if(a){try{var e=JSON.parse(decodeURIComponent(a[2]));window.gtag("consent","update",{analytics_storage:e.analytics?"granted":"denied",ad_storage:e.marketing?"granted":"denied",ad_user_data:e.marketing?"granted":"denied",ad_personalization:e.marketing?"granted":"denied",functionality_storage:e.preferences?"granted":"denied",personalization_storage:e.preferences?"granted":"denied",security_storage:"granted"})}catch(err){}}
var s = document.createElement('script');
s.src = 'https://cdn.cookiepilot.io/cookiepilot.js?cpkey=' + encodeURIComponent('TWOJ_KLUCZ');
document.head.appendChild(s);
})();
</script>
Okidač: Consent Initialization - All Pages. Tag se mora pokrenuti jednom po stranici. Google tagovi (GA4, Google Ads), Facebook Pixel i ostali marketinški tagovi NE koriste okidač Consent Initialization, već se pokreću kasnije (Consent Checks ili okidač ovisan o privoli). Spremite tag i objavite GTM kontejner.
Redoslijed i okidači
| Redoslijed | Tag | Okidač |
|---|---|---|
| 1 | CookiePilot - Consent Init + Banner | Consent Initialization - All Pages |
| 2 | GA4, Google Ads, UET | All Pages (Consent Mode sam obrađuje privole) |
| 3 | Facebook Pixel, TikTok, LinkedIn itd. | Custom Event cookiepilot_consent_update + uvjet privole (vidi niže) |
Tagovi izvan Googlea (Facebook Pixel, TikTok, LinkedIn)
Google Consent Mode obrađuje samo Google tagove. Za ostale skripte widget pri svakoj promjeni privole pusha u dataLayer event:
dataLayer.push({
event: 'cookiepilot_consent_update',
cookiepilot_consent: {
necessary: true,
analytics: true,
marketing: true,
preferences: false
}
});
Event se šalje i pri svakom dolasku korisnika koji se vraća (kada widget iščita kolačić s privolom), pa će okidač u GTM-u proraditi pri svakom posjetu, ne samo pri prvoj odluci.
Zajednički obrazac (postavlja se jednom)
Ova tri elementa konfigurirate jednom, a zatim ih koristite za sve tagove izvan Googlea.
- Okidač (Triggers → New → Custom Event): naziv eventa
cookiepilot_consent_update. Bez uvjeta, bez „Once per page” (tag se mora moći ponovno pokrenuti nakon promjene odluke). - Data Layer Variable za svaku kategoriju koju koristite:
- Name
cookiepilot_consent.marketing→ varijabla npr.dlv.cp_marketing - Name
cookiepilot_consent.analytics→ varijabla npr.dlv.cp_analytics - Name
cookiepilot_consent.preferences→ varijabla npr.dlv.cp_preferences
- Name
- Trigger Group ili uvjet u okidaču:
dlv.cp_marketing equals true(za marketinške tagove) ili odgovarajuće polje.
U svakom od sljedećih primjera Trigger je isti Custom Event s dodanim uvjetom na odgovarajuću varijablu.
Facebook Pixel
Tag u GTM-u: 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>
- Okidač:
cookiepilot_consent_update+ uvjetdlv.cp_marketing equals true. - Tag firing options: Once per page.
Opcionalno, za potpunu usklađenost s Facebook Limited Data Use, dodajte drugi tag koji poziva fbq('consent','revoke') s okidačem dlv.cp_marketing equals false.
TikTok Pixel
Tag u GTM-u: 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>
- Okidač:
cookiepilot_consent_update+ uvjetdlv.cp_marketing equals true. - Tag firing options: Once per page.
ttq.grantConsent() je novi TikTok API (od 2024.). Bez njega TikTok dobiva hashirane podatke bez privole, što krši uvjete.
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>
- Okidač:
cookiepilot_consent_update+ uvjetdlv.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>
- Okidač:
cookiepilot_consent_update+ uvjetdlv.cp_analytics equals true. - Tag firing options: Once per page.
Hotjar spada pod analytics, ne marketing (mjeri ponašanje, a ne oglase). Provjerite vlastitu politiku kolačića; neke tvrtke Hotjar klasificiraju drugačije.
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>
- Okidač:
cookiepilot_consent_update+ uvjetdlv.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>
- Okidač:
cookiepilot_consent_update+ uvjetdlv.cp_marketing equals true. - Tag firing options: Once per page.
Microsoft Ads (UET)
UET podržava Google Consent Mode od kraja 2023., pa vam ne treba Custom Event okidač. Umetnite tag na standardan način (All Pages, Once per page), a UET sam čita ad_storage iz GCM-a koji postavlja widget.
Mapiranje kategorija (sažetak)
| Tag | Kategorija | Polje u 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 okidača) | obrađuje gtag('consent','update') |
API Reference
CookiePilot izlaže objekt window.CookiePilot:
| Metoda | Opis |
|---|---|
CookiePilot.getConsent() | Trenutno stanje privola ili null ako odluke nema. |
CookiePilot.acceptAll() | Privola za sve kategorije. |
CookiePilot.rejectAll() | Odbija sve osim necessary. |
CookiePilot.updateConsent(partial) | Ažurira odabrane kategorije, npr. { analytics: true }. |
CookiePilot.showSettings() | Otvara modal s preferencijama. |
CookiePilot.hideSettings() | Zatvara modal s preferencijama. |
CookiePilot.showMyConsent() / hideMyConsent() | Prikazuje/skriva plutajući gumb. |
Primjer
const consent = CookiePilot.getConsent();
// { necessary: true, analytics: true, marketing: false, preferences: false }
CookiePilot.updateConsent({ analytics: true });
document.getElementById('cookie-settings').addEventListener('click', () => {
CookiePilot.showSettings();
});
Poveznica „Upravljanje kolačićima” u podnožju
<a href="#" onclick="CookiePilot.showSettings(); return false;">Upravljanje kolačićima</a>
JavaScript eventi
Widget dispatcha nativni event cookiepilot:consent na window. Listener mora biti registriran prije učitavanja widgeta ako želite uhvatiti event za korisnika koji se vraća (dispatch se šalje odmah nakon pokretanja widgeta):
<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 sadrži isti payload kao getConsent(). Za integraciju putem GTM-a umjesto toga koristite dataLayer event opisan ranije, jer je dataLayer persistentno polje pa GTM hvata i povijesne evente.
Kategorije privola
| Kategorija | Opis | Zadano |
|---|---|---|
necessary | Nužni za rad stranice | Uvijek aktivni |
analytics | Statistika i analitika | Potrebna privola |
marketing | Oglasi i remarketing | Potrebna privola |
preferences | Personalizacija, jezik | Potrebna privola |
Mapiranje na Google Consent Mode
| Kategorija CookiePilot | Polja Consent Mode |
|---|---|
analytics | analytics_storage |
marketing | ad_storage, ad_user_data, ad_personalization |
preferences | functionality_storage, personalization_storage |
| (uvijek) | security_storage: granted |
Google Consent Mode v2
Verzija 2 dodala je ad_user_data i ad_personalization (obavezni od ožujka 2024. za EU/EEA kod Google oglasa).
| Parametar | Opis |
|---|---|
ad_storage | Oglasni kolačići |
analytics_storage | Analitički kolačići |
ad_user_data | Slanje korisničkih podataka Googleu |
ad_personalization | Personalizacija oglasa |
functionality_storage | Funkcionalni kolačići |
personalization_storage | Personalizacijski kolačići |
security_storage | Uvijek granted |
Mehanizam:
- Stub sinkrono postavlja sva polja na
denied, uzwait_for_update: 500. - Nakon odluke korisnika widget pušta
gtag('consent', 'update', {...})s mapiranjem iznad. - Za korisnika koji se vraća točka 2 šalje se odmah nakon pokretanja widgeta, na temelju kolačića.
Konfiguracija izgleda
U nadzornoj ploči: Domena → Konfiguracija:
- Izgled: pozicija, boje, raspored (BAR / BOX / MODAL).
- Tekstovi: naslov, opis, oznake gumba, opisi kategorija. 13 jezika (EN, PL, DE, FR, ES, IT, NL, PT, SV, CS, RO, EL, HU).
- Gumb za privole: plutajući gumb „Postavke kolačića” vidljiv nakon prve odluke (donji lijevi/desni kut).
- Custom CSS: polje za vlastite stilove. Widget se renderira u Shadow DOM-u, pa CSS selektori iz glavnog dokumenta neće djelovati. Samo putem ovog polja.
Pristupačnost (WCAG 2.1 AA)
- ✅ Navigacija tipkovnicom (Tab, Shift+Tab, Enter, Escape).
- ✅ ARIA labels, role="dialog", aria-modal.
- ✅ Focus trap u modalu.
- ✅ Čitač zaslona (live regions pri promjeni stanja).
- ✅ Responzivnost.
Integracije
WordPress
Imamo službeni dodatak: CookiePilot na WordPress.org.
- WordPress admin → Dodaci → Dodaj novi → potražite „CookiePilot”.
- Instalirajte i aktivirajte.
- Postavke → CookiePilot → zalijepite API ključ iz nadzorne ploče.
Dodatak sam umeće stub i tag u <head> (s ispravnim redoslijedom prije ostalih skripti) i izlaže shortcode [cookiepilot_settings] za poveznicu „Upravljanje kolačićima” u podnožju.
Ako radije bez dodatka: upotrijebite „Insert Headers and Footers” i zalijepite isječak iz koraka 2 Brzog početka u sekciju Header.
Shopify
- Trgovina → Teme → Uredi kod.
- U
theme.liquidzalijepite isječak prije</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" osigurava da se skripta bannera izvrši rano. Imajte na umu da inline stub iz Koraka 2a (zadane privole) dodajete zasebno, u <head> prije te skripte, npr. putem next/script s dangerouslySetInnerHTML ili izravno u app/layout.tsx.
FAQ
Usporava li skripta stranicu?
Bundle je oko 12 KB gzip, učitava se asinkrono. Bez utjecaja na Core Web Vitals.
Koliko se dugo čuvaju privole?
Kolačić s odlukom korisnika: zadano 365 dana (može se konfigurirati u nadzornoj ploči). Događaji u analitici: 2 godine (TTL u ClickHouseu).
Šalje li se event cookiepilot_consent_update za korisnika koji se vraća?
Da. Widget iščitava kolačić pri pokretanju i pusha event u dataLayer. Custom Event okidač u GTM-u proradit će pri svakom posjetu, ne samo pri prvoj odluci.
Gdje prijaviti problem?
kontakt@cookiepilot.io ili chat u nadzornoj ploči.
Kontrolna lista za testiranje nakon implementacije
Nakon instalacije CookiePilota provjerite konfiguraciju prije pokretanja oglasnih kampanja.
1. Test prije privole korisnika
- Otvorite stranicu u anonimnom (incognito) načinu i očistite kolačiće za domenu.
- Otvorite DevTools → Network i osvježite stranicu.
- Prije klika na privolu provjerite da:
- ne nastaju analitički/marketinški kolačići, npr.
_ga,_gcl_*,_fbp,_ttp, - marketinški tagovi ne šalju zahtjeve prema Meti/TikToku/LinkedInu prije marketinške privole,
- je u
dataLayerpostavljeno zadano stanjedeniedzaad_storage,ad_user_data,ad_personalizationianalytics_storage.
- ne nastaju analitički/marketinški kolačići, npr.
2. Test nakon prihvaćanja privola
- Kliknite „Prihvati sve”.
- U DevToolsu provjerite je li se pojavio event
cookiepilot_consent_update. - Za Google tagove provjerite u GTM Preview / Tag Assistant je li Consent Mode promijenio stanje na
grantedza odgovarajuće kategorije. - Za GA4 provjerite u DebugViewu jesu li eventi počeli stizati nakon privole.
- Za Meta Pixel / TikTok / LinkedIn provjerite pokreću li se tagovi tek nakon eventa
cookiepilot_consent_updatei uvjeta marketinške privole.
3. Test odbijanja privola
- Očistite kolačiće i osvježite stranicu.
- Kliknite „Odbij sve”.
- Provjerite da se marketinški kolačići i zahtjevi i dalje ne pokreću.
- Provjerite da nužne funkcije stranice i dalje rade.
4. Najčešće pogreške
- Tag GA4/Google Ads pokreće se na
Consent Initializationumjesto na kasnijem okidaču. - Meta Pixel ili TikTok Pixel nema uvjet na
cookiepilot_consent.marketing. - Na stranici je ostao stari, hardkodirani tracker u
<head>prije CookiePilota. - U dokumentaciji ili predlošku ostao je zastarjeli URL skripte ili stari atribut identifikatora umjesto aktualnog
cookiepilot.jssdata-cpkey.