# Migrate from Brightback.js
This guide shows you how to migrate an existing integration that used the deprecated Brightback.js library to the Chargebee.js Cancel Page integration.
Who should use this guide?
If you already use Chargebee Billing (opens new window), use this guide to migrate your integration.
If you don't use Chargebee Billing yet, you can continue using Brightback.js (opens new window) without interruption. We'll provide a clear migration path to Chargebee.js and notify you when it's available.
# Reasons to migrate
The Brightback.js library is deprecated and will no longer receive updates. Migrating to the new Chargebee.js Cancel Page integration ensures you benefit from:
- Unified integration experience: You only call
Chargebee.init()
once, and the returnedchargebee
object can be reused across Chargebee.js features. - Access to all hosted features: Use the
chargebee
object to access all of Chargebee's hosted features, including Checkout, Portal, Payment Components, Cancel Page, Personalized Offers, Pricing Table, and more. - Centralized configuration: Set common context such as
site
when creating thechargebee
object. You don't need to set up separate authentication for Cancel Page.
# Change summary
To migrate from the Brightback.js library to the Chargebee.js Cancel Page integration, make the following key changes:
- Script source: Replace the Brightback.js script with the Chargebee.js script (
https://js.chargebee.com/v2/chargebee.js
). - Container element: Change the container element
id
frombb-cancel
tocb-cancel
. - Initialization: Initialize Chargebee.js and create a
cancelPage
object before using cancel page features. - API usage:
- Replace
window.Brightback.handleData()
withcancelPage.attachCancelHandler()
. - Replace
window.Brightback.handleDataPromise()
withcancelPage.getPage()
.
- Replace
- API parameters: Update the data structure to match the new schema.
The following code samples illustrate these changes. See the inline comments for more information.
# Simple integration (attach handler)
Use this approach to migrate from Brightback.handleData()
to the new cancelPage.attachCancelHandler()
API with minimal code changes. This method automatically attaches a click handler to your cancel button and initializes the cancel page flow when clicked.
DETAILS
# Before (Brightback.js)
<head>
<!-- OLD: Brightback script URL -->
<script src="https://app.retention.chargebee.com/js/current/brightback.js"></script>
</head>
<body>
<!-- OLD: Uses bb-cancel id for the cancel button. -->
<a id="bb-cancel" href="https://app.yourcompany.com/cancel" class="btn btn-danger">
Cancel Subscription
</a>
<script>
// OLD: Check for Brightback object and call handleData()
if (window.Brightback) {
window.Brightback.handleData({
app_id: 'YOUR_RETENTION_APP_ID', // OLD: Uses app_id
subscription_id: 'CHARGEBEE_BILLING_SUBSCRIPTION_ID',
first_name: 'Jane', // OLD: snake_case naming
last_name: 'Doe', // OLD: snake_case naming
email: 'jane.doe@example.com',
save_return_url: 'https://app.yourcompany.com/save?id=jane_doe', // OLD: snake_case
cancel_confirmation_url: 'https://app.yourcompany.com/cancel_confirm?id=jane_doe', // OLD: snake_case
account: {
billing_id: 'CHARGEBEE_BILLING_CUSTOMER_ID', // OLD: billing_id
created_at: '2024-06-26', // OLD: created_at
internal_id: 'jane_doe', // OLD: internal_id
plan: 'enterprise',
value: 1000.00 // OLD: value
},
custom: {
emailCount: 4208
}
});
}
</script>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# After (Chargebee.js)
<head>
<!-- NEW: Chargebee.js script URL -->
<script src="https://js.chargebee.com/v2/chargebee.js"></script>
</head>
<body>
<!-- NEW: Uses cb-cancel id for the cancel button. -->
<a id="cb-cancel" href="https://app.yourcompany.com/cancel" class="btn btn-danger">
Cancel Subscription
</a>
<script>
// NEW: Initialize Chargebee with site configuration
const chargebee = window.Chargebee.init({
site: "YOUR-CHARGEBEE-SUBDOMAIN",
});
(async () => {
// NEW: Create cancelPage instance using chargebee object
const cancelPage = await chargebee.cancelPage();
// NEW: cancelPage.attachCancelHandler() method instead of Brightback.handleData()
cancelPage.attachCancelHandler({
// NEW: subscription object
subscription: {
id: "CHARGEBEE_BILLING_SUBSCRIPTION_ID",
plan: "enterprise"
},
firstName: "Jane", // NEW: camelCase naming
lastName: "Doe", // NEW: camelCase naming
email: "jane.doe@example.com",
externalUserId: "jane_doe", // NEW: externalUserId instead of internal_id
saveReturnUrl: "https://app.yourcompany.com/save?id=jane_doe", // NEW: camelCase
cancelConfirmationUrl: "https://app.yourcompany.com/cancel_confirm?id=jane_doe", // NEW: camelCase naming
account: {
customerId: "CHARGEBEE_BILLING_CUSTOMER_ID", // NEW: customerId instead of billing_id
firstPurchaseDate: "2024-06-26", // NEW: firstPurchaseDate instead of created_at
contractValue: 1000.00 // NEW: contractValue instead of value
},
custom: {
emailCount: 4208
}
});
})();
</script>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# Advanced integration (prefetch and redirect)
Use this approach to migrate from Brightback.handleDataPromise()
to the new cancelPage.getPage()
API. This method lets you prefetch a personalized cancel page URL and programmatically redirect the user, enabling you to run custom logic before redirection or trigger cancellation from multiple places in your application.
DETAILS
# Before (Brightback.js)
<head>
<!-- OLD: Brightback script URL -->
<script src="https://app.retention.chargebee.com/js/current/brightback.js"></script>
</head>
<body>
<!-- OLD: Uses bb-cancel id for the cancel button. -->
<a id="bb-cancel" href="https://app.yourcompany.com/cancel" class="btn btn-danger">
Cancel Subscription
</a>
<script>
function bindLink(id, url) {
document.getElementById(id).addEventListener('click', () => {
window.location.assign(url);
});
}
// OLD: Call Brightback.handleDataPromise()
const p = window.Brightback.handleDataPromise({
app_id: 'YOUR_RETENTION_APP_ID', // OLD: Uses app_id
subscription_id: 'CHARGEBEE_BILLING_SUBSCRIPTION_ID',
first_name: 'Jane', // OLD: snake_case naming
last_name: 'Doe', // OLD: snake_case naming
email: 'jane.doe@example.com',
save_return_url: 'https://app.yourcompany.com/save?id=jane_doe', // OLD: snake_case
cancel_confirmation_url: 'https://app.yourcompany.com/cancel_confirm?id=jane_doe', // OLD: snake_case
account: {
billing_id: 'CHARGEBEE_BILLING_CUSTOMER_ID', // OLD: billing_id
created_at: '2024-06-26', // OLD: created_at
internal_id: 'jane_doe', // OLD: internal_id
plan: 'enterprise',
value: 1000.00 // OLD: value
},
custom: {
emailCount: 4208
}
});
p.then((success) => {
if (success.valid) {
bindLink('bb-cancel', success.url);
} else {
bindLink('bb-cancel', 'https://app.yourcompany.com/cancel?id=jane_doe');
}
});
</script>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# After (Chargebee.js)
<head>
<!-- NEW: Chargebee.js script URL -->
<script src="https://js.chargebee.com/v2/chargebee.js"></script>
</head>
<body>
<!-- NEW: Uses cb-cancel id for the cancel button. -->
<a id="cb-cancel" href="https://app.yourcompany.com/cancel" class="btn btn-danger">
Cancel Subscription
</a>
<script>
// NEW: Initialize Chargebee with site configuration
const chargebee = window.Chargebee.init({
site: "YOUR-CHARGEBEE-SUBDOMAIN",
});
function bindLink(id, url) {
document.getElementById(id).addEventListener('click', () => {
window.location.assign(url);
});
}
(async () => {
// NEW: Create cancelPage instance using chargebee object
const cancelPage = await chargebee.cancelPage();
const options = {
// NEW: subscription object
subscription: {
id: "CHARGEBEE_BILLING_SUBSCRIPTION_ID",
plan: "enterprise"
},
firstName: "Jane", // NEW: camelCase naming
lastName: "Doe", // NEW: camelCase naming
email: "jane.doe@example.com",
externalUserId: "jane_doe", // NEW: externalUserId instead of internal_id
saveReturnUrl: "https://app.yourcompany.com/save?id=jane_doe", // NEW: camelCase
cancelConfirmationUrl: "https://app.yourcompany.com/cancel_confirm?id=jane_doe", // NEW: camelCase naming
account: {
customerId: "CHARGEBEE_BILLING_CUSTOMER_ID", // NEW: customerId instead of billing_id
firstPurchaseDate: "2024-06-26", // NEW: firstPurchaseDate instead of created_at
contractValue: 1000.00 // NEW: contractValue instead of value
},
custom: {
emailCount: 4208
}
};
// NEW: cancelPage.getPage() method instead of Brightback.handleDataPromise()
cancelPage.getPage(options).then((result) => {
if (result.valid) {
bindLink('cb-cancel', result.url);
} else {
bindLink('cb-cancel', 'https://app.yourcompany.com/cancel?id=jane_doe');
}
});
})();
</script>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# Detailed migration steps
# 1. Load chargebee.js
instead of brightback.js
# Before
<script src="https://app.retention.chargebee.com/js/current/brightback.js"></script>
# After
<script src="https://js.chargebee.com/v2/chargebee.js"></script>
# 2. Update the cancel button element
Change the id
attribute of your cancel button from bb-cancel
to cb-cancel
.
# Before
<a id="bb-cancel" href="https://app.yourcompany.com/cancel" class="btn btn-danger">
Cancel Subscription
</a>
2
3
# After
<a id="cb-cancel" href="https://app.yourcompany.com/cancel" class="btn btn-danger">
Cancel Subscription
</a>
2
3
# 3. Initialize Chargebee.js
Once the page loads, initialize Chargebee.js with your Chargebee site subdomain to enable the use of the SDK.
# Before
Not available in brightback.js
.
# After
const chargebee = window.Chargebee.init({
site: "YOUR-CHARGEBEE-SUBDOMAIN",
});
2
3
# 4. Create the Cancel Page object
Use the cancelPage()
function to instantiate Cancel Page.
# Before
Not available in brightback.js
.
# After
const cancelPage = await chargebee.cancelPage();
# 5. Replace Retention integration methods
# Option A: Simple integration (attach handler)
Use this approach to migrate from Brightback.handleData()
to the new cancelPage.attachCancelHandler()
API with minimal code changes. This method automatically attaches a click handler to your cancel button and initializes the cancel page flow when clicked.
DETAILS
# Before
// OLD: Check for Brightback object and call handleData()
if (window.Brightback) {
window.Brightback.handleData({
app_id: 'YOUR_RETENTION_APP_ID', // OLD: Uses app_id
subscription_id: 'CHARGEBEE_BILLING_SUBSCRIPTION_ID',
first_name: 'Jane', // OLD: snake_case naming
last_name: 'Doe', // OLD: snake_case naming
email: 'jane.doe@example.com',
save_return_url: 'https://app.yourcompany.com/save?id=jane_doe', // OLD: snake_case
cancel_confirmation_url: 'https://app.yourcompany.com/cancel_confirm?id=jane_doe', // OLD: snake_case
account: {
billing_id: 'CHARGEBEE_BILLING_CUSTOMER_ID', // OLD: billing_id
created_at: '2024-06-26', // OLD: created_at
internal_id: 'jane_doe', // OLD: internal_id
plan: 'enterprise',
value: 1000.00 // OLD: value
},
custom: {
emailCount: 4208
}
});
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# After
cancelPage.attachCancelHandler({
// NEW: subscription object
subscription: {
id: "CHARGEBEE_BILLING_SUBSCRIPTION_ID",
plan: "enterprise"
},
firstName: "Jane", // NEW: camelCase naming
lastName: "Doe", // NEW: camelCase naming
email: "jane.doe@example.com",
externalUserId: "jane_doe", // NEW: externalUserId instead of internal_id
saveReturnUrl: "https://app.yourcompany.com/save?id=jane_doe", // NEW: camelCase
cancelConfirmationUrl: "https://app.yourcompany.com/cancel_confirm?id=jane_doe", // NEW: camelCase naming
account: {
customerId: "CHARGEBEE_BILLING_CUSTOMER_ID", // NEW: customerId instead of billing_id
firstPurchaseDate: "2024-06-26", // NEW: firstPurchaseDate instead of created_at
contractValue: 1000.00 // NEW: contractValue instead of value
},
custom: {
emailCount: 4208
}
});
})();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Parameter schema changes
See full list of parameter schema changes.
# Option B: Advanced integration (prefetch and redirect)
Use this approach to migrate from Brightback.handleDataPromise()
to the new cancelPage.getPage()
API. This method lets you prefetch a personalized cancel page URL and programmatically redirect the user, enabling you to run custom logic before redirection or trigger cancellation from multiple places in your application.
DETAILS
# Before
function bindLink(id, url) {
document.getElementById(id).addEventListener('click', () => {
window.location.assign(url);
});
}
// OLD: Call Brightback.handleDataPromise()
const p = window.Brightback.handleDataPromise({
app_id: 'YOUR_RETENTION_APP_ID', // OLD: Uses app_id
subscription_id: 'CHARGEBEE_BILLING_SUBSCRIPTION_ID',
first_name: 'Jane', // OLD: snake_case naming
last_name: 'Doe', // OLD: snake_case naming
email: 'jane.doe@example.com',
save_return_url: 'https://app.yourcompany.com/save?id=jane_doe', // OLD: snake_case
cancel_confirmation_url: 'https://app.yourcompany.com/cancel_confirm?id=jane_doe', // OLD: snake_case
account: {
billing_id: 'CHARGEBEE_BILLING_CUSTOMER_ID', // OLD: billing_id
created_at: '2024-06-26', // OLD: created_at
internal_id: 'jane_doe', // OLD: internal_id
plan: 'enterprise',
value: 1000.00 // OLD: value
},
custom: {
emailCount: 4208
}
});
p.then((success) => {
if (success.valid) {
bindLink('bb-cancel', success.url);
} else {
bindLink('bb-cancel', 'https://app.yourcompany.com/cancel?id=jane_doe');
}
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# After
// NEW: Initialize Chargebee with site configuration
const chargebee = window.Chargebee.init({
site: "YOUR-CHARGEBEE-SUBDOMAIN",
});
function bindLink(id, url) {
document.getElementById(id).addEventListener('click', () => {
window.location.assign(url);
});
}
(async () => {
// NEW: Create cancelPage instance using chargebee object
const cancelPage = await chargebee.cancelPage();
const options = {
// NEW: subscription object
subscription: {
id: "CHARGEBEE_BILLING_SUBSCRIPTION_ID",
plan: "enterprise"
},
firstName: "Jane", // NEW: camelCase naming
lastName: "Doe", // NEW: camelCase naming
email: "jane.doe@example.com",
externalUserId: "jane_doe", // NEW: externalUserId instead of internal_id
saveReturnUrl: "https://app.yourcompany.com/save?id=jane_doe", // NEW: camelCase
cancelConfirmationUrl: "https://app.yourcompany.com/cancel_confirm?id=jane_doe", // NEW: camelCase naming
account: {
customerId: "CHARGEBEE_BILLING_CUSTOMER_ID", // NEW: customerId instead of billing_id
firstPurchaseDate: "2024-06-26", // NEW: firstPurchaseDate instead of created_at
contractValue: 1000.00 // NEW: contractValue instead of value
},
custom: {
emailCount: 4208
}
};
// NEW: cancelPage.getPage() method instead of Brightback.handleDataPromise()
cancelPage.getPage(options).then((result) => {
if (result.valid) {
bindLink('cb-cancel', result.url);
} else {
bindLink('cb-cancel', 'https://app.yourcompany.com/cancel?id=jane_doe');
}
});
})();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Parameter schema changes
See full list of parameter schema changes.
# Input parameter schema changes
The input parameters for the methods have been changed as follows:
Brightback.js | Chargebee.js | Notes |
---|---|---|
app_id | Not needed. | Site is configured globally in Chargebee.init() . |
first_name | firstName | Changed to camel case. |
last_name | lastName | Changed to camel case. |
full_name | fullName | Changed to camel case. |
save_return_url | saveReturnUrl | Changed to camel case. |
cancel_confirmation_url | cancelConfirmationUrl | Changed to camel case. |
account.company_name | account.companyName | Changed to camel case. |
account.company_domain | account.companyDomain | Changed to camel case. |
account.billing_id | account.customerId | Renamed. |
account.value | account.contractValue | Renamed. |
account.created_at | account.firstPurchaseDate | Renamed. |
account.internal_id | externalUserId | Renamed and moved to top level. |
account.plan | subscription.plan | Moved to subscription object. |
account.plan_term | subscription.planTerm | Moved to subscription object. |
subscription_id | subscription.id | Renamed and moved to subscription object. |
# Best practices
# Local development
By default and for security reasons, Chargebee does not respond to cancel page API requests from localhost. For local development to work, temporarily map a domain to your localhost to verify the XHR request or use a tunnel service like ngrok (opens new window) or localtunnel (opens new window). Watch the network tab in your DOM inspector to diagnose any additional issues.
# Render within iframes
You can embed the Chargebee cancel page within your application using an iframe (opens new window). To do so securely, you must configure a vanity domain that matches the domain of your website. For example, if your app runs at https://app.yourcompany.com
, the iframe must load from a domain like https://cancel.yourcompany.com
. Domains like yourcompany.chargebee.com
cannot be embedded in an iframe due to cross-origin restrictions.