Custom Implementation

Use callbacks for complete control over handling customer events.

Churnkey provides two types of callbacks for hooking into the offboarding flow: handler callbacks and listener callbacks.

Handler Callbacks

Handler callbacks are intended for when you want to handle changes to a customer's subscription instead of having Churnkey do it on your behalf. If a handler callback for a customer event is defined, Churnkey will not take action on your behalf when this event occurs.

Most handler type callbacks (with the exception of handleSupportRequest) are JavaScript Promise objects. Calling resolve will advance Churnkey's flow to a success state. Optionally, you can pass a message which will be shown to the customer. Calling reject will advance Churnkey's to an error state. Again, you can optionally pass a message to show the customer.

{
// AVAILABLE NOW
handlePause: <Promise>,
handleCancel: <Promise>,
handleDiscount: <Promise>,
handleSupportRequest: <function>
// COMING SOON
handlePlanChange: <Promise>,
}

Example Callbacks

For example, if you want to implement your own pause logic, instead of using Stripe's default pausing mechanism, you can defined the handlePause option. Similarly, you can use the handleCancel option to implement your own cancellation. These callbacks will be fired in when your customer selects that they would like to pause or cancel their subscription, respectively. And, if the respective callbacks are defined, Churnkey will not attempt to take action on your behalf by interfacing with Stripe to pause or cancel the subscription.

window.churnkey.init('show', {
appId: 'YOUR_APP_ID',
customerId: 'STRIPE_CUSTOMER_ID',
authHash: 'HMAC_HASH,
handlePause: (customer, { pauseDuration }) => {
return new Promise(async (resolve, reject) => {
try {
//////////
// YOUR CUSTOM PAUSING FUNCTION GOES HERE
//////////
// Optionally, display a custom message by passing a `message` when resolving
// if you don't pass a message, a generic pause confirmation message will be shown
resolve({ message: `Account has been paused for ${pauseDuration} month${duration === 1 ? '' : 's'}` });
} catch (e) {
console.log(e);
reject({ message: 'Failed to pause account. Please reach out to us through our live chat.' });
}
});
},
handleCancel: (customer, surveyAnswer) => {
// customer is the Stripe customer object (string)
// surveyAnswer is the reason they're leaving (string)
return new Promise(async (resolve, reject) => {
try {
///////////
// CANCEL THE CUSTOMERS SUBSCRIPTION HERE
//////////
// Optionally, display a custom message by passing a `message` when resolving
// if you don't pass a message, the generic message below will be displayed
resolve({ message: 'Your account has been canceled. You will not be billed again' });
} catch (e) {
console.log(e);
reject({ message: 'Failed to cancel account. Please reach out to us through our live chat.' });
}
});
},
})

The below example snippet implements handleSupportRequest, triggering an Intercom chat. handleSupportRequest is slightly different than the other handle-type callbacks in that it is a normal function, not a promise. This is intended as implementations of handleSupportRequest should not require backend changes and should (in nearly all cases) be synchronous.

window.churnkey.init('show', {
appId: 'YOUR_APP_ID',
customerId: 'STRIPE_CUSTOMER_ID',
authHash: 'HMAC_HASH,
handleSupportRequest: customer => {
console.log(customer);
window.Intercom('showNewMessage', 'Attention: Offboarding Customer Needs Help ASAP.\n');
window.churnkey.hide();
},
})

Note that window.churnkey.hide() is also called here, since the offboarding flow can usually be closed when support is requested.

Listener Callbacks

Listener callbacks are used to listen for events so that you can take appropriate action in your application. Unlike handler callbacks, if listener callbacks are defined, Churnkey will still take action on your behalf to update customer accounts in Stripe.

An example use case for the onCancel listener callback would be initiate client-side, client-specific business logic which needs to take place when a customer cancels there account, such as limiting the features available to them. Often times, this same logic client-side logic can be implemented using Stripe webhooks, and it will typically just come down to what works best for your application.

{
// AVAILABLE NOW
onPause: <function(customer, { pauseDuration }>,
onCancel: <function(customer)>,
onDiscount: <function(customer, coupon)>,
// COMING SOON
onPlanChange: <function>,
}

All available callbacks

handlePause(customer, { pauseDuration }): <Promise>

handleCancel(customer, surveyAnswer): <Promise>

handleDiscount(customer, coupon): <promise>

handleSupportRequest(customer): <function>

onCancel(customer): <function>

onPause(customer, { pauseDuration }): <function>

onDiscount(customer, coupon): <function>