Skip to Content

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

FieldTypeRange
discount_enabledbooleantoggles the entire offer
discount_offer.kindliteral'percent' (only value supported at launch)
discount_offer.percent_offnumber0 < x ≤ 100 (decimals allowed, e.g. 12.5)
discount_offer.durationenumonce or repeating
discount_offer.duration_in_monthsinteger1–12 (only when duration='repeating')
discount_offer.namestring1–40 chars; merchant-facing label
discount_cooldown_daysinteger0–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

Last updated on