How to Set Up Free Shipping Bar on Shopify Without an App

2026-09-18 · shipping fulfillment

You can build a free shipping progress bar in Shopify without paying for an app or adding a third-party script. The whole thing is roughly 40 lines of Liquid, a small block of CSS, and two template edits. It runs on your own theme, so there's no monthly fee and no external request slowing down your store.

The bar works by reading the cart's current subtotal, comparing it to a threshold you set, and telling the customer how much more they need to spend to unlock free shipping. That single sentence moves average order value because it gives shoppers a specific, achievable target instead of a vague promise.

Why a Free Shipping Bar Lifts Average Order Value

Free shipping is one of the strongest purchase triggers in e-commerce, but a static banner that says "Free shipping over $50" only helps customers who were already planning to spend $50. A progress bar does something different: it shows the gap between what's in the cart right now and the threshold.

A customer with $38 in the cart sees "You're $12 away from free shipping." That's a concrete nudge with a defined finish line, and it's far more persuasive than a generic offer. Two behaviors follow:

The mechanic only works if the threshold is set where your margins can absorb it. If free shipping at $50 destroys your profit on a $45 order, set it at $65 and let the bar do its job.

What You Need Before You Start (Theme Access and Backups)

Before you touch any code:

One decision to make now: will the bar appear only on the cart page, or sitewide in the header? Sitewide gets more impressions but can feel intrusive on product pages. Cart-page-only is the safer starting point.

Step 1: Add the Progress Bar Snippet to Your Theme

Snippets are reusable chunks of Liquid. Putting the bar in a snippet means you write it once and render it in multiple places.

In your theme editor, open the snippets folder and click Add a new snippet. Name it free-shipping-bar.liquid.

Paste this:

{%- assign threshold = 5000 -%}
{%- assign remaining = threshold | minus: cart.total_price -%}

<div class="fsb" data-threshold="{{ threshold }}">
  {%- if cart.total_price >= threshold -%}
    <p class="fsb__message fsb__message--unlocked">
      You've unlocked free shipping.
    </p>
  {%- else -%}
    <p class="fsb__message">
      You're {{ remaining | money }} away from free shipping.
    </p>
  {%- endif -%}

  <div class="fsb__track">
    <div class="fsb__fill" style="width: {{ cart.total_price | times: 100 | divided_by: threshold | at_most: 100 }}%"></div>
  </div>
</div>

Two things to understand here. First, threshold is written in cents, so 5000 means $50.00. Change that number to your own threshold. Second, the width calculation multiplies the cart total by 100 and divides by the threshold, then caps it at 100 with at_most so the bar never overflows past full.

If your store uses a currency where the base unit isn't cents, adjust the threshold value accordingly and test the output.

Step 2: Insert the Bar Into Your Cart and Header Templates

Now render the snippet where customers will see it.

Cart page: Open sections/main-cart-items.liquid (in some themes it's templates/cart.liquid). Place this line near the top of the cart items list, above the line items:

{% render 'free-shipping-bar' %}

Header: Open sections/header.liquid and add the same render line just inside the header wrapper, above the navigation:

{% render 'free-shipping-bar' %}

If your theme uses a different header section name, search the sections folder for "header" and open the file that contains the site logo markup.

Save both files. The bar should now appear in preview. If it doesn't, check that the snippet filename matches exactly what you typed in the render tag, including hyphens.

Step 3: Style the Bar With CSS to Match Your Brand

Add styles to your theme's main stylesheet, usually assets/base.css or assets/theme.css. Append at the bottom:

.fsb { padding: 10px 16px; text-align: center; font-size: 14px; }
.fsb__message { margin: 0 0 6px; }
.fsb__message--unlocked { font-weight: 600; }
.fsb__track {
  height: 6px;
  background: #e5e5e5;
  border-radius: 3px;
  overflow: hidden;
}
.fsb__fill {
  height: 100%;
  background: #111;
  transition: width 0.3s ease;
}

Swap the background colors for your brand palette. Keep the track light and the fill dark enough to read at a glance. The transition makes the bar animate when a customer adds an item, which draws the eye to the change.

If your theme uses CSS variables, use those instead of hex codes so the bar inherits your brand automatically.

Step 4: Test the Bar Across Cart Values and Devices

Test these cases before publishing:

Cart subtotal Expected bar state What to check
$0 (empty cart) Bar mostly empty, message shows full remaining amount Message uses correct currency format
$25 of $50 threshold Bar half full, message reads "$25.00 away" Width math is correct
$49.99 of $50 threshold Bar nearly full, message reads "$0.01 away" No rounding errors
$50 or more Bar full, unlocked message shows Width caps at 100%
$500 order Bar full, no overflow at_most filter working

Then check devices:

Add an item to the cart and watch the bar animate. Remove it and confirm the message resets.

Common Errors and How to Fix Them

Tracking Results: Measuring the Impact on AOV

Set a baseline before you publish. In Shopify admin, go to Analytics > Reports and find your average order value for the last 30 days. Note it.

After two weeks with the bar live, compare. A meaningful lift is usually 3% to 8% on stores with a sensible threshold. If AOV is flat, the threshold may be too high for your typical basket size, or the bar isn't visible enough.

Watch these alongside AOV:

Use Shopify's built-in reports rather than guessing. If you want deeper segment tracking, Google Analytics 4 with Shopify's integration can show behavior by traffic source.

Conclusion

A free shipping bar is one of the few conversion tools you can build yourself in under an hour, with no app subscription and no third-party script. The code is short, the logic is simple, and the payoff shows up directly in average order value. Build it in a duplicate theme, test it against the table above, and publish only once the math checks out.

FAQ

Does this work with any Shopify theme? Yes, as long as the theme uses Liquid and you can edit sections. Online Store 2.0 themes and most legacy themes both work. The only variable is which section files hold your header and cart markup, so search the sections folder if the filenames differ.

Will the bar update live when a customer adds an item? On the cart page, no. The page reloads on cart changes, so the bar recalculates then. In a slide-out cart drawer, you'd need to add JavaScript that listens for Shopify's cart update events and re-renders the bar.

What if my free shipping threshold changes seasonally? Edit the threshold value in the snippet. Because it's a single assign line, you can change it in seconds. If you want to change it without touching code, you'd need a theme setting block, which is more setup but lets you adjust it from the theme customizer.