Why most cancel flows don't work
The usual cancel flow shows everyone the same screen: a survey, then the same 20% discount. Customers who are leaving because the product is too expensive might take it. Customers who simply aren't using it, are switching tools, or hit a bug get an offer that doesn't address their reason, and you lose margin on the ones who would have stayed anyway. A good save offer depends on why this particular customer is leaving.
How the Lokuna cancel page works
- The customer clicks cancel in your app. Your button opens their Lokuna cancel page, either as a normal link or as a pop-up over your app.
- They tell you why. They pick a reason (too expensive, not using it enough, missing a feature, switching to another tool, technical issues, or something else) and can add a note in their own words. You can rename the reasons to fit your product.
- Lokuna picks one offer for that customer. It looks at their stated reason, what they wrote, and what Stripe knows: their plan, how much they pay, how long they have been a customer and whether their billing is current. Then it chooses a single option: a discount, a pause, a call with you, or no offer at all.
- They accept or cancel. An accepted discount or pause is applied to their subscription in Stripe right away. If they still want to leave, one click cancels, and the subscription ends at the end of the period they already paid for.
One offer, chosen per customer, inside your limits
You decide what the cancel page is allowed to do: which offer types are on, the discount range (for example 10 to 30% for 1 to 3 months), the longest pause, and whether a call is possible (it needs your booking link). Within that space, an AI model recommends the option most likely to keep that customer. It only uses a discount when a discount is what is most likely to make that person stay. Someone who isn't using the product is more likely to be offered a pause; someone who hit a technical problem may be offered a call instead of money off.
The limits are enforced by code, not by the model. An amount outside your range is clamped back into it, an offer type you turned off is rejected, and if the recommendation fails for any reason (a timeout, an invalid answer) a fixed rule picks the offer from the same settings. A customer is never shown an offer you didn't authorize, and a slow or failed AI call never blocks the customer from cancelling.
Connecting it to your cancel button
There is nothing to build. Use either option:
- A plain link from your cancel button to your workspace's cancel page, with the customer's Stripe customer ID in the URL.
- The one-line loader script, which opens the same hosted page as a pop-up over your app and returns the customer to where they were if they close it:
<script src="https://app.lokuna.com/embed.js" data-workspace="YOUR_WORKSPACE_ID"></script>
<button data-lokuna-cancel data-customer="cus_123">Cancel subscription</button>The script only opens the cancel page. It does not track visitors or collect events on your site. When you connect Stripe, Lokuna also sets up the cancellation settings of your Stripe customer portal as a fallback, so customers who cancel there are asked for a reason and keep access until the end of their period.
What happens after
Reasons and outcomes show up in your dashboard. The reasons customers give, together with their replies to Lokuna's emails, feed the weekly Customer Voice report, which ranks what customers ask for most. If someone cancels anyway, Lokuna sends one genuine feedback request a few days later. It doesn't start a months-long win-back drip.
If you sell to customers in places with click-to-cancel rules, our article on New York City's click-to-cancel rule covers what to check. For how the cancel page fits with failed payments and scheduled cancellations, see how Lokuna works and failed payment recovery.

