Subscription churn is the single biggest revenue leak for indie Flutter apps, and winback campaigns are the single highest-ROI retention lever. Apple shipped the Win Back Offers API in iOS 18 and Google added the equivalent reacquisition offers to Play Billing. Both are now accessible via the RevenueCat Flutter SDK in 2026 but almost nobody writes about how to wire them. This guide walks through the full stack including offer types, paywall variants, segmentation, conversion benchmarks, and legal.
Short version: winback campaigns recover roughly 8 to 18 percent of churned subscribers when done well, at near-zero acquisition cost. The mechanics are: Apple and Google offer the user a price-cut, extended trial, or lifetime-discount offer the next time they open the App Store or Play Store, and your app shows a matching paywall when the user returns. RevenueCat handles the entitlement sync. You build two things: the offers in the store consoles and the paywall variant that matches them.
Why winback is the best retention lever for indie apps
- The user already knows your product. They subscribed once. Re-acquisition cost is zero compared to paid-ad CAC of $8-$25 per install.
- Platforms do the heavy lifting. Apple and Google present the offer inside the App Store or Play Store before the user even opens your app. You don't need a push notification or an email list.
- The offer is contextual. The user canceled yesterday; Apple can show them a price cut tomorrow. Timing is perfect.
- Conversion benchmarks are surprisingly high. 8-18 percent is a typical range for winback offers versus 2-5 percent for first-time paywalls.
The four winback offer types (and when to use each)
| Offer type | What it does | Typical win rate | Best for |
|---|---|---|---|
| Price cut | Same plan, discounted price for a fixed period (1-3 months) | 12-18% | Users who canceled due to price sensitivity |
| Extended free trial | Fresh 14-30 day trial of the paid plan | 8-14% | Users who didn't see enough value yet |
| Upgrade to annual at a discount | Move from monthly to annual with 30-50 percent off first year | 10-16% | Retaining monthly subscribers at risk of churn |
| Lifetime unlock | One-time payment replacing the subscription | 4-8% | Power users who hate recurring charges |
Start with the price-cut offer. It converts best, is easiest to configure, and works on both iOS and Android. Add others over time based on your analytics.
Apple Win Back Offers: setup in App Store Connect
Apple's Win Back Offers API landed in iOS 18 and is the native platform feature for presenting offers to churned users. Setup requires three steps in App Store Connect.
- Open your subscription product in App Store Connect, scroll to Subscription Offers, click the "Create Offer" button, and select Win Back as the offer type.
- Configure eligibility: the user must have had an active subscription within the last 90, 180, or 365 days. 180 is the sweet spot for most apps.
- Set the offer details: duration (1 week, 1 month, 2 months, or 3 months), price, and the eligibility window. Apple handles the rest including the Store-level display.
Users see the offer in the App Store subscription management section. The next time they open your app, StoreKit 2 exposes the offer via Product.subscription.offers and you can render a matching paywall.
Google Play reacquisition offers: setup in Play Console
Google added the equivalent as part of the 2025 Play Billing Library 7 update. In Play Console, navigate to Monetize, Subscriptions, Offers, Create reacquisition offer. Configure almost identically to Apple: eligibility window (30-365 days since cancellation), offer type (discount or trial), and duration.
Google surfaces the offer both in the Play Store subscription center AND via the Play Billing API when your app queries for offers. RevenueCat unifies both signals into a single stream.
RevenueCat configuration for winback offers
RevenueCat Flutter SDK handles both platforms via one API. In the RevenueCat dashboard, create a Winback Offer entry linked to the App Store and Play Store offer IDs you just made. The SDK exposes Purchases.getEligibleWinBackOffersForProduct which returns offers the current user qualifies for.
# pubspec.yaml
dependencies:
purchases_flutter: ^8.2.0Future<List<WinBackOffer>> eligibleOffers(StoreProduct product) async {
try {
final offers = await Purchases.getEligibleWinBackOffersForProduct(product);
return offers;
} on PlatformException catch (e) {
// No winback eligibility or user is currently subscribed
return [];
}
}
Future<CustomerInfo> redeemWinBack(
StoreProduct product,
WinBackOffer offer,
) async {
final result = await Purchases.purchaseProductWithWinBackOffer(
product: product,
winBackOffer: offer,
);
return result.customerInfo;
}Paywall variants: matching the offer to the UI
The biggest mistake indie apps make is showing the same paywall to a returning churned user as to a first-time user. Winback paywalls need different copy, different social proof, and different framing.
| Element | First-time paywall | Winback paywall |
|---|---|---|
| Headline | "Unlock Premium" | "Welcome back, here's a special offer" |
| Value props | Feature list + benefits | "Here's what you missed since you left" (new features added since) |
| Price display | Plain price | Strike-through original + discounted price + limited-time tag |
| Social proof | Review count | "12,000 users rejoined in the last 30 days" (if true) |
| CTA | "Start free trial" | "Claim 50 percent off" or "Reactivate with trial" |
The more specific you are about the user's history (they know they used the app before), the better this converts. Generic paywalls for returning users feel like spam.
Using Superwall for variant paywall testing
Superwall's Flutter SDK supports winback paywalls via placements. Define a placement called winback and configure the paywall variant in Superwall's dashboard. Trigger it when a returning churned user opens the app.
if (await Purchases.getEligibleWinBackOffersForProduct(product) is not empty) {
await Superwall.shared.register(
placement: 'winback',
params: {
'offerType': 'price_cut',
'daysSinceCancellation': 45,
},
);
}Superwall lets you A/B test multiple winback paywall variants without shipping a new app version. Measure click-through, conversion, and revenue per variant.
Segmentation: showing the right offer to the right user
Not every churned user deserves the same offer. Segment into four buckets.
- Recent churners (less than 30 days). They might come back on their own. Offer the price-cut or extended-trial to nudge.
- Mid-range churners (30-180 days). The prime winback window. Show your most aggressive offer here.
- Long-tail churners (180-365 days). Less likely to convert but also cheapest to try. Show a smaller offer or the lifetime unlock.
- Chronic churners (cycled in and out multiple times). These users have high lifetime value if you catch them. Show the lifetime unlock option.
RevenueCat's Customer attribute API lets you query the subscription history and segment. Combine with a Superwall placement to show the right variant.
Measuring winback conversion
Track these events in your analytics:
winback_offer_eligible(user has at least one eligible offer)winback_paywall_shown(you rendered a winback paywall)winback_offer_tapped(user tapped the redeem button)winback_purchase_success(offer was successfully redeemed)winback_trial_to_paid(if the offer was a trial, did it convert)
Typical funnel: 100 eligible users, 60 see the paywall, 20 tap, 15 convert. 15 percent of eligible users win back. Your numbers will vary.
Legal: refund and cooling-off rules
- EU consumer law. Users in the EU have 14 days to cancel any subscription (including winback offers) without reason. Apple and Google handle refunds automatically for in-app purchases, but the user may still dispute via your email support.
- Restore purchases. If a user claims they redeemed an offer but the entitlement didn't sync, the Restore Purchases button in your paywall must recover the entitlement. Tie it to
Purchases.restorePurchases(). - Disclosure requirements. Apple requires winback offers to display the original price crossed out alongside the discount. Your paywall must show both.
What The Flutter Kit ships
The Flutter Kit ships with the winback flow pre-wired: aWinbackBloc that checks eligibility on app start, a dedicated winback paywall template with the strike-through price UI, Superwall placement wiring for variant testing, and analytics events tied to PostHog. Configure your offers in App Store Connect and Play Console, register them in RevenueCat, and the paywall flow handles the rest.
$69 one-time, unlimited commercial projects. See every integration on the features page or jump to checkout.
Final recommendation
Winback is the highest-ROI retention work you can do. Start with a single price-cut offer (50 percent off for 2 months, 180-day eligibility window). Ship it for iOS first since Apple's Win Back Offers are more mature. Add Android once you validate the conversion math. Segment by days-since-cancellation and show different variants via Superwall. Expect to recover 8-18 percent of churned subscribers, which for most indie apps is more revenue than a full paid-ad campaign at a fraction of the cost.