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
-
Customer makes a subscription purchase & chooses Beam in cart or on the post purchase thank you page
-
Customer logs into their Recharge customer portal and can see their impact growing with each subsequent purchase, directly above the point of churn
-
If the customer decides to select a new nonprofit, they can do so for their next subscription renewal
Opt into Beam after the first subscription purchase
-
Customer makes a subscription purchase & does not use Beam
-
Customer logs into their Recharge customer portal and sees the opportunity to select a nonprofit for their active subscription
-
Customer chooses a nonprofit to make an impact with their upcoming subscriptions
![Screen Shot 2023-12-28 at 5.22.36 PM.png](Screen_Shot_2023-12-28_at_5.22.36_PM 1.png)
Integration Process​
- Reach out to your Beam CS Lead if you’re interested in the Beam | Recharge Integration
- Your CS Lead will follow up with mocks of the integration customized to your site for your team to react to
- 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.
- We have worked with a wide variety of setups and will customize the integration code for your specific Recharge theme, platform, and plan (e.g. Affinity, Novum, Prima, etc.)
Integration Theme Implementation​
-
Novum theme
- Beam will add custom Liquid scripts into the Recharge theme. This is typically done in
Themes/subscriptions.html
The Beam custom liquid script will be added to this beam container:
<!-- BEAM START -->
{% if active_subscriptions | length %}
<div id="beam-widget-recharge-container">
<h3 style="line-height: 38px; margin-top: 25px;">Make An Impact With Your {{ Partner Name }} Subscription(s)</h3>
<div class="rc_subscription_card_element_wrapper" id="beam-widget-recharge" style=" padding:20px 30px 30px;border-radius: 10px;">
<beam-partner-logos id="beamPartnerLogos" partnername="{{ Partner Name }}" partnerlogourl="https://sdk.beamimpact.com/chains/img/{{ Partner Logo }}"></beam-partner-logos>
</div>
</div>
{% endif %}
<!-- BEAM END -->To determine where to place this code snippet, look for a loop in Liquid that would indicate it’s rendering the list of subscriptions. For instance, you may see something like this:
{% if active_subscriptions | length %}
<h2>Active Subscriptions</h2>
<div class="container-subscription-wrapper">
{% for address_id, subscriptions in active_subscriptions %}
<section class="subscriptions-item">
</section>
{% endfor %}
</div>
{% endif %}In this example, we can add the Beam snippet either inside or outside of the
container-subscription-wrapper
depending on how much space on the page we want the widget to take up. This may require testing a few placements to see what works the best.{% if active_subscriptions | length %}
<h2>Active Subscriptions</h2>
<div class="container-subscription-wrapper">
{% for address_id, subscriptions in active_subscriptions %}
<section class="subscriptions-item">
</section>
{% endfor %}
</div>
<!-- BEAM START -->
<div id="beam-widget-recharge-container">
... Snippet Code Above ...
</div>
<!-- BEAM END -->
{% endif %} - Beam will add custom Liquid scripts into the Recharge theme. This is typically done in
-
Affinity theme, Recharge PRO Plan
- To integrate the Beam subscription management widget, start by adding the following script to the header section of your theme:
<script
type="module"
async
crossorigin
src="https://sdk.beamimpact.com/web-sdk/{{ sdk_version }}/dist/components/subscription-management.esm.js"
></script>Next, you need to add the widget script to the subscriptions.html page of your theme:
<script type="module" async>
import {
events
} from "https://production-beam-widgets.beamimpact.com/web-sdk/{{ sdk_version }}/dist/integrations/utils.esm.js";
let beamApiKey = "{{ api storefront_component_api_key }}";
const email = '{{customer.email}}';
// Convert subscriptions data to a JavaScript array
let subscriptionArray = [];
{% for subscription in subscriptions %}
subscriptionArray.push({
id: "{{ subscription.id }}",
status: "{{ subscription.status }}",
email: "{{ customer.email }}",
// Add other necessary properties here
});
{% endfor %}
let activeSubscriptions = subscriptionArray.filter(subscription => subscription.status === 'ACTIVE');
let firstActiveSubscription = activeSubscriptions[0];
// Create or update subscriptions for all subscriptions
activeSubscriptions.forEach(subscription => {
postFindOrCreateSubscription(String(subscription.id), subscription.email);
});
async function postFindOrCreateSubscription(subscriptionId, email) {
const requestOptions = {
method: "POST",
headers: {
"Authorization": `Api-Key ${beamApiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"remoteSubscriptionId": subscriptionId,
"email": email,
})
};
try {
await fetch("https://production-central-backend-ne.beamimpact.com/api/v3/subscriptions/findOrCreateSubscription", requestOptions);
} catch (error) {
console.error("Error in postFindOrCreateSubscription:", error);
}
}
async function updateSubscription(subscriptionId, nonprofitId, selectionMethod) {
const requestOptions = {
method: 'POST',
headers: {
"Authorization": `Api-Key ${beamApiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"remoteSubscriptionId": subscriptionId,
"nonprofitId": nonprofitId,
"selectionMethod": selectionMethod,
}),
};
try {
await fetch("https://production-central-backend-ne.beamimpact.com/api/v3/subscriptions/updateSubscriptionNonprofit", requestOptions);
} catch (error) {
console.error("Error in updateSubscription:", error);
}
}
window.addEventListener("beamnonprofitselect", async (event) => {
const selectedNonprofitId = event.detail.selectedNonprofitId;
await Promise.all(
activeSubscriptions.map(subscription =>
updateSubscription(String(subscription.id), selectedNonprofitId, 'dashboard')
)
);
});
</script>Finally, insert the Beam subscription management widget in the desired location on the subscriptions page:
{% assign first_valid_subscription_found = false %}
{% for subscription in subscriptions | sort(attribute="id", reverse=True) | sort(attribute="status") %}
{% if first_valid_subscription_found == false and subscription.status == 'ACTIVE' %}
<div class="beam-subscription-management-container">
<p class="subscriptions_title">Make an impact with your next {{ Brand Name }} Subscription</p>
<beam-subscription-management apiKey="{{ api storefront_component_api_key }}"
email="{{ customer.email }}" subscriptionId="{{ subscription.id }}" storeId="{{ store_id }}">
</beam-subscription-management>
</div>
{% assign first_valid_subscription_found = true %}
{% endif %}
{% endfor %} -
Affinity theme, Non-Pro Plan
- If you do not subscribe to Recharge’s Pro Plan, the “slot”-based custom content functionality is not supported. However, Beam will can mimic this functionality with additional scripts modeled after the slot-functionality
<script
type="module"
async
crossorigin
src="https://sdk.beamimpact.com/web-sdk/{{ sdk_version }}/dist/components/subscription-management.esm.js"
></script>
<div id="beam-widget-container"></div>
<script type="module" async>
import {
events
} from "https://production-beam-widgets.beamimpact.com/web-sdk/{{ sdk_version }}/dist/integrations/utils.esm.js";
let beamApiKey = "{{ storefront_component_api_key }}";
let subscriptionArray = window.ReCharge.subscriptions;
let activeSubscriptions = subscriptionArray.filter(subscription => subscription.status === 'ACTIVE');
let firstActiveSubscription = activeSubscriptions[0];
// Create or update subscriptions for all subscriptions
activeSubscriptions.forEach(subscription => {
postFindOrCreateSubscription(String(subscription.id), subscription.email);
});
if (firstActiveSubscription) {
const widgetContainer = document.getElementById('beam-widget-container');
const beamWidget = document.createElement('beam-subscription-management');
beamWidget.setAttribute('apiKey', beamApiKey);
beamWidget.setAttribute('email', firstActiveSubscription.email);
beamWidget.setAttribute('subscriptionId', String(firstActiveSubscription.id));
widgetContainer.appendChild(beamWidget);
}
async function postFindOrCreateSubscription(subscriptionId, email) {
const requestOptions = {
method: "POST",
headers: {
"Authorization": `Api-Key ${beamApiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"remoteSubscriptionId": subscriptionId,
"email": email,
})
};
try {
await fetch("https://production-central-backend-ne.beamimpact.com/api/v3/subscriptions/findOrCreateSubscription", requestOptions);
} catch (error) {
console.error("Error in postFindOrCreateSubscription:", error);
}
}
async function updateSubscription(subscriptionId, nonprofitId, selectionMethod) {
const requestOptions = {
method: 'POST',
headers: {
"Authorization": `Api-Key ${beamApiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"remoteSubscriptionId": subscriptionId,
"nonprofitId": nonprofitId,
"selectionMethod": selectionMethod,
}),
};
try {
await fetch("https://production-central-backend-ne.beamimpact.com/api/v3/subscriptions/updateSubscriptionNonprofit", requestOptions);
} catch (error) {
console.error("Error in updateSubscription:", error);
}
}
window.addEventListener("beamnonprofitselect", async (event) => {
const selectedNonprofitId = event.detail.selectedNonprofitId;
await Promise.all(
activeSubscriptions.map(subscription =>
updateSubscription(String(subscription.id), selectedNonprofitId, 'dashboard')
)
);
});
</script>
Recharge Flow Example​
Click to see a screen recording of the user journey below.
https://drive.google.com/file/d/1nXmDCj6f6PVJj50WegF0q8UzEYVqek5y/view?usp=sharing