More Tutorials

Implement an in-product usage-based upsell with Chargebee Growth's Offers APIs

Growth
Personalized Offers

Overview

Customers approaching usage or feature entitlement limits often have high purchase intent. Showing a timely upgrade offer at these moments helps convert them. Chargebee Growth's Offers APIs helps you do this.

This tutorial explains how to implement usage-based upsell offers where your application provides real-time usage context (in this case, storage consumption) and requests a personalized offer from Chargebee Growth. If the subscriber qualifies—for example, when their storage usage is 80% or more—Chargebee returns an upgrade offer that you render in your UI.

When the subscriber accepts the offer, Chargebee applies the configured subscription change (in this case, adding an addon) directly to the subscription.

Architecture overview

The flow splits responsibilities between your backend and Chargebee as follows.

Your application:

  • Computes and tracks usage data
  • Requests offers from Chargebee with customer and usage context
  • Renders the upgrade prompt
  • Notifies offer engagement events to Chargebee
  • Creates an offer fulfillment on acceptance

Chargebee:

  • Evaluates offer eligibility
  • Selects the appropriate offer
  • Records offer engagement events
  • Fulfills the offer by applying the subscription change
Usage-based upsell architecture overview.
Usage-based upsell architecture overview.

A typical flow:

  1. When a user logs in or when usage is updated, fetch a personalized offer from Chargebee, providing the customer and subscription identifiers and the usage field.
  2. If an offer is returned, show an in-product upgrade prompt using the offer content.
  3. For engagement tracking, notify Chargebee when the offer is viewed or dismissed. Stop here if the user dismisses the offer.
  4. When the user accepts the offer, create an offer fulfillment request at Chargebee.
  5. Chargebee applies the addon or upgrade to the subscription.

Before you start

For this tutorial to work, you need the following setup:

Set up your development environment

  1. Obtain a full-access API key from Chargebee Billing.
  2. Install the Chargebee client SDK for your server-side stack.
  3. Have product/feature usage tracking in your system (for example, storage consumption).

Set up Chargebee Billing and Growth

Users with access to Chargebee Growth must complete these steps.

  1. Have Chargebee Growth enabled and connected to your Chargebee Billing site.
  2. Ensure that the required configuration has been completed in Chargebee so the APIs return offers at runtime.

Implementation steps

Follow these steps to implement the usage-based upsell flow using Chargebee Growth's Offers APIs.

Usage-based upsell sequence diagram.
Usage-based upsell sequence diagram.

Step 1: Track usage data

In your application, track product/feature usage (for example, storage consumption). The usage value will be passed to Chargebee in the next step and used to evaluate offer eligibility.

Step 2: Fetch the personalized offer

At customer login or when usage is updated, compute the current usage value and pass it in the custom object to the Personalized Offers API. Call the API with the customer and subscription identifiers plus the usage data.

curl  https://YOUR_CHARGEBEE_SUBDOMAIN.grow.chargebee.com/api/v2/personalized_offers \
     -u YOUR_CHARGEBEE_API_KEY:\
     --header 'Content-Type: application/json;charset=UTF-8' \
     --data '{
     "subscription_id": "sub_123",
     "customer_id": "cus_9AbCDe",
     "custom": { "storage_used_percent": 82 }
}'

If the subscriber matches one or more configured plays in Growth, Chargebee returns the offer corresponding to the play of highest priority. Example response:

{
  "personalized_offers": [
    {
      "id": "vdyjO2qlLD_715653d4",
      "offer_id": "vdyjO2qlLD",
      "content": {
        "title": "<div class=\"slate-p\">Running out of storage?</div>",
        "description": "<div class=\"slate-p\">You've used 80% of your storage. Add 100 GB instantly and keep working without interruption.</div>"
      },
      "options": [
        {
          "id": "6cd5280e",
          "label": "Add 100 GB storage",
          "processing_type": "billing_update"
        }
      ]
    }
  ],
  "expires_at": 1732790400
}

The response includes a processing_type of billing_update, which means the offer is configured for fulfillment via Chargebee Billing.

When no offer is returned

If the response has an empty personalized_offers list, do not show an upgrade prompt. An empty response means the user isn't eligible (for example, the request parameters don't match any active plays, or the offer was already accepted or dismissed).

Step 3: Render the in-product upgrade prompt

If a personalized offer is returned, use the offer content to show an upgrade prompt inside your application. Depending on how prominent you want the message, you can use one of these UI patterns:

  • A banner at the top of the dashboard
  • A modal
  • An inline callout near the usage indicators

Use the offer content as follows to render the upgrade prompt:

This ensures that the offer is displayed to the user dynamically based on the current configuration in Chargebee Growth.

Usage-based upsell in-product prompt.
Usage-based upsell in-product prompt.

Step 4: Track offer interactions

To measure engagement in Growth, record the following offer events:

  • Record a viewed event each time the offer is displayed.
  • Record a dismissed event when the user closes or ignores the offer.

Send these events from your backend after the corresponding UI action using the Offer Events API with the personalized_offer_id from the Personalized Offers response:

curl  https://YOUR_CHARGEBEE_SUBDOMAIN.grow.chargebee.com/api/v2/offer_events \
     -u YOUR_CHARGEBEE_API_KEY:\
     --header 'Content-Type: application/json;charset=UTF-8' \
     --data '{
     "type": "viewed",
     "personalized_offer_id": "vdyjO2qlLD_715653d4"
}'

These events are for reporting; the dismissed event also affects offer cooldown. They do not affect fulfillment behavior.

Step 5: Create offer fulfillment on CTA click

When the subscriber selects the acceptance CTA, call your backend to create an offer fulfillment. Use the Offer Fulfillments API with the personalized_offer_id and option_id from the offer returned in Step 2.

curl  https://YOUR_CHARGEBEE_SUBDOMAIN.grow.chargebee.com/api/v2/offer_fulfillments \
     -u YOUR_CHARGEBEE_API_KEY:\
     --header 'Content-Type: application/json;charset=UTF-8' \
     --data '{
     "personalized_offer_id": "vdyjO2qlLD_715653d4",
     "option_id": "6cd5280e"
}'

The API returns a response like the following:

{
  "offer_fulfillment": {
    "id": "507c340b",
    "personalized_offer_id": "vdyjO2qlLD_715653d4",
    "option_id": "6cd5280e",
    "processing_type": "billing_update",
    "status": "in_progress"
  }
}

At this point, Chargebee applies the addon to the subscription without any intervention required on your side or the subscriber's side.

(Optional) Step 6: Poll fulfillment status

You can optionally poll the fulfillment status for asynchronous tasks such as syncing conversion events to your analytics system. Use the Retrieve an Offer Fulfillment API to do this.

curl  https://YOUR_CHARGEBEE_SUBDOMAIN.grow.chargebee.com/api/v2/offer_fulfillments/507c340b \
     -u YOUR_CHARGEBEE_API_KEY:

As seen in the response below, when the billing update has completed successfully and the addon has been applied, offer_fulfillment.status becomes completed.

{
  "offer_fulfillment": {
    "id": "507c340b",
    "personalized_offer_id": "vdyjO2qlLD_715653d4",
    "option_id": "6cd5280e",
    "processing_type": "billing_update",
    "status": "completed"
  }
}

Error handling

Fulfillment errors

When you poll the fulfillment status as described in Step 6, use these guidelines:

  • If offer_fulfillment.status is in_progress, wait before polling again.
  • If offer_fulfillment.status is failed, check the offer_fulfillment.error.code to determine the reason.

Multiple CTA clicks by the same user

As a best practice, disable the offer acceptance CTA button in the UI immediately after it's clicked. If there's a duplicate click and you request a new offer fulfillment, the API returns an error because multiple fulfillments aren't allowed for the same personalized_offer_id.

Handle the error as follows:

  1. Fetch the offer_fulfillment.id saved earlier in Step 5.
  2. Retrieve the fulfillment status using the offer_fulfillment.id.
  3. Check for fulfillment errors as described above.

Same offer accepted by different users

Calling the Offer Fulfillments API succeeds only once for the same base offer_id when the offer originates from the same Play.

If you're a B2B business with multiple users per subscription, the same offer from the same Play can be seen by different signed-in users at the same time. In this case, after the first user accepts the offer, the Offer Fulfillments API returns the following error for subsequent users:

Fulfillment is already in progress/completed. Retrieve the fulfillment to know the latest status.

Show a message to the user such as, "This offer has already been accepted."

Summary

In this tutorial, you learned how to:

  • Fetch a personalized usage-based offer at login or when usage is updated.
  • Use the offer content to render an in-product upgrade prompt.
  • Record offer events (viewed and dismissed) for reporting.
  • Create an offer fulfillment when the subscriber accepts, so Chargebee applies the addon to the subscription.
  • Optionally retrieve fulfillment status for analytics.
  • Handle fulfillment errors, multiple CTA clicks by the same user, and the same offer accepted by different users.

Appendix

Details

Required setup in Chargebee

This section describes the setup required in both Chargebee Billing and Chargebee Growth to enable usage-based upsell offers to be returned by Chargebee APIs. The steps below configure an expansion offer that targets subscribers whose usage meets a threshold (for example, 80% storage used), shows copy such as "Running out of storage?", and uses Chargebee Billing for fulfillment.

Administrators or growth marketers with access to Chargebee Growth and Billing typically handle this configuration.

1. Create an addon in Billing

Create an addon in Chargebee Billing for the addon or upgrade you want to offer.

2. Create the offer in Growth

Define the expansion offer and how it is applied when accepted.

  1. In Growth, navigate to Offers > In-app.
  2. Create a new offer with the following configuration:
    1. Offer objective: Expansion.
    2. Offer category: Subscription change.
    3. Under Button settings:
      1. Set the Button processing to Billing integration.
      2. Set the Button action > Choose button offer subcategory to Addon.
      3. In the New addon dropdown, select the addon you created in the previous step.
      4. In the How would you like to apply the subscription change? toggle, select one of the following:
      • Immediate: The addon is applied to the subscription immediately.
      • End of term: The addon is applied to the subscription on the next billing date of the subscription.
      1. In the right pane, edit the offer copy (for example, "Running out of storage?") and the button text (for example, "Add 100 GB storage").
  3. Select Done and then Publish now to save the offer.

3. Create and map a custom field for "storage used percent" in Growth

  1. In Growth, navigate to Settings > Setup.
  2. Under Field mappings, select Map fields.
  3. Scroll down to Field Mapping and select the button View & map passed data. A modal appears.
  4. On the modal, under Custom Chargebee Retention fields, select the +add a new field button and enter the following details:
    1. Field Label: "Storage used percent".
    2. Data Type: "Integer".
    3. JS Name: "custom.storage_used_percent".
  5. Select the Save changes button. The modal closes.
  6. Scroll down and fill in the form above the Add custom field button:
    1. Name: "Storage used percent".
    2. Type: "Integer".
    3. Source Field dropdown: Under API & Chargebee.js, select Storage used percent.
  7. Select the Add custom field button.
  8. Select the Save changes button.

4. Create an audience in Growth

  1. In Growth, navigate to People > Audiences.
  2. Create a new audience with the following rule:
    1. Property: "Storage used percent" (or the label for your mapped field).
    2. Operator: "Greater than or equal to".
    3. Value: "80".
  3. Select the Done button to save the audience.

Only requests that match this condition are evaluated when you fetch personalized offers.

5. Create a play in Growth

  1. In Growth, navigate to Plays > Expansion.
  2. Create a new play.
  3. Select the in-app offer play type.
  4. Select the audience created in the previous step.
  5. For Trigger, select Any page load (or the trigger that fits your flow).
  6. For Action, select Show offer.
  7. Select the offer created in the previous step.
  8. Set the play priority.
  9. Select the Publish Play button.
Was this tutorial helpful ?
Need more help?

We're always happy to help you with any questions you might have! Click here to reach out to us.