Возьмём типичный отчёт воронки интернет‑магазина: «Каталог → Товар → Корзина → Оформление заказа → Оплата». До последнего шага дошло 38% сессий, остальные 62% потерялись между «Оформлением» и «Оплатой». Так это выглядит в Яндекс Метрике, Google Analytics и любой другой системе веб‑аналитики — доля дошедших до цели известна, причина потерь нет.
Для продуктовой аналитики эти 62% — повод для гипотезы «форма оформления слишком длинная» и задачи на редизайн. Для команды разработки те же 62% — конкретная JavaScript ошибка на странице оформления заказа — с текстом, стек‑трейсом, версией браузера и числом затронутых сессий. Разница между этими объяснениями практическая: первое нужно проверять неделями и по итогам может выясниться, что гипотеза была неверной, второе — готовая задача к исполнению. Но пока данные о конверсии и данные об ошибках лежат в разных системах, выбор между ними происходит наугад.
Меня зовут Надя Фердман, я занимаюсь продуктовым развитием Proto Observability. Сегодня я расскажу, как мы решили задачу «перестать угадывать» почему отваливаются пользователи.
Скрестить ежа с ужом
Инструменты веб‑аналитики знают только о состоявшихся событиях. Конверсия засчитывается, когда код магазина после успешного создания заказа вызывает reachGoal(“purchase”) или кладёт событие purchase в dataLayer. Если до этого вызова дело не дошло — при клике на «Оплатить» в обработчике возникло исключение, запрос к /api/orders не ушёл, заказ не создался — отправлять нечего. На шаге «Оплата» такая сессия в воронке просто не появится. Пользователь, у которого сломалась кнопка, и пользователь, который передумал платить, выглядят в отчёте одинаково: оба не дошли до цели.
При этом в моменте, когда не сработала кнопка «Оплатить», в браузере были все необходимые данные: текст ошибки, стек‑трейс, версия браузера и приложения, время загрузки страницы, был ли перед этим rage click. Но несмотря на это воронка продолжала жить в системе веб‑аналитики и оперировала достигнутыми целями. Ошибки — в системе мониторинга. Общего измерения, по которому их можно сопоставить, не было.
Мы исправили это, добавив в наш модуль Real User Monitoring инструмент Анализ путей. Он автоматически строит по данным сессий Customer Journey Map с видимостью переходов по веб или мобильному приложению и индикатором здоровья по каждой странице — долей просмотров с ошибками и временем загрузки. Отдельный режим «Анализ ошибок» отображает на карте только проблемные места пути пользователя и информацию по ошибкам.

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

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

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

Клик, после которого произошла ошибка, помечается так, чтобы его не нужно было искать. Разворачивая событие видим сразу текст ошибки, стек‑трейс и контекст, который обычно и приходится выпытывать у пользователя: город, IP, устройство и версия ОС, браузер, версия приложения, часовой пояс, страница входа и реферер. Даже если пользователь не идентифицирован, по нему выводится сквозной анонимный ID, и кнопка «Все сессии пользователя» показывает все остальные его визиты.
Хронология сессии группируется по просмотрам или по страницам и фильтруется по типу событий: просмотры, действия, ошибки, ресурсы, длительные задачи. По каждому просмотру показываются LCP, FCP, INP, TTFB, CLS, время загрузки, сколько пользователь провёл на странице, сколько сделал действий и сколько словил ошибок. Здесь же видно, что было входом, а что перезагрузкой.
Внутри просмотра разворачивается список ресурсов со статусом, методом, типом, размером и длительностью. Платформа сама расставляет акценты: сколько мегабайт весила страница, сколько ресурсов оказались медленными, какой из них самый тяжёлый, что вернулось без ответа и что заблокировало отрисовку. Между ресурсами в той же ленте показываются клики с текстом элемента, на который нажимали, и длительные задачи с временем исполнения.
На этих данных гипотеза и превращается в факт. Те 62%, что потерялись между «Оформлением» и «Оплатой», перестают быть поводом для версий — видно, что пользователь пришёл из поиска, что страница оформления грузилась 5,7 секунды при LCP 4,7, что три ресурса вернули ошибку, а основной поток на две секунды заблокировала конкретная библиотека. Форма не была слишком длинной. У разработки готовая задача, у продукта — сэкономленный спринт на редизайн, который ничего бы не изменил.
От разбора постфактум к проактивному контролю
Узнавать о просадке конверсии из отчётов — значит узнавать последним. Через сломанный шаг пройдут тысячи пользователей, поверх проблемного релиза возможно выйдет ещё несколько, и связь между изменением и проблемой придётся доказывать дольше.
Поэтому мы сделали оповещения по конверсии. Правило отслеживает долю сессий, доходящих до целевой страницы, и присылает уведомление, как только она уходит вниз. Порог можно настроить под себя.

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

