Привет!
Я Георгий, бизнес-аналитик в компании Crystal Service Integration (CSI). Наша компания занимается разработкой и внедрением кассовых решений в сетевых магазинах по всей России и за ее пределами.
В силу специфики деятельности у разработчиков кассовой системы на руках есть вся информация, связанная с покупательскими чеками — их количество, частота, состав, суммы и прочее, что, в свою очередь, является необходимой основой для развития системы лояльности. Этим направлением и занимается подразделение, в котором я работаю: цель нашего продукта Set Loyalty — предоставить маркетологу инструменты, позволяющие выстраивать программы лояльности для привлечения и удержания покупателей торговой сети.

И в этой статье я хочу рассказать о том, как мы прошли путь от калькулятора акций до CDP-платформы, позволяющей собирать разнородные данные, тонко сегментировать аудиторию, активно с ней взаимодействовать и оценивать множество аналитических метрик по запущенным программам лояльности. Если интересно узнать о том, как встраивалась система лояльности в кассовую систему, то об этом подробно и интересно написал в своей статье мой коллега Игорь (он лид команды разработки, знает, о чем пишет).
Предыстория
Практически все ритейлеры, которые выходят за рамки схемы “привези товар - положи на полку - продай через кассу”, задумываются о том, как повысить эффективность бизнеса через работу со своими покупателями. Их задача привлечь к себе клиентов в том числе за счет более привлекательных предложений.
Тут на помощь приходит программа лояльности - система предоставления преференций покупателям за выполнение каких-то условий при приобретении товаров:
возьми 3 шоколадки и получи 4-ю бесплатно!
успей купить до конца недели арбуз по специальной цене!
купи набор “обои + клей” и получи скидку на чек 10%!
копи бонусы с каждого чека и трать их на следующие покупки!
соверши покупку на 5000 и получи купон на бесплатную жвачку!
….десятки других механик, о которых и так много написано.
Подобные акции встречаются почти во всех магазинах, и покупателей ими не удивишь. Кажется, что постоянные скидки и распродажи на половину ассортимента - само собой разумеющееся. Многие ритейлеры попали в “промо ловушку”, вынуждая друг друга сбивать цены. И для нас, как покупателей, это хорошо.
Для нас, как вендора системы лояльности, это тоже хорошо ? Потому что ритейлерам теперь требуется не просто инструмент предоставления скидок всем подряд, а возможность более тонкого взаимодействия со своей покупательской базой.
Стало важно не просто идентифицировать покупателя, внеся в базу CRM ФИО, дату рождения, номер телефона и затем отправить массовую рассылку. Стало важно работать с конкретной группой людей, которая отличается по своим социально-демографическим показателям; поведенческим паттернам; произвольным атрибутам в персональных данных. Появилась задача сегментировать покупателей.
Сегментация покупателей и внедрение ClickHouse
Подобная потребность вызвала необходимость пересмотреть способы хранения и обработки данных. Ранее мы хранили информацию о покупателях только в транзакционном хранилище (Postgres). Такое решение отлично подходит для точечной работы с конкретными покупателями. Но перед нами стояла задача быстро (за секунды) отобрать определенную часть покупательской базы среди миллионов профилей. Критерии отбора разнообразные:
блок критериев по анкетным данным, например дата рождения, информация о детях, наличие автомобиля, согласие на коммуникацию и любые другие данные, которые маркетолог решит собирать о своих клиентах
блок критериев по истории покупок: тут маркетолог может отобрать тех, например, у кого средний чек за период в диапазоне от 2000 до 3000; кто приобрел определенные товары заданное количество раз; кто совершил свою последнюю покупку до начала текущего года и многое другое.
Важно, что все эти критерии могут быть по-разному скомбинированы. В результате нужно, например, сформировать аудиторию покупателей в возрасте от 35 до 40 лет, которые купили за прошедшие 180 дней определенный гель для душа более 1 раза, но НЕ купили за этот период определенный шампунь.

Решение подобной задачи потребовало использования отдельного аналитического хранилища. Выбор пал на колоночную СУБД Clickhouse. Ответственный за транспорт данных - KAFKA (что это и как используется написал в своей статье другой мой коллега, тоже Игорь, системный архитектор).
Эта связка позволила обеспечить доставку данных с сотен касс через транзакционное хранилище в аналитическое в режиме онлайн. Через 1-3 минуты после регистрации, новый покупатель уже оказывается в ClickHouse; столько же времени нужно на то, чтобы доставить чек с кассы.
Помимо данных с касс, по KAFKA также доставляются другие данные:
по покупателям (при регистрации нового покупателя, либо при внесении изменений в его анкету)
по сегментам покупателей
по накоплениям покупателей
по акциям
по купонным механикам
по бонусным транзакциям
….
Ниже показан ландшафт системы, который у нас получился, с основными ее элементами (Set Centrum / Set Retail - это кассовая часть)

Завершая тему сегментирования покупательской базы, нужно отметить, что сам по себе сегмент не является самоцелью. Сегмент - это группа покупателей, достаточно узкая и специфичная, чтобы предложить ей что-то определенное и провести эффективную коммуникацию. Поэтому сегменты стали широко использоваться в таких блоках системы Set Loyalty, как:
кассовые акции. Это выгода, которая предоставляется покупателю в момент совершения покупки на кассе или в онлайн канале (примеры таких акции приведены ранее).
стимулирующие акции. Это вознаграждение покупателя по определенному триггеру. Например, за вхождение покупателя в сегмент “Самые активные”, ему начисляются бонусные баллы.
коммуникации (рассылка сообщений по разным каналам связи на определенную аудиторию покупателей)
Модуль аналитики
Получив мощный инструмент работы с данными, при помощи которого смогли заводить более тонко настроенные механики, перешли к решению следующей задачи: как понять, что аудитория выбрана корректно и предложение было востребованным?
Получить однозначный ответ на эти вопросы сложно, но судить можно по косвенным показателям. Нужно только эти показатели рассчитать и визуализировать.
Были проведены серии встреч с клиентами, которые позволили выявить набор базовых отчетов/графиков/показателей, на основе которых маркетологи могли бы принимать решения об эффективности запущенных механик и осознанно вносить корректировки.
Подготовили макеты - ниже пример одного из дашбордов.

На этом этапе встал вопрос о том, как разрабатывать этот и другие дашборды? Путь, к которому мы привыкли, подразумевал: формализацию требований → разбор с командой разработки → разработку → тестирование → приемку → внедрение. Но данный случай усложнялся тем, что на стороне 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 в наш ландшафт. Результатом стала вот такая архитектура:

Есть и более подробная архитектурная схема. Пишите, если кому интересно.
По результату внедрения в продукте Set Loyalty появилась возможность создания аналитических дашбордов, позволяющих оценить результаты запущенных механик, коммерческие показатели и другую информацию. За этот этап отвечает уже не разработчик/архитектор, а аналитик. Шаги по достижению цели:
понять бизнес задачу, которую должны помочь решить график/диаграмма/таблица/показатель
проверить достаточность информации в аналитической базе данных
сформировать запрос к данным
построить по ним нужный элемент визуализации
кастомизировать элемент по необходимости
проверить корректность и наглядность полученных данных
Подобный подход позволил значительно быстрее проверять гипотезы и оперативно вносить изменения в продукт, не проходя по стандартному пути разработки программного обеспечения и уменьшить количество человек, вовлеченных в процесс.
Остановимся поподробнее на создании графика на простом примере: График по среднему чеку.
В ходе сбора требований была выявлена потребность в отображении верхнеуровневых показателей сети. Так и назвали один из дашбордов. На нем был расположен помимо прочего график изменения среднего чека.
Для его создания понадобилось:
В штатном редакторе SQL запросов в Apache Superset составить запрос к БД, который выводил бы результат простого расчета (сумма чеков на продажу - сумма чеков на возврат) / количество чеков на продажу.
Указать динамические фильтры с использованием шаблонизации Jinja. Это позволило накладывать условия из выбранных фильтров на дашборде.

На основе полученного запроса (датасета) построить график в соответствующем редакторе Apache Superset.
Разместить график на дашборде.
Проделав аналогичные действия с другими графиками, получили готовый дашборд и пошли показывать его нашим клиентам. Важно отметить, что все необходимые компоненты были установлены всем клиентам, а значит им можно было показывать их же реальные данные.

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

В редакторе графика обновляем состав показателей

Готово. Даже, если редактирование запроса требует какого-то времени, оно явно меньше, чем если бы нам пришлось идти по пути привлечения разработчиков. Продемонстрировать изменения и проверить гипотезу можно в течение дня.

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


Важно отметить и нефункциональные возможности. Изначально закладывались принципиальные требования:
отчеты должны строиться быстро, в пределах единиц секунд, на больших данных - миллионы покупателей и сотни миллионов чеков.
повышение потребления ресурсов не должно быть больше 15%.
Говоря коротко, эти требования выполнены. Например, рассмотренный ранее график по среднему чеку (по анонимным и идентифицированным покупателям) за последние 4 месяца рассчитывается за 3 секунды. Количество чеков около 15 миллионов за этот период.

Заключение
Стоит упомянуть о том, что у реализации нашего модуля Аналитики есть и свои нюансы:
если в Superset что-то не настраивается так, как требуется, то “допилить” его довольно проблематично. По крайней мере пока у нас небольшой опыт в этом направлении.
при сравнении разработанных графиков с первоначальными макетами видно, что есть расхождения. Над некоторыми мы продолжаем работать. Например, над локализацией. Разделители разрядов не соответствуют привычным; некоторые слова не русифицированы; формат даты в фильтре и подобное.
требуются прокаченные навыки в работе с SQL в ClickHouse. Причем эти навыки должны быть у аналитика, а не разработчика.
Однако все эти нюансы перекрываются описанными ранее плюсами. Set Loyalty стала самодостаточной системой лояльности, обеспеченной быстрой доставкой данных, широким функционалом для запуска различных механик, а также возможностью оценить результативность запущенных акций и их влияние на покупательскую базу.