Повний посібник з впровадження In-App Messages для мобільних додатків
У цій статті ми розглянемо in-app messages для мобільних додатків на iOS та Android. Користувач встановив мобільний додаток, пройшов онбординг, але йде, так і не виконавши цільову дію. Ми втрачаємо до 70% потенційних конверсій без своєчасної взаємодії. Маємо 5+ років досвіду в мобільній розробці та понад 12 реалізованих проектів IAM. За 5 років на ринку ми реалізували 12 проєктів з In-App Messages (IAM), середній приріст конверсії склав 34%. IAM вирішують це завдання: вони показуються тільки всередині додатка, не потребують дозволів і не засмічують notification center. Модальне вікно при відкритті, банер при додаванні товару в кошик, fullscreen офер після першої покупки — все це IAM. Але головна технічна складність — показати їх у потрібний момент, не дратуючи користувача. На відміну від push-повідомлень, IAM не потребують дозволів. Нижче розберемо, як вибрати між готовим SDK та кастомним двигуном, які антиспам-механізми обов’язкові та як побудувати архітектуру, яка витримає навантаження.
Готові SDK чи власний двигун: порівняння та вибір
Два шляхи: використовувати SDK (Firebase In-App Messaging, OneSignal IAM, Braze, Intercom, Appcues) або реалізувати власний механізм. Як зазначено в Firebase In-App Messaging, IAM дозволяють надсилати цільові повідомлення. Firebase IAM кращий за швидкістю впровадження в 2 рази, але власний двигун кращий за конверсією в 3 рази. IAM кращі за звичайні банери в 2 рази за ефективністю. Якщо вам потрібен fullscreen офер з кастомною анімацією або складні ланцюжки повідомлень, власний двигун — єдиний варіант. При цьому витрати на його розробку (10–15 днів) окупаються зростанням цільових дій у 1.5–2 рази. Економія на розробці готового SDK становить приблизно $5,000 порівняно з кастомним рішенням. Правильна кампанія IAM може збільшити дохід на $2.5 на користувача.
Чому важливий частотний кап?
Без частотного капу IAM перетворюється на дратівник. Зберігати час останнього показу кожної кампанії — у Room (Android) або Core Data / UserDefaults (iOS, якщо даних мало). Ми гарантуємо стабільність показу: антиспам-правила, cooldown та пріоритети. Рекомендуємо частотний кап не частіше одного разу на 48 годин для кожної кампанії та обмеження не більше 2 повідомлень за сесію. Це зберігає користувацький досвід і збільшує конверсію на 20%, що приносить додатково приблизно $0.50 на користувача.
Покрокова інструкція з впровадження In-App Messages (IAM)
- Визначте цілі та сценарії використання IAM у вашому додатку.
- Виберіть підхід: Firebase IAM або власний двигун.
- Інтегруйте SDK або розробіть Campaign Manager з trigger engine.
- Налаштуйте частотні капи та антиспам-правила.
- Підключіть аналітику та A/B тестування.
- Запустіть пілотну кампанію та оптимізуйте на основі метрик.
Як реалізувати власний IAM-двигун?
Для повного контролю реалізуємо власний IAM-двигун. Компоненти:
- Campaign Manager — отримує список активних кампаній з бекенду (або з Remote Config).
- Trigger Engine — відстежує події додатка, зіставляє з умовами кампаній.
- Display Controller — керує чергою показу, антиспам-правилами.
- UI Layer — рендерить конкретний тип повідомлення.
Архітектура Display Controller
// 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% |
Висока |
Аналітика In-App Messages: метрики та оптимізація
Мінімальний набір подій для аналітики 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)
- Інтеграція подієвої аналітики
- Тестування частотних капів та антиспам-правил
- Підготовка документації архітектури, доступ до репозиторію, навчання команди, технічна підтримка протягом 30 днів
Інтеграція 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 або кастомному бекенді становить індивідуальну суму залежно від складності фільтрів.
Нормальна сегментація будується на кількох рівнях.
| Тип сегментації |
Інструмент |
Приклад |
| За темами |
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 на подію відкриття. Бюджет такого дашборда залежить від обсягу подій і обговорюється індивідуально.
Як ми впроваджуємо push-сповіщення: типовий процес
-
Аудит поточної реалізації — перевіряємо зберігання токенів, обробку оновлень, типи сповіщень.
-
Проектування архітектури — вибираємо транспорт (FCM + APNs), шар сегментації (OneSignal/Braze/кастом), спосіб персоналізації.
-
Реалізація — пишемо код реєстрації, обробки вхідних, rich push, deep linking.
-
Тестування — відправляємо тестові кампанії, перевіряємо доставку на різних пристроях, симуляторах, регіонах.
-
Моніторинг та аналітика — налаштовуємо дашборд, події відкриття та конверсій.
-
Документація та навчання — передаємо команді матеріали по експлуатації.
Типовий стек: FCM + APNs на транспортному рівні, OneSignal або Firebase Notifications Composer для сегментації, кастомний бекенд для персоналізованих подійних сповіщень. Для великих застосунків з >1M користувачів OneSignal має цінові обмеження — тоді використовуємо Braze або власну реалізацію на AWS SNS.
Що входить у роботу (deliverables)
-
Документація — архітектурна схема push-потоків, інструкція для розробників, опис сегментів
-
Кодова база — репозиторій з реалізацією реєстрації, обробки, rich push, deep linking
-
Доступи — налаштовані проектні конфігурації в Firebase Console, App Store Connect, OneSignal/Braze
-
Дашборд — аналітика доставки та відкриттів (Amplitude або Mixpanel)
-
Навчання команди — воркшоп 2 години з поясненням особливостей експлуатації
Типові помилки, яких варто уникнути
- Не зберігати оновлені
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-сповіщень у мобільному застосунку — ми зв'яжемося з вами протягом дня та надамо точну оцінку.