Skip to content
Development
Skill

/win-back-offers

Generates the complete win-back offer flow for churned subscribers — StoreKit Message API handling, eligibility verification, offer sheet presentation, and analytics. Use when implementing win-back campaigns or re-engagement for lapsed subscribers.

From plugin
rshankras-apple-skills
848181 skills

Claude Code

$ npx -y skills add rshankras/claude-code-apple-skills --skill win-back-offers --agent claude-code

SKILL.md

win-back-offers.SKILL.md
name: win-back-offers
description: Generates the complete win-back offer flow for churned subscribers — StoreKit Message API handling, eligibility verification, offer sheet presentation, and analytics. Use when implementing win-back campaigns or re-engagement for lapsed subscribers.
allowed-tools: [Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion]
last_verified: 2026-07-16
review_by: 2027-06-22
os_version: iOS 27 / macOS 27

Win-Back Offers Generator

Generate a complete win-back flow for recovering churned subscribers using StoreKit 2's win-back offer APIs (iOS 18+), Message API handling, and fallback promotional offers for older OS versions.

When This Skill Activates

Use this skill when the user:

  • Asks to "win back" or "re-engage" churned subscribers
  • Mentions "lapsed subscribers" or "subscriber recovery"
  • Wants to implement "win-back offers" (iOS 18+)
  • Asks about "subscription churn" reduction
  • Mentions "Message API" for subscription offers
  • Wants to reduce subscriber attrition

Minimum Eligibility

Win-back offers involve meaningful engineering and ASC configuration. Check these thresholds before proceeding:

| Churned Subscribers | Recommendation | |----|---| | **Under 50** | Not worth the setup effort. Use personal email outreach instead — write individual messages to churned users. Focus energy on preventing churn (improve onboarding, engagement). | | **50-500** | Implement basic win-back via promotional offers (simpler than full win-back flow). Use offer codes distributed via email. | | **500+** | Full win-back implementation justified. Native iOS 18+ win-back offers, Message API handling, automated pipeline. |

**If you don't know your churn numbers:** Check App Store Connect > Subscriptions > Retention metrics. If your total subscriber base is under 200, you likely don't have enough churn volume to justify this skill yet.

Pre-Generation Checks

1. Project Context Detection

  • [ ] Check for existing StoreKit implementation
  • [ ] Check deployment target (iOS 18+ for native win-back, iOS 16+ for promotional offer fallback)
  • [ ] Look for existing subscription management code
  • [ ] Check if `subscription-offers` skill was already used
  • [ ] **Check churn volume** — is the number of churned subscribers worth automating?

2. Conflict Detection

Glob: **/*WinBack*.swift, **/*Reengag*.swift
Grep: "winBackOffers" or "Message.messages" or "presentWinBackOffer"

Configuration Questions

Ask user via AskUserQuestion:

1. **Win-back approach**

  • Native win-back offers only (iOS 18+ required)
  • Promotional offer fallback (supports iOS 16+)
  • Both (recommended)

2. **Message handling**

  • Handle App Store messages in-app (recommended)
  • Let system handle messages
  • Custom message presentation

3. **Analytics integration**

  • Basic (print logging)
  • Custom analytics protocol
  • Specific SDK (specify which)

Generation Process

Step 1: Read Templates

Read `templates.md` for all win-back implementation code.

Step 2: Create Core Files

1. **WinBackOfferManager.swift** — Win-back offer detection, eligibility, and presentation 2. **WinBackMessageHandler.swift** — StoreKit Message API integration for in-app offer display 3. **WinBackEligibility.swift** — Churn detection and eligibility logic 4. **WinBackOfferView.swift** — Custom win-back offer presentation UI

Step 3: Create Optional Files

5. **WinBackAnalytics.swift** — Track win-back funnel metrics 6. **WinBackFallback.swift** — Promotional offer fallback for iOS < 18

Step 4: Determine File Location

- If Sources/Store/ exists → Sources/Store/WinBack/
- If Store/ exists → Store/WinBack/
- Otherwise → WinBack/

Output Format

Files Created

Store/WinBack/
├── WinBackOfferManager.swift      # Core win-back logic
├── WinBackMessageHandler.swift    # Message API handling
├── WinBackEligibility.swift       # Churn detection
├── WinBackOfferView.swift         # Custom offer UI
├── WinBackAnalytics.swift         # Funnel tracking (optional)
└── WinBackFallback.swift          # iOS < 18 fallback (optional)

Integration Steps

**App Entry Point — Message Handling:**

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .storeMessagesTask { message in
                    // Handle win-back messages from App Store
                    await WinBackMessageHandler.shared.handle(message)
                }
        }
    }
}

**Check Win-Back Eligibility:**

let manager = WinBackOfferManager()
let winBackOffer = await manager.checkWinBackAvailability(
    productID: "com.app.subscription.monthly"
)

if let offer = winBackOffer {
    // Show win-back UI
    showWinBackSheet(offer: offer)
}

**Present Win-Back Offer:**

// Native (iOS 18+) — raw StoreKit path
if case .verified(let renewalInfo) = status.renewalInfo,
   let bestID = renewalInfo.eligibleWinBackOfferIDs.first,   // first ID = best offer
   let offer = product.subscription?.winBackOffers.first(where: { $0.id == bestID }) {
    let result = try await product.purchase(options: [.winBackOffer(offer)])
}

// With StoreKit views, choose the merchandised offer instead
SubscriptionStoreView(groupID: groupID)
    .preferredSubscriptionOffer { product, subscription, offers in
        offers.first { $0.type == .winBack }
    }

Hide win-back merchandising from anyone still entitled with auto-renew on — the offer is for lapsed subscribers only.

Where Offers Surface (WWDC24)

The App Store does the distribution — eligible lapsed subscribers see your win-back offer on:

  • Your **product page** (offer card)
  • **Today / Games / Apps** editorial placements
  • The App Store's **Subscriptions** management page
  • **In-app**, via the APIs above

**Streamlined purchasing is ON by default:** users can redeem on the App Store before ever reopening your app, so the transaction arrives via `Transaction.updat

Read more
@rshankras
Ships withrshankras-apple-skills

A collection of Claude Code skills for iOS, macOS, watchOS, visionOS, and Apple platform development. These skills help you plan and build apps, maintain code quality, ensure HIG compliance, and guide you from idea to App Store.

Stars on GitHub

Momentum

stars in total
848
Star history of rshankras/claude-code-apple-skills on GitHub, a chart by star-history.com

Other skills on rshankras-apple-skills.

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about win-back-offers.

Which coding agents can use win-back-offers?
win-back-offers installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.