Skip to main content

Shopify + LiveShopping

Integrate Bambuser Live Shopping with your Shopify store​

img

In order to integrate the Bambuser LiveShopping player into a Shopify store, you will need to add some code to your Shopify LiveShopping landing page (wherever you want to embed the player). The embed and integration codes can be added by adding script tags to your page content or theme codes.

Below you'll find a sample Shopify integration code that you can use when integrating Bambuser One-to-many player into your Shopify store.



Steps:

  1. Embed show(s) into a page πŸ”—
  2. Add the sample integration code to your page πŸ”—
  3. Add Conversion Tracking πŸ”—
Compatibility

Due to Shopify's technical limitations, the Miniplayer feature is not compatible with Shopify stores. You can read more about the Miniplayer compatibility here.


Get started​

Embedding a show​

The simplest way to embed a One-to-many show on a Shopify store page is to copy-paste the embed code to your page content. In the Bambuser dashboard, on each show setup page, you will find a code snippet that contains the embed code for that show. You can simply copy-paste it to any page (as HTML).

  1. Copy the embed code from the show setup page on the Bambuser dashboard.

img

  1. On your Shopify page, switch the editor to HTML view.

img

  1. Paste the embed code and save the page.

img

Further customization

To learn more about the embed code, how to make it autoplay, or how to customize the triggering element, read the Initial Setup guide.

Embedding multiple shows on one page​

If you want to embed multiple shows on one page you can call window.initBambuserLiveShopping method multiple times to register more than one show.

Bind an element to trigger a live shopping show
window.initBambuserLiveShopping({
showId: 'BAMBUSER-LIVESHOPPING-SHOW-ID-HERE', // ShowID from the Dashboard
node: document.getElementById('myCoolClickableThing'), // Triggering element
type: 'overlay',
});

In the example below you see how to have more than one show embedded into your landing page.

Example code
<!-- Your very cool interactive element here provided with a id attribute -->
<div id="myCoolClickableThing-1">Watch episode 1</div>

<div id="myCoolClickableThing-2">Watch episode 1</div>

<script>
(function() {
if (!window.initBambuserLiveShopping) {
window.initBambuserLiveShopping = function(item) { window.initBambuserLiveShopping.queue.push(item) };
window.initBambuserLiveShopping.queue = [];
var scriptNode = document.createElement('script');
scriptNode['src'] = 'https://lcx-embed.bambuser.com/your-brand-name/embed.js';
document.body.appendChild(scriptNode);
}

// Multiple shows can be embedded in a single page as below
// node: The trigger element for opening the specified show
window.initBambuserLiveShopping({
showId: 'BAMBUSER-LIVESHOPPING-SHOW-ID-HERE',
node: document.getElementById('myCoolClickableThing-1'),
type: 'overlay',
});

window.initBambuserLiveShopping({
showId: 'BAMBUSER-LIVESHOPPING-SHOW-ID-HERE',
node: document.getElementById('myCoolClickableThing-2'),
type: 'overlay',
});
})();
</script>

Cart Integration​

To add product and cart functionalities to the player, you need to implement Cart Integration into your Shopify store.

Sample integration code​

Here you find a sample integration code that implements the Cart Integration feature into your Shopify store. This sample code works on almost all Shopify stores that have standard product models without any changes required. However, if you have a special product setup, you may need to modify the code to justify that with your case.

In the next section, we explain how you should add the integration code into your Shopify store.

Sample code
<script>
// ====================================== Define constants ========================================
// Reduces server calls if a product has a crazy number of images.
const MAX_IMAGES_COUNT = 6;

// Extracts product handle from the product URL
const SHOPIFY_PRODUCT_URL_HANDLE_REGEX = /\/products\/(.[\w\d-+]+)/;

// ====================================== General helper methods for Shopify ========================================
// Sometimes image URLs miss the protocol at the beginning
// E.g. '//cdn.shopify.com/s/files/.../image.jpg'
window.urlSanitizer = (url) => {
if (typeof url === 'string') {
if (url.startsWith('//')) return `https:${url}`;
else if (url.toLocaleLowerCase().startsWith('http')) return url;
else console.log(`Not a valid URL: ${url}`);
} else console.log(`Not a valid URL: ${url}`);
return null;
};

// Returns the store's active currency for the current user
// E.g,: 'EUR'
window.getActiveCurrency = () => {
// 1. From the Shopify object
const getCurrencyFromContext = Shopify?.currency?.active;
if (getCurrencyFromContext) return getCurrencyFromContext;

// 2. From the 'cart_currency' cookie
const currencyFromCookies = document.cookie
.split('; ')
.find((row) => row.startsWith('cart_currency'))
?.split('=')[1];
if (currencyFromCookies) return currencyFromCookies;

// If no currency found
return null;
};

//========== Shopify Ajax API Helper methods ===============

window.oneToManyStoreApi = {};

oneToManyStoreApi.getProductByUrl = (url) => {
const handle = SHOPIFY_PRODUCT_URL_HANDLE_REGEX.exec(url);
try {
if (typeof handle[1] == 'string' && handle[1].length > 0) {
return fetch('/products/' + handle[1] + '.js', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
}).then((resp) => resp.json());
}
} catch (error) {
throw new Error(
'Cannot find the handle in the product URL: ' + url + '/n' + error
);
}
};

oneToManyStoreApi.addToCart = (itemId) =>
fetch('/cart/add.js', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
items: [
{
quantity: 1,
id: itemId,
},
],
}),
}).then((resp) => resp.json());

oneToManyStoreApi.updateItemInCart = (itemId, quantity) =>
fetch('/cart/update.js', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
updates: {
[itemId]: quantity,
},
}),
}).then((resp) => resp.json());

oneToManyStoreApi.getCartState = () =>
fetch('/cart.js', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
}).then((resp) => resp.json());

oneToManyStoreApi.getVariantIdFromUrlParams = (url) => {
// Extract the variant ID from the URL
// URL Ex. https://www.MY-SHOPIFY-STORE.com/products/my-product-handle?variant=VARIATION_ID
const variantId = new URL(url).searchParams.get('variant');
return typeof variantId == 'string' && variantId.length == 14
? variantId
: null;
};

//=========== Bambuser onReady Handler =================

window.onBambuserLiveShoppingReady = (player) => {
// ---- Start of player configuration ----
player.configure({
currency: getActiveCurrency() || 'USD',
locale: 'en-US',
buttons: {
dismiss: player.BUTTON.CLOSE,
},
});
// ---- End of player configuration ----

// ---- Start of Cart Integrations ----
player.on(player.EVENT.ADD_TO_CART, (addedItem, callback) => {
oneToManyStoreApi
.addToCart(addedItem.sku)
.then((res) => {
if (res.items) {
callback(true);
console.log('Item added succussfully!');
} else if (res.description && res.description.includes('sold out')) {
callback({ success: false, reason: 'out-of-stock' });
} else callback(false);
})
.catch((error) => {
callback(false);
console.error('Add to cart error! ', error);
});
});

player.on(player.EVENT.UPDATE_ITEM_IN_CART, (updatedItem, callback) => {
console.log(
`Cart updated! ${updatedItem.previousQuantity} --> ${updatedItem.quantity}`
);
oneToManyStoreApi
.updateItemInCart(updatedItem.sku, updatedItem.quantity)
.then((res) => {
if (res.items) {
callback(true);
console.log('Item updated succussfully!');
} else callback(false);
})
.catch((error) => {
callback(false);
console.error('Error on updating item! ', error);
});
});

player.on(player.EVENT.SYNC_CART_STATE, () => {
// Use your method to check if the user has checkout
oneToManyStoreApi.getCartState().then((res) => {
if (res.item_count == 0) {
// Emptying the in-player cart
player.updateCart({
items: [],
});
}
});
});

player.on(player.EVENT.CHECKOUT, () => {
// Use the showCheckout() method to safely
// navigate the user to your checkout page
player.showCheckout(window.location.origin + '/cart');
});
// ---- End of Cart Integrations ----

// ---- Start of Product Hydration ----
player.on(player.EVENT.PROVIDE_PRODUCT_DATA, (event) => {
// Iterates over all the products you have added to the show on the dashboard
event.products.forEach(({ ref: sku, id, url }) => {
const variantId = oneToManyStoreApi.getVariantIdFromUrlParams(url);
try {
// Your method to fetch a product data
oneToManyStoreApi.getProductByUrl(url).then((item) => {
//Uncomment the line below for debugging retrieved product data
//console.log(item);
player.updateProduct(id, (productFactory) =>
productFactory.product((detailsFactory) =>
detailsFactory
.name(item.title)
.sku(item.id)
.brandName(item.vendor)
.description(item.description)
.defaultVariationIndex(
variantId
? item.variants.findIndex(
(variant) => variant.id == variantId
)
: 0
)
.variations((variationFactory) =>
item.variants.map((variation) =>
variationFactory()
.attributes((attributeFactory) =>
attributeFactory.colorName(variation.title)
)
.imageUrls([
// Adding the featured image of the chosen variation (if existed) at the beginning of the images array
...(variation.featured_image
? [variation.featured_image.src]
: []),
// Adding product imgaes
...item.images
.slice(0, MAX_IMAGES_COUNT - 1)
.map((url) => urlSanitizer(url))
.filter((url) => typeof url === 'string'),
])
.name(variation.title)
.sku(item.id)
.sizes((sizeFactory) => [
sizeFactory()
.name(variation.title)
.sku(variation.id)
.inStock(variation.available)
.price((priceFactory) =>
priceFactory
.original(variation.compare_at_price / 100)
.current(variation.price / 100)
),
])
)
)
)
);
});
} catch (error) {
console.warn('CANNOT HYDRATE THE PRODUCT! \n', error);
}
});
});
};
</script>

How the Cart Integration works

For more detailed information about the Cart Integration feature and its implementation, read Cart Integration guide.

Adding integration code to your Shopify​

There are different ways to add the integration code to the Shopify store. You need to make sure that your integration code is included in all pages that you have the player embedded on.

(Option 1) Add to the page content​

Recommended if:

  • You only have a single landing page for the incoming traffic to the live show

Steps:

  1. Copy-paste the provided sample integration code to your page content (in HTML mode)

(Option 2) Add to all pages​

Recommended if:

  • You have the player embedded on multiple or all pages
  • You have the FAB widget embedded on all pages

Steps:

  1. In your Shopify theme codes, create a snippet and add the sample integration code there
  2. Assuming that you named the snippet bambuser-cart-integration.liquid, add this snippet to the theme.liquid layout as below:
theme.liquid
{% render 'bambuser-cart-integration'%}

(Option 3) Add to a specific page template​

Recommended if:

  • You have a set of pages where you embed the player

Steps:

  1. In your Shopify theme codes, create a snippet and add the sample integration code there
  2. Assuming that you named the snippet bambuser-cart-integration.liquid, you can add this snippet to your page template(s) as below:
page.yourTemplateName.liquid
{% render 'bambuser-cart-integration'%}

The result​

Once you have the cart integration working, you should be seeing the following behaviour:

  • The product prices are shown in the product list
  • Clicking a product shows the product details view in the player
  • You can add products to the cart
  • You can manage the cart and go to check out

img


Conversion Tracking on Shopify​

Adding the Bambuser Conversion Tracking to your Shopify store enables your team to track sales that are attributed to Bambuser shows.

Implement via Shopify Custom Pixel​

Implement Bambuser Conversion Tracking in your Shopify store using a Shopify Custom Pixel.

  1. Log in to your Shopify Admin dashboard
  2. From the bottom-left select Settings
  3. Choose Customer events from the left menu
  4. From the top-right, click on Add custom pixel
  5. Give it a name and click Add Pixel
  6. You should see a code box. If there are some codes already in the code box please remove them.
  7. Copy the code below (Select Global/EU servers based on your account's region!), and paste it on the Custom Pixel code box.
  8. Press Save and then press Connect
Global Servers

Tracking library URL is different depending on location of servers that your dashboard is set up on. Use Global servers URL https://cdn.liveshopping.bambuser.com/metrics/bambuser.min.js if the login to your Bambuser dashboard is on following link: https://lcx.bambuser.com/.

// ---------------------------------------------------------
// Bambuser Conversion Tracking for Shopify Pixels.
// Shopify Admin -> Settings -> Customer events
// ---------------------------------------------------------
// (IMPORTANT)
// Change the value to true only if your Bambuser dashboard's base URL matches lcx-eu.bambuser.com
const USE_EU_SERVER = false;
// ---------------------------------------------------------
// For debugging
const LOGGING_ENABLED = false;
// ---------------------------------------------------------

// Subscribe to customer events using the analytics.subscribe() API
analytics.subscribe('checkout_completed', (event) => {
LOGGING_ENABLED && console.log('πŸ›’ - Running Conversion Tracking Customer Event...');
const checkout = event.data.checkout;

// Send the conversion data above to Bambuser
function onPurchaseBambuser () {
var data = {
event: 'purchase', // value needs to be β€œpurchase”
orderId: checkout.order.id, // The order id
orderValue: checkout.totalPrice.amount, // Total gross order value
currency: checkout.totalPrice.currencyCode, // The currency used for the order value
orderProductIds: checkout.lineItems.map((item) => item.id.toString()), // Array or comma-separated string of all product ids in the order
};

// Send the conversion data above to Bambuser
window._bambuser.collect(data);
LOGGING_ENABLED && console.log('πŸ›’ - If relevant, the purchase should be collected now!', data);
}

// Load the tracking library and sec invoke onPurchase() method
LOGGING_ENABLED && console.log('πŸ›’ - Mounting tracking script!');
var bamSrcElm = document.createElement('script');
bamSrcElm.src = USE_EU_SERVER ? 'https://cdn.liveshopping.bambuser.com/metrics/bambuser-eu.min.js' : 'https://cdn.liveshopping.bambuser.com/metrics/bambuser.min.js';
bamSrcElm.onload = onPurchaseBambuser;
document.body.appendChild(bamSrcElm);
});

Troubleshooting​

If you have any issues, check out the Conversion Tracking troubleshooting checklist. To find out more, see the Bambuser Conversion Tracking πŸ›’ documentation.