---
title: "Как сделать cookie-баннер: готовый скрипт и настройка под 152-ФЗ"
description: "Как сделать cookie баннер с категориями и отложенным запуском аналитики: готовый скрипт, вставки для Tilda и WordPress. Проверьте свой сайт бесплатно."
created_at: 2026-08-21
updated_at: 2026-08-21
category: "Cookie и согласие"
tags:
  - "cookie"
  - "152-ФЗ"
  - "баннер"
  - "скрипт"
  - "согласие"
source_url: "https://152fztest.ru/blog/kak-sdelat-cookie-banner-skript/"
source: "152fztest.ru"
---

Cookie-баннер, скопированный «с чужого сайта» пять минут назад, чаще всего не соответствует требованиям 152-ФЗ: одна кнопка без отказа, счётчики грузятся сразу, согласие нигде не сохраняется. Разберём, как сделать cookie баннер, который реально соответствует закону, — с рабочим скриптом, вставками для Tilda и WordPress и логикой хранения согласия. Если баннер уже есть и нужно просто проверить его на соответствие 152-ФЗ, смотрите чеклист в статье [Cookie-баннер по 152-ФЗ: как настроить и не получить штраф](/blog/cookie-banner-po-152-fz-kak-nastroit/).

## Из чего состоит правильный баннер технически

С точки зрения кода задача сводится к четырём частям:

1. **Разметка** — сам баннер: текст, ссылка на политику, кнопки выбора.
2. **Хранение выбора** — где и как запоминается решение посетителя (localStorage, cookie, сервер).
3. **Управление скриптами** — [обработка](/glosarij/obrabotka-personalnyh-dannyh/) третьих лиц (Метрика, пиксели, счётчики) запускается только после согласия на соответствующую категорию.
4. **Возможность отозвать выбор** — ссылка или кнопка «Настройки cookie», доступная в любой момент.

Разделение по категориям — не украшение, а требование закона: с 1 сентября 2025 года согласие должно быть отдельным по каждой цели обработки, а не единым пакетом «на всё». Поэтому в скрипте ниже минимум две категории — «необходимые» (без согласия) и «аналитика/реклама» (с согласием).

## Готовый скрипт для самописного сайта

Вставьте перед закрывающим тегом `</body>`. Это рабочий минимум с двумя кнопками, сохранением выбора и отложенным запуском аналитики.

```html
<div id="cookie-banner" style="position:fixed;bottom:0;left:0;right:0;
  background:#1f2937;color:#fff;padding:16px;display:none;z-index:9999;
  font:14px/1.5 sans-serif">
  <span>Мы используем cookie для работы сайта и аналитики. Аналитические и
  рекламные cookie включаются только с вашего согласия. Подробнее — в
  <a href="/privacy/" style="color:#93c5fd">политике конфиденциальности</a>.</span>
  <span style="margin-left:12px;white-space:nowrap">
    <button onclick="cookieChoice(true)">Принять всё</button>
    <button onclick="cookieChoice(false)">Только необходимые</button>
  </span>
</div>

<script>
  var CONSENT_KEY = 'cookieConsent';
  var CONSENT_VERSION = '2026-08'; // меняйте при правках политики — старое согласие станет неактуальным

  function cookieChoice(consent) {
    var payload = { value: consent ? 'all' : 'necessary', ts: Date.now(), version: CONSENT_VERSION };
    localStorage.setItem(CONSENT_KEY, JSON.stringify(payload));
    document.getElementById('cookie-banner').style.display = 'none';
    if (consent) initAnalytics();
    logConsentToServer(payload); // необязательно, но полезно для доказательства при проверке
  }

  function getConsent() {
    try {
      var raw = localStorage.getItem(CONSENT_KEY);
      if (!raw) return null;
      var parsed = JSON.parse(raw);
      return parsed.version === CONSENT_VERSION ? parsed : null;
    } catch (e) {
      return null;
    }
  }

  window.addEventListener('load', function () {
    var consent = getConsent();
    if (!consent) {
      document.getElementById('cookie-banner').style.display = 'block';
    } else if (consent.value === 'all') {
      initAnalytics();
    }
  });

  function initAnalytics() {
    // сюда — код Яндекс.Метрики, рекламных пикселей и других аналитических скриптов
  }

  function logConsentToServer(payload) {
    // POST на свой endpoint: /api/consent-log — фиксируем факт и время согласия на сервере
    // fetch('/api/consent-log', { method: 'POST', body: JSON.stringify(payload) });
  }

  // Ссылку "Настройки cookie" в футере привяжите к этой функции — она снова открывает баннер
  function openCookieSettings() {
    document.getElementById('cookie-banner').style.display = 'block';
  }
</script>
```

Три момента, которые обычно упускают:

- **`CONSENT_VERSION`** — если вы меняете список cookie или политику, поднимите версию, и у всех посетителей баннер покажется заново. Без этого люди годами живут со старым согласием на изменившийся набор данных.
- **`logConsentToServer`** — сам по себе localStorage ничего не доказывает Роскомнадзору при проверке, потому что живёт только в браузере конкретного человека. Серверный лог с [обезличенным](/glosarij/obezlichivanie-pdn/) идентификатором, датой и версией политики — то, чем можно подтвердить факт получения согласия.
- **`openCookieSettings`** — обязательная точка входа для отзыва согласия. Разместите ссылку в футере постоянно, а не только в баннере.

## Вставка для Tilda

В Tilda нет нативного конструктора баннеров с категориями, поэтому используется код-вставка:

1. Настройки сайта → вкладка «Ещё» → «Вставка кода в HEAD» — если баннер должен быть на всех страницах.
2. Скрипт из блока выше вставляется в поле **«Код перед закрывающим BODY»** там же.
3. Отключите автозапуск счётчика Яндекс.Метрики в стандартной интеграции Tilda (Настройки → Аналитика) и подключите его вручную внутри функции `initAnalytics()` — иначе счётчик стартует до согласия независимо от баннера.
4. Ссылку на политику в баннере укажите на страницу `/privacy/` (или как называется ваша страница с политикой конфиденциальности на Tilda).

Частая ошибка на Tilda — оставить встроенную интеграцию Метрики включённой «для подстраховки» вместе с ручным скриптом. В итоге счётчик грузится дважды: один раз при загрузке страницы (до согласия), второй — после клика. Автоматическую интеграцию нужно выключить полностью.

## Вставка для WordPress

Вариант без плагинов — через `functions.php` активной темы (или дочерней темы, чтобы не потерять код при обновлении):

```php
add_action( 'wp_footer', function () {
  ?>
  <!-- сюда вставляется HTML и <script> блока из раздела выше -->
  <?php
} );
```

Если аналитика подключена через плагин (например, счётчик Метрики или GTM-плагин), проверьте у него настройку отложенной загрузки или условие подключения — большинство таких плагинов позволяют указать JS-переменную или cookie-флаг, при отсутствии которого скрипт не выводится. Если плагин такой настройки не даёт, надёжнее отключить его автоматическую вставку и вызывать код счётчика вручную из `initAnalytics()`, как в примере для самописного сайта.

Готовые cookie-плагины для WordPress (Cookie Notice, Complianz и аналоги) закрывают эту логику из коробки, но большинство из них по умолчанию настроены под GDPR — при установке проверьте, что в них включён режим блокировки скриптов до согласия, а не только отображение баннера.

## Что должно происходить при отзыве согласия

Кнопка или ссылка «Настройки cookie» должна не просто открывать баннер заново, а реально менять состояние:

- если пользователь ранее согласился, а потом отказался — аналитические cookie нужно не только перестать устанавливать, но и удалить уже установленные (`document.cookie = 'name=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/'` для каждого известного имени cookie счётчика);
- запись в localStorage обновляется на `necessary`, серверный лог — новой записью с отметкой отзыва;
- если аналитический скрипт уже инициализирован и умеет отключаться (у части систем есть API вида `ym(id, 'reachGoal')` только при активном счётчике, но нет штатного «выключить»), проще перезагрузить страницу после отзыва — так скрипт просто не подключится заново.

## Как проверить, что баннер работает правильно

После установки откройте сайт в приватном окне браузера (или очистите localStorage и cookie) и проверьте через вкладку «Сеть» в инструментах разработчика:

- запросы к счётчикам аналитики (`mc.yandex.ru`, `google-analytics.com` и т.п.) **не должны** появляться до клика по «Принять»;
- после клика «Только необходимые» эти запросы по-прежнему не должны идти;
- после клика «Принять всё» запросы появляются, а выбор сохраняется — обновите страницу, баннер не должен показаться снова.

Это тот самый момент, где чаще всего расходится теория и реальность: баннер визуально корректен, но счётчик Метрики как был зашит в `<head>` напрямую через интеграцию конструктора, так и продолжает грузиться при каждом заходе. С позиции 152-ФЗ это означает, что согласие получают уже после того, как данные собраны, — то есть фактически не получают вовсе. Автоматический сканер сайта проверяет именно это — не только наличие баннера, но и реальный порядок загрузки скриптов относительно клика по кнопке.

## Типичные технические ошибки при внедрении

- **Счётчик подключён напрямую в `<head>` через конструктор сайта.** Даже если баннер визуально настроен правильно, встроенная интеграция аналитики (в Tilda, WordPress-теме или в шаблоне лендинга) часто подключает счётчик отдельно от вашего скрипта согласия. Проверяйте это отдельно от самого баннера — через вкладку «Сеть» в инструментах разработчика, как описано выше.
- **Согласие хранится только в cookie с коротким сроком жизни.** Если срок жизни cookie с флагом согласия — сутки или неделя, баннер будет показываться повторно слишком часто, а часть пользователей начнёт нажимать «Принять всё» просто чтобы избавиться от плашки, не читая условия. Ставьте разумный срок — от 6 до 12 месяцев, и обязательно сбрасывайте его при смене `CONSENT_VERSION`.
- **Баннер загружается с задержкой в несколько секунд после счётчиков.** Если скрипт баннера подключён в конце `</body>`, а счётчик аналитики — в `<head>` тем же файлом шаблона, есть окно в пару секунд, когда счётчик уже сработал, а баннер ещё не появился. Технически это тоже обработка без согласия — просто короткая по времени. Инициализация аналитики должна физически зависеть от результата проверки `getConsent()`, а не просто идти позже по разметке.
- **Один и тот же флаг согласия используется для всех категорий.** Если в коде нет разделения между «необходимые», «аналитика» и «реклама», а есть только общий `true/false`, вы технически не можете предложить пользователю согласиться на одно и отказаться от другого — а это прямое требование закона с 1 сентября 2025 года.
- **Мобильная версия баннера перекрывает контент и не даёт кнопке «Отклонить» появиться на экране без скролла.** Формально кнопка есть в коде, но фактически недоступна на маленьком экране без прокрутки — с точки зрения UX-аудита это тоже трактуется как затруднённый отказ.

## Штраф, если баннер не работает как надо

Если аналитические cookie грузятся до согласия или согласие оформлено как единственная кнопка без отказа, это квалифицируют как обработку персональных данных без согласия — ч. 2 ст. 13.11 КоАП, до 700 000 ₽ для юрлиц, при повторном нарушении до 1 500 000 ₽. Если при этом в политике не описано, какие cookie использует сайт и зачем, добавляется отдельный состав за неполноту политики — до 60 000 ₽ по ч. 3 ст. 13.11 КоАП. Полный разбор требований к согласию — в статье [Нужно ли согласие на cookie: что требует закон и что делает Роскомнадзор](/blog/nuzhno-li-soglasie-na-cookie/), а весь список проверяемых пунктов сайта — в чеклисте [Как привести сайт в соответствие с 152-ФЗ: 9 пунктов](/blog/kak-privesti-sajt-v-sootvetstvie-152-fz-cheklist/).

Проще всего проверить готовый баннер не вручную через DevTools, а прогнать сайт через автоматический сканер — он покажет, срабатывают ли счётчики до согласия и корректно ли настроена сама форма согласия.

Все статьи по теме — в хабе [Cookie и согласие](/152-fz/cookie-i-soglasiya/).

## Частые вопросы

### Как запретить загрузку метрики до согласия

Не вставляйте код счётчика (Яндекс.Метрики, рекламных пикселей) напрямую в &lt;head&gt;. Оберните его инициализацию в функцию вроде <code>initAnalytics()</code> и вызывайте её только из обработчика клика на кнопку «Принять», либо при загрузке страницы — но только если в хранилище уже есть сохранённое согласие на аналитические cookie. Если счётчик подключён через Google Tag Manager или Яндекс.Диспетчер тегов, настройте в них триггер, срабатывающий по флагу согласия, а не по загрузке страницы.

### Как хранить подтверждение согласия на cookie

Минимум — сохранить факт и дату выбора в localStorage браузера, этого достаточно для работы самого баннера. Но для юридической защиты при проверке Роскомнадзора одного localStorage мало: он живёт только у конкретного посетителя и обнуляется при очистке кэша. Лучше дополнительно логировать событие согласия на сервере — IP или обезличенный идентификатор сессии, timestamp, версию политики, выбранные категории. Так вы сможете подтвердить факт получения согласия, даже если пользователь почистил браузер.

### Нужна ли кнопка «Отклонить» в баннере

Да, и она обязана быть так же заметна, как кнопка «Принять». Согласие, которое пользователь не может свободно отклонить, юридически не считается согласием — это прямо следует из требования к добровольности и осознанности согласия по 152-ФЗ. Баннер с одной кнопкой «Хорошо, понятно» и без варианта отказа Роскомнадзор трактует как нарушение: у посетителя нет реального выбора.

### Как сделать cookie-баннер на Tilda

В Tilda нет встроенного конструктора cookie-баннеров с категориями, поэтому баннер добавляют через код: Настройки сайта → Ещё → Вставка кода в HEAD и перед BODY (либо в конкретную страницу). Верстку и скрипт баннера вставляете в поле «Код перед закрывающим BODY», а инициализацию счётчиков Метрики выносите из автоматических интеграций Tilda в свою функцию, которая вызывается только после согласия. Готовый пример — в разделе ниже.
