Возьмём типичный отчёт воронки интернет‑магазина: «Каталог → Товар → Корзина → Оформление заказа → Оплата». До последнего шага дошло 38% сессий, остальные 62% потерялись между «Оформлением» и «Оплатой». Так это выглядит в Яндекс Метрике, Google Analytics и любой другой системе веб‑аналитики — доля дошедших до цели известна, причина потерь нет.

Для продуктовой аналитики эти 62% — повод для гипотезы «форма оформления слишком длинная» и задачи на редизайн. Для команды разработки те же 62% — конкретная JavaScript ошибка на странице оформления заказа — с текстом, стек‑трейсом, версией браузера и числом затронутых сессий. Разница между этими объяснениями практическая: первое нужно проверять неделями и по итогам может выясниться, что гипотеза была неверной, второе — готовая задача к исполнению. Но пока данные о конверсии и данные об ошибках лежат в разных системах, выбор между ними происходит наугад.

Меня зовут Надя Фердман, я занимаюсь продуктовым развитием Proto Observability. Сегодня я расскажу, как мы решили задачу «перестать угадывать» почему отваливаются пользователи.

Скрестить ежа с ужом

Инструменты веб‑аналитики знают только о состоявшихся событиях. Конверсия засчитывается, когда код магазина после успешного создания заказа вызывает reachGoal(“purchase”) или кладёт событие purchase в dataLayer. Если до этого вызова дело не дошло — при клике на «Оплатить» в обработчике возникло исключение, запрос к /api/orders не ушёл, заказ не создался — отправлять нечего. На шаге «Оплата» такая сессия в воронке просто не появится. Пользователь, у которого сломалась кнопка, и пользователь, который передумал платить, выглядят в отчёте одинаково: оба не дошли до цели.

При этом в моменте, когда не сработала кнопка «Оплатить», в браузере были все необходимые данные: текст ошибки, стек‑трейс, версия браузера и приложения, время загрузки страницы, был ли перед этим rage click. Но несмотря на это воронка продолжала жить в системе веб‑аналитики и оперировала достигнутыми целями. Ошибки — в системе мониторинга. Общего измерения, по которому их можно сопоставить, не было.

Мы исправили это, добавив в наш модуль Real User Monitoring инструмент Анализ путей. Он автоматически строит по данным сессий Customer Journey Map с видимостью переходов по веб или мобильному приложению и индикатором здоровья по каждой странице — долей просмотров с ошибками и временем загрузки. Отдельный режим «Анализ ошибок» отображает на карте только проблемные места пути пользователя и информацию по ошибкам.

Customer Journey Map в Proto Observability
Customer Journey Map в Proto Observability

Как из RUM‑сессий получается граф путей

Давайте разберём механику получения графа путей, чтобы инструмент не воспринимался чем‑то из маркетинговых презентаций. На деле Journey Map — это граф, собранный из view‑событий, которые наш RUM‑агент обрабатывает.

Браузерный SDK Proto на каждую навигацию создаёт view‑событие. В SPA агент платформы различает первичную загрузку и смену роута через атрибут loading_type: initial_load или route_change. Внутри одной сессии эти события выстраиваются в последовательность страниц. Последовательности агрегируются по всем сессиям — получается потоковая диаграмма (Sankey), где узел — это страница, а толщина ленты между узлами — число сессий за переход.

Ошибки и время загрузки прямо на карте

Чтобы, глядя на диаграмму можно было сразу понять техническая ли причина у падения конверсии, в Proto каждая проблемная страница помечается восклицательным знаком ⚠ желтого или красного цвета в зависимости от выполнения следующих условий:

Условия применения индикации проблем на Customer Journey Map в Proto Observability
Условия применения индикации проблем на Customer Journey Map в Proto Observability

Пороги подбирались не из головы, а на реальных данных.

Отсечка по времени загрузки установлена 8 секунд, так как согласно Apdex пользователь считается неудовлетворённым при времени отклика выше 4T, и при типовом T в 2 секунды это ровно 8 секунд.

Может возникнуть вопрос, почему не установили четыре секунды, знакомые по Core Web Vitals как граница плохого Largest Contentful Paint. Причина в том, что LCP перестаёт обновляться после первого взаимодействия пользователя со страницей. Смена роута в SPA всегда следует за кликом, поэтому для таких переходов LCP не существует вовсе, а на карте путей это заметная часть узлов. Метрика loading_time считается и для них: от клика до первого момента, когда активность на странице прекращается. Для первичных загрузок она тоже не совпадает с LCP: в неё попадают сетевые запросы и изменения DOM уже после отрисовки самого крупного элемента, поэтому значения систематически выше. На практике это подтвердилось сразу — с порогом в четыре секунды значок появлялся почти у каждого узла, и карта переставала быть читабельной.

Порог по времени отвечает на вопрос «не слишком ли долго грузилось». Но пользователь мог упереться и в то, что кнопка вовсе не сработала. Отсюда вторая величина на узле — доля просмотров с ошибками. Порогов два: от 5% — предупреждение, от 25% — критический уровень.

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

Режим "Анализ ошибок" на Customer Journey Map в Proto Observability
Режим «Анализ ошибок» на Customer Journey Map в Proto Observability

От карты до источника проблемы в один клик

Проектируя Customer Journey Map, мы понимали, что ответа на вопрос «где пользователь упирается в баг» недостаточно, нужно показать, что именно пошло не так — конкретную ошибку со стек‑трейс и контекстом, в котором она возникла. Поэтому мы реализовали переход от карты к анализу проблемных сессий по клику:

  • Клик по странице — выводится список сессий, в которых открывали эту страницу.

  • Клик по переходу — показываются сессии, где был переход со страницы A на страницу B. Переход в «Выход» даёт выборку ровно тех сессий, что завершились на этом шаге.

  • Клик по идентификатору сессии — открывается выбранная сессия.

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

Анализ проблемных сессий в Proto Observability
Анализ проблемных сессий в Proto Observability

Клик, после которого произошла ошибка, помечается так, чтобы его не нужно было искать. Разворачивая событие видим сразу текст ошибки, стек‑трейс и контекст, который обычно и приходится выпытывать у пользователя: город, IP, устройство и версия ОС, браузер, версия приложения, часовой пояс, страница входа и реферер. Даже если пользователь не идентифицирован, по нему выводится сквозной анонимный ID, и кнопка «Все сессии пользователя» показывает все остальные его визиты.

Хронология сессии группируется по просмотрам или по страницам и фильтруется по типу событий: просмотры, действия, ошибки, ресурсы, длительные задачи. По каждому просмотру показываются LCP, FCP, INP, TTFB, CLS, время загрузки, сколько пользователь провёл на странице, сколько сделал действий и сколько словил ошибок. Здесь же видно, что было входом, а что перезагрузкой.

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

На этих данных гипотеза и превращается в факт. Те 62%, что потерялись между «Оформлением» и «Оплатой», перестают быть поводом для версий — видно, что пользователь пришёл из поиска, что страница оформления грузилась 5,7 секунды при LCP 4,7, что три ресурса вернули ошибку, а основной поток на две секунды заблокировала конкретная библиотека. Форма не была слишком длинной. У разработки готовая задача, у продукта — сэкономленный спринт на редизайн, который ничего бы не изменил.

От разбора постфактум к проактивному контролю

Узнавать о просадке конверсии из отчётов — значит узнавать последним. Через сломанный шаг пройдут тысячи пользователей, поверх проблемного релиза возможно выйдет ещё несколько, и связь между изменением и проблемой придётся доказывать дольше.

Поэтому мы сделали оповещения по конверсии. Правило отслеживает долю сессий, доходящих до целевой страницы, и присылает уведомление, как только она уходит вниз. Порог можно настроить под себя.

Анализ конверсии на Customer Journey Map в Proto Observability
Анализ конверсии на Customer Journey Map в Proto Observability

Представим, что в четверг утром вы получили алерт о том, что конверсия упала. Открываете «Анализ путей» в режиме «К странице», выбираете страницу «Заказ оформлен», период — сутки. Платформа показывает пути, которые к ней ведут, и считает, какая доля сессий за период до неё дошла. Рядом с конверсией указывается изменение к прошлым суткам в процентных пунктах, и смотреть нужно именно на него. Включаете «Анализ ошибок». Диаграмма оставляет только проблемные места пути. Если страница, отмечена как проблемная, причина техническая: клик по ней открывает список прошедших через неё сессий, клик по сессии — хронологию с ошибкой и стек‑трейсом. Если не отмечена — сбоев нет, и гипотезу надо искать в продуктовой плоскости.

Что в итоге

Воронка без ошибок — это вопрос без ответа: известно, что пользователи теряются, но неизвестно почему, из‑за этого часто оптимизируют вслепую и чинят дизайном то, что сломано кодом.

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

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