Як 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%.







