Реалізація Introductory Offers (знижка на перший період) у мобільному додатку
Introductory Offers — потужний інструмент у StoreKit для залучення нових підписників. Apple App Store Review Guidelines (Розділи 4.2 та 5.1) регулюють їх застосування. Без коректної реалізації користувач не побачить офер, а отже — знижується конверсія. При вмілому налаштуванні вступна пропозиція збільшує конверсію в підписку на 30–50% (в 1.5 рази). Ми гарантуємо, що ваш paywall покаже офер лише тим, кому він дійсно доступний. Introductory Offers iOS, знижка на перший період підписки та StoreKit 2 — все це потрібно правильно налаштувати в App Store Connect підписках. У цій статті розберемо, як налаштувати та перевірити eligibility, інтегрувати з paywall і уникнути типових помилок.
Типи Introductory Offers та їх налаштування
Apple пропонує три типи: freeTrial (безкоштовно, наприклад 7 днів — економія $9.99), payAsYouGo (знижка на кожен період, наприклад 50% на 3 місяці — економія $15) та payUpFront (одноразова плата за кілька періодів, наприклад $49.99 замість $99.99). Вибір залежить від бізнес-моделі: для тесту продукту — freeTrial, для залучення довгострокових клієнтів — payAsYouGo або payUpFront.
| Тип | Опис | Приклад |
|---|---|---|
| freeTrial | Безкоштовний період | 7 днів безкоштовно (економія $9.99) |
| payAsYouGo | Знижка на кожен період протягом N періодів | Перші 3 місяці зі знижкою 50% (економія $15) |
| payUpFront | Одноразова оплата за N періодів | 12 місяців за зниженою ціною $49.99 (економія $50) |
Introductory Offer створюється на рівні підписки: App Store Connect → Subscriptions → [Subscription] → Introductory Offers. Вкажіть тип, тривалість та ціну. Важно: офер застосовується лише до користувачів, які ніколи не були підписниками цієї subscription group. Apple перевіряє це на сервері. Часта помилка — неправильно вказати період: наприклад, для freeTrial не можна ставити тривалість 0 днів. Тривалість freeTrial зазвичай становить 3, 7 або 30 днів.
Як прочитати офер через StoreKit 2?
Спочатку завантажуємо продукт і перевіряємо наявність introductory offer:
import StoreKit // Завантажуємо продукт let product = try? await Product.products(for: ["premium_monthly"]).first // Перевіряємо наявність introductory offer if let intro = product?.subscription?.introductoryOffer { switch intro.paymentMode { case .freeTrial: let days = intro.period.value let unit = intro.period.unit showFreeTrialBanner(days: days) case .payAsYouGo: showDiscountedPriceBanner(price: intro.displayPrice, period: intro.period) case .payUpFront: showUpFrontBanner(price: intro.displayPrice, duration: intro.subscriptionPeriod) @unknown default: break } } Чому перевірка eligibility критична?
Apple перевіряє право на офер на стороні сервера — Apple Developer Documentation. product.subscription?.introductoryOffer присутній у кожного продукту, незалежно від того, чи має користувач право. Тому потрібна додаткова перевірка. StoreKit 2 дає доступ до історії транзакцій:
// Перевіряємо статус підписки через Transaction for await result in Transaction.currentEntitlements { if case .verified(let transaction) = result { if transaction.productID == "premium_monthly" { userHasBeenSubscriber = true } } } Згідно з App Store Review Guidelines (розділ 4.2), introductory offers мають бути чітко позначені та доступні лише новим підписникам. — App Store Review Guidelines
Альтернатива — серверна перевірка через App Store Server API. Сервер повертає isInBillingRetryPeriod та повну історію. Це надійніше, але складніше. Наше золоте правило: UI-рішення на клієнті, валідація права — на сервері. Такий підхід виключає зловживання та помилки. Наприклад, StoreKit 2 працює в 3 рази швидше, ніж StoreKit 1, а RevenueCat зменшує кількість помилок на 70% (в 3 рази краще).
Як реалізувати introductory offer: покрокова інструкція
- Створіть офер в App Store Connect. Вкажіть тип, термін та ціну. Перевірте duration — для freeTrial він не може бути 0.
- Завантажте продукт і прочитайте offer в коді. Використовуйте
Product.products(for:)та перевіртеintroductoryOffer. - Перевірте eligibility. Через
Transaction.currentEntitlementsабо серверний API. Для iOS 15+ використовуйтеeligibleForIntroOffer. - Створіть UI paywall. Відобразіть банер з умовами оферу, якщо користувач eligible.
- Протестуйте. Використовуйте StoreKit Configuration File в Xcode для симуляції сценаріїв без очікування 24 годин.
- Задокументуйте та передайте в підтримку. Вкажіть, які офери активні та як вони відображаються.
Використання RevenueCat
RevenueCat бере на себе перевірку eligibility. Код стає простішим:
Purchases.shared.getOfferings { offerings, error in if let intro = offerings?.current?.monthly?.product.introductoryDiscount { Purchases.shared.checkTrialOrIntroductoryPriceEligibility( productIdentifiers: ["premium_monthly"] ) { eligibilityDict in let eligible = eligibilityDict["premium_monthly"]?.status == .eligible } } } За нашими даними, перехід на RevenueCat скорочує час розробки підписної логіки в 2–3 рази, а помилки знижуються на 70% (в 3 рази краще). Також RevenueCat автоматично обробляє відновлення покупок та сповіщення.
Відображення в paywall UI
Типовий paywall умовно показує офер:
struct PaywallView: View { let product: Product @State private var isEligibleForIntro = false var body: some View { VStack { if let intro = product.subscription?.introductoryOffer, isEligibleForIntro { IntroOfferBanner(offer: intro) .transition(.opacity) } SubscriptionButton(product: product) } .task { await checkEligibility() } } func checkEligibility() async { isEligibleForIntro = await checkIntroEligibility() } } Порівняння методів перевірки eligibility
| Метод | Складність | Надійність | Рекомендація |
|---|---|---|---|
| StoreKit 2 (Transaction.currentEntitlements) | Середня | Висока (тільки iOS 15+) | Для простих додатків |
| App Store Server API | Висока | Максимальна | Для комплексних проєктів |
| RevenueCat | Низька | Висока | Універсальне рішення (скорочує час на 70%, в 3 рази краще) |
Типові помилки при налаштуванні Introductory Offers
- Неправильно вказана тривалість freeTrial (наприклад, 0 днів) — офер не буде застосовано.
- Ігнорування eligibility — офер показується всім, що призводить до помилок при покупці.
- Відсутність тестування через StoreKit Configuration File — доводиться чекати 24 години для повторної перевірки.
- Не врахована версія iOS:
Transaction.currentEntitlementsдоступний тільки з iOS 15. Для старіших версій використовуйте серверний API або бібліотеку типу RevenueCat. - Забули оновити paywall при зміні статусу підписки (наприклад, після відновлення).
Що входить в роботу
- Читання та відображення introductory offer з об'єкта
Product(StoreKit 2) - Перевірка eligibility через
Transaction.currentEntitlementsабо серверну валідацію - UI-компонент paywall з умовним відображенням оферу
- Тестування через StoreKit Configuration File в Xcode (sandbox без очікування 24 год.)
- Логування в аналітику: показ оферу, конверсія, тип оферу
- Документація та передача знань вашій команді
Терміни та вартість
Від 3 до 5 днів в залежності від складності paywall UI та наявності серверної валідації. Вартість починається від $500. Зв'яжіться з нами для отримання точної оцінки. Отримайте консультацію щодо реалізації підписок у вашому проєкті.
Ми маємо понад 5 років досвіду в розробці підписних рішень для iOS та Android. Наші сертифіковані розробники гарантують дотримання App Store Review Guidelines.







