В большом мобильном продукте коммуникации запускаются разными командами. Подписки, апселлы, промоакции и A/B-эксперименты развиваются параллельно и часто независимо друг от друга.

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

Меня зовут Михаил Христокьян. Я работаю над мобильными продуктами Почты и Облака Mail и занимаюсь архитектурой и развитием системы продуктовых коммуникаций внутри приложения. Сегодня я расскажу о том, как мы решили эту проблему.

Но прежде, чем перейти к статье, несколько слов о том, как она родилась. Чтобы рассказать коллегам, как правильно использовать новый инструмент, мы провели «Разборки». Это внутренний формат обучения внутри VK, в ходе которого собирается разовая встреча посвященная прикладному разбору конкретного инструмента. В рамках таких встреч мы не только рассказываем про идею, возможности и планы на будущее, а также показываем коллегам как решать их конкретные задачи на реальных кейсах.

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

Когда скорость запуска коммуникаций — это не маркетинговая прихоть

Давайте представим, что вы открываете мобильное приложение. Вас встречает предложение подключить подписку со скидкой. Через пару дней — напоминание о новой функции. Параллельно идёт A/B-эксперимент с альтернативным экраном. А маркетинг уже готовит новую акцию, которая должна стартовать «вчера».

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

В Mail мы ежедневно работаем с продуктами, где коммуникации — это не разовые баннеры, а множество гипотез, экспериментов и других сценариев. Скорость их запуска напрямую влияет на удержание внимания пользователя, продуктовые метрики и, конечно, выручку.

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

Что такое ферма коммуникаций

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

  • заказчик или маркетолог;

  • продукт-менеджер;

  • дизайнер;

  • аналитик;

  • тестировщик;

  • разработчик (iOS/Android).

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

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

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

Важно, что ферма:

  • работает рядом с нативными решениями и не заменяет их;

  • учитывает приоритеты и ограничения других сценариев;

  • централизует правила показа;

  • позволяет запускать A/B-эксперименты и гипотезы за часы, а не недели.

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

Фактически, ферма отделяет две вещи:

  • разработку инфраструктуры;

  • управление коммуникациями.

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

Как ферма принимает решение о показе

В основе фермы лежит простой, но важный принцип: коммуникации не инициируют показ сами. Они становятся кандидатами. Процесс выглядит так:

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

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

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

Как выглядит конфигурация фермы

После того как ферма получает список доступных коммуникаций из A/B-сервиса, она работает не с кодом, а с конфигурациями. Каждая коммуникация описывается JSON-контрактом: в нём содержатся параметры показа, ограничения, приоритет и ссылка на вёрстку. Такой JSON может выглядеть следующим образом:

{
   "id": "<название>",
   "config_json": { ... },
   "config_url": ""
   "mount_point": "", 
   "plateRule": {
      "period": -1,
      "priority": 0, 
      "end_condition" : { 
          "shows_count" : 0, 
          "actions_count" : 0 
      },
      "triggers": { 
         "isPaidUser" : false, 
         "isBizUser" : false, 
         "isCorpUser" : false, 
         "skipFirstLaunch": false,

         <...>
      }
   },
   "screens" : [...],
   "presentationStyle": {
      "" : {}
   }
}

Конфигурация не привязана к конкретному типу интерфейса. Один и тот же JSON используется для разных форматов коммуникаций и других сценариев показа. Меняются только тип и ссылка на вёрстку, а правила показа остаются одинаковыми.

При просмотре конфигурации может возникнуть вопрос: зачем в контракте сразу несколько полей, связанных с вёрсткой — config_json, config_url и mount_point?

config_json

Содержит саму вёрстку коммуникации в формате JSON. Используется для небольших конфигураций или при тестировании.

config_url

Ссылка на удалённую вёрстку. На практике используется чаще, так как позволяет хранить большие конфигурации вне A/B-сервиса и обновлять их независимо.

mount_point

Формат, который подойдёт в том случае, когда заказчик не в силах самостоятельно создать вёрстку, или сценарий слишком сложный (здесь нужно залезать в репозиторий Kotlett и создавать вёрстку с помощью DSL).

Автоматизация процессов

Для ещё большего сокращения TTM вокруг фермы были построены инструменты, которые упрощают работу с типовыми сценариями. Админ-панель:

В ней можно настроить:

  • название и идентификатор коммуникации;

  • период активности;

  • сегменты аудитории;

  • ограничения показов;

  • ссылки на изображения;

  • тексты и кнопки;

  • аналитические события;

  • ссылку на вёрстку.

После сохранения админка формирует JSON-конфигурацию, которая публикуется в A/B-сервисе и становится доступной для фермы.

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

Результаты внедрения

  • С помощью фермы стало возможна работа с единым типом конфигурации. Это активно используется в Android/iOS-клиентах, причём не только в одном приложении.

  • Решён конфликт с параллельными запусками А/В-экспериментов.

  • Ресурс тестирования с каждой задачи по запуску сокращён на 2-3 часа.

  • Спринты мобильных разработчиков стали гибкими.

По сути, ферма стала единым механизмом, через который в приложении появляются продуктовые коммуникации — от простых подсказок до полноценных промосценариев.

Комментарии (0)