Overview
In this tutorial, you'll learn how to display a Chargebee pricing table for existing customers in your application using Chargebee Growth Plays. This approach lets you create pricing page sessions securely on the server and render them in a dedicated container using Chargebee.js.
This tutorial is intended for developers building a web app (e.g. JavaScript, React, Vue, or Angular) with a backend that can call Chargebee's API.
By the end of this tutorial, you'll be able to:
- Include and initialize Chargebee.js on the frontend with the correct site configuration.
- Add a container
<div>with the parameters required for API-driven pricing tables. - Call the Pricing Page Session API from your backend for existing subscriptions.
- Request a pricing table session from the frontend and render it using Chargebee.js
open().
Background
- Chargebee.js is a client-side library that lets you embed Chargebee components (such as pricing tables and Checkout) in your frontend. You load the script, initialize it with your site, and use methods like
pricingTable.open()to display a pricing table. - Pricing Page Sessions are created via the Chargebee REST API on the server for existing subscriptions (plan changes, upgrades, downgrades). The API returns a pricing table object based on Play configurations in Chargebee Growth. Chargebee.js uses this object to render the table.
- By keeping session creation on the backend, you never expose your Chargebee API key to the browser; the frontend only receives the session payload and passes it to Chargebee.js.
Before you start
Before you start the tutorial, you should:
- Have a Chargebee Billing account and a Chargebee Growth account.
- Have one or more pricing tables created in Chargebee Growth and associated them with one or more Plays in Chargebee Growth.
- Obtain a full-access API key from your Chargebee Billing test site (required for the Pricing Page Session API).
- Have a running frontend and backend so you can add the script, a backend endpoint, and a frontend call to fetch the session and open the pricing table.
Step 1: Integrate the Chargebee REST API (Backend)
Use the Chargebee REST API from your backend to create pricing page sessions. Chargebee provides client libraries (e.g. PHP, Ruby, Python, Java, .NET, Node, Go) that wrap the HTTP API; use the one that matches your stack.
Configure your client with your Chargebee Billing site and full-access API key. Never expose the API key to the frontend.
Then implement a POST endpoint that:
- Accepts a request from the frontend with customer details, such as
subscription_id. - Calls the Create pricing page for existing subscription API that returns a pricing table object based on Play configurations in Chargebee Growth.
- Returns the pricing page session object to the frontend as JSON.
// Example: Express route that creates a pricing page session for an existing subscription
app.post("/api/create_pricing_table", async (req, res) => {
const chargebee = require("chargebee");
chargebee.configure({ site: "YOUR_SITE", api_key: "YOUR_API_KEY" });
const subscriptionId = req.body.subscription_id; // Required: existing subscription ID
if (!subscriptionId) {
return res.status(400).json({ error: "subscription_id is required" });
}
try {
const result = await chargebee.pricing_page_session
.create_for_existing_subscription({
subscription: { id: subscriptionId },
})
.request();
res.json(result.pricing_page_session);
} catch (error) {
console.error(error);
res.status(500).json({ error: error.message });
}
});
import chargebee
chargebee.configure("your_site_domain", "your_api_key")
@app.route('/api/create_pricing_table', methods=['POST'])
def create_pricing_page_session():
data = request.get_json() or {}
subscription_id = data.get("subscription_id") # Required
if not subscription_id:
return jsonify({"error": "subscription_id is required"}), 400
result = chargebee.PricingPageSession.create_for_existing_subscription({
"subscription": {"id": subscription_id},
})
pricing_page_session = result._response['pricing_page_session']
return jsonify(pricing_page_session)
ChargeBee.configure(site: "your_site_domain", api_key: "your_api_key")
post "/api/create_pricing_table" do
subscription_id = params[:subscription_id] # Required
return { error: "subscription_id is required" }.to_json, 400 unless subscription_id
result = ChargeBee::PricingPageSession.create_for_existing_subscription(
subscription: { id: subscription_id }
)
content_type :json
result.pricing_page_session.to_json
end
Environment.configure("your_site_domain", "your_api_key");
// In your controller/servlet (e.g. POST /api/create_pricing_table):
String subscriptionId = request.getParameter("subscription_id"); // Required
if (subscriptionId == null || subscriptionId.isEmpty()) {
response.setStatus(400);
return;
}
Result result = PricingPageSession.createForExistingSubscription()
.subscriptionId(subscriptionId)
.request(new Environment("your_site_domain", "your_api_key"));
PricingPageSession pricingPageSession = result.pricingPageSession();
response.setContentType("application/json");
response.getWriter().print(pricingPageSession.jsonObj);
ChargeBee_Environment::configure("your_site_domain", "your_api_key");
// Route: POST create_pricing_table
public function createPricingPageSession(Request $request) {
$subscriptionId = $request->input("subscription_id"); // Required
if (!$subscriptionId) {
return response()->json(["error" => "subscription_id is required"], 400);
}
$result = ChargeBee_PricingPageSession::createForExistingSubscription([
"subscription" => ["id" => $subscriptionId],
]);
$session = $result->pricingPageSession();
return response()->json($session->getValues(), 200);
}
Ensure your backend returns the pricing page session object and that the response is JSON. The frontend will send this payload to Chargebee.js in the next step.
Step 2: Request a pricing table and open it (Frontend)
From the frontend, request a pricing table session from your backend and pass the result to Chargebee.js so it can render the table inside the container <div>.
1. Load the Chargebee.js script – Load the Chargebee.js script and initialize it with your Chargebee Billing site.
2. Call your backend – When the user should see the pricing table (e.g. on page load or when clicking “View plans”), send a POST request to your endpoint (e.g. /api/create_pricing_table) with subscription_id in the request body.
3. Return a Promise that resolves to the session – The pricingTable.open() method expects a pricingTable option that is a function returning a Promise that resolves to the pricing page session object. Typically this function calls your backend and returns response.json().
4. Call pricingTable.open() – Get the pricing table component from your Chargebee instance, then call open() with that function. Chargebee.js will use the resolved session to render the table in the div with id="chargebee-pricing-table".
<script src="https://js.chargebee.com/v2/chargebee.js" onload="onLoad()"></script>
<script>
async function onLoad() {
const chargebee = Chargebee.init({
site: "YOUR-CHARGEBEE-BILLING-SUBDOMAIN",
})
const pricingTable = await chargebee.pricingTable();
pricingTable.open({
pricingTable: function() {
return fetch('https://YOUR_DOMAIN/api/create_pricing_table', {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
subscription_id: "SUBSCRIPTION_ID", // Required
}),
}).then(response => response.json());
},
});
</script>
<div
id="chargebee-pricing-table"
data-pricing-table-integration-type="api"
></div>
import React, { useEffect } from 'react';
import Chargebee from 'chargebee';
function PricingPage() {
useEffect(() => {
const cbInstance = Chargebee.init({
site: "YOUR-CHARGEBEE-BILLING-SUBDOMAIN",
})
const pricingTable = await cbInstance.pricingTable();
pricingTable.open({
pricingTable: function() {
return fetch('https://YOUR_DOMAIN/api/create_pricing_table', {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
subscription_id: "SUBSCRIPTION_ID", // Required
}),
}).then(response => response.json()),
},
});
}, []);
return (
<div className="App">
<div
id="chargebee-pricing-table"
data-pricing-table-integration-type="api"
></div>
</div>
);
}
export default PricingPage;
<script setup lang="tsx">
import Chargebee from 'chargebee';
import { onMounted } from 'vue';
onMounted(() => {
const cbInstance = Chargebee.init({
site: "YOUR-CHARGEBEE-BILLING-SUBDOMAIN",
})
const pricingTable = await cbInstance.pricingTable();
pricingTable.open({
pricingTable: function() {
return fetch('https://YOUR_DOMAIN/api/create_pricing_table', {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
subscription_id: "SUBSCRIPTION_ID", // Required
}),
}).then(response => response.json()),
},
});
});
</script>
<template>
<div
id="chargebee-pricing-table"
data-pricing-table-integration-type="api"
></div>
</template>
import { Component } from '@angular/core';
import Chargebee from 'chargebee';
@Component({
selector: 'pricing-page-component',
templateUrl: './pricing-page.component.html',
styleUrls: ['./pricing-page.component.css'],
})
export class PricingPageComponent {
title = 'pricing-page-component';
params: { [index: string]: any } = {};
ngOnInit() {
const cbInstance = Chargebee.init({
site: "YOUR-CHARGEBEE-BILLING-SUBDOMAIN",
})
const pricingTable = await cbInstance.pricingTable();
pricingTable.open({
pricingTable: function() {
return fetch('https://YOUR_DOMAIN/api/create_pricing_table', {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
subscription_id: "SUBSCRIPTION_ID", // Required
}),
}).then(response => response.json()),
},
});
}
}
After this step, the pricing table should appear inside the <div> you configured.
We're always happy to help you with any questions you might have! Click here to reach out to us.