GDPR требует явного согласия пользователя до загрузки любых нерегламентированных cookie и трекеров - баннер “мы используем cookie” с одной кнопкой “Принять” этому не соответствует. На headless-сайте задача усложняется: state согласия негде хранить на сервере при статической генерации, а скрипты аналитики часто подключены напрямую в билд-пайплайн. Ниже - рабочая архитектура, которая закрывает и юридический риск, и просадку конверсии.
По данным опроса IAPP-EY за 2024 год, штрафы по GDPR в ЕС превысили 5,88 млрд евро с 2018 года, и заметная доля взысканий связана именно с cookie-практиками - отсутствием granular-согласия или трекерами, которые грузятся до клика пользователя. В проектах Exceltic.dev мы регулярно видим одну и ту же ошибку у компаний, переезжающих на международный рынок: команда подключает готовый cookie-баннер как декоративный элемент, а Google Tag Manager продолжает стрелять пикселями в фоне независимо от выбора пользователя. В этой статье - как устроить согласие технически правильно на статически генерируемом сайте, не потеряв часть конверсии на UX-трении.
Отдельная сложность headless-архитектуры: при статической генерации (Astro, Next.js SSG) на сервере нет сессии и нет пользователя в момент сборки страницы - весь state согласия должен жить и обрабатываться на клиенте, синхронно с первой отрисовкой.
Компании, выходящие на рынок ЕС или США с европейскими пользователями, регулярно ошибаются в одну из двух сторон: либо не ставят баннер вовсе и получают юридический риск, либо ставят тяжёлый баннер-стену, который блокирует контент и роняет конверсию на 15-30% на входе. Обе крайности - следствие того, что consent management решают как чисто дизайнерскую задачу, а не как архитектурную.
CMP (Consent Management Platform): сервис или скрипт, который показывает баннер согласия, хранит выбор пользователя по категориям cookie и передаёт этот выбор в скрипты аналитики и рекламы.
Почему cookie-баннер для галочки - юридический и репутационный риск
GDPR (статьи 6 и 7, в связке с ePrivacy Directive) требует, чтобы согласие было предварительным - до загрузки любых cookie, не относящихся к строго необходимым (сессия, безопасность, баланс нагрузки). Аналитика, реклама и большинство heatmap-инструментов под это не попадают.
Второе требование - granular opt-in: пользователь выбирает категории отдельно (аналитика, маркетинг, персонализация), а не одну общую кнопку “Принять всё”. Формулировка вроде “продолжая пользоваться сайтом, вы соглашаетесь” юридически не считается согласием ни по GDPR, ни по трактовке большинства регуляторов ЕС (CNIL, ICO, Datatilsynet).
Третье - равнозначный отказ. Кнопка “Отклонить всё” должна быть на баннере на том же уровне видимости, что и “Принять всё”, без дополнительных кликов через настройки. Немецкий регулятор LfD Niedersachsen и французский CNIL уже штрафовали сайты именно за асимметричный дизайн баннера - крупная зелёная кнопка согласия против мелкой серой ссылки отказа.
Репутационный риск идёт параллельно с юридическим: B2B-покупатели из ЕС и энтерпрайз-клиенты при due diligence поставщика технологий проверяют cookie-политику и реальное поведение сайта. Баннер, который не соответствует собственному тексту политики, - красный флаг для юридического отдела клиента ещё до звонка продавца.
Что теряется при наивной реализации
Самая частая ошибка - визуальный баннер без технической блокировки. Плагин показывает кнопки, но Google Tag Manager, Meta Pixel и аналитика инициализируются в <head> независимо от выбора пользователя. Формально согласие спросили, фактически - трекеры уже отправили первый hit до клика.
Вторая ошибка - cookie-стена без реального выбора: контент сайта скрыт полноэкранным оверлеем, пока пользователь не нажмёт “Принять всё”, а кнопка отказа либо отсутствует, либо ведёт в многошаговое меню настроек. Это не согласие, а принуждение - и один из самых частых поводов для жалоб в надзорные органы ЕС.
Третья - потеря состояния при статической генерации. На headless-сайте HTML страницы собирается один раз на сборке, до визита конкретного пользователя. Если разработчик пытается решить consent на уровне сервера (например, через middleware, которое решает, рендерить ли тег GTM), он упирается в то, что на этапе рендеринга статической страницы пользователя ещё нет. Решение неизбежно клиентское - и должно быть заложено в архитектуру с самого начала, а не добавлено поверх готового сайта.
В сумме это даёт сайт, который выглядит соответствующим GDPR, но по факту нарушает его - и вдобавок несёт репутационные издержки от плохого UX баннера.
Архитектура согласия на headless-сайте
На статически генерируемом сайте state согласия не может жить на сервере в момент сборки - его негде взять до визита пользователя. Практическая схема:
- Хранение - выбор пользователя пишется в cookie или
localStorageбраузера при первом взаимодействии с баннером. Cookie предпочтительнее, если нужна консистентность между сабдоменами или future server-side чтение. - CMP-скрипт - лёгкий JS-модуль (Cookiebot, Osano, CookieYes, Klaro или self-hosted решение), который рендерится сразу после гидратации страницы и блокирует остальные скрипты до получения согласия.
- Google Consent Mode v2 - механизм Google, который вместо жёсткой блокировки скрипта передаёт GTM/GA4/Google Ads сигнал о состоянии согласия по категориям (
ad_storage,analytics_storage,ad_user_data,ad_personalization). Теги технически подключены, но до согласия работают в urezanном, cookieless-режиме. - Порядок загрузки - CMP-скрипт должен быть первым в
<head>, до любого тега аналитики или рекламы. На headless-сайте это означает: тег-менеджер подключается через<Script>-компонент фреймворка со стратегиейbeforeInteractiveили её аналогом, а не просто вставлен в шаблон без контроля порядка.
Ключевое архитектурное решение - серверная блокировка тегов невозможна на чистом SSG, поэтому вся логика gating переносится на клиент и должна быть частью первого рендера, а не постфактум-скрипта, догружаемого через несколько секунд после интерактивности страницы.
Пошаговая реализация
1. Выбор CMP
Для большинства проектов на Astro или Next.js подходит готовая CMP с легковесным клиентским SDK - она закрывает юридическую сторону (актуальные тексты политик, региональные варианты баннера через геолокацию по IP) без написания собственного consent-движка с нуля. Self-hosted open-source вариант (например, Klaro) оправдан, если у компании уже есть выделенный юридический контроль над формулировками и требование не подключать сторонний скрипт вовсе.
2. Интеграция с Google Tag Manager и Consent Mode
GTM подключается с изначально заданными default consent state - все категории, кроме строго необходимых, выставлены в denied до явного выбора пользователя. Это настраивается в самом GTM (тег Consent Mode default) и продублировано на уровне сайта, чтобы не зависеть от задержки загрузки самого GTM-контейнера.
После выбора пользователя CMP вызывает update для Consent Mode, и GTM пересчитывает поведение подключённых тегов без перезагрузки страницы.
3. Блокировка скриптов до согласия
Пример подключения GTM с учётом Consent Mode на Astro
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('consent', 'default', {
ad_storage: 'denied',
analytics_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied',
wait_for_update: 500
});
</script>
<script async src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXXX"></script>
После согласия пользователя CMP вызывает gtag('consent', 'update', {...}) с новыми значениями по категориям.
Важно: сам тег GTM технически загружается всегда (это часть механики Consent Mode v2 - Google собирает обезличенные конверсионные сигналы через cookieless-моделирование даже без согласия). А вот теги без нативной поддержки Consent Mode - сторонние пиксели, heatmap-скрипты, чаты со сбором данных - должны быть физически заблокированы CMP до явного согласия по своей категории.
4. Сохранение выбора пользователя
Выбор хранится с сроком действия (обычно 6-12 месяцев по рекомендациям большинства DPA) и переспрашивается при следующем визите после истечения. Изменение выбора должно быть доступно в любой момент - футер сайта с ссылкой “Настройки cookie” обязателен, не факультативен.
Как не потерять конверсию
Баннер, оформленный как модальное окно на весь экран с затемнением фона, статистически даёт больше кликов “Принять всё” - но и больше отказов уйти с сайта вовсе. Ненавязчивый баннер внизу экрана, не блокирующий контент, обычно даёт более здоровое соотношение: пользователь читает страницу, решение принимает без давления.
Что технически можно, а что нельзя. Можно: визуально выделить кнопку “Принять всё” акцентным цветом бренда - это стандартный UI-паттерн, не нарушение. Нельзя: делать кнопку отказа менее заметной по размеру или контрасту, прятать её за дополнительный клик, использовать формулировки, вызывающие чувство вины (“я согласен поддержать сайт” против серой мелкой “нет, я не хочу помогать”).
При частичном согласии (только необходимые cookie) аналитика в GA4 через Consent Mode v2 переходит в режим моделирования конверсий - платформа восстанавливает недостающие данные статистически на основе агрегированных паттернов согласившихся пользователей. Точность падает, но полного разрыва данных, характерного для до-Consent Mode эпохи, не происходит. Ожидать стоит plausible-диапазон в 10-25% расхождения между reported и modeled конверсиями в зависимости от доли отказов - точная цифра зависит от трафика и рынка.
Типичные ошибки реализации
- CMP подключён, но порядок скриптов в билде не гарантирует, что он загружается раньше GTM - трекеры успевают выстрелить до появления баннера.
- Категории cookie в CMP не соответствуют реальным тегам в GTM - пользователь отключил аналитику, а тег всё равно шлёт событие, потому что не привязан к нужному consent-triggeru.
- Баннер локализован только на английский, хотя аудитория - мультиязычная (для сайтов с hreflang и несколькими языковыми версиями текст согласия и региональные требования должны совпадать с версией сайта - подробнее в статье про мультиязычные сайты и hreflang).
- Согласие не пересохраняется при обновлении cookie-политики - юридически требуется повторный запрос при существенном изменении списка используемых cookie.
- Тестирование ведётся только в браузере разработчика без включённого блокировщика рекламы - в проде часть пользователей с расширениями видит баннер иначе или не видит вовсе, а замер конверсии этого не учитывает.
Для кого это критично
Критично для компаний, которые ведут разработку сайта под международный рынок для выхода на рынок ЕС и других юрисдикций со строгим регулированием данных (Великобритания, Швейцария, отчасти Калифорния через CCPA) - штраф и репутационный риск здесь реальны, а не гипотетичны. Также актуально для компаний с уже работающим международным сайтом, где cookie-баннер стоит для вида, но техническая блокировка трекеров не реализована - в этом случае нужна точечная доработка сайта без пересборки всего сайта - только слой согласия и порядок загрузки скриптов.
Часто задаваемые вопросы
Обязателен ли cookie-баннер, если сайт не использует рекламные пиксели?
Если сайт использует только строго необходимые cookie (сессия, защита от CSRF, балансировка нагрузки), баннер формально не требуется по GDPR - но большинство сайтов используют хотя бы базовую аналитику (Google Analytics, Yandex Metrika), которая уже попадает под требование согласия. Стоит явно проверить список подключённых скриптов через DevTools или сетевой анализатор перед принятием решения не ставить баннер.
Что такое Google Consent Mode v2 простыми словами?
Это механизм, при котором теги Google (GA4, Google Ads, GTM) остаются технически подключёнными, но передают серверам Google явный сигнал о том, что согласие не дано. Вместо полной блокировки скрипта происходит переход в cookieless-режим со статистическим моделированием недостающих данных. С марта 2024 года Consent Mode v2 обязателен для показа персонализированной рекламы аудиториям ЕЭЗ через сервисы Google.
Как Consent Mode влияет на точность аналитики?
При высокой доле отказов от согласия (30% и выше) отчётность в GA4 начинает заметно расходиться с реальным трафиком - конверсии восстанавливаются моделированием, но не отражают индивидуальное поведение каждого пользователя. Для бизнеса с небольшим трафиком (до нескольких тысяч визитов в месяц) точность моделирования снижается сильнее, чем для крупных сайтов с большим объёмом данных для калибровки модели.
Нужен ли отдельный баннер для каждой языковой версии headless-сайта?
Текст баннера должен быть переведён и юридически адаптирован под региональные требования (например, Германия и Франция исторически строже трактуют CNIL/LfD-рекомендации, чем усреднённый текст GDPR). Технически баннер один и тот же компонент, но с локализованным контентом, подключённым через ту же систему i18n, что и остальной контент сайта.
Можно ли использовать готовый плагин CMP на кастомном headless-стеке без CMS?
Большинство CMP-провайдеров (Cookiebot, Osano, CookieYes) распространяются как ванильный JS-скрипт без привязки к конкретной CMS, поэтому подключаются на Astro, Next.js или любой другой headless-стек без ограничений. Разница - в том, насколько удобно провайдер интегрируется с фреймворком SSR/SSG на уровне порядка загрузки скриптов; это стоит проверить на staging-окружении перед продакшн-запуском.
Итог
Согласие на cookie на headless-сайте - это архитектурная задача, а не косметическая надстройка: state согласия живёт на клиенте, скрипты гейтятся до явного выбора, а Consent Mode v2 держит аналитику рабочей даже при частичном отказе. Если вы выводите сайт на рынок ЕС и не уверены, что баннер технически блокирует трекеры так, как должен, - опишите архитектуру текущего сайта команде Exceltic.dev. Проверим порядок загрузки скриптов и оценим объём доработки.