DIY. Подглядываем за посетителями
- пятница, 22 декабря 2017 г. в 03:13:53
Иногда у владельцев сервисов, менеджеров проекта и SEO-специалистов возникает желание подглядеть за пользователем, как он нажимает кнопочки и обо что разбивает лоб. Случается, что подобное желание подглядывать позволяет выявить интерфейсные проблемы, что может косвенно влиять на эффективность работы сервиса, а то и прибыль.
Мне известно несколько способов решения этой проблемы:
Вполне себе вариант, требующий, тем не менее, решения ряда вопросов:
Даже успешное решение вышеуказанных вопросов не гарантирует более-менее достоверного результата, а затраты на организацию процесса уже пугают. Кроме того есть риск потери граничных случаев, не таких уж и редких при использовании в бою.
Пожалуй не в этот раз.
Большинство сервисов предлагает тепловые карты кликов и состояния прокрутки, что позволяет более-менее достоверно определить то, что пользователи увидели на сайте и на что обратили внимание.
Некоторые предлагают анализ форм, key logging и отслеживание выделения и копирования, что позволяет отследить еще и сложные схемы человеко-машинного взаимодействия.
Навскидку нашлась пара сервисов:
За неимением экономически обоснованной цели, берем WebVisor. Сервис обещал запомнить и проиграть для нас всю пользовательскую сессию, т.е. повторить поведение пользователя на ресурсе от начала и до конца. Первичная интеграция тривиальная, достаточно просто добавить код на страницы.
Сразу стоит отметить, что заведомо деструктивные для состояния сессии запросы (т.е., все кроме GET) игнорируются.
Существует две версии. Принцип работы у них примерно одинаковый. Сначала получаем параметры аутентификации пользователя и передаем на сервер, который скачивает текущую страницу и сохраняет ее. На стороне клиента собирает действия пользователя: перемещения мышь, клики, ввод данных и прочее. Внедренный код транслирует действия на сервер с временной меткой (дельта от начала или дата/время, не выяснял).
Позже можно зайти на страницу сессий пользователя в сервисе Яндекс.Метрика и проиграть пользовательские действия. Вроде все хорошо, но есть ряд проблем.
Версия первая:
Версия вторая находится в состоянии бета-тестирования и содержит те же недостатки, плюс иногда, как порядочная бета, не работает от слова “совсем”.
До HotJar руки не дошли. Если у вас имеется опыт интеграции с SPA — поделитесь, пожалуйста, но у меня есть подозрения, что там будут те же страдания.
И тут плавно подходим к моменту “а, дай-ка, попробую!”.
Что нужно реализовать:
Сбор аналитики следует рассматривать для двух вариантов качества подключения к сети — для низкоскоростного нестабильного канала и для более благоприятных случаев.
Начальное состояние можно получить двумя способами:
В обоих случаях нужно отключить все скрипты со сохраняемой страницы, так как отклик интерфейса на действия пользователя будем делать самостоятельно по записям действий пользователя.
Остается вопрос со стилями и статическими данными. В общем случае их можно оставить как есть, но возможны спецэффекты в случае изменения статики в момент между получением начального состояния и моментом просмотра записанной активности.
В момент загрузки страницы сохраняем текущие размеры объекта window.
Нужно отслеживать все события DOM-поддерева независимо от использования stopImmediatePropagation() / stopPropagation(). Для этого будем использовать addEventListener() с параметром useCapture=true.
Для отслеживания изменений в структуре документа и атрибутах можно использовать механизм — MutationObserver. DOM Node для регистрации обработчиков примем в параметрах инициализации, по умолчанию — document.
Также необходимо следить за положение прокрутки окна document.scroll и изменением размеров окна window.resize.
Для идентификации объекта события будем строить CSS селектор.
За неимением практических данных будем использовать формат JSON для обмена. Для борьбы с блокировщиками рекламы и всякого прочего, стоит использовать GET запросы и возвращать маленькое изображение, допустим, формата GIF. Для примера, URL /path/to/api/[JSON string].gif.
Стоит помнить, что URL — не резиновый, у него есть ограничение в 2000 символов. Достаточно маленькая величина, с учетом отправки информации об изменении структуры документа, поэтому стоит сразу озаботится сжатием данных, допустим, с применением алгоритма GZIP, JavaScript-реализация которого существует. Чтобы передать сжатые данные, придется дополнительно закодировать их в BASE64.Также нужно предусмотреть передачу по частям, но для проверки концепции будет излишне на данном этапе.
Исходный код прототипа клиентской библиотеки здесь.
Для экспериментов был выбран реальный проект:
Интеграция проблем не вызвала, падения производительности браузера визуально не наблюдается.
Генерируемый трафик оказался не так велик, как ожидалось. С учетом ограничений сохранять раз в 10 секунд или, по накоплению, 100 событий данные не превышали 4 килобайт. Коэффициент сжатия сильно плавает от единиц до десятков, но для достаточно больших объемов (десятки килобайт) лежит в районе десятков, что логично, т.к. данные текстовые и есть много повторяющихся подстрок.
Прототип показал свою жизнеспособность. Чтобы совсем стало ясно, необходимо реализовать плеер и серверную часть, где предвидится ряд проблем:
Стоит не забывать об особенностях при изменении атрибутов. Например, атрибут style нельзя просто взять через коллекцию атрибутов (Element.attributes), придется использовать свойство HTMLElement.style.cssText. Количество таких нюансов на данный момент не поддается оценке.
Если использовать headless браузер с предварительным проигрыванием пользовательской активности, то стоит рассмотреть вариант записи видео. В этом случае отпадает необходимость в плеере, но увеличивается необходимое количество вычислительных ресурсов и размер хранилища результирующих данных, что не всегда может быть рациональным.