Articles on: App testing and setup

Why does the website/page refresh when a product is added to cart?

Some themes have a built-in cart listener code that automatically updates the cart items & total in real-time whenever a product/discount is added by third party apps like Monk. But a handful of themes do not support this functionality - in these cases a page refresh is needed to display the updated cart details and total.

Whether the app should trigger a page refresh or not is controlled by the ‘Refresh the page’ setting on Page 2 of a funnel setup under 'Advance Configuration'

Please Note: The screenshot attached below is of the Cross Sell Funnel settings, you can find the Refresh option on page 2 of the settings under 'Advance Configuration' for all the funnels



If your theme has a cart listener, it can efficiently handle cart updates without the need for a page refresh. In such cases, you can disable the above setting.

If your theme has a cart listener in the theme code, the document is NOT relevant to you.

On the other hand, if your theme lacks a cart listener you can either

- enable the 'Refresh the page' setting.
This will trigger a page refresh to ensures that any products/discounts added by the app are reflected in the cart items and total

OR

- add a cart listener to your theme.
Either by following the below mentioned steps or by contacting us via live chat/email support, we'll add it in for you

What are Sections?


Sections are liquid files that allow you to create reusable modules of content that can be customized by merchants. Follow the below link for more information:

https://shopify.dev/docs/themes/architecture/sections

What are Selectors?


Selectors are CSS-based classes, IDs, or any valid CSS selector that is used to select any element. We use the selector to replace the inner HTML of the selected element with the new HTML code we receive after calling the section API. Check the below code for more context.

Adding a cart listener requires editing of the theme code - you/your developer or agency can refer to the steps mentioned to achieve this:

Find the main or global asset of the theme in order to put the code in that file because you will need to run it on theme load
In the global file, you need to put the below code, but before that we need to find the Section IDs and selector for sections
After getting all the right selectors you can simply paste them below in the file

// handles the rendering of updated sections
const renderContents = (parsedState, sectionsToRender) => {
    sectionsToRender.forEach((section) => {
    // get the element present in current DOM to update
    const sectionElement = section.selector
      ? document.querySelector(section.selector)
      : document.getElementById(section.id);
    if (parsedState[section.id])
      // get the innerHTML of fetched updated element based on id and selector
      sectionElement.innerHTML = getSectionInnerHTML(
        parsedState[section.id],
      section.selector
    );
  });
};

const getSectionInnerHTML = (html, selector) =>
  // parses string to HTML
  new DOMParser()
    .parseFromString(html, "text/html")
    .querySelector(
      selector.slice(0, 1) === "#" && !selector.includes("shopify-section")
        ? `#shopify-section-${selector.slice(1)}`
        : selector
    ).innerHTML;

// adds a event listener to the custom event
document.addEventListener("cart:refresh", () => {
  checkSectionConditionsAndUpdate();
});

// checks for all the length of sections to fetch and update
// because max length which API can fetch is 5 only
const checkSectionConditionsAndUpdate = () => {
  const isCartPage = window.location.pathname.includes("/cart");

  const sectionsConfig = [
    ...getCommonSectionsToRender(),
    ...(isCartPage
      ? getCartPageSectionsToRender()
      : getCartDrawerSectionsToRender()),
  ];

  const sectionUpdateConfig = {
    sectionsLimitReached: false,
    sectionsConfig,
  };

  // conditions for length
  if (sectionsConfig.length > 5) {
    let startRemovePosition = 0;

    for (let i = 0; i < Math.ceil(sectionsConfig.length / 5); i += 1) {
      getSectionsAndUpdate({
        ...sectionUpdateConfig,
        startRemovePosition,
        sectionsLimitReached: true,
      });
      startRemovePosition += 5;
    }
  } else getSectionsAndUpdate(sectionUpdateConfig);
};

// fetches the sections and updates them accordingly
const getSectionsAndUpdate = async ({
  sectionsLimitReached,
  startRemovePosition = 0,
  sectionsConfig,
}) => {
  // concatenates sections IDs to a string
  const sectionsToFetch = (
    sectionsLimitReached
      ? sectionsConfig.slice(
          startRemovePosition,
          sectionsConfig.length < startRemovePosition + 5
            ? sectionsConfig.length
            : startRemovePosition + 5
        )
      : sectionsConfig
  ).reduce(
    (curr, section, i) => (i ? `${curr},${section.id}` : curr),
    sectionsConfig[startRemovePosition].id
  );

  const sectionData = await fetch(
    `${window.location.pathname}?sections=${sectionsToFetch}`
  );
  const data = await sectionData.json();

  renderContents(data, sectionsConfig);
};

const getCommonSectionsToRender = () => {
  return [
    {
      id: "cart-icon-bubble",
      selector: "#cart-icon-bubble",
    },
  ];
};

const getCartDrawerSectionsToRender = () => {
  return [
    {
      id: "cart-drawer",
      selector: "cart-drawer",
    },
  ];
};

const getCartPageSectionsToRender = () => {
  return [
    {
      id: "template--19704478892306__main",
      selector: "#shopify-section-template--19704478892306__main",
    },
    {
      id: "cart-live-region-text",
      selector: "#cart-live-region-text",
    },
    {
      id: "template--19704478892306__main",
      selector: "#shopify-section-template--19704478892306__main",
    },
  ];
};


Copy this code in the file, and then replace the selector appropriately

For common selector, you need to update in getCommonSectionsToRender function
For the cart page selector you need to update in getCartPageSectionsToRender function
For the cart drawer selector you need to update in getCartDrawerSectionsToRender function

After updating this, the cart should update without a page refresh. Pay extra attention when finding the Section IDs and selector or else the code might not execute as expected.

If you DO NOT have a developer who can custom code the cart listener into your theme or if your developer is unable to find the right Sections IDs & selectors, please reach out to us at support@monkcommerce.com or via live chat - we'll be happy to assist and get this up and running for your store at no additional cost

Updated on: 05/12/2023