Introduktion
CookiePilot är en plattform för samtyckeshantering (CMP), i linje med GDPR, lagen om elektronisk kommunikation (2022:482) och Google Consent Mode v2. I Sverige är det Integritetsskyddsmyndigheten (IMY) som utövar tillsyn över de här reglerna.
Vem den är för
- Webbplatsägare: driftsätt utan att skriva en rad kod.
- Utvecklare: API, händelser, GTM-integrationer.
- Byråer: white-label, hantering av flera domäner.
Snabbstart
Steg 1: Registrera dig
- Skapa ett konto på app.cookiepilot.io/register.
- Lägg till din domän i panelen och kopiera API-nyckeln (formatet
cp_live_...).
Steg 2: Installera koden
En direkt installation är två skript i <head>, i den här ordningen.
Steg 2a: Standardsamtycke (inline-stub). Klistra in det här först, före alla andra skript (cookiepilot.js, GA, GTM, annons- och spårningstaggar):
<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>
Det här inline-snippet sätter omedelbart varje kategori till denied (med wait_for_update: 500), så att standardläget för Google Consent Mode v2 är klart innan något annat laddas. För en återvändande besökare läser det det sparade samtycket direkt från cookien och avfyrar en consent update.
Steg 2b: Bannerskript. Lägg till det här direkt efter inline-stubben:
<!-- CookiePilot -->
<script async src="https://cdn.cookiepilot.io/cookiepilot.js" data-cpkey="TWOJ_KLUCZ"></script>
Steg 3: Konfigurera bannern
I panelen: Domän → Konfiguration → Utseende:
- bannerns position (topp, botten, modal),
- färger och texter,
- en flytande knapp "Cookie-inställningar" för återvändande besökare.
Integration med Google Tag Manager
Genom GTM installerar du CookiePilot med en enda Custom HTML-tagg som sätter standardläget för samtycke och laddar bannern i GTM:s tidigaste fas. Du behöver ingen separat stub-fil eller en andra tagg.
Tagg: CookiePilot - Consent Init + Banner
I GTM, skapa en Custom HTML-tagg (Tags → New → Custom HTML) och klistra in:
<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. Taggen måste avfyras en gång per sida. Google-taggar (GA4, Google Ads), Facebook Pixel och andra marknadstaggar använder INTE triggern Consent Initialization; de avfyras senare (Consent Checks eller en samtyckesberoende trigger). Spara taggen och publicera GTM-containern.
Ordning och triggers
| Ordning | Tagg | Trigger |
|---|---|---|
| 1 | CookiePilot - Consent Init + Banner | Consent Initialization - All Pages |
| 2 | GA4, Google Ads, UET | All Pages (Consent Mode sköter samtycket själv) |
| 3 | Facebook Pixel, TikTok, LinkedIn m.fl. | Custom Event cookiepilot_consent_update + samtyckesvillkor (se nedan) |
Taggar utanför Google (Facebook Pixel, TikTok, LinkedIn)
Google Consent Mode täcker bara Google-taggar. För varje annat skript pushar widgeten en händelse till dataLayer vid varje samtyckesändring:
dataLayer.push({
event: 'cookiepilot_consent_update',
cookiepilot_consent: {
necessary: true,
analytics: true,
marketing: true,
preferences: false
}
});
Händelsen avfyras också vid varje besök från en återvändande användare (när widgeten läser samtyckescookien), så GTM-triggern fungerar vid varje besök, inte bara vid det första beslutet.
Gemensamt mönster (gör det här en gång)
Du konfigurerar de här tre delarna en gång och återanvänder dem sedan för alla taggar utanför Google.
- Trigger (Triggers → New → Custom Event): Event name
cookiepilot_consent_update. Inga villkor, inget "Once per page" (taggen måste kunna avfyras igen efter ett ändrat beslut). - Data Layer Variable för varje kategori du använder:
- Name
cookiepilot_consent.marketing→ variabel t.ex.dlv.cp_marketing - Name
cookiepilot_consent.analytics→ variabel t.ex.dlv.cp_analytics - Name
cookiepilot_consent.preferences→ variabel t.ex.dlv.cp_preferences
- Name
- Trigger Group eller ett villkor på triggern:
dlv.cp_marketing equals true(för marknadstaggar) eller det relevanta fältet.
I vart och ett av exemplen nedan är Trigger samma Custom Event med ett villkor tillagt på rätt variabel.
Facebook Pixel
Tagg i 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+ villkordlv.cp_marketing equals true. - Tag firing options: Once per page.
Valfritt, för full efterlevnad med Facebook Limited Data Use, lägg till en andra tagg som anropar fbq('consent','revoke') med triggern dlv.cp_marketing equals false.
TikTok Pixel
Tagg i 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+ villkordlv.cp_marketing equals true. - Tag firing options: Once per page.
ttq.grantConsent() är TikToks nya API (infört 2024). Utan det tar TikTok emot hashade data utan samtycke, vilket bryter mot villkoren.
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+ villkordlv.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+ villkordlv.cp_analytics equals true. - Tag firing options: Once per page.
Hotjar hör under analytics, inte marketing (det mäter beteende, inte annonser). Kontrollera din egen cookiepolicy, en del företag klassificerar Hotjar annorlunda.
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+ villkordlv.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+ villkordlv.cp_marketing equals true. - Tag firing options: Once per page.
Microsoft Ads (UET)
UET har stött Google Consent Mode sedan slutet av 2023, så du behöver ingen Custom Event-trigger. Lägg till taggen på vanligt sätt (All Pages, Once per page) och UET läser ad_storage från GCM själv, det som widgeten sätter.
Kategorimappning (sammanfattning)
| Tagg | Kategori | Fält i 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, ingen trigger) | hanteras av gtag('consent','update') |
API-referens
CookiePilot exponerar objektet window.CookiePilot:
| Metod | Beskrivning |
|---|---|
CookiePilot.getConsent() | Det aktuella samtyckesläget, eller null om inget beslut fattats. |
CookiePilot.acceptAll() | Samtyck till alla kategorier. |
CookiePilot.rejectAll() | Avvisar allt utom necessary. |
CookiePilot.updateConsent(partial) | Uppdaterar valda kategorier, t.ex. { analytics: true }. |
CookiePilot.showSettings() | Öppnar inställningsmodalen. |
CookiePilot.hideSettings() | Stänger inställningsmodalen. |
CookiePilot.showMyConsent() / hideMyConsent() | Visar/döljer den flytande knappen. |
Exempel
const consent = CookiePilot.getConsent();
// { necessary: true, analytics: true, marketing: false, preferences: false }
CookiePilot.updateConsent({ analytics: true });
document.getElementById('cookie-settings').addEventListener('click', () => {
CookiePilot.showSettings();
});
Länk "Hantera cookies" i sidfoten
<a href="#" onclick="CookiePilot.showSettings(); return false;">Hantera cookies</a>
JavaScript-händelser
Widgeten skickar en nativ cookiepilot:consent-händelse på window. Lyssnaren måste registreras innan widgeten laddas om du vill fånga händelsen för en återvändande besökare (utskicket sker omedelbart när widgeten startar):
<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 innehåller samma payload som getConsent(). För GTM-baserade integrationer, använd dataLayer-händelsen som beskrivs ovan i stället för den här, eftersom dataLayer är en persistent array och GTM plockar upp historiska händelser.
Samtyckeskategorier
| Kategori | Beskrivning | Standard |
|---|---|---|
necessary | Krävs för att webbplatsen ska fungera | Alltid på |
analytics | Statistik och analys | Kräver samtycke |
marketing | Annonsering och remarketing | Kräver samtycke |
preferences | Personalisering, språk | Kräver samtycke |
Mappning till Google Consent Mode
| CookiePilot-kategori | Consent Mode-fält |
|---|---|
analytics | analytics_storage |
marketing | ad_storage, ad_user_data, ad_personalization |
preferences | functionality_storage, personalization_storage |
| (alltid) | security_storage: granted |
Google Consent Mode v2
Version 2 lade till ad_user_data och ad_personalization (obligatoriskt sedan mars 2024 i EU/EES för Google-annonsering).
| Parameter | Beskrivning |
|---|---|
ad_storage | Annonscookies |
analytics_storage | Analyscookies |
ad_user_data | Att skicka användardata till Google |
ad_personalization | Annonspersonalisering |
functionality_storage | Funktionella cookies |
personalization_storage | Personaliseringscookies |
security_storage | Alltid granted |
Så fungerar det:
- Stubben sätter varje fält till
deniedsynkront, medwait_for_update: 500. - Efter användarens beslut avfyrar widgeten
gtag('consent', 'update', {...})med mappningen ovan. - För en återvändande besökare avfyras steg 2 omedelbart när widgeten startar, baserat på cookien.
Konfiguration av utseende
I panelen: Domän → Konfiguration:
- Utseende: position, färger, layout (BAR / BOX / MODAL).
- Texter: rubrik, beskrivning, knapptexter, kategoribeskrivningar. 13 språk (EN, PL, DE, FR, ES, IT, NL, PT, SV, CS, RO, EL, HU).
- Samtyckesknapp: en flytande knapp "Cookie-inställningar" som visas efter det första beslutet (nere till vänster/höger).
- Egen CSS: ett fält för dina egna stilar. Widgeten renderas i Shadow DOM, så CSS-selektorer från huvuddokumentet fungerar inte. Använd bara det här fältet.
Tillgänglighet (WCAG 2.1 AA)
- ✅ Tangentbordsnavigering (Tab, Shift+Tab, Enter, Escape).
- ✅ ARIA-etiketter, role="dialog", aria-modal.
- ✅ Focus trap i modalen.
- ✅ Stöd för skärmläsare (live regions vid tillståndsändring).
- ✅ Responsiv design.
Integrationer
WordPress
Vi har ett officiellt plugin: CookiePilot på WordPress.org.
- WordPress-admin → Tillägg → Lägg till nytt → sök efter "CookiePilot".
- Installera och aktivera.
- Inställningar → CookiePilot → klistra in API-nyckeln från panelen.
Pluginet lägger själv in stubben och taggen i <head> (i rätt ordning, före andra skript) och tillhandahåller en shortcode [cookiepilot_settings] för en "Hantera cookies"-länk i sidfoten.
Om du föredrar att inte använda pluginet, använd "Insert Headers and Footers" och klistra in snippet från steg 2 i Snabbstarten i Header-sektionen.
Shopify
- Butik → Teman → Redigera kod.
- I
theme.liquid, klistra in snippet före</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" säkerställer att bannerskriptet körs tidigt. Kom ihåg att inline-stubben från steg 2a (standardsamtycke) läggs till separat, i <head> före det här skriptet, till exempel via next/script med dangerouslySetInnerHTML eller direkt i app/layout.tsx.
Vanliga frågor
Saktar skriptet ner webbplatsen?
Bundeln är omkring 12 KB gzippad och laddas asynkront. Ingen påverkan på Core Web Vitals.
Hur länge lagras samtycket?
Användarens beslutscookie: 365 dagar som standard (konfigurerbart i panelen). Analyshändelser: 2 år (ClickHouse-TTL).
Avfyras händelsen cookiepilot_consent_update för återvändande besökare?
Ja. Widgeten läser cookien vid start och pushar händelsen till dataLayer. Custom Event-triggern i GTM avfyras vid varje besök, inte bara vid det första beslutet.
Var rapporterar jag ett problem?
kontakt@cookiepilot.io eller chatten i panelen.
Testchecklista efter driftsättning
När CookiePilot är installerat, verifiera konfigurationen innan du drar igång annonskampanjer.
1. Testa innan användaren ger samtycke
- Öppna webbplatsen i inkognitoläge och rensa cookies för domänen.
- Öppna DevTools → Network och ladda om sidan.
- Innan du klickar på samtycke, bekräfta att:
- inga analys-/marknadscookies skapas, t.ex.
_ga,_gcl_*,_fbp,_ttp, - marknadstaggar inte skickar requests till Meta/TikTok/LinkedIn före marknadssamtycke,
dataLayerhar standardlägetdeniedförad_storage,ad_user_data,ad_personalizationochanalytics_storage.
- inga analys-/marknadscookies skapas, t.ex.
2. Testa efter att samtycke accepterats
- Klicka på "Acceptera alla".
- Kontrollera i DevTools att händelsen
cookiepilot_consent_updatedök upp. - För Google-taggar, kontrollera i GTM Preview / Tag Assistant att Consent Mode växlade läget till
grantedför de relevanta kategorierna. - För GA4, kontrollera DebugView för att bekräfta att händelser börjar komma in efter samtycke.
- För Meta Pixel / TikTok / LinkedIn, kontrollera att taggarna bara avfyras efter händelsen
cookiepilot_consent_updateoch marknadssamtyckesvillkoret.
3. Testa att avvisa samtycke
- Rensa cookies och ladda om sidan.
- Klicka på "Avvisa alla".
- Bekräfta att marknadscookies och requests fortfarande inte utlöses.
- Bekräfta att webbplatsens grundläggande funktioner fortfarande fungerar.
4. Vanliga misstag
- GA4/Google Ads-taggen avfyras på
Consent Initializationi stället för en senare trigger. - Meta Pixel eller TikTok Pixel saknar villkor på
cookiepilot_consent.marketing. - En gammal, hårdkodad tracker ligger fortfarande i
<head>före CookiePilot. - Dokumentationen eller mallen har fortfarande en föråldrad skript-URL eller ett gammalt identifierarattribut i stället för den aktuella
cookiepilot.jsmeddata-cpkey.
Samtyckesbevis, exporter och DSAR
CookiePilot registrerar samtyckeshändelser så att du kan rekonstruera sammanhanget kring ett besökarbeslut. En post kan innehålla händelsens tidpunkt, händelsetyp, domän, sid- eller käll-URL, samtyckesversion, kategorier och consent string när sådan finns, anonymiserad IP-adress, user-agent-hash, enhetstyp och webbläsare.
Exporter
- Besökarens samtyckesbevis: JSON, CSV eller utskrivbar HTML.
- Domänens revisionslogg: CSV eller JSON för ett valt datumintervall.
- Exporterna är begränsade till din organisation och till de domäner du har åtkomst till.
DSAR-flöde
En Owner eller Admin kan starta en begäran om dataåtkomst från en samtyckesrad eller från DSAR-sidan i panelen. Panelen hittar besökarens händelser, visar intervallet och låter dig ladda ner bevisfiler. En raderingsbegäran kräver ett skäl och loggas i organisationens aktivitetsspår.
Begränsningar
Domänens revisionsexporter använder det valda datumintervallet och kan trunkeras för mycket stora resultatmängder. Lagringen av samtyckesloggen följer den aktiva planen och kontopolicyn, så den publika dokumentationen utlovar inte ett fast antal år.