К содержимому
Hub
Все заметки

22 августа 2026 г. · 2 мин чтения

Счётчик стоял, отчёты пустые: как CSP молча убивала аналитику

CSPАналитикаБезопасностьNext.js

Счётчик стоял на сайте неделю. В отчётах — ноль. Код на месте, номер верный, флаги выставлены. Разбор занял три захода, и каждый нашёл свою причину.

Первая: политика безопасности. В script-src не было домена аналитики, и браузер просто отказывался грузить её скрипт. В консоли лежало прямое сообщение: «violates the following Content-Security-Policy directive». Его никто не читал, потому что сайт работал.

Здесь стоит остановиться. Проверка «работает ли счётчик» через typeof ym === "function" ничего не доказывает: функция-заглушка создаётся встроенным фрагментом ещё до загрузки внешнего скрипта. Она есть всегда, даже когда грузить нечего.

Вторая: флаг defer: true в настройках счётчика. Он отключает автоматическую отправку просмотра — отправлять полагается вручную. Вручную никто не отправлял. Флаг выглядел как забота о скорости, а на деле выключал всё.

Третья, самая неочевидная: вебвизор передаёт запись сессии по веб-сокету. Для политики безопасности wss — отдельная схема, и разрешение на https её не покрывает. Просмотры пошли, а записей сессий не было. По отчётам это выглядело так, будто вебвизор просто не включили в настройках счётчика.

Есть и четвёртая вещь, не связанная с безопасностью. Сайт на Next не перезагружает страницу при переходе по ссылке, а счётчик считает только тот просмотр, на котором его запустили. Без отдельной отправки при смене адреса вся статистика состояла бы из точек входа.

Общий вывод из этой истории простой: аналитика — единственная часть сайта, которая молчит одинаково и когда всё хорошо, и когда всё сломано. Проверять её надо по факту доставленных данных, а не по наличию кода на странице.

TypeScript
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("; ");