Discount
What this offer does
When a customer accepts, we create a fresh, single-use Stripe coupon and attach it to their subscription. The coupon is locked with max_redemptions=1 and expires in one hour, so it can’t be shared or reused. See The five offers — Discount for the full description.
Configuration
In your Unchurn dashboard, under Widget → Discount, pick a mode:
- Manual — you set one fixed offer (percent off, duration, length in months) and every eligible customer sees it.
- Intelligent — you set ceilings (max percent, max months) and the LTV-calibrated agent picks a percentage within those bounds per customer.
Manual offer fields
| Field | Type | Range |
|---|---|---|
discount_enabled | boolean | toggles the entire offer |
discount_offer.kind | literal | 'percent' (only value supported at launch) |
discount_offer.percent_off | number | 0 < x ≤ 100 (decimals allowed, e.g. 12.5) |
discount_offer.duration | enum | once or repeating |
discount_offer.duration_in_months | integer | 1–12 (only when duration='repeating') |
discount_offer.name | string | 1–40 chars; merchant-facing label |
discount_cooldown_days | integer | 0–365 (per-customer, prevents re-takes) |
Cooldown
After a customer accepts a discount, the widget won’t offer them another one for discount_cooldown_days days. This stops a customer from cycling through the cancel flow to stack discounts.
Trialing customers
Trialing subscriptions can only receive one-time coupons, not repeating ones. The widget enforces this server-side. If your manual offer is set to repeating, trialing customers won’t see it — the waterfall moves on.
What gets called on Stripe
When the customer accepts, we create a single-use coupon and attach it to the subscription:
// app/lib/offers/discount.ts
const coupon = await stripe.coupons.create({
percent_off: offer.percent_off,
duration: offer.duration,
duration_in_months: offer.duration_in_months,
max_redemptions: 1,
redeem_by: Math.floor(Date.now() / 1000) + 3600,
});
await stripe.subscriptions.update(subscriptionId, {
discounts: [{ coupon: coupon.id }],
});The customer’s next eligible invoice is reduced. Existing draft or open invoices are not changed. See the Stripe subscriptions update reference .
When this offer is hidden
The widget hides the discount tile when the subscription already has an active coupon, when there are unresolved invoices, or when the subscription has automatic_tax enabled. See Supported subscriptions for the complete list.
Common configurations
20% off for 3 months, repeating. A meaningful price drop with a clear end date — the default for most SaaS.
{
"discount_enabled": true,
"discount_offer": {
"kind": "percent",
"percent_off": 20,
"duration": "repeating",
"duration_in_months": 3,
"name": "20% off for 3 months"
},
"discount_cooldown_days": 90
}One-time 50% off. A bigger single discount with no recurring revenue impact after the next invoice.
{
"discount_enabled": true,
"discount_offer": {
"kind": "percent",
"percent_off": 50,
"duration": "once",
"duration_in_months": null,
"name": "50% off once"
},
"discount_cooldown_days": 180
}Pitfalls
- The coupon expires in 1 hour. If a customer leaves the dialog open and returns the next day, the coupon is expired and the action fails. The widget fetches a new one and shows the offer again.
- Repeating coupons don’t appear for trialing customers. Check the dashboard ineligibility breakdown to confirm your live trialing customers see the offer you expect.
- The cooldown is per-customer, not per-subscription. A customer who accepts a discount on one subscription won’t see a discount on their other subscription until the cooldown window passes.
Next steps
- Pause — the typical second offer when discount is declined
- The five offers — the conceptual overview
- Supported subscriptions — full eligibility rules