Skip to main content

iOS Subscription Offers

πŸ“˜

This guide assumes you already have your iOS products set up in App Store Connect.

Subscription Offers allow developers to apply custom pricing and trials to new customers and to existing and lapsed subscriptions.

Subscription Offers are supported in the Purchases SDK, but require some additional setup first in App Store Connect and the RevenueCat dashboard.

Types of Subscription Offers​

Offer TypeApplies ToSubscription Key RequiredNotesAuto-Renewal
Introductory OffersNew UsersπŸ”‘ Required (in StoreKit2)Applied to eligible purchases automatically. How to check eligibility.βœ…
Promotional OffersExisting and Lapsed UsersπŸ”‘ RequiredNot applied automatically, see implementation guide belowβœ…
Offer CodesNew and Existing UsersπŸ”‘ RequiredRequires iOS SDK 3.8.0+, see implementation guide belowβœ…
Win-Back OffersLapsed UsersπŸ”‘ RequiredWin-Back Offers are only available to users on iOS18.0+.βœ…
⚠️ Not recommended
In-App Purchase Promo Codes
New and Existing UsersNot RequiredTreated as a regular purchase, revenue will not be accurate in Charts and Integrations due to Apple/StoreKit limitations. Codes don't auto-renew, aren't compatible with presentCodeRedemptionSheet, restricted to non-commercial use, and restricted to 1,000 codes every 6 months.❌

In-App Purchase Keys​

For RevenueCat to securely authenticate and validate a Subscription Offer request with Apple, you'll need to upload an In-App Purchase Key following our guide.

Promotional Offers​

In iOS 12.2, Apple announced a new feature for subscription developers called β€œPromotional Offers.”

1. Configure the Offer in App Store Connect​

Promotional Offers are created from within App Store Connect and are included as a pricing option to an existing subscription product. When you click the "+" option next to Subscription Prices, you'll see an option to Create Promotional Offer.

Subscription Offers are created as new pricing options in App Store Connect

To create the offer there are two fields that you need to specify: Reference Name, which is just used for your reference, and the Promotional Offer Product Code, which is what you will actually use to activate a specific offer in your app. On the next screen you'll select the type of offer you wish to provide. Just like introductory offers, there are three types of Promotional Offers:

  1. Pay-up-front β€” The customer pays once for a period of time, e.g. $0.99 for 3 months. Allowed durations are 1, 2, 3, 6 and 12 months.
  2. Pay-as-you-go β€” The customer pays a reduced rate, each period, for a number of periods, e.g. $0.99 per month for 3 months. Allowed durations are 1-12 months. Can only be specified in months.
  3. Free β€” This is analogous to a free trial, the user receives 1 of a specified period free. The allowed durations are 3 days, 1 week, 2 weeks, 1 month, 2 months, 3 months, 6 months, and 1 year.
πŸ“˜

Don't forget to click Save in the upper right after you configure the offer.

2. Show the Promotional Offer to Desired Users​

It's up to you to decide which users you want to present a Promotional Offer to. The only eligibility requirements are that the user had (or currently has) an active subscription. Apple automatically enforces this requirement for you - if it's not met users will be shown the regular product regardless of the offer you try to present.

Fetch the PromoOffer​

Before you can present a Promotional Offer to a user, you first need to fetch the PromoOffer. This is done by passing the StoreProduct and a StoreProductDiscount to the .getPromotionalOffer method, which uses the Subscription Key from above to validate the discount and to provide a valid PromoOffer:

if let discount = package.storeProduct.discounts.first {
Purchases.shared.getPromotionalOffer(forProductDiscount: discount,
product: package.storeProduct) { (promoOffer, error) in
if let promoOffer {
// Promotional Offer validated, show terms of your offer to your customers
} else {
// Promotional Offer was not validated, default to normal package terms
}
}
}

// OR: if using async/await
let promoOffers = await package.storeProduct.eligiblePromotionalOffers()

Purchase the Product with the Promotional Offer​

After successfully fetching the PromoOffer, you can now display the Promotional Offer to the user however you'd like. If the user chooses to purchase, pass a Package and PromoOffer to the .purchase(package:promotionalOffer:) method.

Purchases.shared.purchase(package: package,
promotionalOffer: promoOffer) { transaction, customerInfo, error, userCancelled in
if customerInfo?.entitlements.all[<your_entitlement_id>]?.isActive == true {
// Unlock that entitlements content
}
}

Offer Codes​

With iOS 14, Apple announced a new feature for subscription developers called β€œOffer Codes.” Offer Codes allow developers to offer custom pricing and trials, in the form of a redeemable code, to their customers.

1. Configuring an Offer Code​

Offer Codes are configured similarly to Subscription Offers in App Store Connect.

Screen Shot 2020-12-01 at 10.02.15 AM.png

2. Redeeming an Offer Code​

Option 1: In-app Redemption Sheet​

❗️

Since launch, Apple's in-app Offer Code redemption sheet has proven to be extremely unstable. For example, the sheet may not connect, may not dismiss after a successful redemption, and may not accept valid codes. Additionally, sandbox and TestFlight behavior has been seen to be inconsistent.

A workaround may be to instead redirect customers to the App Store app to redeem codes as described below.

To allow your users to redeem Offer Codes, you'll need to present the Offer Code redemption sheet. In Purchases SDK 3.8.0, you can call the presentCodeRedemptionSheet method.

Purchases.shared.presentCodeRedemptionSheet()

Apple does not provide a callback to determine if the code redemption was successful. Since the Purchases SDK will automatically pick up on new transactions that enter the underlying transaction queue, you should implement the receivedUpdated delegate or listener to respond to changes in CustomerInfo. Once we sync the Offer Code transaction, we'll automatically refresh CustomerInfo.

⚠️

The Offer Code redemption sheet may not display on a device if you haven't yet launched the App Store app and accepted the terms agreement.

Option 2: Redirect to App Store app​

You can link to the App Store with a prefilled code for redemption with the following URL format: https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}

You can find your Apple App ID in your app settings in App Store Connect (General -> App Information).

When users click your link within your app to redeem the offer code, it will take them outside of the app to complete the purchase. It is important to call syncPurchases when the user returns back to your app to retrieve their purchase. This may be done by recording when the user leaves the app due to the link, and calling syncPurchases when the user returns to the app. If not, the user may need to trigger a restore within your app when they come back.

Considerations​

  • In order for RevenueCat to accurately track revenue for offer codes, you will need to upload an in-app purchase key. See our guide on In-App Purchase Key Configuration for step-by-step instructions.

Win-Back Offers​

Apple introduced win-back offers with iOS 18, which allow developers to provide custom pricing and trials to subscribers who have canceled a subscription and meet specific eligibility criteria set by the developer.

1. Configuring a Win-Back Offer​

⚠️

Win-Back Offers can only be configured for subscription products that have been approved by App Review. Please ensure that your subscription product has been approved by App Review before proceeding.

Navigate to your subscription's page under Apps β†’ Your App β†’ Subscriptions (in the left sidebar) β†’ Your Subscription Group β†’ Your Subscription Product and click the "+" button by "Subscription Prices". If your subscription product has been approved by App Review, you'll see the option "Create Win-Back Offer". Select it.

configure_winback_offer_1.png

To create the win-back offer there are two fields that you need to specify: Reference Name, which is just used for your reference, and the Offer Identifier, which is a distinct ID for the win-back offer.

configure_winback_offer_2.png

Next, you’ll be asked to provide the specifics of your win-back offer, including:

  • Offer Publish Date: The date interval that the win-back offer will be available to churned subscribers. (More Info)
  • Offer Priority: Determines if this win-back offer takes precedence over other offers available for its product.
    • If a subscriber is eligible for multiple offers on the same subscription product, offers with a with a high priority will be displayed instead of offers with a normal priority in StoreKit views.
  • Customer Eligibility: Developer-provided eligibility criteria that determines whether a churned subscriber can purchase a win-back offer.
    • Minimum Paid Duration: The time that a subscriber must have been subscribed to that product to be eligible for the offer.
    • Time Since Last Subscribed: A time interval describing how long a subscriber must have been lapsed to be eligible for the offer.
    • Wait Between Offers: The required time a subscriber must wait after a win-back offer ends before redeeming the same offer again. Optional.

configure_winback_offer_3.png

2. Redeeming a Win-Back Offer​

Subscribers can redeem a win-back offer in several ways. We're currently developing support for redeeming win-back offers within our SDK, and we will update this documentation as more redemption options become available.

Win-Back Offer Purchasing MethodSupported By RevenueCat?Notes
Through the App Store with Streamlined Purchasing Enabledβœ… YesShould not be used if you require a subscriber to perform an action before purchasing (e.g. signing in)
Through Your App with Your Own IAP Codeβœ… YesMore info on using your own IAP code here
Through Your App From a StoreKit Messageβœ… YesDeferring when the message is displayed requires SDK version 5.6.0+
Through the App Store with Streamlined Purchasing Disabled❌ No, Coming Soon
Through Your Paywall❌ No, Coming Soon
Through a RevenueCat Paywall❌ No, Coming Soon
Through a StoreKit StoreView❌ No, Coming Soon
Through a StoreKit SubscriptionStoreView❌ No, Coming Soon

Redeeming a Win-Back Offer Through the App Store with Streamlined Purchasing Enabled​

⚠️

Use this method only if you do not require subscribers to perform an action, like signing in before purchasing. If you do require such actions, disable Streamlined Purchasing (instructions here). By default, Streamlined Purchasing is enabled for all apps.

Purchasing win-back offers through the App Store uses Streamlined Purchasing by default, meaning that subscribers can complete the entire win-back offer redemption flow in the App Store. In addition to the steps mentioned above to configure your win-back offer, we recommend doing the following:

  1. Mandatory: Upload an image for your win-back offer in App Store Connect (instructions).
  2. Enable Apple App Store Notifications so that RevenueCat can be notified of win-back offers redeemed through the App Store, even if the user does not open your app.
Testing Win-Back Offers Redeemed Through the App Store with Streamlined Purchasing Enabled​

Testing win-back offers redeemed through the App Store with Streamlined Purchasing enabled can only be performed in the sandbox environment on a physical device. To test win-back offers redeemed this way:

  1. Create a sandbox test account
  2. Add the sandbox test account to your device
  3. Configure a win-back offer on a subscription product in App Store Connect as described above.
  4. Make note of the product ID and the win-back offer ID. You'll need it later!
  5. Cancel any subscriptions that are from the same subscription group as the win-back offer’s subscription.
  6. Open your app and purchase the subscription product that contains the win-back offer.
  7. Cancel the subscription. This can be done easily in the Settings app by navigating to your sandbox test account's page (Settings β†’ App Store β†’ Sandbox Account β†’ Manage β†’ Subscriptions β†’ Cancel Subscription)
  8. Close your app.
  9. Wait for your subscription to expire.
  10. In your sandbox test account's Account Settings page, turn off the "Display Win-back Offer Sheet" toggle

disable_winback_offer_sheet.jpg

  1. Select "Test Transactions"

select_test_transactions.jpg

  1. Enter the product ID of the product you're testing, your app's bundle ID, and the win-back offer's identifier. These values must be valid IDs entered into App Store Connect.

test_transactions.jpg

  1. Tap the "Test Transactions" button at the bottom of the page.
  2. The system presents the App Store [Sandbox] payment sheet for the sandbox environment. Confirm the purchase.
  3. Open your app.
  4. Check that your subscriber receives the proper entitlements from RevenueCat, and that the purchase appears in your RevenueCat dashboard with "Sandbox data" enabled.

Repeat steps 5-16 to test redeeming win-back offers multiple times.

Redeeming a Win-Back Offer In Your App from a StoreKit Message​

In iOS 18+, StoreKit will send your app a message when a subscriber is eligible to redeem a win-back offer. When this message is received, our SDK will automatically present the associated StoreKit win-back offer sheet to the subscriber, which allows them to redeem the win-back offer:

win_back_offer_sk_message.png

If you'd like to defer displaying the win-back offer sheet until a later time, you can do so in iOS SDK versions 5.6.0 and above by setting the showStoreMessagesAutomatically flag to false in the Purchases.configure function. When this flag is set to false, the win-back offer sheet will not be displayed automatically, and you will need to manually display the offer sheet by calling the showStoreMessages function when you'd like it to be displayed:

// Configure Purchases with showStoreMessagesAutomatically set to false
Purchases.configure(
with: .init(withAPIKey: "${YOUR_API_KEY}")
.with(showStoreMessagesAutomatically: false)
)

// Later, when you're ready to display the win-back offer sheet:
await Purchases.shared.showStoreMessages()

If you're running other win-back campaigns on non-iOS stores, we recommend deferring displaying the win-back offer message until after you've checked the subscriber's entitlements. If the subscriber has entitlements, then we'd recommend not displaying the message to avoid the subscriber signing up for multiple win-back offers at the same time.

Testing Win-Back Offers Redeemed In Your App from a StoreKit Message​
  1. Create a sandbox test account
  2. Add the sandbox test account to your device
  3. Configure a win-back offer on a subscription product in App Store Connect as described above.
  4. Make note of the product ID and the win-back offer ID. You'll need it later!
  5. Cancel any subscriptions that are from the same subscription group as the win-back offer’s subscription.
  6. Open your app and purchase the subscription product that contains the win-back offer.
  7. Cancel the subscription. This can be done easily in the Settings app by navigating to your sandbox test account's page (Settings β†’ App Store β†’ Sandbox Account β†’ Manage β†’ Subscriptions β†’ Cancel Subscription)
  8. Close your app.
  9. Wait for your subscription to expire.
  10. In your sandbox test account's Account Settings page, turn on the "Display Win-back Offer Sheet" toggle:

enable_winback_offer_sheet.jpg

  1. Select "Test Transactions":

select_test_transactions.jpg

  1. Enter the product ID of the product you're testing, your app's bundle ID, and the win-back offer's identifier. These values must be valid IDs entered into App Store Connect.

test_transactions.jpg

  1. DO NOT tap the "Test Transactions" button at the bottom of the page. Instead, background the Settings app (do not force close it).
  2. Open your app.
  3. If the Purchases SDK is configured to show StoreKit messages automatically, the win-back offer redemption sheet will be displayed. If not, you can call showStoreMessages() to display the offer sheet.

enable_winback_offer_sheet.jpg

  1. Redeem the win-back offer.
  2. Check that your subscriber receives the proper entitlements from RevenueCat, and that the purchase appears in your RevenueCat dashboard with "Sandbox data" enabled.

Repeat steps 5-17 to test redeeming win-back offers multiple times.

⚠️

In our testing, we've found that this method of testing does not work 100% of the time, and that sometimes there can be a noticeable delay between when you leave the Settings app and when the win-back offer redemption sheet is displayed.

Considerations​

  • Since win-back offers use StoreKit 2 under the hood, you must upload an in-app purchase key to RevenueCat to use win-back offers. See our guide on In-App Purchase Key Configuration for step-by-step instructions.

Next Steps​