Your users leave silently.
RetainFast is one script tag on your billing page. It intercepts your cancel button, asks the one question you never get answered, makes the right offer, and hands the outcome back to your own code.
One script tag · Zero dependencies · Shadow DOM · No Stripe OAuth
<5KB
gzipped, zero deps
0
Stripe permissions
5 min
typical install
$79
once, not monthly
The cancel button is the least designed screen in your product.
Stripe's portal
Asks one canned question, offers one coupon, and keeps the answer somewhere you will never look at it.
The $250/mo tools
Want write access to your Stripe account before they will show you a single screen. That is a long afternoon and a real risk.
So you ship a confirm()
And lose the customer, the reason they left, and the one chance you had to offer them something.
Three steps, about five minutes.
- 01
Paste one script tag
Add data-retainfast to the cancel button you already have. Nothing else about your billing page changes.
- 02
Build the flow
Reasons, offers, copy, colour — in the dashboard, with the real widget previewing beside you as you type.
- 03
Your code does the billing
onSave hands you the offer they took. onCancel hands you the reason. You call Stripe exactly the way you do today.
<script src="https://retainfast.com/w.js" data-key="rf_pub_xxx" defer></script> <button data-retainfast>Cancel subscription</button> <script> // your code, your billing provider RetainFast.onSave = ({ offer }) => yourApi.applyOffer(offer.value); RetainFast.onCancel = ({ reason }) => yourApi.cancelSubscription(reason); </script>
That is the whole integration. RetainFast never asks for a Stripe key, never holds a token, and never issues a refund on your behalf — because it cannot. Your backend stays the only thing that can move money.
Between doing nothing and paying $3,000 a year.
| Stripe portal | Churnkey etc. | RetainFast | |
|---|---|---|---|
| Cancellation reasons | One canned list | Yes | Yes |
| Offers that vary by reason | One coupon | Yes | Yes |
| Save-rate analytics | No | Yes | Yes |
| Needs Stripe write access | n/a | Yes | Never |
| Setup time | Minutes | Half a day | Five minutes |
| Price | Free | $250+/mo | $79 once |
Competitor pricing as published at the time of writing
Everything, for one payment.
—The flow editor
Add, remove and reorder reasons. Attach an offer to each one. Pick your accent colour and watch the real widget update as you type.
—The analytics
A funnel from opened to saved, save rate per offer, a reason breakdown, and every word your customers typed on the way out.
—Shadow DOM isolation
Your host CSS cannot leak in and ours cannot leak out. The widget looks identical on a Tailwind app and a fifteen-year-old Bootstrap theme.
—Zero dependencies
One vanilla JavaScript file under 5KB gzipped. No React, no bundler, no supply chain to worry about.
—Fails quietly
If our analytics endpoint dies, the error is swallowed. Our bad day must never become an outage on your billing page.
—Never touches Stripe
No OAuth, no API keys, no write access, ever. There is no configuration in which we could move your money.
This is the real widget.
Not a video, not a screenshot. The same file your customers would load, running the flow that is configured in the dashboard right now.
A pretend billing page
Hit cancel. The log underneath shows what your backend would receive.
The ones that actually get asked.
Do you need access to my Stripe account?
No, and there is no setting that turns it on. RetainFast owns the interface and the analytics; your backend owns every billing action. That constraint is why install takes five minutes instead of thirty, and why you can trust a stranger's script on your billing page.
What happens when someone accepts an offer?
The widget calls your onSave handler with the offer you configured, including its type and value. Your own code decides what that means and applies it through your billing provider. RetainFast records that it happened, for the funnel — nothing more.
Will it slow down or break my page?
It is one file under 5KB gzipped with no dependencies, loaded with defer. It renders inside a Shadow DOM so no styles cross in either direction, and every analytics call is wrapped so a failure on our side cannot throw inside your page.
Is $79 really the whole price?
Yes. One payment, lifetime, for one site. No subscription, no per-seat charge, and no commission on the revenue you keep. Fair use is 2,000 cancel sessions a month; past that the widget keeps working and the counters simply pause.
What data do you store about my customers?
The reason they picked, the offer they saw, and any freeform text they chose to type. No names, no emails, no IP addresses, no cookies on your visitors. Events are added to a single monthly counter rather than stored one by one.
Can I use it on more than one site?
A licence covers one site. If you run several products, buy a licence for each — it is still cheaper than one month of the subscription tools.
Lifetime. Not per month, not per seat, not a cut of what you save. Pay once and it is yours.
- —The dashboard and the widget, forever
- —Up to 2,000 cancel sessions a month
- —Every future update included
- —No card on file, nothing to renew
- —30-day refund, no argument
- —Whop handles tax and invoicing