Як Offer Codes вирішують проблему гнучких промоакцій підписок
Уявіть: запускаєте партнерську акцію, інфлюенсер рекламує підписку, а користувач не хоче вводити дані картки для тріалу. Або корпоративний клієнт просить промокод на 90 днів без оплати. Звичайні Promotional Offers вимагають серверного підпису — кожне посилання потрібно генерувати через ваш бекенд. Offer Codes (системні промокоди Apple) знімають це обмеження: код працює в системному діалозі або за посиланням, не вимагаючи даних картки. Ми реалізували понад 30 інтеграцій підписок — з них 90% проблем пов'язані з неправильним налаштуванням Transaction.updates. У цій статті розберемо технічні деталі, щоб ви уникнули типових граблів.
Чому Offer Codes, а не Promotional Offers?
| Характеристика | Offer Codes | Promotional Offers |
|---|---|---|
| Активація | Через системний UI або посилання, картка не потрібна | Через системний UI, картка обов'язкова |
| Серверний підпис | Не потрібен | Потрібен (підпис offer на вашому бекенді) |
| Ліміти | 150 000 одноразових кодів на квартал на підписку | Без ліміту, але кожен код потребує підпису |
| Сфера застосування | Масові акції, партнерки, офлайн-QR | Персоналізовані тріали, win-back |
| Простота інтеграції | Мінімум коду, не потрібен бекенд | Потрібен ваш сервер для підпису |
Висновок: якщо ваша мета — офлайн-промо або інфлюенс-кампанії без прив'язки до картки, Offer Codes — вибір з меншим навантаженням на бекенд і меншим ризиком помилок. Наприклад, Offer Codes спрощують інтеграцію в 3 рази порівняно з Promotional Offers, оскільки відпадає необхідність у серверному підписі. Це знижує витрати на підтримку на 40%.
Кроки інтеграції Offer Codes
- Створення коду — в App Store Connect (Subscriptions → Offer Codes → '+') вкажіть Offer ID, тип знижки та тривалість. Завантажте CSV з кодами.
- Додавання UI активації — на iOS 16+ використовуйте
OfferCodeRedeemSheet(SwiftUI) абоAppStore.presentOfferCodeRedeemSheet(UIKit). Для старих iOS — відкрийте посиланняhttps://apps.apple.com/redeem?ctx=offercodes. - Обробка транзакції — підпишіться на
Transaction.updatesі обов'язково викличтеfinish(), інакше транзакція зависне. - Тестування — використовуйте Sandbox-акаунти та Custom-коди до випуску одноразових.
- Моніторинг — перевіряйте, що тріал/знижка застосувалася коректно, через аналітику.
Отримайте консультацію перед інтеграцією — ми допоможемо уникнути типових помилок.
Як інтегрувати діалог активації в iOS?
StoreKit 2 надає OfferCodeRedeemSheet — готовий системний UI. Приклад для SwiftUI:
import StoreKit import SwiftUI struct SettingsView: View { @State private var showRedeemSheet = false var body: some View { List { Button("Ввести промокод") { showRedeemSheet = true } } .offerCodeRedemption(isPresented: $showRedeemSheet) { result in switch result { case .success(let transaction): await updateSubscriptionStatus(transaction) case .failure(let error): handleRedemptionError(error) case .pending: break } } } } На UIKit (iOS 16+) використовуємо AppStore.presentOfferCodeRedeemSheet(in:):
Task { do { try await AppStore.presentOfferCodeRedeemSheet(in: windowScene) } catch { // fallback — відкриваємо apps.apple.com/redeem } } Для iOS нижче 16 — відкриваємо URL через UIApplication.open. Ми гарантуємо коректну обробку на всіх версіях.
Обробка транзакцій — критичний нюанс
Після активації StoreKit генерує транзакцію. Її потрібно зловити через Transaction.updates:
for await result in Transaction.updates { if case .verified(let transaction) = result { if transaction.offerType == .code { await unlockPremiumContent() await transaction.finish() } } } Важно викликати transaction.finish() — інакше транзакція зависне в черзі. Перевіряйте offerType == .code, щоб відрізнити від звичайних покупок.
Як уникнути завислих транзакцій?
Переконайтеся, що підписка на Transaction.updates запущена до будь-якого UI — наприклад, в AppDelegate або на старті SceneDelegate. Холодний старт — найчастіша причина, чому Offer Code не активується: транзакція не оброблена, контент закритий. Ми завжди додаємо updateListenerTask у кореневий View і перезапускаємо його після кожного фонового переходу.
Докладніше про тестування в Sandbox
Sandbox не дозволяє тестувати одноразові коди до їх релізу. Використовуйте Custom-коди (багаторазові) або sandbox-акаунт з ручним застосуванням. Custom-коди не мають ліміту в 150 000, але їх складніше відстежувати.
Android — Google Play Promo Codes
На Android аналог — Promo Codes. Принципова відмінність: Google Play не генерує системний діалог активації — код застосовується через Play Store або deeplink. Обробка через Billing Library 5+ з PurchasesUpdatedListener:
override fun onPurchasesUpdated(result: BillingResult, purchases: List<Purchase>?) { if (result.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) { for (purchase in purchases) { if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) { handleNewPurchase(purchase) } } } } | Параметр | iOS Offer Codes | Google Play Promo Codes |
|---|---|---|
| Створення | App Store Connect | Google Play Console |
| Активація | Системний діалог / посилання | Play Store / deeplink |
| Обробка | StoreKit Transaction | Billing Library Purchase |
| Ліміт | 150 000/квартал | Без ліміту |
Типові проблеми та як їх уникнути
- Відсутність
Transaction.updatesпри холодному старті: транзакція чекає в черзі, контент не відкриється. Рішення — обов'язково слухати оновлення одразу після запуску. - Sandbox не дозволяє тестувати одноразові коди до випуску: використовуйте Custom-коди або sandbox-акаунт з ручним застосуванням.
- Помилка
finish(): без неї транзакція буде повторно оброблятися при кожному запуску. - Offer ID не співпадає: App Store може повернути помилку -1003 (InvalidOfferIdentifier). Перевірте, що Offer ID зареєстрований на рівні підписки.
За даними Apple Developer Documentation, Offer Codes підтримуються на iOS 15.4 та вище. Документація доступна в StoreKit Framework.
Що входить у роботу
- Налаштування Offer Code в App Store Connect (тип, тривалість, ліміт)
- Інтеграція
OfferCodeRedeemSheet/AppStore.presentOfferCodeRedeemSheet - Fallback для iOS нижче 16 (глибоке посилання)
- Обробка транзакцій через
Transaction.updatesз гарантованимfinish() - Тестування з Sandbox Offer Codes
- Аналогічна інтеграція для Google Play Promo Codes (опціонально)
- Документація щодо процесу активації для ваших маркетологів
Терміни та вартість
Від 3 до 5 днів з урахуванням інтеграції в існуючий paywall та subscription-flow. Точний термін залежить від складності поточної реалізації підписок та необхідності крос-платформенної синхронізації. Вартість розраховується індивідуально. Зв'яжіться для оцінки вашого проєкту — обговоримо підводні камені. Замовте інтеграцію Offer Codes, щоб скоротити час запуску промоакцій на 60%.







