Что изменилось: 152-ФЗ и согласие на cookies на сайте
С декабря 2024 года КоАП серьёзно ужесточили: за обработку персональных данных без согласия — до 700 тысяч штрафа для юрлица, за повторные нарушения — до 18 миллионов. С 2026 года добавились оборотные штрафы. Это сразу же отразилось на технической стороне: Роскомнадзор и большинство российских юристов сошлись в позиции, что IP-адрес посетителя и идентификатор счётчика Метрики (_ym_uid) — это персональные данные. Значит, ставить счётчик до явного согласия пользователя нельзя.
На практике это означает простую вещь: на каждом сайте, ориентированном на российскую аудиторию, должен быть cookie-баннер с возможностью отказа от аналитики. Метрика, рекламные пиксели, ремаркетинговые скрипты — всё это грузится только после клика «Принять». Это технический минимум, который позволяет привести сайт к 152-ФЗ и не получить штраф по жалобе одного пользователя.
Сам по себе баннер не сложный. Сложности начинаются дальше: пользователь приходит из рекламы, видит баннер, не нажимает «Принять», заполняет форму и уходит. Метрика так и не запустилась. Директ не получил конверсию. Стратегия «Максимум конверсий» оптимизируется на половине данных и сливает бюджет. Об этом и пойдёт речь.
Почему Метрика не загружается до согласия и как это ломает Директ
Схема корректной загрузки счётчика выглядит так. На странице есть скрипт, который проверяет: есть ли в localStorage запись о согласии на аналитику? Если нет — Метрика не подключается, в DOM не появляется <script src="mc.yandex.ru/metrika/tag.js">, никакие GET-запросы на серверы Яндекса не уходят. Если есть — счётчик инициализируется, отправляется первый хит, начинается обычная жизнь Метрики.
Теперь представим типичный сценарий из Яндекс.Директа. Человек ищет «проверка сайта 152-ФЗ», видит ваше объявление, кликает. URL посадочной — https://example.ru/services/152fz/?yclid=4504935055255666687&utm_source=yandex&utm_medium=cpc. Появляется страница, поверх — cookie-баннер. Пользователь либо проматывает баннер вниз и читает контент, либо сразу нажимает «Только нужные», либо вообще закрывает баннер крестиком. Во всех трёх случаях аналитика не подключилась.
Дальше пользователь заполняет форму заявки и отправляет. На сервере у вас лежит готовая заявка. В Метрике — ничего: ни визита, ни цели, ни связи с рекламной кампанией. По данным Метрики этот клик «не дошёл» до конверсии. Яндекс.Директ принимает решения автостратегий именно по этим данным — и считает, что объявление работает плохо.
Цена ошибки: что происходит со стратегиями оптимизации Директа
Атрибуция в Директе работает так: каждый клик размечается идентификатором (yclid), который Метрика обычно ловит и связывает с визитом. Когда визит достигает цели, цель привязывается к этому yclid, цена клика и цена конверсии посчитаны корректно, Директ дальше оптимизирует кампанию на основе этих данных.
Если consent-rate на сайте 50% (а это типичная цифра для русскоязычных сайтов — половина пользователей баннер закрывают, не принимая), Метрика видит ровно половину реальных конверсий. Директ оптимизирует стратегию на этих данных и считает CPA, например, 3 000 ₽ — хотя по факту, с учётом скрытых конверсий, реальная CPA вдвое ниже.
По моему опыту, у сайтов с грамотным cookie-баннером без передачи yclid в форму CR (конверсия) в кабинете Директа падает на 30–50% относительно реальной. Стратегия «Максимум конверсий» начинает «обучаться на половине данных» — она режет ставки на тех условиях, где как раз и происходят реальные заявки. Это не сразу заметно: первую неделю ничего не меняется, потом постепенно начинает расти CPL и падать общий объём.
Дополнительная проблема: автостратегии экспериментируют — повышают ставки на одних связках, понижают на других. Если у части кампаний consent-rate выше (например, на лендингах услуг для бизнеса), а у других ниже (на лендингах для физлиц) — Директ начинает считать первые «более конверсионными» и отдавать им бюджет. Решение неверное, но Директ этого не знает.
Проверю, как теряются конверсии и подберу схему под 152-ФЗ. Бесплатная диагностика — 1 рабочий день, отчёт без воды.
yclid: что это и почему он спасает атрибуцию
yclid — это технический GET-параметр, который Яндекс.Директ автоматически добавляет к URL объявления при клике. Выглядит как длинное число: yclid=4504935055255666687. Это идентификатор клика, не идентификатор пользователя. По нему нельзя восстановить ни имя, ни email, ни IP-адрес посетителя — это просто число, которое Директ выдал данной комбинации «объявление + время + аукционная сессия».
С точки зрения 152-ФЗ это не персональные данные: yclid сам по себе не позволяет идентифицировать конкретного человека. По нему Директ может только сказать «по этому клику пришли с такого-то объявления». Поэтому yclid можно ловить и сохранять до согласия пользователя на cookies — это технический параметр URL, как и любой другой UTM.
Идея простая: на лендинге запускается крошечный JS-сниппет, который читает yclid из window.location.search и кладёт значение в hidden-поле формы и в localStorage (на 90 дней — это окно атрибуции Директа). Когда пользователь отправляет заявку — yclid уходит вместе с её данными в вашу CRM. Дальше вы выгружаете эти yclid в Директ как офлайн-конверсии — и стратегия видит реальную картину.
Аналог в мире Google Ads — это gclid: тот же принцип, тот же подход к захвату. Если ведёте трафик с обоих систем — ловите оба идентификатора одним сниппетом. У Яндекс.Директа подробное описание yclid и его роли в офлайн-конверсиях в справке.
Как ловить yclid до согласия: код для лендинга
Минимальный рабочий сниппет, который ставится в <head> или в подвал перед </body>. Загружается синхронно (не нужен DOMContentLoaded) и не зависит от состояния cookie-баннера:
(function () {
var KEY = 'attribution_v1';
var TTL = 90 * 86400 * 1000; // 90 дней
var FIELDS = ['yclid', 'gclid', 'utm_source', 'utm_medium',
'utm_campaign', 'utm_term', 'utm_content'];
var params = new URLSearchParams(location.search);
var hit = {};
FIELDS.forEach(function (k) {
var v = params.get(k);
if (v) hit[k] = v;
});
if (Object.keys(hit).length === 0) return;
var stored = {};
try {
var raw = localStorage.getItem(KEY);
var obj = raw ? JSON.parse(raw) : null;
if (obj && obj.ts && Date.now() - obj.ts < TTL) stored = obj;
} catch (e) {}
// overwrite для click-id, first-touch для UTM
var freshClick = !!(hit.yclid || hit.gclid);
var next = freshClick ? {} : Object.assign({}, stored);
FIELDS.forEach(function (k) {
if (hit[k]) next[k] = hit[k];
else if (stored[k]) next[k] = stored[k];
});
next.ts = Date.now();
try { localStorage.setItem(KEY, JSON.stringify(next)); } catch (e) {}
})();
Дальше при отправке формы добавляем yclid и UTM-метки в FormData (или в hidden-поля) — на стороне сервера принимаем как обычные строки и пишем в карточку заявки. Подробнее ниже про CRM.
Передача yclid в CRM: AmoCRM, Битрикс24, 1С
В CRM yclid должен приехать вместе с заявкой и закрепиться за карточкой сделки или клиента. Стандартное место — отдельное кастомное поле «yclid» или «Источник перехода». В AmoCRM и Битрикс24 такие поля создаются за пять минут через UI: тип «Текст», ширина 64 символа, привязка к сделке. Когда заявка прилетает через webhook или REST API, это поле заполняется значением из формы.
В Битрикс24 есть готовая интеграция со сквозной аналитикой — она умеет принимать yclid и UTM напрямую через open-line-источник или CRM-форму. Если форма у вас своя (PHP-handler или Node-backend), просто добавьте поля yclid и utm_* в payload, который уходит в Битрикс через REST. Документация Битрикса описывает это в разделе про CRM-формы и обработку лидов.
В AmoCRM логика похожая: создаём кастомное поле в карточке сделки, в API передаём при создании. Дополнительно стоит писать туда первичную UTM-связку (utm_source, utm_medium, utm_campaign) — это пригодится для отчётов по каналам и для условных автоматизаций (например, лиды с Директа автоматически идут в воронку «Платный трафик»).
В 1С (особенно если речь про 1С:Управление торговлей или 1С:CRM) ситуация чуть сложнее — там нет «нативного» поля под yclid. Решение — добавить в справочник «Контрагенты» или в документ «Заказ покупателя» дополнительный реквизит «Источник заявки». Если у вас на сайте есть интеграция 1С с сайтом через REST или ODATA, расширьте обмен полем yclid — это десяток строк на стороне 1С.
Если внутренней технической команды нет и каждая такая интеграция кажется отдельным проектом — возьмите сайт на техническую поддержку. Доработка форм, добавление полей в CRM, настройка офлайн-выгрузки в Метрику и контроль расхождений входят в стандартный пакет — не нужно собирать связку из подрядчиков по кускам.
Офлайн-конверсии Яндекс.Директа: загрузка CSV и API
Когда yclid собран в CRM, остаётся передать факт конверсии обратно в Директ. Яндекс называет это «офлайн-конверсии» — и принимает их двумя способами: ручной загрузкой CSV в интерфейсе Метрики или через API. Оба варианта работают, выбор зависит от объёма заявок.
Для ручной выгрузки путь такой: Метрика → нужный счётчик → Загрузка данных → Офлайн-конверсии. Загружается CSV с фиксированными колонками. Пример минимального файла:
UserId,Target,DateTime,Price,Currency
yclid:4504935055255666687,form_submit,1746576000,15000,RUB
yclid:3815857877712371711,form_submit,1746579600,0,RUB
yclid:5167043373476085759,form_submit,1746583200,35000,RUB
Колонка UserId с префиксом yclid: — это и есть наш идентификатор клика. Target — имя цели в Метрике (заранее создаём). DateTime — UNIX timestamp в секундах. Price — стоимость конверсии (для бесплатных аудитов 0, для платных услуг — реальная сумма; влияет на стратегию ROAS).
Лимит на одну загрузку — 1 000 000 строк, частота — раз в 5 минут с одного аккаунта, файлы хранятся 21 день. Для подавляющего большинства b2b-сайтов с десятком заявок в день это с большим запасом. Для интернет-магазинов с потоком в тысячи заявок имеет смысл переходить на API.
API называется «Управление офлайн-конверсиями», документация в Яндекс.Метрике в разделе «Технологии для разработчика». Метод POST /management/v1/counter/{counter_id}/offline_conversions/upload принимает CSV в теле запроса, авторизация — OAuth-токен Метрики. Преимущество — можно слать конверсии в реал-тайме (сразу после оплаты заказа, например), без ручных выгрузок.
Внедряю под ключ: код на лендинге, поля в CRM, выгрузка в Директ. От 30 000 ₽, срок 3–5 дней.
Какую модель атрибуции выбрать после перехода на yclid
В Яндекс.Метрике и Директе есть несколько моделей атрибуции: «Последний переход», «Последний значимый переход», «Первый переход», «Автоматическая модель». Когда cookie-сессия не работает, выбор резко сужается — большинство моделей опираются на цепочку визитов одного пользователя, которой просто нет.
На практике для сайтов с офлайн-конверсиями через yclid лучше всего работают две модели. «Последний значимый переход» — когда конверсия атрибутируется к последнему клику, который что-то значит (то есть рекламный, не прямой заход и не закладка). Это дефолт Директа в большинстве кампаний, и он отлично совмещается с офлайн-конверсиями: yclid однозначно показывает, какой клик «значимый».
«Автоматическая модель» — это умная атрибуция Яндекса, которая распределяет вес между несколькими касаниями. Она хороша на больших объёмах данных, когда у вас тысячи конверсий в месяц. Если объём меньше — лучше «Последний значимый переход», он более предсказуемый и не «учится на маленькой выборке».
Менять модель атрибуции стоит на уровне отчётов в Метрике — все кампании потом видят данные по этой модели. В самом Директе модель атрибуции выставляется отдельно для каждой стратегии — здесь оставляйте «Последний значимый переход» как дефолт.
Цели в Метрике, которые работают без cookies
Главное правило: цели в Яндекс.Метрике, которые срабатывают через JS на странице (ym(counter, 'reachGoal', 'form_submit')), не сработают, если Метрика не загружена. То есть до согласия на cookies любая JS-цель просто молчит.
Решение — серверные цели. Это цели, которые приходят в Метрику не через клиентский JS, а через офлайн-загрузку (тот же CSV или API). Создаются как обычные цели в интерфейсе Метрики, тип «Составная» или «JavaScript-событие», но фактически источник — офлайн-выгрузка с yclid. Такие цели срабатывают на 100% заявок, независимо от того, принял пользователь cookies или нет.
Для b2b-сайтов чаще всего хватает двух целей: form_submit (заявка отправлена) и deal_closed (сделка оплачена). Первая выгружается каждые несколько часов из CRM, вторая — раз в день. Директ оптимизирует стратегию на обеих, и автостратегии получают полную картину воронки, а не только верхушку.
Если же нужна цель «провёл на странице больше 30 секунд» или «прокрутил на 75%» — это всё JS-цели, они зависят от Метрики и сработают только после consent. Не страшно: эти микро-цели не нужны автостратегиям Директа, они нужны для отчётов вебмастеру. Их consent-зависимость не критична.
Чек-лист: 9 шагов внедрения для директолога и разработчика
Ниже — последовательность действий от баннера до полноценной офлайн-выгрузки. Каждый пункт можно делать самостоятельно, но если хотя бы один шаг вызывает сомнение — лучше отдать целиком разработчику.
- Cookie-баннер с opt-in. До нажатия «Принять» — Метрика и любая аналитика не грузятся. Пишем согласие в localStorage с отдельным ключом.
- JS-сниппет захвата yclid. Грузится до баннера, читает URL и кладёт yclid + UTM в localStorage на 90 дней. Не зависит от consent.
- Hidden-поля в формах. Перед отправкой формы — JS читает localStorage и докидывает yclid/UTM в FormData. Это страховка на случай, если backend не умеет читать localStorage.
- Поле yclid в CRM. В AmoCRM/Битрикс24/1С создаём кастомное поле «yclid» (текст, 64 символа) в карточке сделки. Опционально — поля под все utm_*.
- Backend пишет yclid в CRM. Webhook или REST-вызов из формы передаёт yclid в карточку. Важно: пишем сразу при создании сделки, не «потом подтянем».
- Цель в Метрике. Создаём цель «form_submit» (тип «Составная» или «JavaScript-событие»), включаем учёт в Директе.
- Выгрузка из CRM. Готовим CSV с колонками UserId/Target/DateTime/Price/Currency. Делается отчётом в CRM или скриптом — за вчерашний день.
- Загрузка в Метрику. Метрика → Загрузка данных → Офлайн-конверсии → CSV. Раз в день руками или автоматизация через API.
- Контроль данных. Через 7–14 дней сверяем число заявок в CRM с числом конверсий в Директе по той же цели. Расхождение >10% — есть утечка, ищем где.
На каждом шаге можно споткнуться: где-то браузер не отдаёт URL-параметры, где-то CRM режет длину поля до 32 символов и yclid обрезается, где-то выгрузка падает по таймауту. Поэтому пилотный запуск делайте на одной кампании, проверяйте каждый шаг, и только потом раскатывайте на весь Директ.
Заключение и частые вопросы (FAQ)
Если коротко: 152-ФЗ не запрещает рекламу в Директе и не убивает аналитику. Закон требует получить согласие пользователя на загрузку счётчика — и это правильно. Но автостратегии Директа сильно зависят от данных Метрики, поэтому без обходного пути через yclid и офлайн-конверсии стратегии теряют точность. Пара сотен строк кода на лендинге, одно поле в CRM и ежедневная выгрузка CSV — этого достаточно, чтобы Директ снова видел реальную картину.
yclid — это персональные данные?
Нет. yclid — это идентификатор клика, который Яндекс.Директ генерирует на момент аукциона. По нему нельзя восстановить ни имя, ни телефон, ни IP пользователя. Это технический параметр URL, аналогичный UTM-меткам. Поэтому его допустимо ловить и сохранять до получения согласия на cookies.
Можно ли передавать yclid без согласия пользователя?
Да, но с оговорками. Сам yclid — нет, это не ПДн. Но если вы передаёте yclid вместе с email или телефоном клиента (например, в офлайн-конверсиях), то весь набор уже считается данными, которые регулирует 152-ФЗ. На этапе отправки формы согласие на обработку ПДн всё равно нужно — оно даётся чекбоксом «Согласен на обработку персональных данных» при отправке формы.
Сколько времени хранить yclid в CRM?
Технически — пока интересна сама сделка. На практике 90 дней (окно атрибуции Директа) полностью покрывают цикл «клик — заявка — оплата». Дальше yclid теряет смысл — Директ всё равно не примет конверсию старше 90 дней. В CRM можно хранить дольше, для исторической аналитики.
Что будет, если ничего не делать?
Ничего катастрофического — кампания продолжит работать. Но автостратегии будут оптимизироваться на 50–70% реальных конверсий. На дистанции 1–3 месяцев это превращается в «непонятный рост CPA», падение объёма заявок и общее ощущение «Директ работает хуже, чем раньше». Чем дольше тянете — тем больше бюджета сольётся в неоптимизированные связки.
Сколько стоит и сколько по времени внедрить связку под ключ?
Технически — от 30 000 ₽ за стандартную связку (лендинг + одна CRM + офлайн-выгрузка). Срок 3–5 рабочих дней. Если у вас несколько лендингов или нестандартная CRM — оценивается отдельно. Аудит 152-ФЗ под ключ с правкой форм, согласий и аналитики — от 15 000 ₽, срок 1–2 дня.
От 15 000 ₽ — полная проверка форм, согласий, аналитики и политики обработки ПДн. Срок 1–2 дня, PDF-отчёт с конкретными правками. Гарантия — устранение замечаний бесплатно. Бесплатная экспресс-диагностика за пару часов.
Заказать аудит