Cancel waterfall
What this offer does
Cancel is the terminal step, not a retention offer. When the customer declines every other offer, we schedule the subscription to cancel at period end. The cancel-confirm screen is your last chance to reframe the decision — that’s where the loss-aversion bullets and personalization tokens appear. See The five offers — Cancel for the full description.
Configuration
The cancel screen has three configuration surfaces:
Waterfall toggle
| Field | Type | Default |
|---|---|---|
waterfall_enabled | boolean | true |
When true, a customer who declines the first offer sees a different-type backup offer before reaching cancel-confirm. The hard cap is 2 offer screens before cancel-confirm. Set this to false to reduce the flow to feedback → first offer → confirm — useful if your jurisdiction requires a shorter path.
Loss-aversion bullets
Configured per Stripe price ID in plan_copy_config.feature_loss_bullets:
| Field | Type | Limits |
|---|---|---|
feature_loss_bullets | string array | each ≤ 80 characters, max 8 entries |
The widget shows each bullet as a “you will lose X” line on the cancel-confirm screen. If a price has no bullets configured, the widget falls back to: “You will lose all the benefits in your current plan.” Bullets are set via direct DB update or CLI — a dashboard editor ships in a later release.
Personalization
Pass customerFirstName to the widget. It fills in as {firstName} in copy (“Ready to cancel, Sarah?”). The value is used locally and never sent to Unchurn’s servers, PostHog, or any LLM.
// your-app/cancel-button.tsx
import { showCancelFlow } from '@unchurn.dev/widget'
showCancelFlow({
merchantId: 'mch_abc',
subscriptionId: 'sub_123',
authToken,
customerFirstName: user.firstName,
})customerAttributes is also accepted as a prop but is plumbing-only at launch — it’s received and ignored by every screen. A future release will expose attribute-based copy interpolation.
What gets called on Stripe
When the customer confirms cancellation, we schedule cancel-at-period-end:
// app/lib/offers/cancel.ts
await stripe.subscriptions.update(subscriptionId, {
cancel_at_period_end: true,
});The subscription is scheduled to cancel at the end of the current period. The customer keeps access through what they paid for. The database records cancel_scheduled, not terminal canceled. See the Stripe subscriptions update reference .
When automated cancel is blocked
Some subscription shapes aren’t safe for automated cancel — multi-item subscriptions, subscriptions with attached schedules, subscriptions in past_due or incomplete, subscriptions with a foreign pause_collection, and unrecognized Stripe states. For these the widget records a manual cancellation request instead. The customer sees “your cancellation request has been received” and you get a dashboard notification to complete the cancellation in Stripe. See Unusual subscriptions for the rationale and Supported subscriptions for the full blocked-shape list.
Common configurations
Loss bullets for a “Pro” plan. Concrete features and integrations — specific items outperform generic copy.
{
"feature_loss_bullets": [
"Access to your 12 saved workflows",
"Slack and Linear integrations",
"Priority email support",
"Unlimited team seats"
]
}Personalization on the confirm screen. Pass first name to fill {firstName} into copy.
showCancelFlow({
merchantId: 'mch_abc',
subscriptionId: 'sub_123',
authToken,
customerFirstName: 'Sarah',
})A bullet like "Hey {firstName}, you'll lose your saved workflows" shows as “Hey Sarah, you’ll lose your saved workflows”.
Pitfalls
- Loss bullets are per-price, not per-merchant. A merchant with three plans needs three sets of bullets in
plan_copy_config. Missing bullets leave the fallback line on every cancel-confirm. - Personalization values are local-only. They never reach the server, so analytics events don’t carry them. Send usage data through your own pipeline if you need it in your dashboard.
- Disabling the waterfall cuts your second-offer save rate roughly in half. A different-type second offer recovers 10–20% of first-offer decliners. Only disable if a compliance review requires a shorter flow.
Next steps
- The five offers — the conceptual overview of all offers
- Unusual subscriptions — why some subscriptions route to manual cancellation
- Supported subscriptions — full eligibility rules