How to update cart without reload after adding a gift product

Hi everyone !
I’m new to Shopify.
Based on theme Dawn, I have created a snippet that automatically add to cart a gift product, if cart total >= 100$, and remove gift is cart total < 100.
The problem is that I have to reload the page once to see the gift added to cart, twice to update the cart count bubbles. How to update efficiently my cart without reloading?

Thanks for your help !

Here is my code :

// assets/free-gift.js

document.addEventListener("DOMContentLoaded", function () {
    const settings = window.freeGiftSettings; 
    const giftProductId = settings.giftProductId;
    const minimumCartValue = settings.minimumCartValue;
    let giftAdded = false;

    function updateCartDrawer() {
      const drawerItems = document.querySelector('cart-drawer-items');
      if (drawerItems && typeof drawerItems.onCartUpdate === 'function') {
        drawerItems.onCartUpdate();
      } else {
        document.dispatchEvent(new Event('cart:updated'));
      }
    }
    
    function checkCartForGift() {
      fetch("/cart.js")
        .then(response => response.json())
        .then(cart => {
          let cartTotal = cart.total_price;
          let giftItem = cart.items.find(item => item.id === giftProductId);
          if (cartTotal >= minimumCartValue && !giftItem && !giftAdded) {
            addGiftToCart();
          } else if (cartTotal < minimumCartValue && giftItem) {
            removeGiftFromCart(giftItem.key);
          }
        });
    }

    function addGiftToCart() {
      fetch("/cart/add.js", {
        method: "POST", 
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          items: [{
            id: giftProductId, 
            quantity: 1, 
            properties: { is_gift: true }
          }],
        })
      })
      .then(response => {
        if (!response.ok) {
          throw new Error("Erreur lors de l'ajout du cadeau");
        }
        giftAdded = true;
        return fetch("/cart.js"); 
      })
      .then(res => res.json())
      .then(cart => {
        const cartData = cart.items;
        document.dispatchEvent(new CustomEvent('cart:refresh', {
          bubbles: true,
          detail: cartData
        }));
        updateCartDrawer();
        updateCartBubble();
        updateCartUI(); 
      })
      .catch(error => console.error("Erreur lors de l'ajout du cadeau :", error));
    }

    function removeGiftFromCart(itemKey) {
        fetch("/cart/change.js", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
            id: itemKey, 
            quantity: 0 
            })
        })
        .then(response => {
            if (!response.ok) throw new Error("Erreur lors du retrait du cadeau");
            giftAdded = false;
            return fetch("/cart.js");
        })
        .then(response => response.json())
        .then(cart => {
            const cartData = cart.items;
            document.dispatchEvent(new CustomEvent('cart:refresh', {
            bubbles: true,
            detail: cartData
            }));
            updateCartDrawer();
            updateCartBubble();
            updateCartUI();
        })
        .catch(error => console.error("Erreur lors du retrait du cadeau :", error));
    }

    function updateCartUI() {
        document.dispatchEvent(new Event('cart:updated'));
    }

    function updateCartDrawer() {
        document.querySelector('cart-drawer').dispatchEvent(new Event('cart:open'));
    }

    function updateCartBubble() {
        fetch('/?sections=cart-icon-bubble')
            .then(res => res.json())
            .then(data => {
               const cartBubble = document.querySelector('[data-cart-icon-bubble]');
               if (cartBubble && data['cart-icon-bubble']) {
                   cartBubble.innerHTML = data['cart-icon-bubble'];
               }
            })
            .catch(error => console.error("Erreur lors de la mise à jour du cart bubble :", error));
    }

    document.addEventListener("cart:updated", checkCartForGift);

    checkCartForGift();
});


You’re right, using a snippet to add and remove a gift product based on cart total can be tricky. The problem is that Shopify doesn’t automatically update the cart after a snippet runs. You’ll need to use JavaScript to force the cart to refresh.

Here’s a step-by-step guide:

  1. Add JavaScript to Your Snippet:

    • Inside your snippet, after the code that adds or removes the gift product, include this JavaScript:
      Shopify.on('cart:update', function(cart) {
        // This function will run whenever the cart is updated
        // You can add code here to update the cart count bubble
        // For example, you could update an element with the ID "cart-count":
        document.getElementById('cart-count').textContent = cart.item_count;
      });
      
  2. Trigger the Cart Update Event:

    • After your snippet adds or removes the gift product, you need to manually trigger the cart:update event so your JavaScript code can run:
      Shopify.on('cart:update', function(cart) {
        // Your existing code
      });
      
      // Trigger the cart update event
      Shopify.on('cart:update', function(cart) {
        // Your existing code
      });
      Shopify.cart.update();
      
  3. Update the Cart Count Bubble:

    • In the JavaScript code within your snippet, update the cart count bubble element. You’ll need to replace #cart-count with the actual ID of your cart count bubble element.

With these changes, your snippet will now automatically update the cart and cart count bubble without needing to reload the page.

Thank you Ava_Tammy for your answer.
Unfortunately I have not been able to work successfully with your solution.

For example, this is my new version to add a gift to cart :

function addGiftToCart() {
        fetch("/cart/add.js", {
          method: "POST", 
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            items: [{
              id: giftProductId, 
              quantity: 1, 
              properties: { is_gift: true }
          })
        })
          .then(response => response.json())
          .then(()=> {
            Shopify.on('cart:update', function(cart) {
                document.querySelector('[data-cart-icon-bubble]').textContent = cart.item_count;
            });
            Shopify.cart.update();
            giftAdded = true;
            updateCartUI(); 
          })
          .catch(error => console.error("Erreur lors de l'ajout du cadeau :", error));
      }

I have some errors in the console, like Shopify.cart.update() is not a known function… And I still need to reload twice the page to see the gift in the cart.
Is there something I might be missing ?

Please be careful suggesting code, what you have supplied does not exist.

It is also completely down to the theme you’re using. Some themes will emit and listen to some events similar to these but not all.