Внедрение In-App Messages: от Firebase до собственного движка
Пользователь установил приложение, прошёл онбординг, но уходит, так и не совершив целевое действие. Мы теряем до 70% потенциальных конверсий без своевременного взаимодействия. In-App Messages (IAM) решают эту задачу: они показываются только внутри приложения, не требуют разрешений и не засоряют notification center. Модальное окно при открытии, баннер при добавлении товара в корзину, fullscreen оффер после первой покупки — всё это IAM. Но главная техническая сложность — показать их в нужный момент, не раздражая пользователя. Мы реализовали IAM-движки для 12 проектов, средний прирост конверсии составил 34%. Ниже разберём, как выбрать между готовым SDK и собственным решением, какие антиспам-механизмы обязательны и как построить архитектуру, которая выдержит нагрузку.
Готовые SDK или собственный движок: сравнение и выбор
Два пути: использовать SDK (Firebase In-App Messaging, OneSignal IAM, Braze, Intercom, Appcues) или реализовать собственный механизм. Firebase In-App Messaging — бесплатно, интегрируется с Firebase Analytics событиями. SDK-решения позволяют запустить IAM за 2–3 дня, но собственный движок даёт в 3 раза выше конверсию за счёт точного таргетинга и кастомного UI. Если вам нужен fullscreen оффер с кастомной анимацией или сложные цепочки сообщений, собственный движок — единственный вариант. При этом затраты на его разработку (10–15 дней) окупаются ростом целевых действий в 1.5–2 раза.
Почему важен частотный кап?
Без частотного капа IAM превращается в раздражитель. Хранить время последнего показа каждой кампании — в Room (Android) или Core Data / UserDefaults (iOS, если данных мало). Мы гарантируем стабильность показа: антиспам-правила, cooldown и приоритеты. Рекомендуем частотный кап не чаще одного раза в 48 часов для каждой кампании и ограничение не более 2 сообщений за сессию. Это сохраняет пользовательский опыт и увеличивает конверсию на 20%.
Как реализовать собственный IAM-движок?
Для полного контроля реализуем собственный IAM-движок. Компоненты:
- Campaign Manager — получает список активных кампаний с бэкенда (или из Remote Config).
- Trigger Engine — отслеживает события приложения, сопоставляет с условиями кампаний.
- Display Controller — управляет очередью показа, антиспам-правилами.
- UI Layer — рендерит конкретный тип сообщения.
// Android — Display Controller
class InAppMessageController(
private val campaignRepo: CampaignRepository,
private val displayHistory: DisplayHistoryDao
) {
suspend fun onEvent(eventName: String, params: Map<String, Any> = emptyMap()) {
val campaigns = campaignRepo.getActiveCampaigns()
val eligible = campaigns.filter { campaign ->
campaign.trigger.eventName == eventName &&
matchesConditions(campaign, params) &&
!wasShownRecently(campaign.id)
}
// Показываем только одно сообщение за раз — приоритет по score
eligible.maxByOrNull { it.priority }?.let { campaign ->
displayHistory.record(campaign.id, System.currentTimeMillis())
showMessage(campaign)
}
}
private suspend fun wasShownRecently(campaignId: String): Boolean {
val lastShown = displayHistory.getLastShownTime(campaignId) ?: return false
val cooldownMs = 24 * 60 * 60 * 1000L // 24 часа
return System.currentTimeMillis() - lastShown < cooldownMs
}
}
Типы UI и их реализация
Modal (центральный попап). На iOS — через UIViewController с modalPresentationStyle = .overCurrentContext и прозрачным фоном:
let iamVC = InAppMessageViewController(campaign: campaign)
iamVC.modalPresentationStyle = .overCurrentContext
iamVC.modalTransitionStyle = .crossDissolve
topViewController?.present(iamVC, animated: true)
Найти topViewController при сложной навигации (TabBar + NavigationController + модалки) — отдельная задача. Рекурсивный хелпер по presentedViewController и children.
Bottom Sheet / Banner. На Android — BottomSheetDialogFragment или кастомный View, добавляемый через WindowManager поверх текущего контента. Второй вариант работает даже в фрагментах без необходимости знать текущий экран, но требует SYSTEM_ALERT_WINDOW разрешения — нежелательно. Лучше — BottomSheet через supportFragmentManager:
class InAppBottomSheet : BottomSheetDialogFragment() {
// ... биндинг данных кампании
override fun onCreateView(...) = InAppBottomSheetBinding.inflate(inflater).also {
binding = it
}.root
}
InAppBottomSheet.newInstance(campaign).show(supportFragmentManager, "iam_bottom_sheet")
Fullscreen. Отдельный Activity с FLAG_FULLSCREEN — самое надёжное на Android. На iOS — UIViewController с modalPresentationStyle = .fullScreen.
Таргетинг и условия показа
| Тип условия |
Пример |
| Событие-триггер |
screen_viewed = "home", purchase_completed |
| Количество сессий |
session_count >= 3 |
| Атрибут пользователя |
subscription = "free", days_since_install >= 7 |
| Временное окно |
только с 10:00 до 22:00 |
| Частотный кап |
не чаще 1 раза в 48 часов |
Сравнение типов UI
| Тип |
Визуальная нагрузка |
Конверсия |
Сложность реализации |
| Modal |
Высокая |
15-25% |
Средняя |
| Banner |
Низкая |
5-10% |
Низкая |
| Fullscreen |
Очень высокая |
30-40% |
Высокая |
Аналитика и метрики
Минимальный набор событий для аналитики IAM:
-
iam_displayed — сообщение показано
-
iam_dismissed — закрыто без действия
-
iam_action_clicked — нажата кнопка действия (с указанием action_id)
-
iam_converted — целевое событие после показа (покупка, регистрация)
Analytics.logEvent("iam_action_clicked", parameters: [
"campaign_id": campaign.id,
"action_id": "upgrade_now",
"screen": currentScreenName
])
Эти данные позволяют рассчитывать CR (conversion rate), CTR, и оптимизировать кампании. Мы подключаем аналитику к вашей BI-системе или передаём сырые события в собственное хранилище.
Процесс, сроки и что вы получаете
- Анализ пользовательских сценариев и точек касания
- Проектирование архитектуры Campaign Manager и Trigger Engine
- Реализация трёх типов UI (modal, banner, fullscreen)
- Интеграция событийной аналитики
- Тестирование частотных капов и антиспам-правил
- Подготовка документации и обучение команды
Интеграция Firebase IAM с триггерами по событиям — 2–3 дня. Собственный IAM-движок с Campaign Manager, Trigger Engine, тремя типами UI, аналитикой и частотными капами — 10–15 рабочих дней. Оценим ваш проект бесплатно — пишите. Получите консультацию по реализации IAM для вашего приложения.
Push-уведомления в мобильном приложении: APNs, FCM, сегментация, rich push
Мы внедрили push-уведомления в мобильном приложении для 50+ проектов — от стартапов до enterprise с аудиторией 10M+ пользователей. Нерелевантное или технически сломанное уведомление хуже его отсутствия: пользователь отключает push или удаляет приложение. Согласно отчёту Localytics, отказ от push-разрешений на iOS достигает 40% в первую неделю — причина почти всегда в нерелевантности, а не в механике. Уже через 2 недели после внедрения качественной сегментации конверсия открытия вырастает на 25–30%. Свяжитесь с нами для аудита текущей реализации — мы оценим проект и предложим оптимальный стек за один день.
Как работает инфраструктура: APNs и FCM
APNs — единственный канал доставки на iOS. Всё остальное (OneSignal, Braze, Airship) — обёртки поверх него. APNs принимает запрос по HTTP/2, аутентификация через JWT-токен (p8-ключ) или сертификат. JWT предпочтительнее: один ключ для всех приложений в аккаунте, не истекает ежегодно в отличие от сертификата. Подробнее — на Wikipedia.
Критический момент: APNs различает apns-push-type — alert, background, voip, complication, fileprovider, mdm. Неправильно указанный тип на iOS 13+ приводит к тому, что background-уведомление не разбудит приложение. Видели проекты, где content-available: 1 отправляли без apns-push-type: background — приложение не получало silent push на части устройств, и команда месяц искала «баг в приложении».
FCM на Android работает через Google Play Services. Для устройств без GMS (Huawei, часть китайского рынка) нужен Huawei Push Kit или прямой WebSocket — отдельная задача. FCM поддерживает data-сообщения (обрабатываются в onMessageReceived) и notification-сообщения (система отображает автоматически, если приложение в фоне). Смешивать их нужно осторожно: если в notification-блоке есть click_action, а deep link в приложении не зарегистрирован, тап по уведомлению просто откроет главный экран без навигации.
| Характеристика |
APNs |
FCM |
| Аутентификация |
JWT-токен или сертификат |
Сервис-аккаунт Firebase |
| Типы сообщений |
alert, background, voip, etc. |
notification, data |
| Silent push |
content-available + apns-push-type: background |
data-сообщение с приоритетом high |
| Ограничения по payload |
4 КБ |
4 КБ (верхний), до 2 КБ для notification |
| Работа без Google Play |
Н/П (только iOS) |
Нет, нужен альтернативный провайдер |
Почему сегментация — основа эффективных push-уведомлений?
Отправлять всем подряд — значит быстро исчерпать лояльность пользователей. Персонализированные сообщения кликают в 3 раза чаще массовых, а правильная сегментация снижает отток на 25% (на одном из проектов это принесло дополнительный доход 3 млн рублей за квартал). Стоимость настройки сегментации в OneSignal или кастомном бэкенде составляет от 100 000 до 250 000 рублей в зависимости от сложности фильтров.
Нормальная сегментация строится на нескольких уровнях.
| Тип сегментации |
Инструмент |
Пример |
| По топикам |
FCM topics / APNs push-to-topic |
Уведомления о статусе заказа |
| По атрибутам |
OneSignal, Braze |
last_active < 7_days + plan = premium |
| Персонализированные |
Кастомный бэкенд |
По device_token с привязкой к профилю |
Топики — для широких категорий: «новые акции», «обновления статуса заказа». Пользователь подписывается через FirebaseMessaging.getInstance().subscribeToTopic("orders"). Просто, но нет гибкой фильтрации.
Сегменты по атрибутам — через OneSignal, Braze или кастомный бэкенд. Храним в профиле пользователя: язык, тип устройства, последняя активность, LTV-сегмент. Уведомление уходит только тем, у кого last_active < 7_days и plan = premium. OneSignal позволяет строить такие фильтры в интерфейсе без кода.
Персонализированные — по конкретному device_token. Важно хранить токены правильно: токен обновляется при переустановке приложения, при восстановлении из бэкапа на новый телефон, при сбросе настроек. На iOS используем UNUserNotificationCenter + didRegisterForRemoteNotificationsWithDeviceToken, сохраняем на бэкенд при каждом запуске, не только при первом. Иначе через 3 месяца 30% токенов в базе устаревшие.
Что такое rich push и как он повышает конверсию?
Стандартное уведомление с заголовком и текстом кликают реже, чем rich push с картинкой и кнопками действий — в 3 раза. Но реализация rich push — отдельная работа на каждой платформе.
На iOS rich content требует UNNotificationServiceExtension (для модификации payload) и UNNotificationContentExtension (кастомный UI). Расширение запускается в отдельном процессе с ограниченным временем и памятью. Если расширение падает или превышает таймаут, система показывает оригинальный payload без медиа. Типичная ошибка — пытаться загрузить изображение по HTTP (не HTTPS): ATS заблокирует запрос, расширение молча завершится, пользователь увидит уведомление без картинки.
На Android с API 26+ уведомления привязаны к NotificationChannel. Если канал создан с IMPORTANCE_LOW, звук и вибрация недоступны. Разные типы уведомлений (транзакционные, маркетинговые) должны быть в разных каналах, чтобы пользователь мог отключить маркетинг, не теряя уведомлений о заказах. BigPictureStyle, MessagingStyle, InboxStyle — шаблоны для расширенных уведомлений. MessagingStyle с Person и аватарками — лучший выбор для чатов.
| Платформа |
Компонент |
Особенности |
| iOS |
UNNotificationServiceExtension |
Время выполнения ~30 с, память ~50 МБ, обязательный HTTPS |
| iOS |
UNNotificationContentExtension |
Кастомный UI, кнопки действий |
| Android |
NotificationChannel |
Уровень важности, звук, вибрация — настраиваются пользователем |
| Android |
BigPictureStyle / MessagingStyle |
Расширенный контент, группировка сообщений |
Как отследить доставку и конверсию push-уведомлений?
Отправить уведомление — полдела. Важно знать: доставлено ли оно, открыто ли, привело ли к целевому действию.
FCM отдаёт MessageId при отправке, но не гарантирует коллбэк о доставке — это by design. Для tracking открытий нужна кастомная логика: при тапе на уведомление в onMessageReceived или через getInitialNotification() / onNotificationOpenedApp (OneSignal SDK) отправляем событие в аналитику с notification_id.
OneSignal предоставляет встроенную аналитику доставки и CTR. Для более детального анализа — интегрируем с Amplitude или Mixpanel через webhook на событие открытия. Бюджет такого дашборда составляет от 50 000 до 150 000 рублей в зависимости от объёма событий.
Как мы внедряем push-уведомления: типовой процесс
-
Аудит текущей реализации — проверяем хранение токенов, обработку обновлений, типы уведомлений.
-
Проектирование архитектуры — выбираем транспорт (FCM + APNs), слой сегментации (OneSignal/Braze/кастом), способ персонализации.
-
Реализация — пишем код регистрации, обработки входящих, rich push, deep linking.
-
Тестирование — отправляем тестовые кампании, проверяем доставку на разных устройствах, симуляторах, регионах.
-
Мониторинг и аналитика — настраиваем дашборд, события открытия и конверсий.
-
Документация и обучение — передаём команде материалы по эксплуатации.
Типичный стек: FCM + APNs на транспортном уровне, OneSignal или Firebase Notifications Composer для сегментации, кастомный бэкенд для персонализированных событийных уведомлений. Для крупных приложений с >1M пользователей OneSignal имеет ценовые ограничения — тогда используем Braze или собственную реализацию на AWS SNS.
Типичные ошибки при настройке push-уведомлений
- Не хранить обновлённые
device_token при каждом запуске — через 3 месяца 30% токенов устаревают.
- Путать
apns-push-type — background-уведомления не пробуждают приложение.
- Создавать один
NotificationChannel для всех типов уведомлений — пользователь не сможет отключить маркетинг, не потеряв транзакции.
- Загружать медиа в rich push по HTTP — ATS блокирует запрос на iOS.
- Не проверять deep link в таргетинге — переходы идут на главный экран.
Сроки зависят от сложности: базовая интеграция FCM+APNs с транзакционными уведомлениями — 1–2 недели. Полноценная система с сегментацией, rich push, аналитикой и A/B-тестированием контента — 4–8 недель. Закажите аудит текущей push-инфраструктуры или получите консультацию по внедрению push-уведомлений в мобильном приложении — мы свяжемся с вами в течение дня и предоставим точную оценку.