Как на самом деле настроить веб-аналитику для SPA и не сойти с ума
С классическими сайтами всё просто: пользователь перешел на другую страницу, она перезагрузилась, счетчик Метрики сам зафиксировал просмотр. В SPA (Single Page Application) эта схема не работает. Пользователь может кликать по разделам, открывать формы и оформлять заказы, а для базового счетчика он всё еще сидит на главной. Страница-то физически не перезагружается — JavaScript просто подтягивает нужный контент на лету.
Поэтому стандартная настройка тут бесполезна. Приходится открывать консоль и собирать воронку руками. Рассказываю, как устроен этот процесс, если убрать из него маркетинговую воду.
Разбираемся с логикой сайта через DevTools
Прежде чем писать код или настраивать триггеры, нужно залезть внутрь приложения и посмотреть, как оно вообще дышит. Для этого открываем панель разработчика (F12) и смотрим три вещи:
Что происходит с URL.
Переходим по вкладкам сайта и смотрим в консоль. Проверяем, используют ли разработчики History API (pushState или replaceState). Если адресная строка в браузере меняется, эти виртуальные переходы можно будет перехватить.
Куда уходят запросы.
Переключаемся на вкладку Network и фильтруем по XHR/Fetch. Нам нужно увидеть, какие запросы сайт отправляет на сервер при кликах на важные кнопки. Если сервер возвращает статус 200 OK — отлично, это наш будущий триггер. Ориентироваться на ответы сервера надежнее, чем на простые клики.
Какие обработчики уже стоят.
Во вкладке Event Listeners проверяем, к каким элементам привязаны JS-скрипты. Это помогает понять, как настроить правила «if-else» для отслеживания динамических блоков или всплывающих окон.
Вытаскиваем элементы для воронки без мусора
Самая частая ошибка — повесить цель на сам факт нажатия кнопки. В итоге в аналитику летит куча мусора.
Воронку нужно собирать аккуратнее:
Контекст кликов.
Мы пишем кастомные JS-обработчики, которые прямо в момент действия считывают текстовые переменные с элементов. Например, какую именно кнопку нажал пользователь и какой текст на ней был написан в этот момент.
Регистрация.
Если пользователь заполнил форму с ошибкой и нажал «Зарегистрироваться», система выдаст предупреждение, но клик-то произойдет. Чтобы не считать такие ложные действия, мы заглядываем в структуру формы, находим уникальные селекторы и привязываем JS-скрипт именно к успешной валидации. Если форма пустая или с ошибкой — скрипт её игнорирует. Так мы фиксируем только реальные анонимные и стандартные регистрации.
Покупка без привязки к «спасибо-странице».
В SPA часто нет отдельного URL для успешной оплаты. Поэтому отслеживание по адресам страниц здесь не работает. Мы ищем переменные в коде, которые появляются строго в момент подтверждения транзакции сервером. При этом сразу отсекаем ручные переводы в банковских приложениях по номеру консультанта, чтобы не раздувать статистику.
Проектируем структуру данных
Когда логика понятна, все эти разрозненные действия нужно объединить в сквозную историю клиента.
Для этого перерабатывается структура DataLayer.Мы настраиваем кастомный JS так, чтобы он мгновенно определял статус пользователя — зашел он авторизованным или анонимным, какой у него ClientID и откуда был вход.
Система должна видеть изменение этих статусов без задержек и передавать данные в рекламные кабинеты в реалтайме.
Здесь же закладывается логика очистки чека. Прямо на фронте мы пишем кастомные JS-функции, которые вычитают стоимость эквайринга и логистики из e-commerce событий. В итоге рекламные системы (Яндекс, VK) получают очищенную сумму и оптимизируют кампании на основе чистой выручки, а не раздутого грязного чека.