/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.
$ npx -y skills add rshankras/claude-code-apple-skills --skill win-back-offers --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/win-back-offers
Context preview
The summary Claude sees to decide when to auto-load this skill.
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.
SKILL.md
win-back-offers.SKILL.mdname: 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
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
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.
Repo: rshankras/claude-code-apple-skills
Other skills on rshankras-apple-skills.
- /app-store
App Store optimization and marketing skills for descriptions, screenshots, keywords, review responses, and comprehensive promotional strategy. Use when user needs help with App Store presence, ASO, marketing, or customer communication.
Open skill - /ad-attribution
Privacy-preserving ad measurement with AdAttributionKit (SKAdNetwork's successor) — install and re-engagement attribution, conversion-value strategy under crowd anonymity, and end-to-end postback testing. Use when running paid acquisition beyond Apple Ads, measuring
Open skill - /app-description-writer
Generate compelling App Store descriptions that convert browsers into users. Use when writing initial descriptions, improving existing copy, or drafting promotional text and What's New for a major update.
Open skill - /apple-search-ads
Apple Search Ads campaign strategy for indie developers — paid acquisition, keyword bidding, budget planning, and ROAS optimization. Use when user asks about running ads, paid user acquisition, or Apple Search Ads campaigns.
Open skill - /iap-finalizer
Take a one-time in-app purchase from MISSING_METADATA to READY_TO_SUBMIT in App Store Connect — set its price schedule and localized display name/description (and optional review screenshot) via the ASC REST API. Use at Phase 6 (Pre-Release), after the IAP is built in-app (Phase
Open skill - /keyword-optimizer
Optimize app title, subtitle, and keywords for maximum App Store discoverability. Use when launching a new app, improving search rankings, entering new markets/languages, or safely optimizing ASO for an app with existing traffic.
Open skill

