Checkout Success Widget
The Mulberry BigCommerce application offers a Post Checkout Success component which allows users to sign up for a Mulberry Unlimited subscription on your BigCommerce order confirmation page. Please follow the steps outlined below in order to enable the component.
Partner Success
Please request that your Partner Success manager turns the component on for your account. If this is not enabled, only Mulberry Unlimited activation will be shown for users who have purchased Unlimited.
Adding the Mulberry SDK
In your base.html file, add the following snippet to the element.
<script src="https://app.getmulberry.com/plugin/static/js/mulberry.js"></script>
This will load the Mulberry SDK onto your site. To initialize the SDK, run the following JavaScript snippet:
await window.mulberry.core.init({
publicToken: 'YOUR_PUBLIC_TOKEN_HERE'
});
It is important that the Mulberry SDK is loaded first and then the Checkout Success Script, as the success script relies on core Mulberry SDK functions.
Checkout Success Script
Edit the theme files to include the script outlined below for Order Confirmation Pages.
// These can be removed if the variables are declared elsewhere
const publicToken = 'YOUR_PUBLIC_TOKEN_HERE'
const orderID = '{{ checkout.order.id }}'
// This has an init function for example purposes, initialize as necessary
async function mulberryInitCheckout() {
await window.mulberry.core.init({
publicToken: publicToken,
})
}
// Embeds the subscription CTA
const embedCta = (hasSubscription) => {
let embeddedCtaHtml = ''
if (hasSubscription) {
embeddedCtaHtml = `
<div class="content-box" style="position: relative;">
<div class="content-box__row mulberry"></div>
</div>
`
} else {
embeddedCtaHtml = `
<div class="content-box" style="position: relative;">
<div class="exclusive-offer">Limited Time Offer</div>
<div class="content-box__row mulberry"></div>
</div>
`
}
const dom = document.createElement('div')
dom.innerHTML = embeddedCtaHtml
dom.style.display = 'none'
// Add the CTA after the main information section
// Can change this if you'd like the placement elsewhere
const targetContainer = document.querySelector('.orderConfirmation-section')
targetContainer.append(dom)
return dom
}
// Gets storefront order details necessary
async function getOrder(orderID) {
const orderResp = await fetch(`/api/storefront/orders/${orderID}`)
const orderResponse = await orderResp.json()
return {
firstName: orderResponse['billingAddress']['firstName'],
lastName: orderResponse['billingAddress']['lastName'],
email: orderResponse['billingAddress']['email'],
state: orderResponse['billingAddress']['stateOrProvinceCode'],
lineItems: orderResponse['lineItems']['digitalItems'].concat(
orderResponse['lineItems']['physicalItems']
),
}
}
// Find non covered items to show to customer
function findNonCoveredItems(lineItems) {
const foundSKUs = []
const nonCoveredLineItems = []
lineItems.forEach((item) => {
if (
item.name === 'Mulberry Unlimited Protection' ||
foundSKUs.includes(item.sku)
) {
return
}
if (item.name.includes('Mulberry Protection')) {
const bracketMatch = item.name.match(/\[(.*?)\]/)
if (bracketMatch) {
const potentialSKU = bracketMatch[1]
if (foundSKUs.includes(potentialSKU)) {
return
}
const protectedProduct = lineItems.find(
(lineItem) => lineItem.sku === potentialSKU
)
if (protectedProduct) {
foundSKUs.push(protectedProduct.sku)
foundSKUs.push(item.sku)
}
}
return
}
if (
lineItems.filter((lineItem) => lineItem.name.includes(item.name))
.length >= 2
) {
// Warranty items are formatted as: Mulberry Protection for test product name (xx months)
const warranty = lineItems.find((lineItem) =>
lineItem.name.includes(`Mulberry Protection for ${item.name}`)
)
if (warranty && !foundSKUs.includes(warranty.sku)) {
foundSKUs.push(warranty.sku)
foundSKUs.push(item.sku)
return
}
}
// If we could not match the product to a warranty, consider it a non covered item
nonCoveredLineItems.push(item)
})
return nonCoveredLineItems
}
const process = async () => {
// Check that this is an order success page
if (
!window.location.href.includes('/checkout/') &&
!window.location.href.includes('/order-confirmation/')
) {
return
}
// orderID is needed for the storefront API call
if (!orderID) {
return
}
const order = await getOrder(orderID)
// Response Example:
// const order = {
// firstName: 'Test',
// lastName: 'Test',
// email: '[email protected]',
// state: 'NY',
// lineItems: [],
// }
// At a minimum, we need their email for checkout success
if (!order.email) {
return
}
const subscriptionLineItem = order.lineItems.find(
(lineItem) => lineItem.name === 'Mulberry Unlimited Protection'
)
// If a customer has already activated their subscription, don't show this
if (subscriptionLineItem && subscriptionLineItem.salePrice === 0) {
return
}
// Get the retailer settings for further logic
const { settings } = window.mulberry.core
// If the user has purchased a subscription, allow them to activate it
if (subscriptionLineItem) {
const component = embedCta(true)
component.style.cssText = 'display:block;margin-bottom:1em;'
window.mulberry.enrollment.init({
settings,
placement: 'big-commerce-order-status',
queryParams: {
utm_campaign: settings.retailer_id,
utm_medium: 'big-commerce-order-status',
utm_source: 'cta-enroll',
},
meta: {
firstName: order.firstName,
lastName: order.lastName,
email: order.email,
state: order.state,
},
onClose: (message) => {
if (message.paymentSuccessful) {
component.style.display = 'none'
}
},
onLoad: () => {
window.mulberry.enrollment.open()
},
})
window.mulberry.cta.init({
type: 'enroll',
settings,
selector: '.content-box__row.mulberry',
meta: {
placement: 'big-commerce-status',
},
onClick: () => {
window.mulberry.enrollment.open()
},
})
} else {
// If the user has not purchased a subscription and this flow is enabled
if (!settings.enable_subscription_order_success_offers) {
return
}
const nonCoveredLineItems = findNonCoveredItems(order.lineItems)
// If all items are covered already, don't show this
if (nonCoveredLineItems.length === 0) {
return
}
const result = await Promise.all(
nonCoveredLineItems.map((product) => {
const payload = {
title: product.name,
price: product.salePrice,
images: [{ src: product.imageUrl }],
}
return window.mulberry.core.getWarrantyOffer(payload)
})
)
const eligibleItems = result.filter((item) => {
return item.at(0)?.product?.is_subscription_eligible
})
// If there are no eligible items for the subscription, don't show this
if (eligibleItems.length === 0) {
return
}
const product = eligibleItems.reduce(function (prev, current) {
return prev[0].product_price > current[0].product_price ? prev : current
})
// Initialize the component if we have decided to show it
const component = embedCta(false)
component.style.display = 'block'
window.mulberry.subscription.init({
settings,
placement: 'big-commerce-order-confirmation',
queryParams: {
utm_campaign: settings.retailer_id,
utm_medium: 'big-commerce-order-confirmation',
utm_source: 'modal-subscribe',
},
meta: {
firstName: order.firstName,
lastName: order.lastName,
email: order.email,
state: order.state,
product: product.length ? product[0].product_meta : {},
},
onClose: (message) => {
if (message.paymentSuccessful) {
component.style.display = 'none'
}
},
onLoad: () => {
window.mulberry.subscription.open()
},
})
window.mulberry.cta.init({
type: 'subscribe',
settings,
selector: '.content-box__row.mulberry',
meta: {
products: eligibleItems,
placement: 'big-commerce-order-confirmation',
},
onClick: () => {
window.mulberry.subscription.open()
},
})
}
}
window.addEventListener('load', async function () {
// Await for initialization because we need core operations first
await mulberryInitCheckout()
process()
})
Success
Customers who have not purchased Unlimited will now see Mulberry Unlimited offers for relevant products they purchased. These offers will be displayed upon checkout on the Order status page as shown below:
Customers who have purchased Unlimited, but have not activated it yet, will now see a placement that allows them to.
Updated about 1 year ago