22 августа 2026 г. · 2 мин чтения
Счётчик стоял, отчёты пустые: как CSP молча убивала аналитику
Счётчик стоял на сайте неделю. В отчётах — ноль. Код на месте, номер верный, флаги выставлены. Разбор занял три захода, и каждый нашёл свою причину.
Первая: политика безопасности. В script-src не было домена аналитики, и браузер просто отказывался грузить её скрипт. В консоли лежало прямое сообщение: «violates the following Content-Security-Policy directive». Его никто не читал, потому что сайт работал.
Здесь стоит остановиться. Проверка «работает ли счётчик» через typeof ym === "function" ничего не доказывает: функция-заглушка создаётся встроенным фрагментом ещё до загрузки внешнего скрипта. Она есть всегда, даже когда грузить нечего.
Вторая: флаг defer: true в настройках счётчика. Он отключает автоматическую отправку просмотра — отправлять полагается вручную. Вручную никто не отправлял. Флаг выглядел как забота о скорости, а на деле выключал всё.
Третья, самая неочевидная: вебвизор передаёт запись сессии по веб-сокету. Для политики безопасности wss — отдельная схема, и разрешение на https её не покрывает. Просмотры пошли, а записей сессий не было. По отчётам это выглядело так, будто вебвизор просто не включили в настройках счётчика.
Есть и четвёртая вещь, не связанная с безопасностью. Сайт на Next не перезагружает страницу при переходе по ссылке, а счётчик считает только тот просмотр, на котором его запустили. Без отдельной отправки при смене адреса вся статистика состояла бы из точек входа.
Общий вывод из этой истории простой: аналитика — единственная часть сайта, которая молчит одинаково и когда всё хорошо, и когда всё сломано. Проверять её надо по факту доставленных данных, а не по наличию кода на странице.
const METRIKA = "https://mc.yandex.ru";const METRIKA_WS = "wss://mc.yandex.ru";const contentSecurityPolicy = [ "default-src 'self'", `script-src 'self' 'unsafe-inline' 'unsafe-eval' ${METRIKA}`, "style-src 'self' 'unsafe-inline'", "img-src 'self' data: blob: https:", // wss — отдельная схема: разрешение на https её не покрывает, // и запись сессий блокировалась, пока просмотры шли нормально. `connect-src 'self' ${METRIKA} ${METRIKA_WS}`, "frame-ancestors 'none'", "object-src 'none'",].join("; ");