Skip to main content
Version: v1

Recharge

Overview

Beam drives an 8% lift in subscription revenue by increasing conversion and lifetime. With Beam, when a customer chooses a nonprofit at checkout for a subscription, a portion of that purchase and each recurring purchase goes to the nonprofit selected.

Our Recharge subscription widget lives in your Recharge customer portal and enables users to visualize the impact they’re making over time as well as the community’s impact for that nonprofit. Users can change their preferred nonprofit at any time. Additionally users who have an active subscription can choose to opt into a Beam donation at any time.

This builds emotional buy in over time as they return to their customer portal, re-affirming their subscription purchase and decreases cancellation.

Customer Journey + Lifecycle

Opt into Beam on the first subscription purchase

  1. Customer makes a subscription purchase & chooses Beam in cart or on the post purchase thank you page

    Recharge In Cart

  2. Customer logs into their Recharge customer portal and can see their impact growing with each subsequent purchase, directly above the point of churn

    Recharge Customer Portal

  3. If the customer decides to select a new nonprofit, they can do so for their next subscription renewal

    Recharge Next Renewal

Opt into Beam after the first subscription purchase

  1. Customer makes a subscription purchase & does not use Beam

  2. Customer logs into their Recharge customer portal and sees the opportunity to select a nonprofit for their active subscription

  3. Customer chooses a nonprofit to make an impact with their upcoming subscriptions

    Recharge After First Purchase


Integration Process

  1. Reach out to your Beam CS Lead if you’re interested in the Beam | Recharge Integration
  2. Your CS Lead will follow up with mocks of the integration customized to your site for your team to react to
  3. We’ll schedule a 2-3 day integration window with the Beam team during which we will develop the widget in your Recharge dashboard, QA, and publish it to your users. We’ll work within your preferred dev process to get this up and running without any lift on your end.
Recharge Plan Requirements

Please note that Recharge requires a Recharge Pro plan, or Custom plan, in order to add custom content to your Recharge Customer Portal

Integration Implementation

The following code snippet should be placed in the Footer HTML/CSS/JS section of your Recharge Customer Portal, under Customize styles.

Replace the following in the example

  • beamApiKey - This is your Beam-provided API key
  • beamStoreId - This is your Beam-provided store id
beam-recharge-integration
<!-- BEAM START -->
<script
type="module"
async
crossorigin
src="https://sdk.beamimpact.com/web-sdk/{{ sdk_version }}/dist/components/subscription-management.esm.js"
></script>

<script type="text/html" data-recharge-slot="*.footer">
<div id="beam-subscription-management-section" style="display:none;">
<div id="beam-subscription-management-container" style="margin:16px auto 0; border:none; max-width:100%"></div>
</div>
</script>

<script type="module">
const beamSubscriptionManagementWidgetManager = {
wrapperContainerId: "beam-subscription-management-section",
targetContainerId: "beam-subscription-management-container",
activeSubscriptions: [],
activeCustomer: null,
beamApiKey: "{{ storefront_component_api_key }}",
beamStoreId: "{{ store_id }}",
isBeamLiveForEveryone: true,
session: null,

async getSession() {
const session = await recharge?.auth?.loginCustomerPortal()
.catch((error) => {
console.error("[Beam] Authentication failed:", error);
throw error;
});
return session;
},

async getSubscriptions() {
if (!this.session) {
this.session = await this.getSession();
}
const { subscriptions } = await recharge?.subscription?.listSubscriptions(this.session, {
sort_by: "id-asc",
status: "Active",
})
.catch((error) => {
console.error("[Beam] Fetching subscriptions failed:", error);
throw error;
});
return subscriptions ?? [];
},

async getCustomer() {
if (!this.session) {
this.session = await this.getSession();
}
const customer = await recharge.customer.getCustomer(this.session);
return customer;
},

shouldShowBeam(customerEmail) {
return (
this.isBeamLiveForEveryone || customerEmail?.includes("@beamimpact.com")
);
},

async updateSubscription(subscriptionId, nonprofitId, selectionMethod) {
const requestOptions = {
method: "POST",
headers: {
Authorization: `Api-Key ${this.beamApiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
remoteSubscriptionId: subscriptionId,
nonprofitId: nonprofitId,
selectionMethod: selectionMethod,
}),
};

try {
await fetch("https://api.beamimpact.com/api/v3/subscriptions/updateSubscriptionNonprofit", requestOptions);
} catch (error) {
console.error("[Beam] Error in updateSubscription:", error);
}
},

handleBeamNonprofitSelectEvent(event) {
const selectedNonprofitId = event.detail.selectedNonprofitId;
const selectionSource = event.detail.source;
if (selectionSource != "select-subscription-nonprofit") {
return;
}

await Promise.all(
this.activeSubscriptions.map((subscription) =>
this.updateSubscription(String(subscription?.id), selectedNonprofitId, "dashboard")
)
);
},

unmountWidget() {
window.removeEventListener("beamnonprofitselect", this.handleBeamNonprofitSelectEvent);
document.getElementById(this.wrapperContainerId).style.display = "none";
document.querySelector("beam-subscription-management")?.remove();
},

mountWidget(activeSubscription, customer) {
const subscriptionId = activeSubscription?.id;
const customerEmail = customer?.email;

if (subscriptionId && this.shouldShowBeam(customerEmail)) {
const beamSubscriptionManagementEl = document.createElement("beam-subscription-management");
beamSubscriptionManagementEl.setAttribute("apiKey", this.beamApiKey);
beamSubscriptionManagementEl.setAttribute("subscriptionId", subscriptionId);
beamSubscriptionManagementEl.setAttribute("storeId", this.beamStoreId);
beamSubscriptionManagementEl.setAttribute("email", customerEmail);
const targetElement = document.getElementById(this.targetContainerId);
targetElement?.appendChild(beamSubscriptionManagementEl);

document.getElementById(this.wrapperContainerId).style.display = "block";
}

this.handleBeamNonprofitSelectEvent = this.handleBeamNonprofitSelectEvent.bind(this);

window.addEventListener("beamnonprofitselect", this.handleBeamNonprofitSelectEvent);
},

async init() {
const isBeamAlreadyLoaded = document.querySelector("beam-subscription-management");
if (isBeamAlreadyLoaded) {
return;
}

try {
this.activeSubscriptions = await this.getSubscriptions();
this.activeCustomer = await this.getCustomer();
if (this.activeSubscriptions && this.activeSubscriptions[0]) {
this.mountWidget(this.activeSubscriptions[0], this.activeCustomer);
}
} catch (error) {
console.error("[Beam] Initialization failed:", error);
}
},
};

document.addEventListener("Recharge::slot::mounted", (event) => {
if (event.detail.name === "footer" && event.detail.pathname === "/subscriptions") {
beamSubscriptionManagementWidgetManager.init();
}
});

document.addEventListener("Recharge::slot::unmounted", (event) => {
if (event.detail.name === "footer" && event.detail.pathname === "/subscriptions") {
beamSubscriptionManagementWidgetManager.unmountWidget();
}
});
</script>
<!-- BEAM END -->

Recharge Flow Example

Click to see a screen recording of the user journey below.

https://drive.google.com/file/d/1nXmDCj6f6PVJj50WegF0q8UzEYVqek5y/view?usp=sharing