Where you can achieve what your competitors can’t


Free Shipping Progress Bar in Shopify

This custom code is completely free to use, but please note it does not include 1-on-1 technical support. If you need a bespoke, done-for-you solution to customize your Shopify store, my team is here to help! Head to my channel homepage and use the link in the trailer to reach out.

{% assign threshold_value = 50 %}
{% assign threshold_cents = threshold_value | times: 100 %}
{% assign cart_total = cart.total_price %}
{% assign amount_left = threshold_cents | minus: cart_total %}
{% assign progress_percentage = cart_total | times: 100.0 | divided_by: threshold_cents %}

{% if progress_percentage > 100 %}
  {% assign progress_percentage = 100 %}
{% endif %}

{% if amount_left < 0 %}
  {% assign amount_left = 0 %}
{% endif %}

<style>
  .onhow-studio-freeshipping {
    display: block;
    width: 100%;
    margin: 15px 0;
    font-family: inherit;
    box-sizing: border-box;
  }
  .onhow-studio-freeshipping-message {
    text-align: center;
    margin-bottom: 10px;
    font-size: 15px;
    line-height: 1.5;
    color: inherit;
  }
  .onhow-studio-freeshipping-success {
    font-weight: 600;
    color: #10b981;
  }
  .onhow-studio-freeshipping-remaining {
    font-weight: 400;
  }
  .onhow-studio-freeshipping-remaining strong {
    font-weight: 600;
  }
  .onhow-studio-freeshipping-progress {
    width: 100%;
    height: 8px;
    background-color: color-mix(in srgb, currentColor 10%, transparent);
    border-radius: 99px;
    overflow: hidden;
    position: relative;
  }
  .onhow-studio-freeshipping-bar {
    height: 100%;
    background-color: rgb(var(--color-button, 0, 0, 0));
    border-radius: 99px;
    transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
    width: 0%;
  }
</style>

<div class="onhow-studio-freeshipping" data-threshold="{{ threshold_cents }}">
  <div class="onhow-studio-freeshipping-message">
    {% if progress_percentage >= 100 %}
      <span class="onhow-studio-freeshipping-success">🎉 Congratulations! You've unlocked Free Shipping!</span>
    {% else %}
      <span class="onhow-studio-freeshipping-remaining">You are <strong>{{ amount_left | money }}</strong> away from Free Shipping!</span>
    {% endif %}
  </div>
  <div class="onhow-studio-freeshipping-progress">
    <div class="onhow-studio-freeshipping-bar" style="width: {{ progress_percentage }}%;"></div>
  </div>
</div>

<script>
  (function () {
    var container = document.querySelector('.onhow-studio-freeshipping');
    if (!container) return;

    var threshold = parseInt(container.getAttribute('data-threshold'), 10);

    function updateBar(cart) {
      var total = cart.total_price;
      var amountLeft = threshold - total;
      var percentage = (total / threshold) * 100;

      if (percentage > 100) percentage = 100;
      if (amountLeft < 0) amountLeft = 0;

      container.querySelector('.onhow-studio-freeshipping-bar').style.width = percentage + '%';

      var msg = container.querySelector('.onhow-studio-freeshipping-message');
      if (percentage >= 100) {
        msg.innerHTML = '<span class="onhow-studio-freeshipping-success">\uD83C\uDF89 Congratulations! You\'ve unlocked Free Shipping!</span>';
      } else {
        var locale = window.Shopify && window.Shopify.locale ? window.Shopify.locale : 'en-US';
        var money = new Intl.NumberFormat(locale, { style: 'currency', currency: cart.currency }).format(amountLeft / 100);
        msg.innerHTML = '<span class="onhow-studio-freeshipping-remaining">You are <strong>' + money + '</strong> away from Free Shipping!</span>';
      }
    }

    function checkCart() {
      var url = window.Shopify && window.Shopify.routes ? window.Shopify.routes.root + 'cart.js' : '/cart.js';
      fetch(url)
        .then(function (r) { return r.json(); })
        .then(updateBar)
        .catch(function (e) { console.error(e); });
    }

    document.addEventListener('cart:update', function (e) {
      var resource = e.detail && e.detail.resource;
      if (resource && resource.total_price !== undefined) {
        updateBar(resource);
      } else {
        checkCart();
      }
    });
  })();
</script>