# 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 returned chargebee 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 the chargebee 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 from bb-cancel to cb-cancel.
  • Initialization: Initialize Chargebee.js and create a cancelPage object before using cancel page features.
  • API usage:
  • 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>
1
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>
1
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>
1
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>
1
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>
1

# After

<script src="https://js.chargebee.com/v2/chargebee.js"></script>
1

# 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>
1
2
3

# After

<a id="cb-cancel" href="https://app.yourcompany.com/cancel" class="btn btn-danger">
  Cancel Subscription
</a>
1
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",
});
1
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();
1

# 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
    }
    });
}
1
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
    }
    });
})();
1
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');
    }
});
1
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');
    }
    });
})();
1
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.

# Additional resources