Add a Free Shipping Progress Bar to Shopify Cart Drawer

Share
Why Add A Free Shipping Progress Bar?
Let’s be real: “Free shipping” is the oldest trick in the ecommerce book — because it still works. But it works better when shoppers see how close they are to earning it. A free shipping progress bar adds visual urgency, encourages higher average order value, and does it without discounts or gimmicks.
⚠️ Heads-up Before You Start
Editing your Shopify theme code requires a basic understanding of HTML, CSS, and JavaScript. Always duplicate your theme to create a backup before making any changes.
Step 1: Set Free Shipping Rule in Shopify Admin
From your Shopify admin:
- Go to → Settings → Shipping and delivery
- Under General shipping rates, click Manage rates
- Add a new rate:
- Condition: Based on order price
- Minimum price: 50 (or 100 depending on your threshold)
- Rate name: Free Shipping
- Price: 0.00
- Save the settings
Step 2: Create A Snippet
In your theme:
- Go to Online Store → Themes → Edit code
- Under the Snippets folder, create a New file
- Name it: a-free-shipping-progress-bar.liquid
- Add the following code and Save it
<div class="cart-shipping__wrapper" style="color: {{ settings.cart_text_color }}; font-size: {{ settings.cart_font_size }}px;" role="region" aria-live="polite"> <p class="cart-shipping__numOuter"> {{ settings.cart_text_before_amount }} <b> <span class="cart-shipping__currency"></span> <span class="cart-shipping__num">0.00</span> </b> {{ settings.cart_text_after_amount }} </p> <p class="cart-shipping__success" style="color: {{ settings.cart_success_color }};" aria-live="assertive"> {{ settings.cart_success_text }} </p> <div class="cart-shippingThreshold__bar" style="background-color: {{ settings.cart_bar_bg_color }}; position: relative;"> <span class="cart-shippingThreshold__progress" style="background: linear-gradient(90deg, {{ settings.cart_bar_fill_color_start }}, {{ settings.cart_bar_fill_color_end }});"></span> </div> </div> <style> .cart-shipping__wrapper { padding: 15px 0; width: 100%; } .cart-shipping__numOuter, .cart-shipping__success { margin-bottom: 6px; font-weight: 600; display: none; } .cart-shippingThreshold__bar { border-radius: 5px; height: 8px; width: 100%; overflow: hidden; display: block; margin-top: 5px; } .cart-shippingThreshold__progress { position: absolute; top: 0; left: 0; height: 100%; width: 0%; border-radius: 5px; transition: width 0.5s ease-in-out; } </style> <script> window.shopUrl = '{{ request.origin }}'; window.routes = { cart_add_url: '{{ routes.cart_add_url }}', cart_change_url: '{{ routes.cart_change_url }}', cart_update_url: '{{ routes.cart_update_url }}', cart_url: '{{ routes.cart_url }}', predictive_search_url: '{{ routes.predictive_search_url }}', }; document.addEventListener("DOMContentLoaded", function () { const threshold = {{ settings.free_shipping_threshold | default: 50 }} * 100; // cents function calculateProgress(currentVal) { const progressBars = document.querySelectorAll('.cart-shippingThreshold__progress'); const progressNums = document.querySelectorAll('.cart-shipping__num'); const progressOuter = document.querySelectorAll('.cart-shipping__numOuter'); const successMsgs = document.querySelectorAll('.cart-shipping__success'); let percent = Math.round((100 * currentVal) / threshold); percent = Math.min(Math.max(percent, 0), 100); progressBars.forEach(el => el.style.width = percent + "%"); let remaining = Math.max(0, (threshold - currentVal) / 100); if (remaining === 0) { successMsgs.forEach(el => el.style.display = 'block'); progressOuter.forEach(el => el.style.display = 'none'); tooltip.style.display = 'none'; } else { successMsgs.forEach(el => el.style.display = 'none'); progressOuter.forEach(el => el.style.display = 'block'); progressNums.forEach(el => el.textContent = remaining.toFixed(2)); document.querySelectorAll('.cart-shipping__currency').forEach(el => { el.textContent = Shopify.currency.active_symbol || '$'; }); if (percent >= 50 && percent < 100) { tooltip.style.display = 'block'; tooltip.textContent = "{{ settings.cart_tooltip_text }}"; } else { tooltip.style.display = 'none'; } } } function fetchAndUpdate() { fetch('/cart.js') .then(res => res.json()) .then(data => calculateProgress(data.total_price)); } fetchAndUpdate(); document.addEventListener("cart:updated", (e) => { if (e.detail && e.detail.cart) { calculateProgress(e.detail.cart.total_price); } else { fetchAndUpdate(); } }); const cartContainer = document.getElementById("CartDrawer") || document.querySelector(".cart-page"); if (cartContainer) { const observer = new MutationObserver(() => fetchAndUpdate()); observer.observe(cartContainer, { childList: true, subtree: true }); } }); </script>
Step 3: Add Settings in settings_schema.json
In the theme edit code editor:
- Open: config/settings_schema.json
- Find the big array [ ... ] where all the settings blocks are listed
- Scroll to the bottom of that list, just before the last ]
- Add a comma (,) after the last item } in the list
- Paste this below code and click Save
{
"name": "Free Shipping Progress Bar",
"settings": [
{
"type": "number",
"id": "free_shipping_threshold",
"label": "Free shipping ammount",
"default": 50
},
{
"type": "text",
"id": "cart_text_before_amount",
"label": "Text before amount",
"default": "You're"
},
{
"type": "text",
"id": "cart_text_after_amount",
"label": "Text after amount",
"default": "away from free shipping!"
},
{
"type": "text",
"id": "cart_success_text",
"label": "Free shipping success text",
"default": "You're eligible for Free Shipping!"
},
{
"type": "number",
"id": "cart_font_size",
"label": "Text size (px)",
"default": 16
},
{
"type": "color",
"id": "cart_text_color",
"label": "Text color",
"default": "#000000"
},
{
"type": "color",
"id": "cart_success_color",
"label": "Success text color",
"default": "#0A962B"
},
{
"type": "color",
"id": "cart_bar_bg_color",
"label": "Progress bar background color",
"default": "#EBEBEB"
},
{
"type": "color",
"id": "cart_bar_fill_color_start",
"label": "Progress bar gradient start",
"default": "#000000"
},
{
"type": "color",
"id": "cart_bar_fill_color_end",
"label": "Progress bar gradient end",
"default": "#0A962B"
}
]
}
Step 4: Add Snippet To Your Cart Drawer
In the theme edit code editor:
- Open: snippets/cart-drawer.liquid
- Or wherever your cart content lives
- Paste this right after the opening <form> tag:
{% render 'a-free-shipping-progress-bar' %}
- Save and preview your cart drawer or page
Step 5: Customize Free Shipping Progress Bar
In your theme:
- Go to Online Store → Themes → Customize
- In the theme editor, click the Theme settings icon
- Select Free Shipping Progress Bar
- Adjust the settings as needed (amount, text, colors, bar style, etc.)
- Click Save to apply your changes
If you skip or do not follow these 5 Steps, the Free Shipping Progress Bar will not work.
Real-World Insight
Brands like Allbirds and Brooklinen use cart progress bars to nudge customers over a spending threshold. Shopify brands implementing this tactic have reported up to 22% lift in AOV without needing any paid upsell apps.
Final Thoughts
Free shipping still converts — but only when customers know they’re close. With this simple Shopify snippet and shipping setup, you can create an engaging, mobile-friendly progress bar that drives revenue without plugins, pop-ups, or custom apps.