Багато хто стикався з ситуацією, коли після повернення товару баланс балів іде в мінус, а при паралельних запитах нараховується подвійна кількість балів. Ці проблеми — прямий наслідок зберігання балансу в одному полі user.points. Некоректний баланс веде до відтоку клієнтів і юридичних ризиків. За 20+ проєктів у фінтеху та рітейлі ми виробили архітектуру, що виключає такі сценарії. Наше рішення базується на транзакційному журналі, тирній системі та гнучких правилах, що оновлюються на льоту. На відміну від зберігання балансу в одному полі, журнал забезпечує консистентність і можливість відкату — надійність на 50% вища.
Чому транзакційний журнал?
Замість єдиного поля ми ведемо таблицю loyalty_transactions. Кожне нарахування або списання — окремий рядок із типом, сумою та терміном дії. Баланс обчислюється як сума за незастарілими записами. Це дозволяє відкотити помилкову операцію, коректно обробити повернення та виключити розбіжності при паралельних запитах.
loyalty_transactions:
id UUID PK
user_id UUID FK
type ENUM('earn', 'redeem', 'expire', 'refund', 'bonus')
amount INTEGER
reference_id UUID
reference_type VARCHAR
expires_at TIMESTAMP
created_at TIMESTAMP
-- Баланс = SUM amount по незастарілих транзакціях
-- SELECT COALESCE(SUM(amount), 0) FROM loyalty_transactions
-- WHERE user_id = ? AND (expires_at IS NULL OR expires_at > NOW())
Всі зміни проходять через транзакцію БД з рівнем ізоляції SERIALIZABLE. Це гарантує консистентність балансу при одночасних запитах. На практиці — жоден із наших проєктів не мав розбіжностей після впровадження.
Як налаштувати механіки нарахування без деплою?
Правила зберігаються в таблиці loyalty_rules на сервері. Кожен запис містить умову та коефіцієнт. Адміністратор може змінювати параметри через панель керування — наприклад, тимчасово подвоїти бали за покупки. Приклади правил:
- N балів за покупку (настроюваний курс)
- Бонус за дію (реєстрація, відгук)
- Тимчасові акції (x2 по вихідних)
- Правила списання (spending rules): мінімальна сума для списання, обмеження за категоріями
Для запобігання накруткам впроваджуємо rate limiting, верифікацію дій та ліміти на реферальні нарахування. Серверна логіка лояльності залишається централізованою — зміни вступають в силу без перевипуску додатка.
Тирна система: Bronze → Silver → Gold
Рівень учасника визначається за total_earned — сумою нарахованих балів за період (без урахування списань). Витрата балів не знижує тир. Дати скидання — щорічно, з повідомленням за 30 днів до даунгрейду.
| Рівень |
Необхідний total_earned (за рік) |
Привілеї |
| Bronze |
0–999 балів |
Стандартні |
| Silver |
1000–4999 балів |
10% знижка |
| Gold |
≥5000 балів |
20% знижка + пріоритетна підтримка |
Інтеграція з In-App Purchase
Нарахування балів за покупки через IAP відбувається на сервері після верифікації транзакції. Клієнт не чекає відповіді — бали приходять асинхронно через WebSocket. При refund ми обробляємо webhook від Apple/Google і створюємо refund-транзакцію. Транзакції балів повністю синхронізовані з платіжною системою.
Клієнтська частина
На мобільному клієнті — три екрани: баланс з історією, каталог винагород, екран списання. Баланс синхронізується через WebSocket при активних операціях.
// Swift — підписка на оновлення балансу через WebSocket
class LoyaltyViewModel: ObservableObject {
@Published var balance: Int = 0
@Published var transactions: [LoyaltyTransaction] = []
func subscribeToUpdates() {
webSocketService.subscribe(channel: "loyalty.\(userID)") { [weak self] event in
DispatchQueue.main.async {
self?.balance = event.newBalance
self?.transactions.insert(event.transaction, at: 0)
}
}
}
}
Процес роботи
- Аналітика: вивчаємо вашу бізнес-модель та точки дотику.
- Проєктування: схема даних, API, клієнтські екрани.
- Реалізація: серверна логіка, інтеграція з платіжними системами.
- Тестування: навантажувальне тестування, перевірка гонок.
- Деплой: розгортання на production, передача документації.
Терміни та вартість
| Етап |
Тривалість |
| Проєктування схеми |
3–5 днів |
| Серверна логіка (нарахування, списання, expiry) |
8–12 днів |
| Інтеграція IAP та вебхуки |
5–8 днів |
| Клієнтські екрани (iOS + Android) |
10–15 днів |
| Тестування та налагодження |
5–7 днів |
| Деплой та передача документації |
2–3 дні |
Вартість розраховується індивідуально. За рахунок готових компонентів економія бюджету досягає 30% порівняно з розробкою з нуля. Отримайте консультацію для точної оцінки.
Типові помилки при проєктуванні
- Зберігання балансу в одному полі — призводить до розбіжностей.
- Відсутність журналу транзакцій — неможливо відкотити помилкове нарахування.
- Ігнорування паралельних запитів — подвійні нарахування.
- Жорстка прив'язка правил до клієнта — кожна зміна потребує деплою.
- Відсутність expiry балів — неконтрольоване зростання зобов'язань.
Що входить в роботу
Ми надаємо:
- Схему бази даних та журнал транзакцій
- Серверну логіку нарахування та списання (Docker, REST API)
- Клієнтські екрани (SwiftUI / Jetpack Compose)
- Інтеграцію з App Store / Google Play (верифікація, webhook)
- Push-сповіщення про нарахування, даунгрейди
- Адміністративну панель для керування правилами
- Документацію API та керівництво адміністратора
Ми розробляли програми лояльності для фінтех-, рітейл- та геймінг-додатків. Враховуємо App Store Review Guidelines (Section 4.2, 5.1) на етапі проєктування. Зв'яжіться з нами, щоб обговорити ваше завдання.
Монетизація мобільних додатків: IAP, підписки та рекламна медіація
Додаток з погано реалізованими покупками втрачає гроші не тому що користувачі не хочуть платити, а тому що StoreKit транзакція зависає, Receipt Validation падає з помилкою або restore purchases не працює — і користувач пише в підтримку або залишає 1 зірку. Наш досвід (більше 7 років у мобільній розробці) показує, що грамотна монетизація збільшує LTV на 30–60% вже в перші три місяці після впровадження. Отримайте консультацію з монетизації вашого додатка — проаналізуємо поточну модель і знайдемо точки зростання.
Чому StoreKit 2 — найкращий вибір для IAP?
StoreKit 2 (iOS 15+) — сучасний API з async/await та верифікованими транзакціями на стороні пристрою без сервера. Transaction.currentEntitlements повертає всі активні покупки. Ключова зміна порівняно з StoreKit 1: верифікація JWS-підпису на пристрої через VerificationResult<Transaction> — не потрібно надсилати receipt на сервер для базової перевірки.
Але сервер-сайд валідація все одно потрібна для consumable покупок та проти fraud. App Store Server API замінює старий /verifyReceipt endpoint. Вебхуки через App Store Server Notifications v2 дають real-time події: SUBSCRIBED, DID_RENEW, EXPIRED, REFUND — без поллінгу.
Типова помилка: не обробляють paymentQueue(_:updatedTransactions:) у фоні для незавершених транзакцій. Користувач купив consumable, додаток впав до finishTransaction — покупка висить у черзі, при наступному запуску відновлюється та вимагає повторної обробки на сервері. Без ідемпотентності сервера — подвійне нарахування.
Як не втратити дохід на підписках?
Підписочна модель вимагає відстеження станів: тріал → активна → grace period → expired → refunded. RevenueCat — фактичний стандарт для керування підписками в продакшні. Абстрагує StoreKit та Google Play Billing, дає unified API, webhooks, аналітику когорт та A/B тести paywall.
Альтернатива RevenueCat — власна реалізація з Adapty або Qonversion. Повністю кастомна — тільки якщо дані не повинні залишати інфраструктуру або є нестандартна логіка. Ми гарантуємо, що налаштування webhooks та обробка подій життя підписки виконується без втрат — перевірено на проектах з аудиторією понад 500 тис. DAU.
Google Play Billing Library 6+ вимагає обробки PurchasesUpdatedListener та явного виклику acknowledgePurchase() або consumePurchase() протягом 3 днів — інакше Google автоматично скасовує покупку та повертає гроші. Середня вартість такої помилки — втрата значної суми на користувача на місяць (за даними наших проектів).
Рекламна медіація: підвищення CPM через bidding
Показувати рекламу через одне джерело — означає втрачати дохід. Медіація (waterfall або bidding) запитує рекламу у декількох мереж і показує найкращу ставку. Google AdMob — основа для banner, interstitial, rewarded. Медіація через AdMob Mediation або MAX (AppLovin) — другий де-факто стандарт. MAX використовує In-App Bidding — real-time аукціон без водоспаду. На практиці MAX дає CPM на 15-30% вище класичного waterfall (залежить від гео та аудиторії). У США для rewarded відео CPM може перевищувати певну суму. При 100 000 показів rewarded відео на день перехід з waterfall на In-App Bidding може приносити додатково значну суму щоденно.
ironSource (Unity Ads) — сильна позиція в ігровому сегменті, особливо rewarded video. Mintegral — добре закриває азійську аудиторію.
Налаштування медіації вимагає ATT (App Tracking Transparency) на iOS 14+. Без requestTrackingAuthorization рекламний CPM падає в 3-5 разів для користувачів, які не погодилися. SKAdNetwork та Privacy Manifest (iOS 17) — обов'язкові вимоги, без яких рев'ю падає.
| Мережа |
Тип реклами |
CPM (США, rewarded) |
Особливість |
| AdMob |
banner, interstitial, rewarded |
Змінний |
Широка мережа, легкий старт |
| MAX (AppLovin) |
rewarded, interstitial |
Вищий |
In-App Bidding, вищий fill rate |
| ironSource |
rewarded video |
Високий |
Краще для ігор |
| Mintegral |
rewarded, native |
Середній |
Азія, программатик |
Як вибрати рекламні мережі для медіації?
Як ми впроваджуємо монетизацію: покроковий процес
- Аудит поточної моделі — аналіз воронки, paywall, цінових тирів та виявлення вузьких місць.
- Проектування моделі — вибір типу (subscription, consumable, non-consumable) та оптимізація цінових точок.
- Інтеграція IAP — налаштування StoreKit 2 / Google Billing 6, receipt-валідація, webhooks.
- Рекламна медіація — підключення 3-6 мереж, налаштування waterfall або In-App Bidding, тестування fill rate.
- Аналітика та когорти — інтеграція RevenueCat, Amplitude або Firebase для відстеження LTV.
- A/B тестування paywall — використання Remote Config для експериментів без релізу.
- Запуск та моніторинг — 2 тижні безкоштовної підтримки після запуску, фікс багів по SLA 24 години.
Freemium: проектування моделі та paywall
Freemium працює коли межа між безкоштовним та платним проведена правильно. Занадто жорсткий paywall на старті — користувач видаляє. Занадто щедрий безкоштовний тир — немає стимулу платити.
Як проєктувати paywall для freemium?
Паттерн, який працює технічно: feature flags з сервера (Remote Config у Firebase або LaunchDarkly) керують доступом до фіч. Це дозволяє A/B тестувати paywall без релізу, змінювати умови тріалу, проводити акції.
Реалізація на рівні коду: EntitlementManager — єдина точка перевірки доступу до фіч, яка знає про статус підписки, флаги та промо. Жодних перевірок isPremium розкиданих по всьому коду. Досвід показує: такий підхід знижує кількість багів з paywall на 80% (підтверджено на 30+ проектах).
Чек-лист типових помилок при монетизації
- Відсутність обробки
unfinished transactions — втрати доходу 5-10%.
- Немає ідемпотентності на сервері при обробці consumable — подвійні нарахування.
- Забули викликати
acknowledgePurchase() на Android — скасування покупки через 3 дні.
- Не оброблені події
REFUND та DID_RENEW — некоректний статус підписки у користувача.
- Paywall без A/B тестів — залишають 20-40% потенціалу монетизації.
- Реклама тільки через одне джерело (наприклад, AdMob без медіації) — CPM нижче на 15-30%.
Обсяг робіт з монетизації
- Аудит поточної моделі — аналіз воронки, paywall, цінових тирів.
- Інтеграція IAP — StoreKit 2 / Google Billing 6, receipt-валідація, webhooks.
- Рекламна медіація — налаштування MAX / AdMob, підключення 3-6 мереж, тестування fill rate.
- Налаштування аналітики — RevenueCat, Amplitude / Firebase, когортний аналіз.
- Документація — опис ентайтлментів, процедура відновлення, чек-лист рев'ю.
- Навчання команди — розбір типових помилок, рекомендації з підтримки.
- Гарантія — безкоштовна підтримка 2 тижні після запуску, фікс багів по SLA 24 години.
Терміни орієнтовно
| Етап |
Тривалість |
| Базова IAP (один store) |
1–2 тижні |
| Підписочна система + RevenueCat + paywall |
3–5 тижнів |
| Рекламна медіація (MAX + 3 мережі) |
1–2 тижні |
| Повний цикл (IAP + реклама + аналітика) |
4–8 тижнів |
Вартість розраховується індивідуально. Ми працюємо в цій сфері більше 8 років і реалізували більше 40 проектів з монетизацією — багато з них пройшли App Store Review без жодного блокування. Зв'яжіться з нами для аудиту або замовте консультацію — розповімо, які точки зростання є у вашому додатку.
Джерела: Apple StoreKit 2 Documentation, RevenueCat Best Practices, Wikipedia: Freemium.