Back to home

Installation Guide

KeepFlow adds a retention flow in front of your cancel button. Installation is two steps: add one script tag, then call KeepFlow.open() when a customer clicks “Cancel subscription”. Most teams are done in under 15 minutes.

Before you start

Step 1: Add the script

Add this tag to any page where customers can cancel (your billing or account-settings page), or globally in your layout. Replace YOUR_API_KEY with the key from your project's Install tab.

<script src="https://keepflow.io/widget/keepflow.js" data-api-key="YOUR_API_KEY"></script>

The API key is publishable — it's safe in your page source. It only identifies your project and can't read data or touch subscriptions the visitor doesn't own. The script is ~7 KB, loads asynchronously (plain async and tag-manager installs are supported), and does nothing until you call it.

As soon as the script is live, your dashboard's Install tab flips to “Installation detected” so you can confirm this step worked before writing any code.

Step 2: Trigger the widget

Call KeepFlow.open() from your cancel button instead of canceling directly:

document.getElementById('cancel-button').addEventListener('click', () => {
  KeepFlow.open({
    // Required — from your own Stripe integration
    customerId: 'cus_xxx',        // the customer's Stripe ID
    subscriptionId: 'sub_xxx',    // the subscription being canceled

    // Optional — values for {{variables}} in your widget headline
    userData: { name: 'Ada', planName: 'Pro' },

    // Optional — where to send users if the widget can't load
    fallbackUrl: 'https://billing.stripe.com/p/session/...',

    onComplete: (result) => {
      if (result.status === 'saved') {
        // Customer accepted an offer — subscription unchanged or discounted
      } else {
        // Customer canceled (at period end) — update your UI
      }
    },
    onError: (error) => {
      // Widget failed — let your normal cancel flow proceed
    },
  });
});

What KeepFlow does with the result

API reference

OptionTypeDescription
customerIdstring, requiredStripe customer ID (cus_…). Must own the subscription.
subscriptionIdstring, requiredStripe subscription ID (sub_…) being canceled.
userDataobjectValues interpolated into {{variable}} placeholders in your widget copy.
fallbackUrlstring (https)Shown as “Manage Subscription” if the widget can't load (e.g. your Stripe customer-portal link).
onComplete(result)functionresult.status is 'saved', 'canceled', or 'fallback_cancel'; result.reason is the selected reason ID.
onError(error)functionCalled when the widget can't load or submit. Fall back to your own cancel flow here.
onFallbackCancel(info)functionCalled when the user chooses to cancel from the fail-safe screen — complete the cancellation in your own backend.

FAQ

Does this work from my domain? (CORS)

Yes — the widget API is built for cross-origin use and works from any domain where you embed the script.

Can KeepFlow cancel the wrong subscription?

No. The server verifies the subscription belongs to the customer you pass before doing anything, and every Stripe action happens on your connected account with the IDs you provided.

What if KeepFlow is down when someone tries to cancel?

The widget times out after 10 seconds and shows a fail-safe screen so your customer can always cancel — via your fallbackUrl or your own flow through onFallbackCancel. KeepFlow never blocks a cancellation.

I use React / Next.js / Vue — anything special?

No framework adapter needed. Load the script tag once (e.g. in your root layout or with your framework's Script component) and call window.KeepFlow.open() from your cancel handler.

Need help with your integration?

Email support@keepflow.io — integration questions are answered same-day.

Start Your Free Trial