Въведение
CookiePilot е платформа за управление на съгласията за бисквитки (CMP), съвместима с ОРЗД (Общия регламент относно защитата на данните), българския Закон за електронните съобщения и Google Consent Mode v2. Спазването на тези изисквания се следи от Комисията за защита на личните данни (КЗЛД).
За кого е предназначена
- Собственици на сайтове: внедряване без програмиране.
- Разработчици: API, събития, интеграции с GTM.
- Агенции: white-label, управление на множество домейни.
Бърз старт
Стъпка 1: Регистрация
- Създайте акаунт на app.cookiepilot.io/register.
- Добавете домейн в панела и копирайте 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 веднага задава всички категории на denied (с wait_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 файл или втори таг.
Таг: CookiePilot - Consent Init + Banner
В 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 |
|---|---|---|
| 1 | CookiePilot - Consent Init + Banner | Consent Initialization - All Pages |
| 2 | GA4, Google Ads, UET | All Pages (Consent Mode сам обработва съгласията) |
| 3 | Facebook 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.
- Trigger (Triggers → New → Custom Event): име на събитието
cookiepilot_consent_update. Без условия, без „Once per page“ (тагът трябва да може да се задейства отново след промяна на решението). - Data Layer Variable за всяка категория, която използвате:
- Name
cookiepilot_consent.marketing→ променлива напр.dlv.cp_marketing - Name
cookiepilot_consent.analytics→ променлива напр.dlv.cp_analytics - Name
cookiepilot_consent.preferences→ променлива напр.dlv.cp_preferences
- Name
- 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 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, без 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 | Персонализация, език | Изисква съгласие |
Съответствие с Google Consent Mode
| Категория на CookiePilot | Полета на Consent Mode |
|---|---|
analytics | analytics_storage |
marketing | ad_storage, ad_user_data, ad_personalization |
preferences | functionality_storage, personalization_storage |
| (винаги) | security_storage: granted |
Google Consent Mode v2
Версия 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 |
Механизъм:
- Stub-ът задава всички полета на
deniedсинхронно, сwait_for_update: 500. - След решението на потребителя уиджетът изпраща
gtag('consent', 'update', {...})със съответствието по-горе. - За връщащ се потребител точка 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.
- WordPress админ → Приставки → Добави нова → потърсете „CookiePilot“.
- Инсталирайте и активирайте.
- Настройки → CookiePilot → поставете API ключа от панела.
Приставката сама вмъква stub-а и тага в <head> (в правилния ред преди другите скриптове) и предоставя shortcode [cookiepilot_settings] за връзката „Управление на бисквитките“ в долния колонтитул.
Ако предпочитате без приставка: използвайте „Insert Headers and Footers“ и поставете snippet-а от стъпка 2 на Бързия старт в секцията Header.
Shopify
- Магазин → Теми → Редактиране на кода.
- В
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).
Изпраща ли се събитието cookiepilot_consent_update за връщащ се потребител?
Да. Уиджетът прочита бисквитката при старт и изпраща събитието в dataLayer. Trigger-ът Custom Event в GTM ще се задейства при всяко посещение, а не само при първото решение.
Къде да съобщя за проблем?
kontakt@cookiepilot.io или чат в панела.
Тестов чеклист след внедряване
След инсталирането на CookiePilot проверете конфигурацията, преди да публикувате рекламни кампании.
1. Тест преди съгласието на потребителя
- Отворете сайта в режим „инкогнито“ и изчистете бисквитките за домейна.
- Отворете DevTools → Network и опреснете страницата.
- Преди да щракнете върху съгласие, проверете, че:
- не се създават аналитични/маркетингови бисквитки, напр.
_ga,_gcl_*,_fbp,_ttp, - маркетинговите тагове не изпращат заявки към Meta/TikTok/LinkedIn преди маркетинговото съгласие,
- в
dataLayerе зададено състоянието по подразбиранеdeniedзаad_storage,ad_user_data,ad_personalizationиanalytics_storage.
- не се създават аналитични/маркетингови бисквитки, напр.
2. Тест след приемане на съгласията
- Щракнете върху „Приемам всички“.
- В DevTools проверете дали се е появило събитието
cookiepilot_consent_update. - За таговете на Google проверете в GTM Preview / Tag Assistant дали Consent Mode е променил състоянието на
grantedза съответните категории. - За GA4 проверете в DebugView дали събитията са започнали да пристигат след съгласието.
- За Meta Pixel / TikTok / LinkedIn проверете дали таговете се задействат едва след събитието
cookiepilot_consent_updateи условието за маркетингово съгласие.
3. Тест на отхвърляне на съгласията
- Изчистете бисквитките и опреснете страницата.
- Щракнете върху „Отхвърлям всички“.
- Проверете, че маркетинговите бисквитки и заявки все още не се задействат.
- Проверете, че необходимите функции на сайта продължават да работят.
4. Най-чести грешки
- Тагът GA4/Google Ads се задейства на
Consent Initializationвместо на по-късен trigger. - Meta Pixel или TikTok Pixel няма условие за
cookiepilot_consent.marketing. - На сайта е останал стар, твърдо кодиран тракер в
<head>преди CookiePilot. - В документацията или шаблона е останал неактуален URL на скрипта или стар атрибут за идентификатор вместо актуалния
cookiepilot.jsсdata-cpkey.