Документация

Документация за разработчици

CookiePilot е платформа за управление на съгласията за бисквитки (CMP), съвместима с ОРЗД, Закона за електронните съобщения и Google Consent Mode v2.

Въведение

CookiePilot е платформа за управление на съгласията за бисквитки (CMP), съвместима с ОРЗД (Общия регламент относно защитата на данните), българския Закон за електронните съобщения и Google Consent Mode v2. Спазването на тези изисквания се следи от Комисията за защита на личните данни (КЗЛД).

За кого е предназначена

  • Собственици на сайтове: внедряване без програмиране.
  • Разработчици: API, събития, интеграции с GTM.
  • Агенции: white-label, управление на множество домейни.

Бърз старт

Стъпка 1: Регистрация

  1. Създайте акаунт на app.cookiepilot.io/register.
  2. Добавете домейн в панела и копирайте API ключа (формат cp_live_...).

Стъпка 2: Инсталиране на кода

Директната инсталация представлява два скрипта в секцията <head>, в този ред.

Стъпка 2a: Съгласия по подразбиране (inline stub). Поставете го пръв, преди всеки друг скрипт (cookiepilot.js, GA, GTM, рекламни и проследяващи тагове):

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

Този inline snippet веднага задава всички категории на deniedwait_for_update: 500), така че състоянието по подразбиране на Google Consent Mode v2 е готово, преди да се зареди каквото и да било друго. За връщащ се потребител той веднага прочита запазеното съгласие от бисквитката и изпраща consent update.

Стъпка 2b: Скрипт на банера. Добавете го непосредствено след inline stub-а:

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

Стъпка 3: Конфигуриране на банера

В панела: Домейн → Конфигурация → Външен вид:

  • позиция на банера (горе, долу, модал),
  • цветове и текстове,
  • плаващ бутон „Настройки на бисквитките“ за връщащи се потребители.

Интеграция с Google Tag Manager

Чрез GTM инсталирате CookiePilot с един Custom HTML таг, който веднага задава съгласията по подразбиране и зарежда банера в най-ранната фаза на GTM. Не са ви нужни отделен stub файл или втори таг.

В GTM създайте Custom HTML таг (Тагове → Нов → Персонализиран HTML код) и поставете:

<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. Тагът трябва да се изпълнява веднъж на страница. Таговете на Google (GA4, Google Ads), Facebook Pixel и другите маркетингови тагове НЕ използват trigger-а Consent Initialization, а се задействат по-късно (Consent Checks или trigger, зависещ от съгласието). Запазете тага и публикувайте GTM контейнера.

Ред и trigger-и

РедТагTrigger
1CookiePilot - Consent Init + BannerConsent Initialization - All Pages
2GA4, Google Ads, UETAll Pages (Consent Mode сам обработва съгласията)
3Facebook Pixel, TikTok, LinkedIn и др.Custom Event cookiepilot_consent_update + условие за съгласие (вижте по-долу)

Тагове извън Google (Facebook Pixel, TikTok, LinkedIn)

Google Consent Mode обработва само таговете на Google. За останалите скриптове уиджетът при всяка промяна на съгласието изпраща в dataLayer събитие:

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

Събитието се изпраща и при всяко влизане на връщащ се потребител (когато уиджетът прочете бисквитката със съгласието), така че trigger-ът в GTM ще се задейства при всяко посещение, а не само при първото решение.

Общ модел (изпълнете веднъж)

Тези три елемента се конфигурират веднъж, след което се използват за всички тагове извън Google.

  1. Trigger (Triggers → New → Custom Event): име на събитието cookiepilot_consent_update. Без условия, без „Once per page“ (тагът трябва да може да се задейства отново след промяна на решението).
  2. Data Layer Variable за всяка категория, която използвате:
    • Name cookiepilot_consent.marketing → променлива напр. dlv.cp_marketing
    • Name cookiepilot_consent.analytics → променлива напр. dlv.cp_analytics
    • Name cookiepilot_consent.preferences → променлива напр. dlv.cp_preferences
  3. Trigger Group или условие в trigger-а: dlv.cp_marketing equals true (за маркетингови тагове) или съответното поле.

Във всеки от примерите по-долу Trigger е същият Custom Event с добавено условие за съответната променлива.

Facebook Pixel

Таг в 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 + условие dlv.cp_marketing equals true.
  • Tag firing options: Once per page.

По избор, за пълно съответствие с Facebook Limited Data Use, добавете втори таг, който извиква fbq('consent','revoke') с trigger dlv.cp_marketing equals false.

TikTok Pixel

Таг в 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 + условие dlv.cp_marketing equals true.
  • Tag firing options: Once per page.

ttq.grantConsent() е новото API на TikTok (от 2024 г.). Без него TikTok получава хеширани данни без съгласие, което нарушава условията.

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 + условие 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 + условие dlv.cp_analytics equals true.
  • Tag firing options: Once per page.

Hotjar попада в категорията analytics, а не marketing (измерва поведение, не реклами). Проверете собствената си политика за бисквитки – някои компании класифицират Hotjar по различен начин.

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 + условие 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 + условие dlv.cp_marketing equals true.
  • Tag firing options: Once per page.

Microsoft Ads (UET)

UET поддържа Google Consent Mode от края на 2023 г., затова не ви е нужен Custom Event trigger. Поставете тага по стандартния начин (All Pages, Once per page), а UET сам чете ad_storage от GCM, което уиджетът задава.

Съответствие на категориите (накратко)

ТагКатегорияПоле в cookiepilot_consent
Facebook Pixelmarketingmarketing
TikTok Pixelmarketingmarketing
LinkedIn Insightmarketingmarketing
Pinterestmarketingmarketing
Hotjaranalyticsanalytics
Microsoft Clarityanalyticsanalytics
Mixpanel, Amplitudeanalyticsanalytics
Intercom, Drift, Crisppreferencespreferences
GA4, Google Ads, UET(GCM, без trigger)обработва се чрез gtag('consent','update')

API Reference

CookiePilot предоставя обекта window.CookiePilot:

МетодОписание
CookiePilot.getConsent()Текущо състояние на съгласията или null, ако няма решение.
CookiePilot.acceptAll()Съгласие за всички категории.
CookiePilot.rejectAll()Отхвърля всичко освен necessary.
CookiePilot.updateConsent(partial)Актуализира избрани категории, напр. { analytics: true }.
CookiePilot.showSettings()Отваря модала с предпочитания.
CookiePilot.hideSettings()Затваря модала с предпочитания.
CookiePilot.showMyConsent() / hideMyConsent()Показва/скрива плаващия бутон.

Пример

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;">Управление на бисквитките</a>

JavaScript събития

Уиджетът диспечира нативно събитие cookiepilot:consent върху window. Listener-ът трябва да бъде регистриран преди зареждането на уиджета, ако искате да уловите събитието за връщащ се потребител (dispatch-ът се случва веднага след старта на уиджета):

<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 съдържа същия payload като getConsent(). За интеграция чрез GTM използвайте dataLayer събитието, описано по-горе, вместо това, защото dataLayer е persistent array и GTM поглъща историческите събития.


Категории на съгласията

КатегорияОписаниеПо подразбиране
necessaryНеобходими за работата на сайтаВинаги активни
analyticsСтатистика и анализИзисква съгласие
marketingРеклами и ремаркетингИзисква съгласие
preferencesПерсонализация, езикИзисква съгласие
Категория на CookiePilotПолета на Consent Mode
analyticsanalytics_storage
marketingad_storage, ad_user_data, ad_personalization
preferencesfunctionality_storage, personalization_storage
(винаги)security_storage: granted

Версия 2 добави ad_user_data и ad_personalization (задължителни от март 2024 г. за ЕС/ЕИП при реклами на Google).

ПараметърОписание
ad_storageРекламни бисквитки
analytics_storageАналитични бисквитки
ad_user_dataИзпращане на потребителски данни към Google
ad_personalizationПерсонализация на рекламите
functionality_storageФункционални бисквитки
personalization_storageБисквитки за персонализация
security_storageВинаги granted

Механизъм:

  1. Stub-ът задава всички полета на denied синхронно, с wait_for_update: 500.
  2. След решението на потребителя уиджетът изпраща gtag('consent', 'update', {...}) със съответствието по-горе.
  3. За връщащ се потребител точка 2 се изпълнява веднага след старта на уиджета, въз основа на бисквитката.

Конфигуриране на външния вид

В панела: Домейн → Конфигурация:

  • Външен вид: позиция, цветове, оформление (BAR / BOX / MODAL).
  • Текстове: заглавие, описание, етикети на бутоните, описания на категориите. 13 езика (EN, PL, DE, FR, ES, IT, NL, PT, SV, CS, RO, EL, HU).
  • Бутон за съгласия: плаващ бутон „Настройки на бисквитките“, видим след първото решение (долу вляво/вдясно).
  • Custom CSS: поле за собствени стилове. Уиджетът се рендира в Shadow DOM, затова CSS селекторите от основния документ няма да работят. Само чрез това поле.

Достъпност (WCAG 2.1 AA)

  • ✅ Навигация с клавиатура (Tab, Shift+Tab, Enter, Escape).
  • ✅ ARIA labels, role="dialog", aria-modal.
  • ✅ Focus trap в модала.
  • ✅ Екранен четец (live regions при промяна на състоянието).
  • ✅ Отзивчивост.

Интеграции

WordPress

Имаме официална приставка: CookiePilot в WordPress.org.

  1. WordPress админ → Приставки → Добави нова → потърсете „CookiePilot“.
  2. Инсталирайте и активирайте.
  3. Настройки → CookiePilot → поставете API ключа от панела.

Приставката сама вмъква stub-а и тага в <head> (в правилния ред преди другите скриптове) и предоставя shortcode [cookiepilot_settings] за връзката „Управление на бисквитките“ в долния колонтитул.

Ако предпочитате без приставка: използвайте „Insert Headers and Footers“ и поставете snippet-а от стъпка 2 на Бързия старт в секцията Header.

Shopify

  1. Магазин → Теми → Редактиране на кода.
  2. В theme.liquid поставете snippet-а преди </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" гарантира, че скриптът на банера ще се изпълни рано. Не забравяйте, че inline stub-ът от Стъпка 2a (съгласия по подразбиране) се добавя отделно, в <head> преди този скрипт, напр. чрез next/script с dangerouslySetInnerHTML или директно в app/layout.tsx.


ЧЗВ

Забавя ли скриптът сайта?

Bundle-ът е около 12 KB gzip, зарежда се асинхронно. Без влияние върху Core Web Vitals.

За колко време се пазят съгласията?

Бисквитката с решението на потребителя: по подразбиране 365 дни (конфигурируемо в панела). Събитията в анализа: 2 години (TTL на ClickHouse).

Да. Уиджетът прочита бисквитката при старт и изпраща събитието в dataLayer. Trigger-ът Custom Event в GTM ще се задейства при всяко посещение, а не само при първото решение.

Къде да съобщя за проблем?

kontakt@cookiepilot.io или чат в панела.


Тестов чеклист след внедряване

След инсталирането на CookiePilot проверете конфигурацията, преди да публикувате рекламни кампании.

1. Тест преди съгласието на потребителя

  1. Отворете сайта в режим „инкогнито“ и изчистете бисквитките за домейна.
  2. Отворете DevTools → Network и опреснете страницата.
  3. Преди да щракнете върху съгласие, проверете, че:
    • не се създават аналитични/маркетингови бисквитки, напр. _ga, _gcl_*, _fbp, _ttp,
    • маркетинговите тагове не изпращат заявки към Meta/TikTok/LinkedIn преди маркетинговото съгласие,
    • в dataLayer е зададено състоянието по подразбиране denied за ad_storage, ad_user_data, ad_personalization и analytics_storage.

2. Тест след приемане на съгласията

  1. Щракнете върху „Приемам всички“.
  2. В DevTools проверете дали се е появило събитието cookiepilot_consent_update.
  3. За таговете на Google проверете в GTM Preview / Tag Assistant дали Consent Mode е променил състоянието на granted за съответните категории.
  4. За GA4 проверете в DebugView дали събитията са започнали да пристигат след съгласието.
  5. За Meta Pixel / TikTok / LinkedIn проверете дали таговете се задействат едва след събитието cookiepilot_consent_update и условието за маркетингово съгласие.

3. Тест на отхвърляне на съгласията

  1. Изчистете бисквитките и опреснете страницата.
  2. Щракнете върху „Отхвърлям всички“.
  3. Проверете, че маркетинговите бисквитки и заявки все още не се задействат.
  4. Проверете, че необходимите функции на сайта продължават да работят.

4. Най-чести грешки

  • Тагът GA4/Google Ads се задейства на Consent Initialization вместо на по-късен trigger.
  • Meta Pixel или TikTok Pixel няма условие за cookiepilot_consent.marketing.
  • На сайта е останал стар, твърдо кодиран тракер в <head> преди CookiePilot.
  • В документацията или шаблона е останал неактуален URL на скрипта или стар атрибут за идентификатор вместо актуалния cookiepilot.js с data-cpkey.