Skip to main content
Version: v1

Post Purchase

Examples

Adina Eden

SIJO Home

Base widget

Replace

  • isBeamLiveForEveryone - true | false; true means that the widget should be shown (”un-gated”), false means that it is going through internal testing.

  • hidePostPurchaseWidget - true | false; true means the Beam post purchase widget should be hidden, but will still register transactions, false means that the Beam post purchase widget will show as normal.

  • useContentBox - true | false, true means add a content box in the post purchase thank you page. false means don’t add a new content box.

  • domain - Set this to your top level domain of the website (ie: if your store is hosted on “store.mystore.com”, this value should be set to “mystore.com”)

  • beam_language - Beam supports changing the displayed language based on a lang parameter passed into the widgets. If your site supports multiple languages, this Liquid variable value should be updated based on any existing language detection method available in the theme. The supported values for this property can be found in the Beam Supported Languages documentation.

  • beamContainerSelector - the parent element that should be targeted to add the Beam widget to. The Beam widget will be added as the last child element in this container.

{% assign beam_language = "en" %}
{% if checkout.currency != shop.currency %}
{{ "/services/javascripts/currencies.js" | script_tag }}
{% endif %}
{% assign beam_sdk_version = "v1.40.2" %}

<script type="module">
import { showBeamOrderPageWidgets } from "https://sdk.beamimpact.com/web-sdk/{{ beam_sdk_version }}/dist/integrations/shopify.js";
import { init } from "https://sdk.beamimpact.com/web-sdk/{{ settings.beam_sdk_version }}/dist/integrations/beam.js";
import {
waitForElement,
getCookieValue,
setCookieValue,
events,
createScopedLocalStorage
} from "https://sdk.beamimpact.com/web-sdk/{{ beam_sdk_version }}/dist/integrations/utils.js";
// Post Purchase widget settings
const isBeamLiveForEveryone = false;
const hidePostPurchaseWidget = false;
const useContentBox = true;
let beamContainerSelector = ".step__sections";

// Note: cannot use variables from theme settings in post-purchase
const beam = await init({
apiKey: "{{ SDK API Key }}",
chainId: {{ Chain Id }},
storeId: {{ Store Id }},
domain: "mystore.com",
baseUrl: "https://api.beamimpact.com",
})

{% assign beamOrder = checkout %}
{% assign beamUseOrder = false %}
{% if order.line_items.size > 0 %}
{% assign beamOrder = order %}
{% assign beamUseOrder = true %}
{% endif %}

// Get order details from Shopify
const orderId = {% if beamUseOrder %} "{{ beamOrder.id }}" {% else %} "{{ beamOrder.order_id }}" {% endif %};
const cartTotal = parseFloat("{{ beamOrder.line_items_subtotal_price | money_without_currency }}");
const customerEmail = "{{ beamOrder.customer.email }}" || "{{ beamOrder.email }}";
const postalCode = "{{ beamOrder.shipping_address.zip }}" || "{{ beamOrder.billing_address.zip }}";
const countryCode = "{{ beamOrder.shipping_address.country_code }}" || "{{ beamOrder.billing_address.country_code }}";
const currencyCode = "{{ beamOrder.currency }}" || Shopify?.currency?.active;
const shopCurrency = "{{ shop.currency }}" || "USD";

const standardizedOrderAmount = convertCurrencyAmountToCurrencyCode(cartTotal, currencyCode, shopCurrency);

const items = [
{% for line_item in beamOrder.line_items %}
{
localAmount: convertCurrencyAmountToCurrencyCode(parseFloat("{{ line_item.final_line_price | money_without_currency }}"), currencyCode, shopCurrency)?.amount,
remoteProductIdentifier: "{{ line_item.sku }}",
},
{% endfor %}
];

// All discount codes in the order
const orderDiscounts = removeDuplicateArrayItemsByProperty([
{% for discount_application in beamOrder.discount_applications %}
{
code: "{{ discount_application.title }}",
applicable: true
},
{% endfor %}
], "code");

const cart = {
schema: { source: "generic" },
content: { items, discounts: orderDiscounts }
};

let orderDiscountCodes = orderDiscounts.map((discount) => discount.code)

const isBeamEmail = customerEmail?.includes("@beamimpact.com");

// UTILS -----------------------------------------------------------------
function shouldShowBeam() {
return (isBeamLiveForEveryone
&& !hidePostPurchaseWidget)
|| isBeamEmail;
}

function convertCurrencyAmountToCurrencyCode(amount, fromCode, toCode) {
if (fromCode === toCode) {
return {
amount: parseFloat(amount),
currencyCode: fromCode
}
}

try {
let convertedAmount = parseFloat(Currency.convert(amount, fromCode, toCode)?.toFixed(2));
return !isNaN(parseFloat(convertedAmount))
? { amount: convertedAmount, currencyCode: toCode }
: { amount: parseFloat(amount), currencyCode: fromCode };
} catch (error) {
console.error(`Beam - error converting currency ${fromCode} to ${toCode}`, error);
return { amount: parseFloat(amount), currencyCode: fromCode }
}
}

function getRecurringLineItems() {
let recurringLineItems = [];
{% for line_item in beamOrder.line_items %}
{% if line_item.selling_plan_allocation.selling_plan.name %}
recurringLineItems.push({
final_line_price: parseFloat("{{ line_item.final_line_price | money_without_currency }}"),
final_price: parseFloat("{{ line_item.final_price | money_without_currency }}"),
sku: "{{ line_item.sku }}",
quantity: {{ line_item.quantity }},
selling_plan: "{{ line_item.selling_plan_allocation.selling_plan.name }}",
isRecurring: ("{{ line_item.selling_plan_allocation.selling_plan.recurring_deliveries }}" === "true"),
});
{% endif %}
{% endfor %}
return recurringLineItems;
}

function removeDuplicateArrayItemsByProperty(data, propertyName) {
if (!data) {
return [];
}
return data.reduce((accumulator, current) => {
if (!accumulator.find((item) => item[propertyName] === current[propertyName])) {
accumulator.push(current);
}
return accumulator;
}, []);
}
// END UTILS -------------------------------------------------------------

if (!shouldShowBeam()) {
document.head.insertAdjacentHTML(
"beforeend",
`<style>[data-beam-widget="post-purchase"]{display:none;}beam-post-purchase{display:none;}</style>`
);
}

await waitForElement(".section");

if (useContentBox && shouldShowBeam()) {
window.Shopify.Checkout.OrderStatus.addContentBox(`<div id="beam-post-purchase-container"></div>`);
beamContainerSelector = "#beam-post-purchase-container";
await waitForElement(beamContainerSelector);
document.querySelector(beamContainerSelector)?.closest(".content-box")?.setAttribute("data-beam-widget", "post-purchase");
}

await showBeamOrderPageWidgets({
apiKey: beam.apiKey,
chainId: beam.chainId,
storeId: beam.storeId,
domain: beam.domain,
orderId,
email: customerEmail,
cartTotal: parseFloat(standardizedOrderAmount?.amount || cartTotal),
cart,
currencyCode: standardizedOrderAmount?.currencyCode || currencyCode,
countryCode,
postalCode,
discountCodes: orderDiscountCodes,
parentSelector: beamContainerSelector,
lang: "{{ beam_language }}",
baseUrl: beam.baseUrl,
debug: false,
});
</script>

Base widget (with Statsig AB Test)

In addition to the code above, include the StatsigPlugin provided with the SDK, and include in your list of Beam plugins.

Replace

  • stagsigApiKey - string; This is the Statsig API Key provided to you by the Beam team.
import { StatsigPlugin } from "https://sdk.beamimpact.com/web-sdk/{{ beam_sdk_version }}/dist/integrations/statsig.js";

const beam = await init({
apiKey: "{{ SDK API Key }}",
chainId: {{ Chain Id }},
storeId: {{ Store Id }},
domain: "mystore.com",
plugins: [
new StatsigPlugin({ statsigApiKey: 'STATSIG_API_KEY' })
],
})

Where to add this code

In Shopify, add the Beam Post Purchase code to your Shopify checkout’s additional scripts section. To find this, open your Shopify administration panel, then select “Settings”. The option for “Checkout” will be in the left-hand navigation.

Screenshot 2023-08-22 at 5.40.07 PM.png

In the Checkout settings, scroll down to the Order status page configuration to find an input box for Additional scripts. This is where you will paste the Beam Post Purchase code that you built earlier. Once you’ve pasted in your code, click the “Save” button at the bottom of the page.

Screenshot 2023-08-22 at 5.46.13 PM.png