← Назад к блогу

Добавление аналитики с приоритетом конфиденциальности в приложение SvelteKit

SvelteKit 2 перехватывает клиентскую навигацию иначе, чем другие фреймворки. Вот правильный шаблон для отслеживания изменений маршрута без cookie или баннера согласия.

SvelteKit 2 ломает интеграции аналитики, которые привязывают измерение к жизненному циклу страницы. Обычный тег <script> срабатывает ровно один раз, при первой загрузке документа, и больше никогда — поэтому вся последующая клиентская навигация остаётся невидимой. Трекер Monoid обходит это, наблюдая за History API вместо жизненного цикла страницы.

Почему обычного тега script недостаточно

Тег <script> в <svelte:head> выполняется один раз за загрузку документа. Маршрутизатор SvelteKit 2 подменяет содержимое на месте, не выгружая документ, поэтому ничто не запускает его повторно. Любой трекер, единственный триггер которого — DOMContentLoaded или load, сообщает о входном маршруте и затем умолкает.

Это корневая причина широко распространённой проблемы, когда Google Analytics GA4 записывает только первый просмотр страницы при начальной загрузке в приложениях SvelteKit 2.

Ответ — обнаруживать саму навигацию, и для этого не нужна интеграция, специфичная для SvelteKit. Клиентский маршрутизатор SvelteKit обновляет URL вызовом history.pushState, поэтому трекер, патчащий history.pushState, видит каждое клиентское изменение маршрута без подписки на $app/navigation или любой хук фреймворка.

Правильный подход

Добавьте скрипт трекера Monoid один раз в ваш корневой +layout.svelte, используя <svelte:head>:

<svelte:head>
  <script
    async
    src="https://api.monoid.website/tracker.min.js"
    data-site-id="YOUR_SITE_ID"
  ></script>
</svelte:head>

Слушатель DOMContentLoaded трекера покрывает начальную загрузку страницы. Для последующих клиентских навигаций его патч history.pushState выполняется сразу после того, как SvelteKit обновил URL, поэтому он читает новый location.pathname и отправляет один просмотр страницы на каждое изменение маршрута.

Важная оговорка: патч покрывает pushState, но не popstate. Кнопки «Назад» и «Вперёд» меняют маршрут, не вызывая pushState, поэтому сейчас они не создают новый просмотр страницы.

Чтобы проверить, откройте вкладку Network в DevTools и наблюдайте за POST-запросами на /collect. Вы должны видеть один запрос на каждое изменение маршрута.

Разделение staging-трафика

Проекты SvelteKit обычно выполняются на localhost во время разработки. Зарегистрируйте отдельный сайт и привяжите его site_id к переменной окружения, чтобы трафик разработки никогда не загрязнял метрики продакшена:

<script>
  const siteId = import.meta.env.VITE_MONOID_SITE_ID
</script>

<svelte:head>
  {#if siteId}
    <script
      async
      src="https://api.monoid.website/tracker.min.js"
      data-site-id={siteId}
    ></script>
  {/if}
</svelte:head>

Установите VITE_MONOID_SITE_ID в .env.local для разработки (или оставьте её неустановленной, чтобы подавить отслеживание) и в вашей среде развёртывания для продакшена. Блок {#if siteId} гарантирует, что трекер никогда не внедряется, когда переменная не установлена.

Что вам не нужно

Никакого баннера согласия на cookie. Никакого обновления политики cookie. Никакой проверки navigator.cookieEnabled. Конечная точка сбора выводит ежедневный хэш посетителя из IP-адреса, User-Agent, серверного секрета и текущей даты:

visitor_hash = SHA-256(IP + UA + SALT_SECRET + YYYY-MM-DD)

Хэш сбрасывается каждые 24 часа и не может быть обращён для восстановления IP или User-Agent. На устройстве посетителя ничего не сохраняется. Это означает, что интеграция не запускает требования согласия ePrivacy или PECR — соглашаться не с чем.

Проверка в дашборде

После развёртывания откройте свой дашборд аналитики и перейдите между несколькими маршрутами на вашем живом сайте. Каждая навигация должна производить новую запись просмотра страницы с правильным путём. Если вы видите только одну запись независимо от навигации, проверьте, что скрипт загружен в корневом макете и что VITE_MONOID_SITE_ID установлен в среде продакшена.

Адаптер SvelteKit, который вы используете (Cloudflare, Vercel, Node, статический), не влияет на сбор аналитики, поскольку отслеживание происходит полностью в браузере после гидратации.

Источники

Comments

Loading comments…