Shopify + LiveShopping

Integrate Bambuser Live Shopping with your Shopify store

In order to integrate the Bambuser LiveShopping player on a Shopify store, we just need to inject some codes below to the Shopify LiveShopping landing page (where we want to show the player).

The whole integrations can be implemented in a Snippet within the active theme and can be rendered in any Liquid template or layout.

Sample of an integrated player on a Shopify store:
https://bamb-integration.myshopify.com/pages/live-shows

Integration Steps

  1. Adding the embed code snippet‍ 
  2. Setting up the player's onReady handler‍  (All further steps will be implemented within this handler block)
  3. Configuring the player
    1. Store default currency
    2. Store default locale
    3. Player buttons configuration
  4. Writing AjaxAPI helper methods
  5. Handle product hydration (provide product data to the player)
  6. Handle add to cart
  7. Handle update an item in the cart
  8. Handle sync cart state
  9. Handle checkout target
  10. Purchase Tracker‍ 

Sample Shopify Integration Codes

Product Hydration & Cart integration

Sample Shopify product object

{ 

     id: 3780507959318, 
     title: "Stratus Backpack", 
     handle: "stratus-backpack", 
     description: 
         '\u003cmeta charset="utf-8"\u003e\n\u003cp\u003e\u003ci\u003eThis is a demonstration store. You can purchase products like this from\u003cspan\u003e \u003ca href="https://caraasport.com" title="Caraa"\u003eCaraa\u003c/a\u003e\u003c/span\u003e.\u003c/i\u003e\u003c/p\u003e\n\u003cp\u003e\u003cspan\u003eLight as air. The Stratus is encased in cloud-like waterproof nylon and features exterior + interior pockets for your water bottle, umbrella, and laptop. Reach around to the side for on-the-go access to the main compartment. Collapse it for easy travel. Your backpack just got an upgrade.\u003c/span\u003e\u003c/p\u003e', 
     published_at: "2020-03-09T16:13:44-04:00", 
     created_at: "2020-03-09T16:13:50-04:00", 
     vendor: "debut-rich-media-demo", 
     type: "", 
     tags: [], 
     price: 17500, 
     price_min: 17500, 
     price_max: 19500, 
     available: true, 
     price_varies: true, 
     compare_at_price: null, 
     compare_at_price_min: 0, 
     compare_at_price_max: 0, 
     compare_at_price_varies: false, 
     variants: [ 
         { 
             id: 29013951414294, 
             title: "Navy", 
             option1: "Navy", 
             option2: null, 
             option3: null, 
             sku: "", 
             requires_shipping: true, 
             taxable: true, 
             featured_image: { 
                 id: 4721544527894, 
                 product_id: 3780507959318, 
                 position: 1, 
                 created_at: "2020-03-09T16:13:51-04:00", 
                 updated_at: "2020-03-09T16:13:51-04:00", 
                 alt: null, 
                 width: 1058, 
                 height: 1039, 
                 src: 
                     "https://cdn.shopify.com/s/files/1/0260/1061/5830/products/main_backpack.png?v=1583784831", 
                 variant_ids: [29013951414294], 
             }, 
             available: true, 
             name: "Stratus Backpack - Navy", 
             public_title: "Navy", 
             options: ["Navy"], 
             price: 17500, 
             weight: 0, 
             compare_at_price: null, 
             inventory_management: "shopify", 
             barcode: "", 
             featured_media: { 
                 alt: null, 
                 id: 1459887833110, 
                 position: 1,
                 preview_image: { 
                     aspect_ratio: 1.018, 
                     height: 1039, 
                     width: 1058, 
                     src: 
                         "https://cdn.shopify.com/s/files/1/0260/1061/5830/products/main_backpack.png?v=1583784831", 
                 }, 
             }, 
         }, 
         { 
             id: 29013951447062, 
             title: "Black", 
             option1: "Black", 
             option2: null, 
             option3: null, 
             sku: "", 
             requires_shipping: true, 
             taxable: true, 
             featured_image: { 
                 id: 4721544658966, 
                 product_id: 3780507959318, 
                 position: 4, 
                 created_at: "2020-03-09T16:13:51-04:00", 
                 updated_at: "2020-03-11T10:45:10-04:00", 
                 alt: null, 
                 width: 1058, 
                 height: 1039, 
                 src: 
                     "https://cdn.shopify.com/s/files/1/0260/1061/5830/products/stratus_03.png?v=1583937910", 
                 variant_ids: [29013951447062], 
             },
             available: true, 
             name: "Stratus Backpack - Black", 
             public_title: "Black", 
             options: ["Black"], 
             price: 19500, 
             weight: 0, 
             compare_at_price: null, 
             inventory_management: "shopify", 
             barcode: "", 
             featured_media: { 
                 alt: null, 
                 id: 1459887964182, 
                 position: 5, 
                 preview_image: { 
                     aspect_ratio: 1.018, 
                     height: 1039, 
                     width: 1058, 
                     src: 
                         "https://cdn.shopify.com/s/files/1/0260/1061/5830/products/stratus_03.png?v=1583784831", 
                 }, 
             }, 
         }, 
         { 
             id: 29013951479830, 
             title: "Red", 
             option1: "Red", 
             option2: null, 
             option3: null, 
             sku: "", 
             requires_shipping: true, 
             taxable: true, 
             featured_image: null, 
             available: false,
             name: "Stratus Backpack - Red", 
             public_title: "Red", 
             options: ["Red"], 
             price: 17500, 
             weight: 0, 
             compare_at_price: null, 
             inventory_management: "shopify", 
             barcode: "", 
         }, 
     ], 
     images: [ 
         "//cdn.shopify.com/s/files/1/0260/1061/5830/products/main_backpack.png?v=1583784831", 
         "//cdn.shopify.com/s/files/1/0260/1061/5830/products/stratus_01.png?v=1583937910", 
         "//cdn.shopify.com/s/files/1/0260/1061/5830/products/stratus_02.png?v=1583937910", 
         "//cdn.shopify.com/s/files/1/0260/1061/5830/products/stratus_03.png?v=1583937910", 
     ], 
     featured_image: 
         "//cdn.shopify.com/s/files/1/0260/1061/5830/products/main_backpack.png?v=1583784831", 
     options: [{ name: "Color", position: 1, values: ["Navy", "Black", "Red"] }], 
     url: "/products/stratus-backpack", 
     media: [ 
         { 
             alt: null, 
             id: 1459887833110, 
             position: 1, 
             preview_image: { 
                 aspect_ratio: 1.018, 
                 height: 1039, 
                 width: 1058, 
                 src: 
                     "https://cdn.shopify.com/s/files/1/0260/1061/5830/products/main_backpack.png?v=1583784831", 
             }, 
             aspect_ratio: 1.018, 
             height: 1039, 
             media_type: "image", 
             src: 
                 "https://cdn.shopify.com/s/files/1/0260/1061/5830/products/main_backpack.png?v=1583784831", 
             width: 1058, 
         }, 
         { 
             alt: null, 
             id: 1461301641238, 
             position: 2, 
             preview_image: { 
                 aspect_ratio: 1.0, 
                 height: 1024, 
                 width: 1024, 
                 src: 
                     "https://cdn.shopify.com/s/files/1/0260/1061/5830/products/StratusBag.jpg?v=1583937876", 
             }, 
             media_type: "model", 
             sources: [ 
                 { 
                     format: "glb", 
                     mime_type: "model/gltf-binary", 
                     url: "https://model3d.shopifycdn.com/models/o/5f491746c036baf6/StratusBag.glb", 
                 }, 
                 { 
                     format: "usdz", 
                     mime_type: "model/vnd.usdz+zip", 
                     url: "https://model3d.shopifycdn.com/models/o/c3b4ad9cbc191499/StratusBag.usdz", 
                 }, 
             ], 
         }, 
         { 
             alt: null, 
         &bsp;   id: 1459887865878, 
         nbsp;   position: 3, 
            preview_image: { 
                 aspect_ratio: 1.018, 
       &nbs;         height: 1039, 
                 width: 1058, 
                 src: 
                     "https://cdn.shopify.com/s/files/1/0260/1061/5830/products/stratus_01.png?v=1583784831", 
             }, 
             aspect_ratio: 1.018, 
             height: 1039, 
             media_type: "image", 
             src: "https://cdn.shopify.com/s/files/1/0260/1061/5830/products/stratus_01.png?v=1583784831", 
             width: 1058, 
         }, 
         { 
             alt: null, 
             id: 1459887931414, 
             position: 4, 
             preview_image: { 
                 aspect_ratio: 1.018, 
                 height: 1039, 
                 width: 1058, 
                 src: 
                     "https://cdn.shopify.com/s/files/1/0260/1061/5830/products/stratus_02.png?v=1583784831", 
             }, 
             aspect_ratio: 1.018, 
             height: 1039, 
             media_type: "image", 
             src: "https://cdn.shopify.com/s/files/1/0260/1061/5830/products/stratus_02.png?v=1583784831", 
             width: 1058, 
         }, 
         { 
             alt: null, 
             id: 1459887964182, 
             position: 5, 
             preview_image: { 
                 aspect_ratio: 1.018, 
                 height: 1039, 
                 width: 1058, 
                 src: 
                     "https://cdn.shopify.com/s/files/1/0260/1061/5830/products/stratus_03.png?v=1583784831", 
             }, 
             aspect_ratio: 1.018, 
             height: 1039, 
             media_type: "image", 
             src: "https://cdn.shopify.com/s/files/1/0260/1061/5830/products/stratus_03.png?v=1583784831", 
             width: 1058, 
         }, 
     ],
};

Store the code below in a Liquid Snippet and render that in your desired page template.

// 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-+]+)/; 
	

 // Sometimes image URLs miss the protocol at the beginning 
 // E.g. '//cdn.shopify.com/s/files/.../image.jpg' 
 const 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; 
 }; 
	

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

 const storeApi = {}; 
	

 storeApi.getProductByUrl = url => { 
     const handle = SHOPIFY_PRODUCT_URL_HANDLE_REGEX.exec(url); 
     return fetch("/products/" + handle[1] + ".js", { 
         method: "GET", 
         headers: { 
             "Content-Type": "application/json", 
         }, 
     }).then(resp => resp.json()); 
 }; 
	

 storeApi.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()); 
	

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

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

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

 window.onBambuserLiveShoppingReady = player => { 
      
     // ---- Start of player configuration ---- 
     const currency = document.cookie 
     .split('; ') 
     .find((row) => row.startsWith('cart_currency')); 
	

     player.configure({ 
         currency: (currency && currency.split('=')[1]) || ' ', 
         locale: "en-US", 
     }); 
     // ---- End of player configuration ---- 
	

     // ---- Start of Cart Integrations ---- 
     player.on(player.EVENT.ADD_TO_CART, (addedItem, callback) => { 
         storeApi 
             .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}`); 
         storeApi 
             .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 
         storeApi.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 }) => { 
             // Your method to fetch a product data 
             storeApi.getProductByUrl(url).then((item) => { 
                 //Uncomment the line below for testing 
                 //console.log(item); 
                 player.updateProduct(id, productFactory => 
                     productFactory.product(detailsFactory => 
                         detailsFactory 
                             .name(item.title) 
                             .sku(item.id) 
                             .brandName(item.vendor) 
                             .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 begining 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) 
                                                 ) 
                                         ]) 
                                 ) 
                             ) 
                     ) 
                 ); 
             }); 
         }); 
     }); 
 };

Read more about Bambuser LiveShopping Purchase Tracker 🛒