Привет!
Я Георгий, бизнес-аналитик в компании Crystal Service Integration (CSI). Наша компания занимается разработкой и внедрением кассовых решений в сетевых магазинах по всей России и за ее пределами.
В силу специфики деятельности у разработчиков кассовой системы на руках есть вся информация, связанная с покупательскими чеками — их количество, частота, состав, суммы и прочее, что, в свою очередь, является необходимой основой для развития системы лояльности. Этим направлением и занимается подразделение, в котором я работаю: цель нашего продукта Set Loyalty — предоставить маркетологу инструменты, позволяющие выстраивать программы лояльности для привлечения и удержания покупателей торговой сети.
![](https://habrastorage.org/getpro/habr/upload_files/b50/6ce/7ed/b506ce7ed3933e0ee7cceccf193e95e6.png)
И в этой статье я хочу рассказать о том, как мы прошли путь от калькулятора акций до CDP-платформы, позволяющей собирать разнородные данные, тонко сегментировать аудиторию, активно с ней взаимодействовать и оценивать множество аналитических метрик по запущенным программам лояльности. Если интересно узнать о том, как встраивалась система лояльности в кассовую систему, то об этом подробно и интересно написал в своей статье мой коллега Игорь (он лид команды разработки, знает, о чем пишет).
Предыстория
Практически все ритейлеры, которые выходят за рамки схемы “привези товар - положи на полку - продай через кассу”, задумываются о том, как повысить эффективность бизнеса через работу со своими покупателями. Их задача привлечь к себе клиентов в том числе за счет более привлекательных предложений.
Тут на помощь приходит программа лояльности - система предоставления преференций покупателям за выполнение каких-то условий при приобретении товаров:
возьми 3 шоколадки и получи 4-ю бесплатно!
успей купить до конца недели арбуз по специальной цене!
купи набор “обои + клей” и получи скидку на чек 10%!
копи бонусы с каждого чека и трать их на следующие покупки!
соверши покупку на 5000 и получи купон на бесплатную жвачку!
….десятки других механик, о которых и так много написано.
Подобные акции встречаются почти во всех магазинах, и покупателей ими не удивишь. Кажется, что постоянные скидки и распродажи на половину ассортимента - само собой разумеющееся. Многие ритейлеры попали в “промо ловушку”, вынуждая друг друга сбивать цены. И для нас, как покупателей, это хорошо.
Для нас, как вендора системы лояльности, это тоже хорошо ???? Потому что ритейлерам теперь требуется не просто инструмент предоставления скидок всем подряд, а возможность более тонкого взаимодействия со своей покупательской базой.
Стало важно не просто идентифицировать покупателя, внеся в базу CRM ФИО, дату рождения, номер телефона и затем отправить массовую рассылку. Стало важно работать с конкретной группой людей, которая отличается по своим социально-демографическим показателям; поведенческим паттернам; произвольным атрибутам в персональных данных. Появилась задача сегментировать покупателей.
Сегментация покупателей и внедрение ClickHouse
Подобная потребность вызвала необходимость пересмотреть способы хранения и обработки данных. Ранее мы хранили информацию о покупателях только в транзакционном хранилище (Postgres). Такое решение отлично подходит для точечной работы с конкретными покупателями. Но перед нами стояла задача быстро (за секунды) отобрать определенную часть покупательской базы среди миллионов профилей. Критерии отбора разнообразные:
блок критериев по анкетным данным, например дата рождения, информация о детях, наличие автомобиля, согласие на коммуникацию и любые другие данные, которые маркетолог решит собирать о своих клиентах
блок критериев по истории покупок: тут маркетолог может отобрать тех, например, у кого средний чек за период в диапазоне от 2000 до 3000; кто приобрел определенные товары заданное количество раз; кто совершил свою последнюю покупку до начала текущего года и многое другое.
Важно, что все эти критерии могут быть по-разному скомбинированы. В результате нужно, например, сформировать аудиторию покупателей в возрасте от 35 до 40 лет, которые купили за прошедшие 180 дней определенный гель для душа более 1 раза, но НЕ купили за этот период определенный шампунь.
![](https://habrastorage.org/getpro/habr/upload_files/8d5/e28/262/8d5e28262c20ceff9d6fc4722f661eb2.png)
Решение подобной задачи потребовало использования отдельного аналитического хранилища. Выбор пал на колоночную СУБД Clickhouse. Ответственный за транспорт данных - KAFKA (что это и как используется написал в своей статье другой мой коллега, тоже Игорь, системный архитектор).
Эта связка позволила обеспечить доставку данных с сотен касс через транзакционное хранилище в аналитическое в режиме онлайн. Через 1-3 минуты после регистрации, новый покупатель уже оказывается в ClickHouse; столько же времени нужно на то, чтобы доставить чек с кассы.
Помимо данных с касс, по KAFKA также доставляются другие данные:
по покупателям (при регистрации нового покупателя, либо при внесении изменений в его анкету)
по сегментам покупателей
по накоплениям покупателей
по акциям
по купонным механикам
по бонусным транзакциям
….
Ниже показан ландшафт системы, который у нас получился, с основными ее элементами (Set Centrum / Set Retail - это кассовая часть)
![](https://habrastorage.org/getpro/habr/upload_files/eef/a03/fc7/eefa03fc75438f78449cc36413b16668.png)
Завершая тему сегментирования покупательской базы, нужно отметить, что сам по себе сегмент не является самоцелью. Сегмент - это группа покупателей, достаточно узкая и специфичная, чтобы предложить ей что-то определенное и провести эффективную коммуникацию. Поэтому сегменты стали широко использоваться в таких блоках системы Set Loyalty, как:
кассовые акции. Это выгода, которая предоставляется покупателю в момент совершения покупки на кассе или в онлайн канале (примеры таких акции приведены ранее).
стимулирующие акции. Это вознаграждение покупателя по определенному триггеру. Например, за вхождение покупателя в сегмент “Самые активные”, ему начисляются бонусные баллы.
коммуникации (рассылка сообщений по разным каналам связи на определенную аудиторию покупателей)
Модуль аналитики
Получив мощный инструмент работы с данными, при помощи которого смогли заводить более тонко настроенные механики, перешли к решению следующей задачи: как понять, что аудитория выбрана корректно и предложение было востребованным?
Получить однозначный ответ на эти вопросы сложно, но судить можно по косвенным показателям. Нужно только эти показатели рассчитать и визуализировать.
Были проведены серии встреч с клиентами, которые позволили выявить набор базовых отчетов/графиков/показателей, на основе которых маркетологи могли бы принимать решения об эффективности запущенных механик и осознанно вносить корректировки.
Подготовили макеты - ниже пример одного из дашбордов.
![](https://habrastorage.org/getpro/habr/upload_files/ea0/8ba/800/ea08ba8005488d185185f4d60ee318dd.png)
На этом этапе встал вопрос о том, как разрабатывать этот и другие дашборды? Путь, к которому мы привыкли, подразумевал: формализацию требований → разбор с командой разработки → разработку → тестирование → приемку → внедрение. Но данный случай усложнялся тем, что на стороне front-end предстояла очень большая работа с визуализацией, и все разработчики должны были быть глубоко погружены в бизнес домен, чтобы четко понимать, какие именно показатели от них ожидаются. Задумались об альтернативе, когда за визуализацию данных отвечает готовый внешний продукт, интегрированный в нашу систему.
Альтернативный подход позволил бы сократить трудозатраты разработчиков, обеспечивающих лишь транспорт и хранение нужных данных (большая часть работы была проделана при подготовке инструмента сегментации). Также потребовалось бы встраивание инструмента в визуал нашего продукта через iframe. Непосредственная работа с дашбордом в этом случае за аналитиком: отбор нужных данных → построение графика → встраивание в дашборд.
Оба подхода ожидаемо имели как плюсы, так и минусы. Приведу нашу таблицу сравнения:
Аспект |
Готовый продукт |
Собственная разработка |
Соответствие нашим макетам |
Нет, но можно попытаться немного изменить при помощи стилей CSS, например |
100% |
Возможность реализации любых UI компонентов |
Нет, использовать, что есть. Но можно попробовать создать свой компонент для выбранного средства (но мы скорее всего так делать не будем) |
Да |
Локализация дашбордов (наименование метрик, столбцов например) |
Нет переключателя языка, т.к. названия задаются в самом дашборде. Но можно, например, готовить несколько дашбордов под разные языки. |
Да |
Возможности интерактивного взаимодействия на дашборде |
Использовать, что есть. Либо писать свои компоненты и часть продукта, что будет архи сложно (мы скорее всего так делать не будем). |
Да |
Скорость добавления/обновления дашбордов |
Выше Если данных достаточно, то можно без разработки что-то добавить изменить, проверить |
Ниже, особенно на старте. Бэкенд, фронтенд, API, компоненты, фильтры, тестирование … |
Vendor lock |
Да Будут задачи на обновление версии продукта с тестированием всех дашбордов. |
Нет |
Устранение ошибок |
Могут быть ошибки, которые будет очень сложно устранить. |
Да |
Поддержка всех браузеров |
Зависит от продукта, но можно попытаться что-то исправлять при помощи CSS. |
Да |
Шансы отказать заказчику в желании чего-то сложного, даже если он готов много платить |
Высокие |
Низкие |
Техническая возможность для заказчика самому строить дашборды |
Есть |
Нет |
Наш выбор пал на использование готового продукта. Выбор подходящего вынудил провести исследование имевшихся на рынке вариантов (1 квартал 2023):
Redash |
Apache Superset |
Metabase |
Plotly + Dash |
Grafana |
Rocket BI |
|
Общие | ||||||
Поддержка ClickHouse |
Да |
Да https://github.com/ClickHouse/metabase-clickhouse-driver |
||||
OpenSource |
Да |
Да |
Да, если OnPrem https://www.metabase.com/pricing/ |
Да (кроме Enterprise) |
Да (кроме Enterperise версии) |
Да |
Тип лицензии |
BSD 2-Clause "Simplified" License |
Apache License 2.0 |
AGPL https://www.metabase.com/license/ |
MIT |
https://github.com/datainsider-co/rocket-bi/blob/main/LICENSE |
|
Страна |
- |
USA |
Canada |
- |
USA |
|
Документация |
https://superset.apache.org/docs/intro/ English |
https://grafana.com/docs/grafana/latest/ English |
||||
Платная поддержка |
Нет, только community |
Есть (Pro, Enterprise) |
В версии Enterprise |
В версии Enterprise |
||
Потребление ресурсов |
Мин 4GB RAM. Минимум 4 контейнера: server scheduler adhoc_worker scheduled_worker |
~ 2 GB RAM 3 контейнера + Redis + PG superset_app superset_worker superset_worker_beat |
Одно java приложение. Мин. 1vCPU + 1GB Рекомендуют 2vCPU + 2GB |
< 100 MB RAM |
Большое. Не менее 7 контейнеров |
|
Тех. стек |
Python (+Redis, +Postgres) |
Python, TypeScript, JavaScript |
Java |
Python |
Go, TypeScript |
Scala, TypeScript, Vue |
Хранение настроек и пр. |
PostgreSQL |
PostgreSQL |
https://www.metabase.com/docs/latest/installation-and-operation/migrating-from-h2 |
Файлы + есть поддержка PostgreSQL |
MySQL |
|
Частота обновлений |
Последняя версия v10.1.0 24.11.2021 До этого примерно раз в год. |
Последняя версия 2.0.1 от 21.12.2022 Несколько раз в год |
Несколько раз в год |
https://grafana.com/blog/2022/12/13/grafana-releases-new-2023-release-schedule/ |
1.4.17 от 04.11.2022 08.02.2023 latest |
|
Проект развивается? |
Нет. Проект включен в состав Databricks. https://redash.io/help/faq/eol |
Да. Тег 2.1.0rc2 от 14.03.2023 |
Да |
Да 9.4.3 от 02 марта 2023 10.0 июнь 2023 |
Да |
|
Возможность кастомизации (стэк) |
Есть плагины для визуализации. https://discourse.metabase.com/t/addding-custom-visualizations-into-meta-base/16817 |
Python |
||||
Поддержка iframe (возможность встраивания в UI) |
Да |
Будет надпись «Powered by Metabase», убирать её нельзя по лицензии |
Да |
Да |
? |
|
Наличие ролевой модели |
Да Edit/View |
Да, очень гибкая |
Да |
Зависит от разработанного приложения |
Да |
В платной версии |
Аутентификация по JWT |
Да |
JWT только в платной версии Но есть REST-API для логина, создания групп, юзеров и много всего. |
Зависит от разработанного приложения |
Да |
||
Query builder |
Да |
Да |
Да |
Нет |
Да |
|
Визуал | ||||||
Широкий выбор диаграмм (минимум: метрика, линейный гр., гистограмма) |
Да |
Да |
Да |
Большой выбор |
Да |
|
Форматирование графиков |
Есть |
Цвет, лейблы и пр. |
Да |
Да |
||
Дизайн, приближенный к макетам |
Фильтры только слева (хотя в интернетах видел намек на размещение сверху, надо разбираться) |
Да |
||||
Локализация всего продукта |
Нет |
Да (русский, но не 100%) |
Да |
Зависит от разработанного приложения |
Есть, но там пока нет русского |
|
Локализация дашбордов |
Да Лейблы, тайтлы, легенда … |
Да |
Да |
Да |
Да (нельзя локализовать период?) |
|
Верстка дашборда |
Да |
Да |
Да |
Да |
||
Построение запросов | ||||||
Возможность гибко задавать переменные в запросе |
https://superset.apache.org/docs/installation/sql-templating/ |
Да |
Да |
Да |
||
Фильтрация по параметру из другого графика (выбрал акцию на одном графике, другой график пересчитался) “cross-filter” |
Есть cross-filter |
По клику на значении колонки из таблицы можно только: перейти в другой дашборд перейти в другой график перейти по ссылке обновить фильтры на дашборде |
Да |
Вроде нет |
||
Плюсы | ||||||
Community продукт. Достаточно много функционала: много видов чартов, кросс фильтры, drill-down … Анимация. Гибкая ролевая модель. Данные для дашборда кешируются в Redis с настройкой времени хранения в кеше. |
Низкий порог вхождения Неплохая локализация |
Большие возможности кастомизации UI и интерактива |
Много компонентов Богатые возможности кастомизации (шрифты, цвета, размеры, трансформация данных) Популярный и развивающийся продукт |
|||
Минусы | ||||||
Проект не развивается |
Проект еще развивается, поэтому были случаи удаления старого функционала в новых версиях Высокий порог вхождения. Python. |
Малое разнообразие элементов Отсутствуют интерактивные фильтры |
Это лишь библиотеки для разработки собственных приложений с дашбордами на Python |
Всё таки Grafana позиционируется для мониторинга, а не для BI, хотя и существуют примеры использования её в этом ключе. Отсутствует кэш. |
Информации о продукте крайне мало Выглядит сырым, т.к. не удалось нормально настроить подключение к Clickhouse, требуется “ковыряние” в массе разбросанных по модулям настроек |
|
Обнаруженные проблемы | ||||||
локализация месяцев в графиках и выборе типа детализации (вообще локализация, как таковая есть, надо разбираться) отсутствует возможность изменять ширину столбцов в таблицах (надо пробовать решить с помощью CSS) |
не удалось создать фильтры для сводной таблицы ,т.к. она создается принципиально по другому в отличие от простой таблицы отсутствует встроенная возможность указания детализации для группировки по датам (день/неделя/месяц и т.п.) не везде можно использовать специфические агрегатные функции Clickhouse, например uniqExactIf |
отсутствует компонент: сводная таблица не русской локали, в т.ч. стандартный фильтр по датам |
не удалось нормально ознакомиться из-за проблем с подключением к БД” |
Исходя из наших продуктовых запросов решили остановиться на Apache Superset.
Начался этап проектирования и встраивания Superset в наш ландшафт. Результатом стала вот такая архитектура:
![](https://habrastorage.org/getpro/habr/upload_files/6a4/cfd/642/6a4cfd6420ecb668c710f19358c629f2.png)
Есть и более подробная архитектурная схема. Пишите, если кому интересно.
По результату внедрения в продукте Set Loyalty появилась возможность создания аналитических дашбордов, позволяющих оценить результаты запущенных механик, коммерческие показатели и другую информацию. За этот этап отвечает уже не разработчик/архитектор, а аналитик. Шаги по достижению цели:
понять бизнес задачу, которую должны помочь решить график/диаграмма/таблица/показатель
проверить достаточность информации в аналитической базе данных
сформировать запрос к данным
построить по ним нужный элемент визуализации
кастомизировать элемент по необходимости
проверить корректность и наглядность полученных данных
Подобный подход позволил значительно быстрее проверять гипотезы и оперативно вносить изменения в продукт, не проходя по стандартному пути разработки программного обеспечения и уменьшить количество человек, вовлеченных в процесс.
Остановимся поподробнее на создании графика на простом примере: График по среднему чеку.
В ходе сбора требований была выявлена потребность в отображении верхнеуровневых показателей сети. Так и назвали один из дашбордов. На нем был расположен помимо прочего график изменения среднего чека.
Для его создания понадобилось:
В штатном редакторе SQL запросов в Apache Superset составить запрос к БД, который выводил бы результат простого расчета (сумма чеков на продажу - сумма чеков на возврат) / количество чеков на продажу.
Указать динамические фильтры с использованием шаблонизации Jinja. Это позволило накладывать условия из выбранных фильтров на дашборде.
![](https://habrastorage.org/getpro/habr/upload_files/862/96b/dfe/86296bdfe18ea789cf4f796cabe4dba1.png)
На основе полученного запроса (датасета) построить график в соответствующем редакторе Apache Superset.
Разместить график на дашборде.
Проделав аналогичные действия с другими графиками, получили готовый дашборд и пошли показывать его нашим клиентам. Важно отметить, что все необходимые компоненты были установлены всем клиентам, а значит им можно было показывать их же реальные данные.
![](https://habrastorage.org/getpro/habr/upload_files/51c/03b/c10/51c03bc106702d3494e7dc52ebd1f3ee.png)
В ходе демонстраций поняли, что недостаточно выводить просто средний чек по магазинам. Маркетологам важно сравнивать между собой средний чек по идентифицированным и анонимным покупателям. Как доработать график?
Идем в редактор запросов и добавляем несколько строк кода
![](https://habrastorage.org/getpro/habr/upload_files/962/da8/66d/962da866da5b0697b2299c94bd3a1d17.png)
В редакторе графика обновляем состав показателей
![](https://habrastorage.org/getpro/habr/upload_files/f4b/8aa/69b/f4b8aa69b14ec8c265e494b9ade04826.png)
Готово. Даже, если редактирование запроса требует какого-то времени, оно явно меньше, чем если бы нам пришлось идти по пути привлечения разработчиков. Продемонстрировать изменения и проверить гипотезу можно в течение дня.
![](https://habrastorage.org/getpro/habr/upload_files/7fa/c9f/3f5/7fac9f3f573e2bffadf240f1a974df94.png)
Открыв доступ к модулю нескольким клиентам мы собрали обратную связь и оперативно внесли корректировки.
Для маркетологов открылись широкие возможности по оценке результатов работы системы лояльности.
Выбрав интересующую акцию и исследуемый сегмент покупателей, маркетолог теперь может посмотреть, а как изменилась активность покупателей, например, после запущенной рассылки? Или, какое количество бонусных баллов выдано тому или иному сегменту в определенных магазинах? Какой оборот в деньгах был по клиентской базе на фоне всего оборота сети?
![](https://habrastorage.org/getpro/habr/upload_files/c03/d7b/bd7/c03d7bbd79def1c0e689cc1bb7e74baa.png)
![](https://habrastorage.org/getpro/habr/upload_files/fe5/de2/14a/fe5de214ac0fab60384a7a531ae5e367.png)
Важно отметить и нефункциональные возможности. Изначально закладывались принципиальные требования:
отчеты должны строиться быстро, в пределах единиц секунд, на больших данных - миллионы покупателей и сотни миллионов чеков.
повышение потребления ресурсов не должно быть больше 15%.
Говоря коротко, эти требования выполнены. Например, рассмотренный ранее график по среднему чеку (по анонимным и идентифицированным покупателям) за последние 4 месяца рассчитывается за 3 секунды. Количество чеков около 15 миллионов за этот период.
![](https://habrastorage.org/getpro/habr/upload_files/3ea/37a/4a3/3ea37a4a33d94ca2b8e7e5f7aed4564c.png)
Заключение
Стоит упомянуть о том, что у реализации нашего модуля Аналитики есть и свои нюансы:
если в Superset что-то не настраивается так, как требуется, то “допилить” его довольно проблематично. По крайней мере пока у нас небольшой опыт в этом направлении.
при сравнении разработанных графиков с первоначальными макетами видно, что есть расхождения. Над некоторыми мы продолжаем работать. Например, над локализацией. Разделители разрядов не соответствуют привычным; некоторые слова не русифицированы; формат даты в фильтре и подобное.
требуются прокаченные навыки в работе с SQL в ClickHouse. Причем эти навыки должны быть у аналитика, а не разработчика.
Однако все эти нюансы перекрываются описанными ранее плюсами. Set Loyalty стала самодостаточной системой лояльности, обеспеченной быстрой доставкой данных, широким функционалом для запуска различных механик, а также возможностью оценить результативность запущенных акций и их влияние на покупательскую базу.
lumaxy
Несколько вопросов по поводу модуля сегментации клиентов:
Сегменты периодически обновляются или они формируются один раз при создании?
Есть ли какая-то логика над сегментами, когда два или больше разных сегментов пересекаются, и надо выбрать, к какому сегменту надо отнести конкретного клиента?
Не было ли идеи добавить ML для формирования сегментов, чтобы не выдумывать самому условия, а с помощью модели найти тех клиентов, кто лучше среагирует на ту или иную маркетинговую активность?
Georgiy_Ubilava Автор
На выбор пользователя. Сегмент может быть статическим (не меняться со временем), а может быть динамическим (автоматически обновляться по заданному расписанию).
Нормальная ситуация, когда клиент входит одновременно в разные сегменты. Их (сегменты) можно комбинировать между собой, доуточняя условия. Например, может быть сегмент "женщины 30+" и сегмент "купившие гель для душа 3 раза за последние полгода". Может быть ситуация, когда клиент сегодня входит в оба сегмента, а спустя время этот клиент будет исключен из второго. Задача состоит в том, чтобы определиться с правилами отбора клиентов и применять каждый из сегментов по назначению.
Хорошая идея. Надо развить в команде соответствующие компетенции. Добавим в бэклог продуктового развития :)