Skip to Content
Configure offersCancel waterfall

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

FieldTypeDefault
waterfall_enabledbooleantrue

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:

FieldTypeLimits
feature_loss_bulletsstring arrayeach ≤ 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

Last updated on