![](https://habrastorage.org/getpro/habr/upload_files/892/213/d68/892213d688d3c1f5d892d0eb73938045.jpg)
Привет, Хабр! Эксперт комьюнити #Сарафан компании GlowByte Александр Долгих расскажет историю из личного опыта о том, как решалась задача интеграции целевого маркетинга и множества самых разных каналов в одном из ведущих банков России (спойлер: о создании собственной централизованной платформы). Все персонажи вымышлены и совпадения случайны (улыбка).
1. Проблема многообразия интеграций
О том, почему нельзя просто взять и сделать единый для всех инструмент и выпустить на рынок. Как подойти к проблеме
Эпоха целевого маркетинга вовсю набрала обороты. Персональные подборки, личные рекомендации, сложные многошаговые квесты и тарифы-конструкторы уже де-факто являются “гигиеной” не только цифровых сервисов, но и банков, телекомов и retail. Но, оставив в стороне великое множество механик подбора таких предложений, я бы хотел сконцентрироваться на том, как их скоординировать между собой и доставить до конечного получателя в правильный момент действенным образом.
Это история из личного опыта о том, как решалась задача интеграции целевого маркетинга и множества самых разных каналов в одном из ведущих банков России.
До 2013 года платформа централизованных рассылок банка (героя моего рассказа) представляла из себя VBA-скрипты и хитрый эксель, заранее определенные фильтры, отсутствие гибкости и масштабируемости. Но так совпало, что был дан старт сразу нескольким большим проектам по внедрению промышленных систем хранения данных и маркетинговой автоматизации и оптимизации. Проекты были успешно завершены, однако проблему "предпоследней мили" решили отложить "на потом", потому что масштабы и потребности бизнеса полностью закрывались тремя-четырьмя каналами рассылки, которые не требовали скорости (сроки подготовки волны коммуникаций обычно составляли месяц), сложной кастомизации и настройки обратной связи, поэтому легко решались двумя администраторами данных.
Спустя три года открылся проект маркетинга реального времени. Все чаще стали появляться идеи геймификаций, многошаговых акций с хитрыми условиями. Активнее стали развиваться новые контентные каналы: push-сообщения, сайт. Процесс стал вплетаться в кредитный пайплайн, а значит появилась необходимость интеграции с кредитными конвейерами, oCRM – тут уже не допускалась задержка в реакции и плановая ручная загрузка. Но в отсутствие платформы решалось все это ситуативно и симптоматически.
Интеграции и многотысячные скрипты под каждый канал и каждый вид условий начали расти как грибы после дождя. Казалось, что нужен месяц-другой спокойной жизни, чтобы привести скрипты в порядок, проработать автоматизацию, что-то упростить, что-то переосмыслить, но, как многие могут догадаться, ни пары спокойных месяцев, ни свободных рук с незагруженной ежедневными заботами головой, ни тем более общих идей по сбору воедино всех разношерстных бизнес-механик под одной согласованной системой не было.
Остроты добавляло то, что “коробки” разных вендоров для маркетинга реального времени и маркетинга массированных рассылок друг про друга знать не хотели, механизмы синхронизации не давали той гибкости, о которой грезили менеджеры. Так родилась идея создания собственной централизованной платформы для интеграции аналитического CRM со всеми возможными и перспективными каналами связи с клиентами, а также всеми техническими каналами, которые могут быть использованы в маркетинге.
Первой мыслью было попытаться найти готовое решение как минимум для вдохновения, как максимум для экономии тысяч человеко-дней на создание чего-то с нуля. На дворе был 2019 год, а значит основными законодателями рынка были крупные вендоры, в качестве механизма интеграции предлагавшие два пути: либо установку встроенных или партнерских систем рассылки, либо возможность настройки выходного потока данных под один из видов интеграции, но не предполагающей синхронизации с каналом доставки. Никаких признаков возможности оркестрации своими силами между внешним RTDM и batch вкупе с консолидированной системой управления шаблонами или контактной политикой не было. Увы, менять текущие системы и перестраиваться так сильно "на горячую" банк не мог.
Второй мыслью стала идея найти интегратора, который уже выполнял на рынке подобный проект, чтобы повторить его без рисков первопроходцев, а значит сэкономить время и ресурсы. Но и тут были нюансы: каждый заказчик систем такого класса – это сложноорганизованный механизм, годами приходивший к своей уникальной топологии, бизнес-процессам, этапам, вендорам, отчетным формам и тонким целям, которые решает aCRM. После трех месяцев поисков найти пример такого же проекта "под ключ", в интерпретируемость которого банк мог бы поверить, не получилось.
Напрашивался вывод: нужна собственная разработка, максимально гибкая, с актуальной архитектурой и инфраструктурой, которые смогли бы позволить решать любые идеи бизнеса без значительных доработок хотя бы 5 лет. В качестве компромисса было решено объединить знания, опыт и “руки” самого опытного подрядчика из тендера, который выиграла компания GlowByte, с энтузиазмом и включенностью только что создаваемой aCRM IT-команды банка.
Результат обещал быть оптимальным, ведь банк не только компенсировал риски от проектирования новой системы (любые теоретические знания внутри банка не особо ценны без опыта, но он в достатке есть у GlowByte), но и получал на выходе обученную внутреннюю команду, досконально понимающую, как работает платформа, и готовую ее в дальнейшем поддерживать и развивать.
2. Выбор ядра идеи
Как формировалась архитектура и логическая модель данных. RT vs Batch
![](https://habrastorage.org/getpro/habr/upload_files/40d/ede/648/40dede648175050d184e4e7099d1e96a.jpg)
Были определены ключевые технические задачи, для решения которых платформа должна была позволять:
автоматизировать интеграцию с исходящими и входящими каналами коммуникации для донесения предложений клиентам;
собирать и хранить отклики клиентов на предложения (по возможности, в режиме, близком к реальному времени);
предоставлять дополнительный функционал управления временем отправки, распределения нагрузки на канал, соблюдения допустимого времени коммуникации;
выступать мастер-системой (единой версией правды) по текущим статусам предложений, коммуникаций и откликов;
обеспечивать синхронизацию предложений и коммуникаций между batch-системой и real-time-системой;
следить за соблюдением контактной политики с клиентом (с возможностью проведения A/B-тестов по контактной политике);
предоставлять функционал по управлению контентом предложений (текст, картинка, html, кнопки и прочее);
предоставлять интеграционные интерфейсы как для управления предложениями, так и для запроса предложений со стороны каналов и кредитных конвейеров;
обеспечивать высокую доступность сервисов и отказоустойчивость архитектуры (маркетинговые предложения участвовали в кредитном процессе, и банк не мог позволить себе потерять данные).
Для решения этих задач была выбрана микросервисная архитектура со связью между модулями через шину и API. Пару слов о технологиях: движок был написан на Java + Spring, СУБД на PostgreSQL, шина Kafka, UI на JS + React.
В концепте система на тот момент состояла из основных элементов:
Входная интеграционная СУБД + java-сервисы, которые должны были определять изменение ее состояния (API SAS и API EVAM).
CMCP – Control Module for Contact Policy, должен был отвечать за принятие решения о том, можно ли коммуницировать с клиентом с точки зрения контактной политики. Крутой фишкой, о которую было сломано много мозгов, из-за которой проведено много часов в дебатах и поисках, была единая матрица контактной политики. Она должна была быть достаточно гибкой, чтобы отслеживать правила на уровне продукта-сегмента-канала-типа кампании, поддерживать A/B-тесты, расширения продуктовой линейки и потенциальное усложнение новыми срезами. Модуль должен был блокировать отправку непосредственно в канал предложения, если видел запрет на клиента по контактной политике. Этот запрет логировался для последующего анализа. Главная задача – уберечь клиента от перегруженности “приветами”. С учетом распределенных по продуктовым командам кампейнеров это требование было обязательным. Таким образом, модуль должен был стать финальным боссом, которого нужно было бы пройти предложению перед тем, как задача отправки попадет в систему доставки. Кроме того, модуль должен был позволять получать копию матрицы кампейнерам в момент формирования кампаний в SAS и EVAM.
CMS – Content Management System. Основное хранилище всего контента. Было решено реализовать этот модуль внутри системы не только для оптимизации передачи данных между модулями, но и для возможности быстро и гибко перенаправлять предложения между различными каналами. Система должна была иметь UI, расширяться какими угодно полями, настроенные шаблоны должны были быть видны в виде варианта настройки в SAS и EVAM. Ну и, само собой, должны были позволять проводить параметризацию и шаблонизацию по всем канонам требований к корпоративному стилю.
ONCM – Offers Nomination & Communication Module. Мастер-система сущностей “предложение” и “номинация”. Должна была хранить исчерпывающую информацию о том, что, кому, когда и как планировали прокоммуницировать. Это же было и основным складом всех доступных предложений для клиента.
RCM – Response Control Module. Мастер-система откликов на предложения. Должна была позволять получать отклики из очередей и через сервисы, т. е. в режиме, близком к реальному времени. Также этот модуль должен был обрабатывать статусы доставки (определяя, что канал вернул статус, модуль должен передавать эту информацию в историю статусов, у себя сохраняя только бизнес-отклики).
FCM – Fast Communication Module. Быстрая операционная база, которая должна хранить только самое необходимое для предоставления pull-каналам списка предложений по клиенту за минимальное время. Данные сюда должны были попадать через CDC в режиме реального времени из ONCM.
CDC, базы данных и архивация. Операционное хранилище платформы заточено под скорость, значит его глубина хранения должна была определяться только требованиями коммуникационной политики. Все остальное должно удаляться. Но для аналитических нужд, архивации данных и для возможности более оптимального использования контактной истории в SAS и EVAM необходимо было реплицировать данные в холодную зону. Желательно без нагрузки на саму платформу. С этим должна была справиться связка Debezium + Kafka + NiFi (данные сохраняются в операционную БД для SAS и EVAM + копируются в общий DWH и используются в отчетности. Спойлер: нам удалось достичь задержку в 200-300 мс).
Шлюзы/ адаптеры каналов. По сути, это различные интеграционные сервисы. Со второй половины проекта команда банка стала сама публиковать интерфейсные соглашения (до этого она больше подстраивалась под каналы). В моменте это могло показаться некоторым зоопарком, однако его можно было легко устранить при желании.
Мониторинг. Он тут просто был необходим и разделен на две большие части: технический мониторинг и бизнес-мониторинг. Первый покрывал все основные критические узлы в разрезе мониторинга отклонений от нормы и позволял использовать систему нотификации. Она была создана на стеке ELK + Influx + Grafana. Второй мониторинг должен был позволить формировать “табло взлетов и посадок” для кампейнеров, которым необходимо не только понимать статус, иметь возможность в режиме реального времени наблюдать за распространением кампании, но и на ранних этапах видеть потенциальные отклонения от изначальной логики, которые легко пропустить роботу. Сделан на базе RDBMS + Tableau.
Балансировка. Система должна была быть отказоустойчивой и выдерживать нагрузки при обращении того же мобильного приложения или операционного CRM в самые пиковые периоды. С точки зрения скорости удалось добиться оптимума за счет хорошей логической модели. Отказоустойчивость должна была решаться кластерностью, россыпью балансировщиков везде, где это можно, горячей репликой баз данных.
![](https://habrastorage.org/getpro/habr/upload_files/831/2b3/47f/8312b347f3cac9a31de13214a78d5922.jpeg)
Архитектура рождалась в муках. Хотелось объять сразу всю функциональность. Отдельное непонимание было с производительностью: по требованию некоторых высоконагруженных каналов платформа должна была мгновенно отдавать по запросу список предложений на клиента, не формируя задержку при отрисовке страницы. Но команды проекта очень слабо представляли, с какими реальными характеристиками нагрузок они столкнутся. Решили, что быстрые реляционные базы будут лучше как начало, но параллельно запроектировали на in-memory базе, чтобы перейти на нее во второй версии системы. Забегая вперед, скажу, что банку повезло: мощности вполне хватило, так что не пришлось тратиться на гораздо более трудозатратный и инфраструктурно дорогой вариант в первой же попытке.
Логическая модель данных
Коротко расскажу о том, как разложили большие массивы данных в платформе. В числе требований были следующие исходные:
Атомаризация. То есть в любой момент времени необходимо понимать, что, кому, когда, как и зачем отправили или, что более важно, не отправили.
Возможность работы с разными сегментами клиентов (retail, sme, cib).
Омниканальность. Нередко предложение фактически отправляется не в тот канал, который планировался в момент подготовки волны, а в тот, который стал резко приоритизирован из-за различных событий. Довольно часто предложения осознанно дублируются в разных каналах. Всю эту логику желательно отслеживать в постанализе.
Большой фокус на real-time. Как и в предыдущем пункте, изначально хотели сделать максимум технических возможностей для формирования самых изощренных механик, включая повсеместное навешивание real-time-моделей и скорингов, которые полностью бы меняли картину, максимально оптимизируя возможности коммуникации.
В итоге были сформулированы такие сущности:
Offer. Это бизнес-слепок предложения. В нем описано все, что необходимо для понимания того, что предлагает банк. При этом факт наличия самого предложения не гарантирует общение. О нем дальше.
Nomination. Это контейнер с техническими настройками и необходимым контентом для отображения в конкретном канале. Если канал требует сложный многосоставный контент (как email или предложение в мобильном приложении), то используется ссылка на шаблон CMS. Nomination ссылается на Offer. Но в отдельных случаях номинации могут идти самостоятельно (например, срочная информационная рассылка без привязки к предложению).
Template. Шаблон контента. Попытка сделать единый справочник всего, что необходимо для отображения в разных каналах, к тому же с возможностью вариаций одних и тех же коммуникаций, но в разных стилях для разных сегментов клиентов.
Contact. Факты попыток отправок или запросов номинаций. Статусная модель определяет результат доставки. И именно от этой сущности строится контактная политика. Естественно, содержит ссылки на номинацию и предложение.
Response. Отклик. Составлено несколько слоев типизации откликов, чтобы сохранять оригинальность каждого канала (какие-то из них могут многое рассказать, какие-то достаточно бинарны). Как второй уровень, есть и обобщенные типы откликов, которые позволяют использовать кросс-канальные правила.
Batch. Разбиение потока предложений на кванты при отправке в некоторые каналы, где это обосновано технически. Позволяет более оптимально переслать предложения в push-каналы.
3. Ошибки юности
Про организационные промахи и неверные решения
![](https://habrastorage.org/getpro/habr/upload_files/252/c8f/a65/252c8fa6593a16868ba90ddb63678a32.jpg)
3.1. Организация
Проект реализовывали отнюдь не юнцы: как со стороны банка, так и со стороны GlowByte были опытные специалисты, за плечами которых – сотни проектов всех калибров и мастей. Но задача была все равно необычной: требовалось смиксовать этапный подход интегратора с большими вехами и работу внутренней гибридной банковской команды по SCRUM (которая, к слову, продолжала выполнять свои непосредственные обязанности, и спринты приоритизировались согласно бизнес-логике).
В этом и крылась проблема номер один: никто не придумал на старте, как подружить две сформировавшиеся, привычные для банка и для GlowByte парадигмы работы. Команда GlowByte очень хороша в больших проектах “под ключ”, эта бизнес модель не раз показывала свою эффективность. Но банк был уверен в своих силах и предложил модель партнерства, когда из двух компаний собирается лучший опыт и формируется гибридная суперкоманда.
Но, в связи с удаленной работой и тем, что детали взаимодействия рождались по ходу пьесы, разделение между командами все равно имело место. В итоге это привело к рассинхрону на этапе разработки, запаздыванию по ревью идей решения задачи, неверной оценке банком сроков на тестирование и бизнес-тестирование фич, проблемам с разной трактовкой функциональных и нефункциональных требований, о которой расскажу ниже, и, как итог, к сдвигу общих сроков.
Решение было очевидным, но пришло не сразу: ввести несколько раз в неделю совместные статусы, дать возможность разработчикам общаться напрямую без менеджеров, фиксировать формирующиеся на ходу правила (как можно, а как нельзя), плюс статусы, технические и бизнес-ретро, демонстрации прототипов и гибкое перераспределение задач за счет взаимного роста экспертизы и команды.
3.2. Репозитории и релизы
Одной из главных, так и не решенных проблем оказался репозиторий. В связи с политикой безопасности и переходным периодом в выборе стека в банке не удалось организовать единое пространство для написания кода. Выглядело все примерно так: разработка велась GlowByte в своем репозитории, банком – в его репозитории. При завершении вехи GlowByte вливала все свои доработки в репозиторий руками, дальше одним commit это раскатывалось на стенды тестирования, уже потом формировался релиз. Ревью и осмысление кода, подготовка к сборке занимали так много времени, что порой превосходили саму разработку. Исправления вносились с новыми кусками функционала. Все это приводило к потере связанности задач на доске с коммитами, сложности при слиянии кода и путанице с релизами на прод.
Но постепенно команды начали уменьшать ветви разработки, насколько это возможно облегчать и параллелить работу над разными элементами. После сборки ядра системы и начала промышленной эксплуатации основных модулей проблема понемногу стала уходить.
Однако честным будет уточнение, что подготовка и запуск первых версий за обозначенный срок предполагали большой объем изначального кода, поэтому отчасти описанные проблемы были неизбежны безотносительно к репозиторию и релизам.
3.3. Трактовка терминов
Бывает так, что терминология воспринимается как универсальная и общепринятая, но практика показывает: всегда лучше договариваться о ней заранее. Например, термин “монолит” и его противоположность “микросервис” могут ощущаться по-разному у разных архитекторов. Различия могут быть в деталях или в мелочах, но в масштабах громадной системы это может выливаться в принципиальные элементы, которые возвращают архитектуру на начальный этап проектирования.
Другим подобным примером может быть достаточность или избыточность отказоустойчивости, защиты от нестандартных сценариев использования или поведения, трактовка стандартов составления кода или использования шины. Решение настолько же простое, насколько и утопичное: общаться, обсуждать, спрашивать и договариваться. Команды проекта для себя нашли формулу в том, чтобы двигаться меньшими, но частыми шагами, почаще показывать промежуточные состояния, не бояться спорить, искать компромиссы и баланс.
3.4. SARS-CoV-2
Он пришел в нашу страну под звуки самоизоляции как раз в тот момент, когда завершился этап архитектурного проектирования системы и первичный этап системного анализа, и проект должен был переходить в стадию разработки. Изначально затевались общекомандные “дейли”, коллаборация, обмен знаниями в едином пространстве – работа в единой мотивации, когда ребята из команды GlowByte проникались бы духом работы целевого маркетинга банка, воочию бы наблюдали за проблемами, победами, рутиной и авралом, процессом генерации идей и общекомандным обсуждением результата. Это, безусловно, должно было сблизить и наполнить радостным предчувствием весь коллектив проекта. Но ровно в тот момент, когда банк определился со схемой рассадки, растолкав соседей по этажу, приоритеты резко изменились…
Руководство банка за две недели вывело практически весь свой штат сотрудников на удаленную работу, придумав решение такого формата (до событий марта 2020 удаленно, да и просто с ноутбука могли работать очень немногие). Точно так же пришлось импровизировать и с доступами для внешних подрядчиков. Все было успешно организовано, но проект потерял в скорости и своем запале. Многое из проблем взаимодействия стало следствием того, что команды работали “вслепую”, так ни разу и не увидев друг друга в полном составе очно.
3.5. Внутренние трансформации и целеполагание
Так совпало, что проект пережил вместе с его участниками несколько организационных изменений, связанных со структурой Retail. Это и переход CVM под крыло другого домена, и смена принципов выстраивания приоритетов, и реорганизация и децентрализация платформ и сервисов всего блока. В связи с этим договоренности по участию смежных команд, которые отвечали за доработку интерфейсов взаимодействия системы с каналами доставки и конвейерами, менялись в неочевидную для проекта сторону, да и план проекта вкупе с его фокусами претерпел изменения десятки раз. Порой было непросто найти общий язык и прийти к общему знаменателю с другими владельцами продуктов. Какие-то из элементов оптимальнее оказывалось вообще не делать, какие-то делать самим, а какие-то переосмыслять архитектурно. Но гибкость, к которой пришли к этому моменту в проектной команде, играла на их стороне – система вышла на заданную орбиту.
4. Что получилось в итоге
Настоящее и будущее платформы
Эта статья была задумана в январе 2022 года как рассказ об очень большом, технологически красивом и обращенном в будущее решении. Но в феврале случилось то, что случилось. Как итог – большие вендоры, решения которых были компонентами платформы, частично или полностью ушли с российского рынка. В заключении я планировал рассказать про метрики, скоростные инкременты и планы по дальнейшему развитию, но все-таки завершу некоторыми размышлениями о том, что было бы без этого решения в подобной ситуации, и том, что потенциально может его ждать.
Взяв курс на собственную разработку и восприятие коробочных решений как отдельных кубиков в архитектуре, банк здорово снизил стресс от того, что какой-то из этих элементов может превратиться в тыкву. По большому счету, внедрение любого другого средства генерации персональных предложений сводится к соблюдению интерфейсных соглашений и возможному переписыванию интеграционных модулей. При этом почти полностью сохраняется логическая модель, сценарии и механизмы управления, ведь все создавалось под бизнес-процессы компании, а не подстраивалось под возможности трендовых решений.
Идея заключается еще и в том, что инструментов генерации предложений может быть не два и не три одновременно. Все самые детальные данные порождаются и хранятся в платформе, а значит и отчетность сохранится и не даст потерять контроль над эффективностью целевого маркетинга. Это позволяет внедрять новое решение при сохранении работы старого, пока лицензии еще активны.
Реальность, скорее всего, скорректирует этот радужный прогноз, и любые существенные изменения компонентов могут обернуться “сюрпризом”. Много инженерных проблем будет ждать своих решений. Но сейчас кажется, что банк сделал удачный выбор.
Архитектурные принципы, заложенные в систему, позволяют гибко ее расширять как под новый функционал, так и под большие нагрузки. Платформу можно и нужно кластеризировать – то, что в числе прочего было нещадно схлопнуто MVP. В угоду срокам проекта были упрощены интеграции с некоторыми каналами, не внедрены все фичи и упрощены интерфейсы.
С интересом можно наблюдать за тем, как идея пройдет испытание в обстоятельствах, где роль и ключевые приоритеты CRM меняются, инфраструктура находится в бурном непрерывном преобразовании, прогнозы работают слабо, ведь тот мир, в котором мы сейчас живем, никогда не был таким ранее. Участие же в этом проекте стало для всех его участников ярким событием в профессиональной карьере и позволило на практике проверить представления о прекрасном.