WebinarUnlocking growth outside the US - 24 July   Join us
How to install the Cancellation Flow snippets


To use Retain's Cancellation Flow/Salvage Offers, we need you to add a bit of Javascript to your web-app so that we can display our widget to your users any time they click the "cancel button".

Before proceeding with the steps below, make sure you have our Engagement data snippet installed so that we can identify which user is cancelling.

You can set up the Cancellation Flow configuration by following these instructions.

Making the widget appear

Whenever a customer clicks on the "cancel button", you have to call profitwell('init_cancellation_flow', {subscription_id: 'sub_12345'}) so that the cancellation flow widget can load on the screen. Example below.

// This is the function called by the "Cancel button" in your company's webpage
function cancel() {
//... Any pre-cancel logic
profitwell('init_cancellation_flow', {subscription_id: 'sub_12345'}).then(result => {
// This means the customer either aborted the flow (i.e.
// they clicked on "never mind, I don't want to cancel"), or
// accepted a salvage attempt or salvage offer.
// Thus, do nothing since they won't cancel.
if (result.status === 'retained' || result.status === 'aborted') {

// At this point, the customer ended deciding to cancel (i.e.
// they rejected the salvage attempts and the salvage offer).
// It could also be the case the widget couldn't be shown properly for
// some reason (for which case, `result.status` will be 'error'), but that
// shouldn't stop them from cancelling.

// The normal cancel flow goes here

It's important to tell us which subscription id the customer is trying to cancel, in case they are on many plans, we need to know which plan to apply the salvage attempt to.

Reading the result

Whenever the flow finishes, we return some information to the profitwell('init_cancellation_flow') caller, so that you can take the proper post-flow action (the most common example is to do something when the customer chooses to cancel, as we do not actually cancel your customers' subscriptions in your system).

Pay attention to the .then(result => {...}) part. That is a callback that will be called whenever the widget disappears from the screen (after the customer decides to either stay/cancel). result will contain all the information regarding how the flow went.

The result object returned from the flow

We return all the information we captured from the flow (i.e., cancellation/satisfaction insight) for your record.

The result object has the following structure:

status: 'error' | 'aborted' | 'chose_to_cancel' | 'retained'
salvageAttemptResult: {
decision: 'accepted' | 'rejected'
resolution: 'accepted' | 'rejected'
hasErrors: boolean
} | null
salvageOfferResult: {decision: 'accepted' | 'rejected'; hasErrors: boolean} | null
additionalFeedback: string | null
cancelReason: string | null
satisfactionInsight: string | null
| 'pause_subscription'
| 'plan_switch'
| 'contact_support_email_notification'
| 'contact_support_meeting_scheduler'
| null
| 'pause_subscription'
| 'plan_switch'
| 'contact_support_email_notification'
| 'contact_support_meeting_scheduler'
| null

Need more help?

Login to your Paddle account to chat directly with our Seller Support Team or…