Backend Driven…аналитика? Backend Driven аналитика

Привет, меня зовут Анна Саботович, я техлид в Альфа-Банке (команда платежей и переводов), отвечаю за развитие BDUI платформы на Android. Я покажу, как мы внедрили аналитику в контракт экранов на BDUI и как связали их с трекерами. Расскажу, с какими сложностями мы столкнулись по пути, какие ограничения предусмотрели и какие задачи положили в бэклог. Вы узнаете, как применяем BDUI в Альфа-Банке, и как собираем продуктовую аналитику, когда пользователь взаимодействует с экраном BDUI. 

ac5bd6923d1e0618a6899e8bb90c2cc7.jpg

Пользователи не обновляются, удаление из сторов, совместимость, или Зачем нам BDUI?

Начну с описания проблемы. 

В мобильной разработке с релизами всегда была тяжело. Релизный цикл мобилки и время раскатки изменений на пользователей гораздо больше, чем на вебе или бэкенде. Кроме того, даже если мы выпустим новую версию приложения, это ещё не значит, что клиент захочет обновиться — он может годы сидеть на старой версии приложения, потому что не хочет ничего менять или боится багов в новой версии. 

На графике мы видим, что 42% наших пользователей использует версии приложения, выпущенные в прошлом году.

d08cd5f4dc84935b455c7e92ae57779a.png

Самый большой сегмент — синий, это как раз последняя версия из Google Play. Почти четверть наших клиентов не перешли на наши новые способы распространения приложения: через сайт и альтернативные сторы. И остальные, как мы видели выше, обновляются гораздо медленнее, чем раньше.

a953fc405f17a90956e16f987488e9a0.png

Это значит, что нам нужен какой-то механизм, который бы позволил нам не полагаться на релизы, а доставлять пользователям новые фичи в обход релизного цикла. И дальше я расскажу вам про этот механизм.

Нам на помощь приходит BDUI. Что это такое? Это когда мобильное приложение не знает, что рисовать, и за контентом отправляется на бэкенд.

Бэкенд отправляет конфиги для отрисовки в формате JSON, а фронт верстает экран используя эти конфиги.

4aacd16c23565eafc73c1c9d35d84a2f.png

Это позволяет менять UI на фронте без релиза и максимально быстро поставлять изменения пользователям. 

Alfa BDUI

У нас в Альфе есть несколько фреймворков реализующих BDUI подход. Сегодня мы остановимся на одном из них — это многошаг. 

4 года назад, на вкладке платежей началось развитие BDUI фреймворка. Мы интегрировали платежный сервис, который может присылать набор различных полей для совершения платежа. Этот набор полей зависит от провайдера, он разный для ЖКУ Москвы и Ростелекома. А также зависит от выбора пользователя на каждом шаге. 

Поля такого экрана мы назвали динамическими полями, а весь динамический сценарий — многошагом. 

41659e0e99d2c8680473c17b71621a92.png

Количество шагов многошага от 1 до бесконечности. Он также может иметь ветвления в логике и выбирать следующий шаг в зависимости от ввода пользователя на предыдущем шаге. Например, если при поиске штрафа он выбрал поиск по данным водителя, то следующим шагом ему придет список полей для ввода данных СТС и водительского удостоверения. А если выберет поиск по номеру постановления, то на следующем экране ему придет поле ввода для номера постановления и картинка с подсказкой, где его искать.

Сейчас многошаг вышел за пределы платежей и распространяется по всему Альфа Мобайлу. Например месяц назад зарелизилась фича — обновленный семейный банк, где можно заказать карту свои родным. Весь сценарий сделан на многошаге.

8138a9a4e11fa7b01389febeb77656c7.png

На схеме вы видите полный сценарий со всеми развилками, который состоит из 26 уникальных шагов. 

d390f8bd05029707fa8ad1228c9c65ae.png

Примечание. Если вы захотите поподробнее узнать про наши BDUI технологии и их реализацию, то добро пожаловать в мою статью «Эволюция Server-Driven UI: динамические поля, хэндлеры и многошаг»

Каждый переход между экранами, показ попапа или ошибки — это риск, что пользователь покинет сценарий и не дойдет до конца. Чтобы этого избежать, и довести пользователя до цели, например, оплаты, нам нужно собирать метрики поведения пользователя, какой экран он открыл, какую кнопку нажал, какую ошибку увидел. Для этого мы и собираем продуктовую аналитику.

BD аналитика

Тут для нас и начались проблемы. 

Раньше единственными событиями аналитики в многошаге были вход в сценарий и успешное завершение оплаты. По этим данным мы могли построить только очень смутные гипотезы. 

Вот график из суперсета, где мы видим количество уникальных клиентов, оплативших штраф.

d6ecba7c4e7cc774804500769fbd917c.png

И еще могли посмотреть конверсию оплаты штрафов для посетивших многошага.

6c239619d47934f27eaeea416ee92fa3.png

Но в нашем сценарии оплаты штрафов ГИБДД много экранов и полей ввода. На каждом шаге пользователь может отвалиться из-за проблем соединения или ошибок валидации. И мы не узнаем почему.

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

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

Первая наивная идея — отправим всё!

Первая идея, с который мы начали груммить — «А не сделать ли нам дешёво и сердито? Не отправить ли просто все значения динамических полей, как они есть, в трекер?»

3383fdb189c8458b688cca440bf7c480.png

И это было бы действительно хорошим и быстрым решением для прототипа. Если бы мы не были банковским приложением. Ведь у нас хранятся самые ценные пользовательские данные — паспортные, адреса, номера карт и количество денег на счету. И мы поняли, что отправлять поля без всякой фильтрации в трекеры совершенно нельзя. 

Значит нужно на каждое поле повесить какой-то признак можно его отправлять или нет? А если можно, то нужно ли его маскировать, например, если это номер карты или счета?

И мы решили выбрать путь героя и сделать всё правильно. 

Делаем Backen-Driven аналитику 

В этом варианте, как и раньше, фронт запрашивает контент экрана у бэкенда.

e5fa7c31bb3552826cd2450da0a496f6.png

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

7debe09591f024c210f16c4814ba6e05.png

Это, конечно, даёт увеличение трафика, нужно хранить конфиги на бэкенде и маппить на фронте. Но с другой стороны, мы получаем возможность гибко настраивать каждую модель аналитики и обогащать события любым бизнес-контекстом, доступным на бэкенде.

3f824b718855b5f3e9baec047acac842.png

Вот как это выглядит: у каждого динамо поля появляется модель (на картинке сокращенная модель).

735dca7aab20422431d40cbd09863580.png

Здесь есть поля label, screen, category, которые необходимы для конструирования события аналитики, и массив параметров, в которых может передаваться дополнительный контекст.

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

Разные типы событий

Итак, вопрос, о котором мы задумались: «Что делать со сложными полями, с которыми пользователь может взаимодействовать по-разному?» Например, в поле ввода он может вводить информацию, может вставить целиком через буфер обмена или очистить всё, нажав крестик?  

Или, например, поле выбора счета: на него можно нажать, откроется шторка со счетами, пользователь выбирает счет и это выбранный счет заполняет поле.

1e2ad999f481bd7d05c8864dc9d08f46.png

Если мы будем иметь только одно событие аналитики на каждое динамополе, то мы не сможем разделить пользовательское поведение: он первый раз нажал на поле выбора счета или уже выбрал конкретный счет?

Какой тут выход? Мы решили, что раз нам не хватает одного объекта аналитики, то мы заведем массив объектов! И каждый из них будет содержать конкретный тип события, чтобы мы могли выбрать правильный объект при наступлении события.

И добавили eventTypes. И массив объектов аналитики.

c14ddc5d79dc545dc91c164f05500a6a.png

Разные трекеры

А что делать, если у нас не один трекер, а несколько? И еще если одни из них внутренние, а другие внешние? И мы хотим приватные данные по счетам пользователей отправлять только во внутренние трекеры?  

cad74beb5d767f8663f1add798a03ec1.png

Тогда мы добавляем ещё один уровень фильтрации — вводим дополнительный параметр, который будет говорить, в какие трекеры мы можем отправить это событие аналитики.

Чтобы разделить события по трекерам, мы добавили параметр analyticsSystems.

836daad7beab2af174272dffec22a749.png

Пользователь ввел данные

До этого все параметры были предзаполнены и приходили с бэкенда. Как нам отправить данные введенные пользователем в динамическом поле?  

4e01deed5acf86b65a45d344702a7da9.png

Нам же надо знать в какой параметр и дименшн положить введенные данные? Значит, номер дименшена должен прийти к нам с бэкенда, чтобы мы туда положили результаты пользовательского ввода.

Мы добавили еще одну модель — это currentValue. Она дублирует модель параметра, но в ней отсутствует поле value, потому что оно заполняется при введении данных пользователем.

9c47f46c8fecb88d65a3a83d5bb0e63f.png

Событие на экране

Что делать, если произошло событие внешнее, относительно динамо полей, например нажатие кнопки сабмит, которая не является частью динамополей?

e36f879bec2a87132813f7dc94f4e4ee.png

Мы думали о том, не отправлять ли просто все события аналитики из массива динамополей при нажатии кнопки? Но опять же решили, что нужно больше гибкости, и добавили специальный eventType FORM_SUBMIT.

f9b298490d8cfbd9b986d5d9b0663c52.png

Это значит, что у динамо поля может быть модель аналитики с eventType FORM_SUBMIT, и при нажатии на кнопку мы пробежимся по всем динамополям и соберем только те модели, у которых есть eventType FORM_SUBMIT. Таким образом мы даем гибкую настройку списка динамополей, которые мы хотим отправлять в аналитику.

Много шагов

Последний вопрос — что делать с контекстом предыдущих шагов?

Представим, что пользователь заполняет анкету на заказ карты для мамы. Он прошел уже три шага анкеты, ввёл много разных данных и находится на четвертом. Нажимает на время доставки карты, а мы бы хотели в этот момент отправить ещё данные с прошлых шагов, например номер счета и ФИО пользователя. Но ведь наше динамическое поле не знает ничего даже о данных на других полях этого же экрана,   не то что уж о других экранах!

4c64f19898f0a0d4e67f02ab38317be5.png

И тут конечно всегда есть наивная идея собирать все данные с формы или ещё лучше — передавать все модели аналитики с прошлых экранов. Но мы же уже выбрали путь, так что этот метод не для нас.

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

Аналитика уровня экрана

Тогда получается, что при нажатии на какое-то динамополя, мы можем примерджить в его модели аналитики еще и данные из модели аналитики уровня поля, чтобы обогатить динамополе дополнительным контекстом. Это уже получается почти что наследование!

46e660ea011c9c7112ccaa889b22e41b.png

Recap BD Аналитика 

Итак, я рассказала про некоторые наши челленджи, давайте подытожим основные моменты.

  • У каждого динамического поля появляется массив объектов аналитики.

  • Конкретный объект мы выбираем по фильтру eventType. 

  • Отправляем только в те трекеры, которые указаны внутри выбранной модели.

  • На уровне экрана у нас тоже есть объект аналитики, внутри которого мы можем хранить дополнительный контекст прошлых шагов много шага.

Финальный контракт

Основная часть позади, осталось всё это собрать в единый финальный контракт. На картинке вы видите экран многошага и сокращенный ответ от бэкенда. 

8113827d841ea8083de0112753193cb0.png

Здесь видно два уровня аналитики — уровень экрана и уровень динамополя. 

Ещё раз повторю:

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

  • Аналитика уровня поля содержит в себе контекст конкретного поля.

Аналитика уровня экрана

Мы видим в параметрах название экрана, номер шага многошага, номер транзакции. Также может быть добавлена любая информация с прошлых шагов и есть другие поля, необходимые для формирования события аналитики: label, screen, category.

26833e16ef66a747282aaf3cae01a022.png

Аналитика уровня поля

Содержит данные, актуальные для поля. В отличие от экрана, динамополе содержит массив аналитик. Конкретная модель выбирается по произошедшему типу события, фильтруется по eventTypes. В этой модели также может быть набор дополнительных параметров.

667fb3b14f3d77b6e7b9eddf91cf5c88.png

Это событие будет отправлено, только если произойдет клик на кнопку сабмит, потому что у поля есть только eventTypes FORM_SUBMIT. 

Если захотим отправлять аналитику при выборе номера счета, нам нужно будет просто прислать с бэкенда ещё одну модель с eventTypes ON_CHANGE.

Как подружить две модели?

Мы посмотрели на контракты моделей аналитики уровня экрана и уровня поля, и наверное у вас возник закономерный вопрос — «И что же со всем этим делать?» 

У нас для поля и экрана используется одна и та же модель, то есть их данные могут дублироваться и пересекаться. Что делать при пересечении, у какого объекта будет приоритет?

2be189185ca69f29c304d2fde74a793d.png

А что если на уровне поля и экрана у параметра будет одинаковый дименшен, но разные значения?

Сейчас я расскажу, как мы это делаем.

Мердж при клике на поле.

441d5592c2c8d3420251b99f90b58449.png

Мердж при клике на экран.

5978b2bb60240a75617e4e1a3fd85ff4.png

Итоги и планы

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

Мы разработали гибкую аналитику, которая настраивается на миддле и приходит на фронт вместе с динамическими полями. 

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

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

39b7fe0fccb7a25b49aca569515581e7.png

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

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

8ab6dedd0fb874004565e8b7fc75b3f4.png

Мы провели тестирование BD Аналитики на штрафах ГИБДД и теперь эта функциональность доступна для любого сценарий на многошаге. И без необходимости релиза мобилки, нужно только добавить модели аналитики на стороне бэкенда!

В этой статье я привела только один из примеров, что backend driven может быть не только интерфейс, но и аналитика. 

Встречались ли у вас подобные проблемы и как вы решили задачу аналитики? А может у вас есть идеи, как можно решить задачу аналитики другим способом?   Мы уже вынесли настройку UI и аналитики на сервер, как думаете, что еще можно вынести, чтобы сделать код еще более гибким?

© Habrahabr.ru