Documentatie

CookiePilot-documentatie

De complete gids voor het installeren, configureren en integreren van CookiePilot op je site.

Kies je installatiemethodeProbeer de interactieve demo

Introductie

CookiePilot is een consent management platform (CMP) dat aansluit op de AVG, artikel 11.7a van de Telecommunicatiewet (de cookiebepaling) en Google Consent Mode v2. In Nederland houdt de Autoriteit Persoonsgegevens (AP) toezicht op deze regels.

Voor wie

  • Site-eigenaren: uitrollen zonder een regel code.
  • Developers: API, events, GTM-integraties.
  • Bureaus: white-label, beheer van meerdere domeinen.

Snelstart

Stap 1: Registreren

  1. Maak een account aan op app.cookiepilot.io/register.
  2. Voeg je domein toe in het paneel en kopieer de API-sleutel (formaat cp_live_...).

Stap 2: Installeer de code

Een directe installatie bestaat uit twee scripts in de <head>, in deze volgorde.

Stap 2a: Standaardtoestemming (inline stub). Plak dit als eerste, vóór elk ander script (cookiepilot.js, GA, GTM, advertentie- en trackingtags):

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

Dit inline snippet zet elke categorie onmiddellijk op denied (met wait_for_update: 500), zodat de standaardstatus van Google Consent Mode v2 klaarstaat voordat iets anders laadt. Voor een terugkerende bezoeker leest het de opgeslagen toestemming rechtstreeks uit de cookie en vuurt het een consent update af.

Stap 2b: Bannerscript. Voeg dit toe direct na de inline stub:

<!-- CookiePilot -->
<script async src="https://cdn.cookiepilot.io/cookiepilot.js" data-cpkey="TWOJ_KLUCZ"></script>

Stap 3: Configureer de banner

In het paneel: Domein → Configuratie → Weergave:

  • bannerpositie (boven, onder, modal),
  • kleuren en teksten,
  • een zwevende knop "Cookie-instellingen" voor terugkerende bezoekers.

Integratie met Google Tag Manager

Via GTM installeer je CookiePilot met één Custom HTML-tag die de standaardtoestemming instelt en de banner in de vroegste GTM-fase laadt. Je hebt geen apart stub-bestand of een tweede tag nodig.

Maak in GTM een Custom HTML-tag (Tags → New → Custom HTML) en plak:

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

Trigger: Consent Initialization - All Pages. De tag moet één keer per pagina afvuren. Google-tags (GA4, Google Ads), Facebook Pixel en andere marketingtags gebruiken de Consent Initialization-trigger NIET; die vuren later af (Consent Checks of een toestemmingsafhankelijke trigger). Sla de tag op en publiceer de GTM-container.

Volgorde en triggers

VolgordeTagTrigger
1CookiePilot - Consent Init + BannerConsent Initialization - All Pages
2GA4, Google Ads, UETAll Pages (Consent Mode handelt de toestemming zelf af)
3Facebook Pixel, TikTok, LinkedIn, enz.Custom Event cookiepilot_consent_update + toestemmingsvoorwaarde (zie hieronder)

Niet-Google-tags (Facebook Pixel, TikTok, LinkedIn)

Google Consent Mode dekt alleen Google-tags. Voor elk ander script pusht de widget bij elke wijziging van de toestemming een event naar de dataLayer:

dataLayer.push({
  event: 'cookiepilot_consent_update',
  cookiepilot_consent: {
    necessary: true,
    analytics: true,
    marketing: true,
    preferences: false
  }
});

Het event vuurt ook af bij elk bezoek van een terugkerende gebruiker (zodra de widget de toestemmingscookie leest), zodat de GTM-trigger bij elk bezoek werkt, niet alleen bij de eerste keuze.

Gedeeld patroon (doe dit één keer)

Je stelt deze drie onderdelen één keer in en hergebruikt ze daarna voor alle niet-Google-tags.

  1. Trigger (Triggers → New → Custom Event): Event name cookiepilot_consent_update. Geen voorwaarden, geen "Once per page" (de tag moet opnieuw kunnen afvuren na een gewijzigde keuze).
  2. Data Layer Variable voor elke categorie die je gebruikt:
    • Name cookiepilot_consent.marketing → variabele bijv. dlv.cp_marketing
    • Name cookiepilot_consent.analytics → variabele bijv. dlv.cp_analytics
    • Name cookiepilot_consent.preferences → variabele bijv. dlv.cp_preferences
  3. Trigger Group of een voorwaarde op de trigger: dlv.cp_marketing equals true (voor marketingtags) of het relevante veld.

In elk van de onderstaande voorbeelden is de Trigger hetzelfde Custom Event met een voorwaarde toegevoegd op de juiste variabele.

Facebook Pixel

Tag in 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 + voorwaarde dlv.cp_marketing equals true.
  • Tag firing options: Once per page.

Optioneel, voor volledige naleving van Facebook Limited Data Use, voeg je een tweede tag toe die fbq('consent','revoke') aanroept met de trigger dlv.cp_marketing equals false.

TikTok Pixel

Tag in 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 + voorwaarde dlv.cp_marketing equals true.
  • Tag firing options: Once per page.

ttq.grantConsent() is de nieuwe TikTok-API (geïntroduceerd in 2024). Zonder deze aanroep ontvangt TikTok gehashte data zonder toestemming, wat de voorwaarden schendt.

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 + voorwaarde dlv.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 + voorwaarde dlv.cp_analytics equals true.
  • Tag firing options: Once per page.

Hotjar valt onder analytics, niet onder marketing (het meet gedrag, geen advertenties). Controleer je eigen cookiebeleid, sommige bedrijven classificeren Hotjar anders.

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 + voorwaarde dlv.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 + voorwaarde dlv.cp_marketing equals true.
  • Tag firing options: Once per page.

Microsoft Ads (UET)

UET ondersteunt Google Consent Mode sinds eind 2023, dus je hebt geen Custom Event-trigger nodig. Voeg de tag op de standaardmanier toe (All Pages, Once per page) en UET leest ad_storage zelf uit GCM, dat de widget instelt.

Categorie-mapping (samenvatting)

TagCategorieVeld in cookiepilot_consent
Facebook Pixelmarketingmarketing
TikTok Pixelmarketingmarketing
LinkedIn Insightmarketingmarketing
Pinterestmarketingmarketing
Hotjaranalyticsanalytics
Microsoft Clarityanalyticsanalytics
Mixpanel, Amplitudeanalyticsanalytics
Intercom, Drift, Crisppreferencespreferences
GA4, Google Ads, UET(GCM, geen trigger)afgehandeld via gtag('consent','update')

API-referentie

CookiePilot stelt het object window.CookiePilot beschikbaar:

MethodeBeschrijving
CookiePilot.getConsent()De huidige toestemmingsstatus, of null als er nog geen keuze is gemaakt.
CookiePilot.acceptAll()Toestemming voor alle categorieën.
CookiePilot.rejectAll()Weigert alles behalve necessary.
CookiePilot.updateConsent(partial)Werkt geselecteerde categorieën bij, bijv. { analytics: true }.
CookiePilot.showSettings()Opent de voorkeurenmodal.
CookiePilot.hideSettings()Sluit de voorkeurenmodal.
CookiePilot.showMyConsent() / hideMyConsent()Toont/verbergt de zwevende knop.

Voorbeeld

const consent = CookiePilot.getConsent();
// { necessary: true, analytics: true, marketing: false, preferences: false }

CookiePilot.updateConsent({ analytics: true });

document.getElementById('cookie-settings').addEventListener('click', () => {
  CookiePilot.showSettings();
});
<a href="#" onclick="CookiePilot.showSettings(); return false;">Cookies beheren</a>

JavaScript-events

De widget dispatcht een native cookiepilot:consent-event op window. De listener moet worden geregistreerd voordat de widget laadt als je het event voor een terugkerende bezoeker wilt opvangen (de dispatch vuurt meteen af zodra de widget start):

<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 bevat dezelfde payload als getConsent(). Gebruik voor GTM-integraties het dataLayer-event dat hierboven is beschreven in plaats van dit event, omdat de dataLayer een persistente array is en GTM historische events oppikt.


Toestemmingscategorieën

CategorieBeschrijvingStandaard
necessaryNodig om de site te laten werkenAltijd aan
analyticsStatistieken en analyseToestemming vereist
marketingAdvertenties en remarketingToestemming vereist
preferencesPersonalisatie, taalToestemming vereist
CookiePilot-categorieConsent Mode-velden
analyticsanalytics_storage
marketingad_storage, ad_user_data, ad_personalization
preferencesfunctionality_storage, personalization_storage
(altijd)security_storage: granted

Versie 2 voegde ad_user_data en ad_personalization toe (verplicht sinds maart 2024 in de EU/EER voor adverteren via Google).

ParameterBeschrijving
ad_storageAdvertentiecookies
analytics_storageAnalysecookies
ad_user_dataGebruikersdata naar Google sturen
ad_personalizationPersonalisatie van advertenties
functionality_storageFunctionele cookies
personalization_storagePersonalisatiecookies
security_storageAltijd granted

Hoe het werkt:

  1. De stub zet elk veld synchroon op denied, met wait_for_update: 500.
  2. Na de keuze van de gebruiker vuurt de widget gtag('consent', 'update', {...}) af met de mapping hierboven.
  3. Voor een terugkerende bezoeker vuurt stap 2 meteen af zodra de widget start, op basis van de cookie.

Weergaveconfiguratie

In het paneel: Domein → Configuratie:

  • Weergave: positie, kleuren, indeling (BAR / BOX / MODAL).
  • Teksten: kop, beschrijving, knoplabels, categoriebeschrijvingen. 13 talen (EN, PL, DE, FR, ES, IT, NL, PT, SV, CS, RO, EL, HU).
  • Toestemmingsknop: een zwevende knop "Cookie-instellingen" die na de eerste keuze wordt getoond (linksonder/rechtsonder).
  • Custom CSS: een veld voor je eigen stijlen. De widget rendert in de Shadow DOM, dus CSS-selectors uit het hoofddocument werken niet. Gebruik alleen dit veld.

Toegankelijkheid (WCAG 2.1 AA)

  • ✅ Bediening met het toetsenbord (Tab, Shift+Tab, Enter, Escape).
  • ✅ ARIA-labels, role="dialog", aria-modal.
  • ✅ Focus trap in de modal.
  • ✅ Ondersteuning voor schermlezers (live regions bij statuswijziging).
  • ✅ Responsief ontwerp.

Integraties

WordPress

We hebben een officiële plugin: CookiePilot op WordPress.org.

  1. WordPress-beheer → Plugins → Nieuwe plugin → zoek naar "CookiePilot".
  2. Installeer en activeer.
  3. Instellingen → CookiePilot → plak de API-sleutel uit het paneel.

De plugin plaatst de stub en de tag zelf in de <head> (in de juiste volgorde, vóór andere scripts) en biedt een [cookiepilot_settings]-shortcode voor een link "Cookies beheren" in de footer.

Wil je de plugin liever niet gebruiken, gebruik dan "Insert Headers and Footers" en plak het snippet uit stap 2 van de Snelstart in de sectie Header.

Shopify

  1. Shop → Thema's → Code bewerken.
  2. Plak in theme.liquid het snippet vóór </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" zorgt dat het bannerscript vroeg draait. Onthoud dat de inline stub uit Stap 2a (standaardtoestemming) apart wordt toegevoegd, in de <head> vóór dit script, bijvoorbeeld via next/script met dangerouslySetInnerHTML of rechtstreeks in app/layout.tsx.


FAQ

Vertraagt het script de site?

De bundle is ongeveer 12 KB gzipped en laadt asynchroon. Geen impact op Core Web Vitals.

Hoe lang wordt de toestemming bewaard?

De keuzecookie van de gebruiker: standaard 365 dagen (instelbaar in het paneel). Analytics-events: 2 jaar (ClickHouse TTL).

Ja. De widget leest de cookie bij het starten en pusht het event naar de dataLayer. De Custom Event-trigger in GTM vuurt bij elk bezoek af, niet alleen bij de eerste keuze.

Waar meld ik een probleem?

kontakt@cookiepilot.io of de chat in het paneel.


Testchecklist na uitrol

Zodra CookiePilot is geïnstalleerd, controleer je de configuratie voordat je advertentiecampagnes start.

1. Test voordat de gebruiker toestemming geeft

  1. Open de site in incognitomodus en wis de cookies voor het domein.
  2. Open DevTools → Network en herlaad de pagina.
  3. Bevestig vóór het klikken op toestemming dat:
    • er geen analytics-/marketingcookies worden aangemaakt, bijv. _ga, _gcl_*, _fbp, _ttp,
    • marketingtags geen verzoeken naar Meta/TikTok/LinkedIn sturen vóór marketingtoestemming,
    • de dataLayer de standaardstatus denied heeft voor ad_storage, ad_user_data, ad_personalization en analytics_storage.

2. Test na het accepteren van toestemming

  1. Klik op "Alles accepteren".
  2. Controleer in DevTools dat het cookiepilot_consent_update-event is verschenen.
  3. Controleer voor Google-tags in GTM Preview / Tag Assistant dat Consent Mode de status naar granted heeft geschakeld voor de relevante categorieën.
  4. Controleer voor GA4 in DebugView dat er events binnenkomen na toestemming.
  5. Controleer voor Meta Pixel / TikTok / LinkedIn dat de tags pas afvuren na het cookiepilot_consent_update-event en de marketingtoestemmingsvoorwaarde.

3. Test het weigeren van toestemming

  1. Wis de cookies en herlaad de pagina.
  2. Klik op "Alles weigeren".
  3. Bevestig dat marketingcookies en -verzoeken nog steeds niet worden geactiveerd.
  4. Bevestig dat de essentiële functies van de site blijven werken.

4. Veelgemaakte fouten

  • De GA4/Google Ads-tag vuurt af op Consent Initialization in plaats van op een latere trigger.
  • De Meta Pixel of TikTok Pixel heeft geen voorwaarde op cookiepilot_consent.marketing.
  • Er staat nog een oude, hardcoded tracker in de <head> vóór CookiePilot.
  • De documentatie of template heeft nog een verouderde script-URL of een oud identifier-attribuut in plaats van de huidige cookiepilot.js met data-cpkey.

Toestemmingsbewijs, exports en DSAR

CookiePilot legt toestemmingsevents vast, zodat je de context van een bezoekerskeuze kunt reconstrueren. Een record kan de tijd van het event bevatten, het type event, het domein, de pagina- of bron-URL, de toestemmingsversie, de categorieën en de consent string indien beschikbaar, het geanonimiseerde IP-adres, een hash van de user-agent, het apparaattype en de browser.

Exports

  • Bewijs van toestemming per bezoeker: JSON, CSV of afdrukbaar HTML.
  • Auditlog van het domein: CSV of JSON voor een gekozen datumbereik.
  • Exports zijn beperkt tot je organisatie en tot de domeinen waartoe je toegang hebt.

DSAR-workflow

Een Owner of Admin kan een inzageverzoek starten vanuit een toestemmingsrij of vanaf de DSAR-pagina in het paneel. Het paneel vindt de events van de bezoeker, toont het bereik en laat je de bewijsbestanden downloaden. Een verwijderingsverzoek vereist een reden en wordt vastgelegd in het activiteitenlog van de organisatie.

Beperkingen

Auditexports van een domein gebruiken het gekozen datumbereik en kunnen bij zeer grote resultaatsets worden afgekapt. De bewaartermijn van het toestemmingslog volgt het actieve plan en het accountbeleid, dus de openbare documentatie belooft geen vast aantal jaren.