โ† All articles

How iOS Promotional Offers Work for Subscriber Win-Back

Promotional offers are discounts you show existing or lapsed subscribers to win them back. How iOS promotional offers work, and how to present one.

How iOS Promotional Offers Work for Subscriber Win-Back

A promotional offer is a discounted or free subscription price you show to an existing or lapsed subscriber, right inside your app, to keep them from churning or win them back after they left. It is the third kind of App Store subscription offer, and the only one aimed at customers who have already subscribed at least once. Unlike a free trial, which appears automatically to new subscribers, a promotional offer is one you choose to present, and redeeming it requires a cryptographically signed payload so the discount cannot be forged.

This post explains how iOS promotional offers differ from the other offer types, who they target, why the signature exists, and how to present one in your paywall (the easy way, with RevenueCat handling the signing).

On this page

The three offer types compared

App Store subscriptions support three kinds of offer, and mixing them up leads to building the wrong thing:

Offer typeWho is eligibleHow it reaches the customerSignature required
Introductory offer (free trial)New subscribers onlyAutomatically on your paywallNo
Promotional offerExisting or lapsed subscribersYou present it in-app, to customers you chooseYes
Offer codeAnyone you give a code toRedeemed via a code, URL, or sheetNo

Promotional offers are the retention and win-back tool. If you want the new-subscriber mechanics, see how to add a free trial; if you want codes to hand out to press or testers, see how App Store offer codes work.

Who promotional offers target

This is the whole point of the feature: promotional offers reach people an introductory offer cannot. You configure the offer on a subscription in App Store Connect and choose eligibility for current subscribers, previously subscribed (lapsed) customers, or both. That makes two campaigns possible that are otherwise impossible:

  • Win-back. Someone cancelled two months ago. You show them "3 months at 50% off to come back." An introductory offer cannot do this, because they are no longer a new customer.
  • Retention. Someone is about to let their subscription lapse. You present a discounted renewal before they go.

Because you decide who sees the offer, your app needs to know the customer's subscription history to target it, which both StoreKit and RevenueCat expose. The offer itself is defined once in App Store Connect and then presented to the customers you select.

Why a promotional offer must be signed

Unlike an introductory offer, a promotional offer only applies when the purchase includes a signature generated with your private subscription key. The signature proves the offer is legitimately yours and has not been tampered with, which is what stops anyone from granting themselves a discount.

The catch is that signing requires a private key (an In-App Purchase key from App Store Connect) that must never ship inside your app, so the signature is generated in a trusted environment, not on-device. This is the part that makes promotional offers more work than the other offer types, and it is the main reason to let a subscription service handle it rather than standing up your own signing server.

Presenting an offer with RevenueCat

RevenueCat removes the signing problem: you upload your In-App Purchase key to RevenueCat once, and it signs offers for you, so no signing server of your own is needed. From the app side it is a two-step flow, fetch the signed offer, then purchase with it:

import RevenueCat
 
func applyWinBackOffer() async {
    do {
        let offerings = try await Purchases.shared.offerings()
        guard let package = offerings.current?.annual else { return }
        let product = package.storeProduct
 
        // Promotional offers configured on this product in App Store Connect.
        guard let discount = product.discounts.first else { return }
 
        // RevenueCat signs the offer using the key you uploaded to it.
        let promoOffer = try await Purchases.shared.promotionalOffer(
            forProductDiscount: discount,
            product: product
        )
 
        // Purchase at the promotional price.
        _ = try await Purchases.shared.purchase(
            package: package,
            promotionalOffer: promoOffer
        )
    } catch {
        // The customer was ineligible, or the purchase failed.
    }
}

If you use StoreKit 2 directly instead, the shape is the same but you own the signing: you generate the signature for the offer with your subscription key server-side, hand it back to the app, and pass it as a purchase option. The RevenueCat subscriptions setup covers uploading the key and wiring the paywall.

When to use them

Promotional offers earn their extra complexity in a few specific moments:

  • Win back churned subscribers. A discounted comeback offer to people who cancelled, timed a few weeks or months after they left.
  • Save an at-risk subscriber. Present a discount to someone who turned off auto-renew but has not fully lapsed yet, pairing well with the billing grace period for customers whose renewal is failing.
  • Reward loyalty. A better rate for long-time subscribers to reduce churn.

They are not for acquiring new customers. That is what introductory offers and offer codes are for. Reaching for a promotional offer to give new users a trial is the most common conceptual mistake.

Common gotchas

  • Do not ship the signing key in the app. The subscription key must stay server-side (or with RevenueCat). Embedding it is a serious security mistake.
  • Promotional offers are not for new users. They require a prior subscription. If you want a new-user trial, that is an introductory offer.
  • Configure the offer in App Store Connect first. The app can only present promotional offers that already exist on the subscription, with eligibility set.
  • Check eligibility before showing it. Presenting a win-back price to an active, ineligible customer at best does nothing and at worst confuses them. Target based on subscription status.
  • Signing failures fail silently if unhandled. If the offer is misconfigured or the key is wrong, signing fails. Handle that path so the paywall degrades to the normal price instead of a dead button.

FAQ

What is an iOS promotional offer?

It is a discounted or free subscription price you present to existing or lapsed subscribers inside your app, used for retention and win-back. It is distinct from an introductory offer (new subscribers) and an offer code (a redeemable code you distribute).

How is a promotional offer different from a free trial?

A free trial is an introductory offer available only to new subscribers and shown automatically. A promotional offer targets customers who have already subscribed at least once, is presented at your discretion, and requires a cryptographic signature to redeem.

Can I use a promotional offer to win back a cancelled subscriber?

Yes, that is its main purpose. You can configure eligibility for previously subscribed customers and present a discounted comeback price. An introductory offer cannot reach a lapsed subscriber, because they are no longer new.

Why do promotional offers need a signature?

The signature, generated with your private subscription key, proves the offer is genuinely yours and untampered, which prevents anyone from granting themselves a discount. Because the key must stay off-device, the signing happens server-side or through a service like RevenueCat.

Do I need my own server to use promotional offers?

Not if you use RevenueCat. You upload your In-App Purchase key to it once and it signs offers for you. With plain StoreKit you generate the signature yourself in a trusted environment, which usually means a small server component.

Can existing active subscribers get a promotional offer?

Yes. You can set eligibility for current subscribers as well as lapsed ones, which is how loyalty and retention discounts work. You choose which segment sees the offer.


Promotional offers only pay off once the subscription, the paywall, and the offer signing are all in place, and the signing is the part that stops most indie apps from ever using them. Spaceport removes that friction. It generates a SwiftUI project with the RevenueCat paywall, purchase, and restore flow already wired in, over subscription products it creates and prices in App Store Connect through the API, so adding a promotional offer is a matter of configuring it in App Store Connect and letting RevenueCat sign it, not building a signing server from scratch. And when you are lining up a waitlist and launch-day audience for the app, our sister tool Lighthouse covers that side.

From an indie iOS dev, for indie iOS devs.

Read more at spaceport.build

Community appsJoin Discord