Use Paddle.Retain.initCancellationFlow() to start a Paddle Retain cancellation flow for a subscription.
Cancellation Flows help you save customers from canceling by presenting them with dynamic salvage attempts while gathering cancellation insights. Retain automatically schedules a cancellation for the subscription in Paddle Billing if a customer proceeds to cancel.
Typically used as part of a cancel subscription workflow.
Paddle Retain only works on live accounts
Paddle Retain only works with live data. While you can initialize Paddle.js with Retain in sandbox accounts, Retain features aren't loaded there.
This method is for Paddle Billing only. If you use Cancellation Flows with another billing platform, use the profitwell method in the ProfitWell.js snippet instead. To learn more, see Configure Cancellation Flows and salvage offers
To specify a subscription to cancel, pass a subscriptionId parameter. This is recommended, but not required where customers only have one subscription and you passed pwCustomer to Paddle.Initialize() or Paddle.Update().
Parameters
pwCustomer has not been passed to Paddle.Initialize() or Paddle.Update(). Paddle Billing only.Returns
abortedCustomer started the cancellation flow, but chose not to cancel by clicking the 'Never mind, I don't want to cancel' option.chose_to_cancelCustomer started the cancellation flow, rejected salvage attempts and salvage offers, and proceeded to cancel.retainedCustomer started the cancellation flow, and accepted a salvage attempt or a salvage offer. They did not cancel.errorThere was a problem starting the cancellation flow.
null if salvage attempts not presented, like if they chose not to cancel or closed the modal.acceptedCustomer accepted a salvage attempt.rejectedCustomer rejected a salvage attempt.
acceptedSalvage attempt prevented a customer from canceling.rejectedCustomer chose to cancel.
null if salvage offers not presented, like if they chose not to cancel or closed the modal.acceptedCustomer accepted a salvage offer.rejectedCustomer rejected a salvage offer.
null if no feedback or not presented to the customer.null if customer chose not to cancel or closed the modal.Not useful right nowCustomer selected the 'Not useful right now' option. Designed to be the inverse of the 'Many things, I'll be back' option in question 2.Didn't see the valueCustomer selected the 'Didn't see the value' option. Designed to be the inverse of the 'Good value' option in question 2.Poor supportCustomer selected the 'Poor support' option. Designed to be the inverse of the 'Helpful support' option in question 2.Missing features/hard to useCustomer selected the 'Missing features/hard to use' option. Designed to be the inverse of the 'Easy to use' option in question 2.OtherCustomer selected the 'Other' option. Designed to be the inverse of the 'Other' option in question 2.
null if customer chose not to cancel or closed the modal.Many things, I'll be backCustomer selected the 'Many things, I'll be back' option. Designed to be the inverse of the 'Not useful right now' option in question 1.Good valueCustomer selected the 'Good value' option. Designed to be the inverse of the 'Didn't see the value' option in question 1.Helpful supportCustomer selected the 'Helpful support' option. Designed to be the inverse of the 'Poor support' option in question 1.Easy to useCustomer selected the 'Easy to use' option. Designed to be the inverse of the 'Missing features/hard to use' option in question 1.OtherCustomer selected the 'Other' option. Designed to be the inverse of the 'Other' option in question 1.
null if customer chose not to cancel or closed the modal.contact_support_email_notificationPresented where the satisfaction insight is 'Other'. Customer is prompted to send a message to your support team to chat more about this.contact_support_meeting_schedulerPresented where the satisfaction insight is 'Helpful support'. Customer is prompted to schedule a meeting using Calendly.pause_subscriptionPresented where the satisfaction insight is 'Many things, I'll be back'. Customer is prompted to pause their subscription for three months.plan_switchPresented where the satisfaction insight is 'Good value, I'll be back'. Customer is prompted to switch to another plan.
null if customer chose not to cancel, closed the modal, or does not accept a salvage attempt.contact_support_email_notificationPresented where the satisfaction insight is 'Other'. Customer is prompted to send a message to your support team to chat more about this.contact_support_meeting_schedulerPresented where the satisfaction insight is 'Helpful support'. Customer is prompted to schedule a meeting using Calendly.pause_subscriptionPresented where the satisfaction insight is 'Many things, I'll be back'. Customer is prompted to pause their subscription for three months.plan_switchPresented where the satisfaction insight is 'Good value, I'll be back'. Customer is prompted to switch to another plan.
Examples
This example shows how you can use Paddle.Retain.initCancellationFlow() to start a cancellation flow.
subscriptionId is passed to Paddle.Retain.initCancellationFlow() to specify the subscription to cancel.
pwCustomer is passed to Paddle.Initialize() to identify the customer to Paddle Retain, but this isn't required. Paddle Retain infers the customer from the subscriptionId passed and presents a cancellation flow.
Retain automatically schedules a cancellation for the subscription in Paddle Billing if a customer proceeds to cancel, so you don't need to build logic to handle this yourself.
<!-- Cancellation button --><button onclick="cancelSubscription()">Cancel my subscription</button>
<script type="text/javascript"> function cancelSubscription() { Paddle.Retain.initCancellationFlow({ subscriptionId: "sub_01h8bqcrwp0vjd1p3bv20y7323", }); }</script>import { initializePaddle } from "@paddle/paddle-js";
const paddle = await initializePaddle({ token: "live_7d279f61a3499fed520f7cd8c08",});
paddle?.Retain.initCancellationFlow({ subscriptionId: "sub_01h8bqcrwp0vjd1p3bv20y7323",});To learn more, see Build cancellation surveys and offers
This example shows how you can attach a callback to a cancellation flow.
It uses the .then() method to attach a callback that logs a message to the console:
- Customer retained
The customer accepted a salvage attempt or a salvage offer, or chose not to cancel. - There was a problem starting the cancellation flow.
Something went wrong while starting the cancellation flow. The customer wasn't given the chance to cancel. - Customer proceeded with cancellation.
The customer rejected salvage attempts and salvage offers and proceeded to cancel.
<!-- Cancellation button --><button onclick="cancelSubscription()">Cancel my subscription</button>
<script type="text/javascript"> // Cancel subscription function cancelSubscription() { Paddle.Retain.initCancellationFlow({ subscriptionId: "sub_01h8bqcrwp0vjd1p3bv20y7323", }) .then((result) => { if (result.status === "retained" || result.status === "aborted") { console.log("Customer retained!"); } else if (result.status === "error") { console.log("There was a problem starting the cancellation flow."); } else { console.log("Customer proceeded with cancellation."); } }) .catch((error) => { console.error(error); }); }</script>import { initializePaddle } from "@paddle/paddle-js";
const paddle = await initializePaddle({ token: "live_7d279f61a3499fed520f7cd8c08",});
paddle?.Retain.initCancellationFlow({ subscriptionId: "sub_01h8bqcrwp0vjd1p3bv20y7323",}) .then((result) => { if (result.status === "retained" || result.status === "aborted") { console.log("Customer retained!"); } else if (result.status === "error") { console.log("There was a problem starting the cancellation flow."); } else { console.log("Customer proceeded with cancellation."); } }) .catch((error) => { console.error(error); });To learn more, see Build cancellation surveys and offers