Sharing sessions across subdomains

lyradesigns
Tourist
5 0 1

I am creating a wordpress blog to augment a shopify storefront, and was trying to make Add to Cart buttons in Wordpress that would sync with the shopify cart.  I wanted to get some Wordpress custom blocks to play nicely with Shopify and I developed a pretty good workaround that gives the flexibility I wanted.

Firstly, I used a trick to dynamically get the product information from the cart API (avoiding CORS) using a <script> tag with the product API URL and a callback function to create a dynamic button.

NOTE: URL stands for your shopify site URL.

function getShopifyProduct(productSlug, callback) {
  let container = document.createElement('div');
  container.setAttribute('id', `product-${productSlug}`);
  document.querySelector('body').appendChild(container);

  const productContainer = document.getElementById(`product-${productSlug}`);
  let script = document.createElement('script');
  script.src=`https://URL.com/products/${productSlug}.json?callback=${callback}`;
  productContainer.appendChild(script); 
}

And you include it like so:

<div class="product__tile product-store" id="product-store-<?php echo $product_handle; ?>">
          <script>
            setTimeout(function(){
              getShopifyProduct('<?php echo $product_handle; ?>', 'showProductStoreTile');
            }, 1000);
          </script>
        </div>

And then the callback function to print the tile:

/**
 * Store product grid tile with ATC button
 * @param {*} data  JSON object returned from shopify product API 
 */
function showProductStoreTile(data) {
  const product = data.product; // handle
  const productContainer = document.getElementById(`product-store-${product.handle}`);
  const firstWord = product.title.split(' ')[0].toLowerCase();
  const collectionName = firstWord === 'clear' ? 'Clear' : firstWord === 'calm' ? 'Calm' : firstWord === 'renew' ? 'Renew' : null;

  let productHTML = `<div class="product">
                      <a href="https://URL.com/products/${product.handle}" target="_blank">
                        <img class="product__img" src="${product.images[0].src}">
                      </a>
                      <span class="product__content">
                        ${collectionName ? `<span class="product__collection">${collectionName}</span>` : ''}
                        <h4 class="product__title"><a href="https://URL.com/products/${product.handle}" target="_blank">${collectionName ? product.title.substr(product.title.indexOf(" ") + 1) : product.title}</a></h4>
                        ${product.body_html}
                        <!--<div id="product-btn-${product.id}"></div>-->
                        <button class="btn btn-primary product__btn" data-variant-id="${product.variants[0].id}" onClick="addToCart(event)">Add to Bag</button>
                        <span class="product__price">$${product.variants[0].price}</span>
                        <a class="product__link" href="https://URL.com/products/${product.handle}" target="_blank">Learn More</a>
                      </span>
                    </div>`;
              
  productContainer.insertAdjacentHTML( 'beforeend', productHTML );
}

Once you have the tile in place, my Add to Cart buttons had an onclick function to handle the action:

/**
 * Add item to shopify cart and update total in header
 * @param {*} e
 */
function addToCart(e) {
  e.preventDefault();
  createCartIframe();
  const btn = e.target,
        addToCartIframe = document.getElementById('addToCartIframe'),
        variantID = e.target.getAttribute('data-variant-id');
  if (!variantID) return false;
  
  console.log(variantID, ' added to cart!');
  addToCartIframe.setAttribute('src', `https://URL.com/cart/add?id=${variantID}&quantity=1`)
  btn.classList.add('item-added');
  setTimeout(function(){
    btn.classList.remove('item-added');
    updateCart();
  }, 1000);
}

The trick is the CreateCartIframe() part - this function gives us a little iframe window into the users' actual shopify cart, and allows us to add items by changing the URL on the iframe.  Here's the function that just creates the iframe if it doesn't exist:

function createCartIframe() {
  if (document.getElementById('addToCartIframe')) return false;
  let addToCartIframe = document.createElement('iframe');
  addToCartIframe.setAttribute('src', 'https://URL.com/cart/add');
  addToCartIframe.setAttribute('id', 'addToCartIframe');
  addToCartIframe.setAttribute('name', 'addToCartIframe');
  addToCartIframe.setAttribute('style', 'height:1px;width:1px;');
  document.querySelector('body').appendChild(addToCartIframe);
}

Let me know if you have any questions - it's working like a charm for me, and lets me setup the product blocks and Add to Cart buttons however I want.  I use a similar trick (with a script tag and the callback function) to get the latest cart: 

0 Likes
lyradesigns
Tourist
5 0 1

I am creating a wordpress blog to augment a shopify storefront, and was trying to make Add to Cart buttons in Wordpress that would sync with the shopify cart.  I wanted to get some Wordpress custom blocks to play nicely with Shopify and I developed a pretty good workaround that gives the flexibility I wanted.

Firstly, I used a trick to dynamically get the product information from the cart API (avoiding CORS) using a <script> tag with the product API URL and a callback function to create a dynamic button.

NOTE: URL stands for your shopify site URL.

function getShopifyProduct(productSlug, callback) {
  let container = document.createElement('div');
  container.setAttribute('id', `product-${productSlug}`);
  document.querySelector('body').appendChild(container);

  const productContainer = document.getElementById(`product-${productSlug}`);
  let script = document.createElement('script');
  script.src=`https://URL.com/products/${productSlug}.json?callback=${callback}`;
  productContainer.appendChild(script); 
}

And you include it like so:

<div class="product__tile product-store" id="product-store-<?php echo $product_handle; ?>">
          <script>
            setTimeout(function(){
              getShopifyProduct('<?php echo $product_handle; ?>', 'showProductStoreTile');
            }, 1000);
          </script>
        </div>

And then the callback function to print the tile:

/**
 * Store product grid tile with ATC button
 * @param {*} data  JSON object returned from shopify product API 
 */
function showProductStoreTile(data) {
  const product = data.product; // handle
  const productContainer = document.getElementById(`product-store-${product.handle}`);
  const firstWord = product.title.split(' ')[0].toLowerCase();
  const collectionName = firstWord === 'clear' ? 'Clear' : firstWord === 'calm' ? 'Calm' : firstWord === 'renew' ? 'Renew' : null;

  let productHTML = `<div class="product">
                      <a href="https://URL.com/products/${product.handle}" target="_blank">
                        <img class="product__img" src="${product.images[0].src}">
                      </a>
                      <span class="product__content">
                        ${collectionName ? `<span class="product__collection">${collectionName}</span>` : ''}
                        <h4 class="product__title"><a href="https://URL.com/products/${product.handle}" target="_blank">${collectionName ? product.title.substr(product.title.indexOf(" ") + 1) : product.title}</a></h4>
                        ${product.body_html}
                        <!--<div id="product-btn-${product.id}"></div>-->
                        <button class="btn btn-primary product__btn" data-variant-id="${product.variants[0].id}" onClick="addToCart(event)">Add to Bag</button>
                        <span class="product__price">$${product.variants[0].price}</span>
                        <a class="product__link" href="https://URL.com/products/${product.handle}" target="_blank">Learn More</a>
                      </span>
                    </div>`;
              
  productContainer.insertAdjacentHTML( 'beforeend', productHTML );
}

Once you have the tile in place, my Add to Cart buttons had an onclick function to handle the action:

/**
 * Add item to shopify cart and update total in header
 * @param {*} e
 */
function addToCart(e) {
  e.preventDefault();
  createCartIframe();
  const btn = e.target,
        addToCartIframe = document.getElementById('addToCartIframe'),
        variantID = e.target.getAttribute('data-variant-id');
  if (!variantID) return false;
  
  console.log(variantID, ' added to cart!');
  addToCartIframe.setAttribute('src', `https://URL.com/cart/add?id=${variantID}&quantity=1`)
  btn.classList.add('item-added');
  setTimeout(function(){
    btn.classList.remove('item-added');
    updateCart();
  }, 1000);
}

The trick is the CreateCartIframe() part - this function gives us a little iframe window into the users' actual shopify cart, and allows us to add items by changing the URL on the iframe.  Here's the function that just creates the iframe if it doesn't exist:

function createCartIframe() {
  if (document.getElementById('addToCartIframe')) return false;
  let addToCartIframe = document.createElement('iframe');
  addToCartIframe.setAttribute('src', 'https://URL.com/cart/add');
  addToCartIframe.setAttribute('id', 'addToCartIframe');
  addToCartIframe.setAttribute('name', 'addToCartIframe');
  addToCartIframe.setAttribute('style', 'height:1px;width:1px;');
  document.querySelector('body').appendChild(addToCartIframe);
}

Let me know if you have any questions - it's working like a charm for me, and lets me setup the product blocks and Add to Cart buttons however I want.  I use a similar trick (with a script tag and the callback function) to get the latest cart: 

0 Likes

Tim,

Are you available for hire to implement such changes?

Best,

TMC

0 Likes
lyradesigns
Tourist
5 0 1

Hi TMC - it's Jonas, and I'd be happy to talk. jonas@lyradesigns.com