Overview
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') {
return
}
// 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
salvageAttemptIntended:
| 'pause_subscription'
| 'plan_switch'
| 'contact_support_email_notification'
| 'contact_support_meeting_scheduler'
| null
salvageAttemptUsed:
| 'pause_subscription'
| 'plan_switch'
| 'contact_support_email_notification'
| 'contact_support_meeting_scheduler'
| null
}