Fixes · Free shipping bars and markets

Free shipping bar says free, but checkout charges shipping

The fix

Your free shipping bar doesn’t read your shipping rates. It counts to a number saved in the theme, and when the two differ, the bar promises what checkout won’t give.

Make the theme’s number match the free rate in Settings > Shipping and delivery, and change both together from then on. If you sell in more than one country, one number can’t be right everywhere: give the bar a threshold per country, in that country’s currency, and hide it where there’s no free rate.

01Why the bar and checkout disagree

Checkout works out shipping from your rates. Each shipping zone has its rates, and a free rate usually comes with a condition, such as a minimum order price. Free shipping can also come from a free shipping discount, which can have a minimum purchase amount and can apply automatically (Shopify Help).

The bar in the basket is drawn by the theme, and nothing hands the theme the spend at which a rate turns free. Shopify’s Ajax cart API can estimate rates, but only for a given destination (its examples pass a country, province and postcode), and it returns prices, not thresholds (Shopify, Cart API reference). So the theme keeps its own copy of the number: a theme setting, or a setting on the cart section.

Three ways the copy goes wrong

  1. 01

    The rate changed and the setting didn’t

    The free shipping threshold changes in the shipping settings and the theme keeps counting to the old number. Some themes hold the number in two places, one for the cart drawer and one for the cart page, so one gets changed and the other doesn’t. Figures written in words drift the same way: an announcement bar, a delivery tab on the product page.

  2. 02

    One number, every market

    The bar compares the basket total, which Liquid gives in the shopper’s own currency (Shopify, the cart object), with a number that isn’t in any currency. On a store that sells abroad, the home market’s figure shows up in every other market’s currency, and it’s wrong unless that market’s threshold happens to be the same figure.

  3. 03

    Free shipping somewhere, the bar everywhere

    If only some zones have a free rate, the bar still counts down in all of them. A shopper reaches the number, reads that they’ve qualified, then pays the carrier’s rate at checkout.

Some themes convert the home figure with the exchange rate (Shopify.currency.rate). That fixes the currency, not the amount: a market’s free rate is usually set in its own currency, at its own round number. On this thread (Apr 2025) the conversion fixed the currency and the threshold was still off. On an older one (Jul 2022) an owner found the store promising free shipping over a figure they had never set up; the replies point to the theme editor or an app, which is where these numbers live.

02One number per country, kept in one place

For store owners: one rule, one number

  1. Write down your real rule

    In Settings > Shipping and delivery, open each shipping profile and go through every zone. Note which rate is free and the minimum order price it needs, in that zone’s currency. Check Discounts as well, for an automatic free shipping discount with a minimum purchase.

  2. Find every number the theme shows

    In the theme editor, look under Theme settings and on the cart drawer and cart page sections for a free shipping threshold. Then look for the figure written in words: the announcement bar, the product page’s delivery or returns tab, your FAQ.

  3. Make them match

    Set the bar’s number to the free rate’s minimum. Read the setting’s help text for the unit: some themes want whole pounds or dollars, others the smallest unit (5000 for 50.00).

  4. Sell abroad? Check each market

    Use your store’s country selector to switch market, add to the basket and read the bar. If a market’s threshold differs, or it has no free rate, one number can’t be right there. That needs a threshold per country (below), or the bar switched off in that market.

  5. Next time, change both

    Whenever you change the free rate, change the theme’s number the same day. Ask your developer to say so in the setting’s help text.

For developers: a threshold per country, and no bar where there’s no free rate

The fix we’d build on any theme: one setting that holds a threshold per country, in that country’s currency, read against localization.country. A country that isn’t listed gets no bar. The number lives in one place for the drawer and the cart page, and it doesn’t depend on per-market theme settings (more on those below).

The setting (config/settings_schema.json)json
{
  "type": "text",
  "id": "free_shipping_by_country",
  "label": "Free shipping thresholds by country",
  "info": "Country code and amount in that country's currency, smallest unit (5000 = 50.00), e.g. CA:7500, AU:9000. Countries not listed get no bar. Must match the free rates in Settings > Shipping and delivery."
}
The bar (snippets/free-shipping-bar.liquid)liquid
{%- liquid
  assign threshold = 0
  assign pairs = settings.free_shipping_by_country | remove: ' ' | upcase | split: ','
  for pair in pairs
    assign parts = pair | split: ':'
    if parts.first == localization.country.iso_code
      assign threshold = parts.last | times: 1
    endif
  endfor
-%}
{%- if threshold > 0 -%}
  {%- assign remaining = threshold | minus: cart.total_price -%}
  <div class="free-shipping-bar">
    {%- if remaining > 0 -%}
      Spend {{ remaining | money }} more for free shipping
    {%- else -%}
      You've unlocked free shipping
    {%- endif -%}
  </div>
{%- endif -%}
  • Render the same snippet in the cart drawer and on the cart page, so the two can’t disagree.
  • cart.total_price is in the shopper’s currency and its smallest unit (Shopify), so the amounts in the setting are too.
  • The bar knows the country the shopper is browsing in (Shopify, the localization object). Checkout charges by the delivery address. A shopper browsing one country and shipping to another sees that country’s bar, and checkout wins.
  • Search the theme and its templates for the figure written as text (an announcement bar, a delivery tab) and either build it from the same setting or list those places in the setting’s help text.

What about Shopify’s per-market theme customisation?

Shopify lets you customise a theme per market on the Advanced plan and up. Its help page lists section content and section settings among what can vary by market, and “Theme settings such as global colors or typography” among what can’t (Shopify Help, Customizing online store for markets).

In practice it’s less clear-cut. On one store we fixed, per-market values for the bar’s theme setting, pushed from git as override files, took effect in two markets the theme was already customised for. For two markets it hadn’t been customised for, the same kind of file was ignored. Saving the value in the theme editor’s market view worked: Shopify listed those markets in config/markets.json, a file it manages (Shopify, markets.json), and wrote its own override files. Adding the markets to that file by hand didn’t make ours apply. We couldn’t find these override files described in Shopify’s docs, and the help page says theme settings can’t vary by market, so we wouldn’t build on it; the per-country setting above works without it.

03Fill a basket either side of the line

  1. Below the line and above it, in every market

    For each country you sell to, fill a basket a little under the threshold, then a little over. Read the bar each time, then go to checkout, enter an address in that country and read the shipping line. Stop before paying.

  2. Or check in the admin

    A draft order shows the rates an address gets without anyone paying: in Orders > Drafts, add products and a customer address, then add shipping and read the options.

  3. Countries with no free rate

    Switch to a market with no free shipping. The bar shouldn’t show at all.

  4. After every change to your rates

    Repeat the first step for the market you changed.

From our work

04Two stores, two different fixes

We found this on two stores we look after, both selling in more than one country, and fixed it differently on each because their themes held the number differently.

A brand selling in several markets. Its bar, on product pages and in the cart drawer, counted to one theme setting. In a market with no free shipping at all, it promised free shipping anyway, in that market’s currency. In another, the real threshold was higher than the bar’s figure, so the bar said free at a basket total that still paid for delivery. We switched the bar off in the first market and set the real figure for the second (16 and 18 Sep 2026).

On 19 Oct the store lowered its home threshold. The setting moved with it, and so did the two places that stated the figure in words: the scrolling strip at the top and the product page delivery tab. But two smaller markets had been following the same setting, and a draft order showed their threshold hadn’t changed, so the bar was now promising free shipping too early there. They got their own values, saved through the theme editor’s market view after the files we pushed from git were ignored.

A retailer selling abroad. The cart drawer held its own threshold, lower than the free rate in the shipping settings, so it promised free shipping before checkout would give it, and the cart page had no bar at all. Free shipping existed in one zone only; every other zone paid a carrier rate at any basket size, and the bar showed there too. On 24 Sep we moved the threshold to one theme setting shared by the drawer and the cart page, with help text saying it must match the shipping rate, and added a list of the countries the bar shows in.

When that store later lowered its threshold, its own team changed the one setting in the theme editor. On 22 Oct 2026 the setting and the free rate matched.

  • In our live log“Free delivery threshold corrected across the basket and product pages”

The bigger picture

05Every figure your theme writes down is a copy

A free shipping bar is a promise made in two places, and only one of them is checkout. The same goes for every figure a theme states in words: delivery times, return windows, prices in banners. Each one is a copy, and copies drift.

If you sell in several markets and aren’t sure what each one shows, that’s the kind of check our support work covers: every market and every message, checked against the store’s real settings.

06Sources

Every step and claim above comes from one of these, or from the fix on the store it describes.

  1. Shopify Help Center: Free shipping discounts
  2. Shopify Help Center: Customizing online store for markets
  3. Shopify developers: Cart API reference (shipping rates)
  4. Shopify developers: Liquid objects, cart
  5. Shopify developers: Liquid objects, localization
  6. Shopify developers: markets.json
  7. Shopify Community: Shipping message wrong (Apr 2025)
  8. Shopify Community: Our store is saying free shipping for purchase over $50 but nothing is setup for that (Jul 2022)

Sources checked on .

Contact

Bar and checkout still disagree?

Tell us which countries you sell to, and what each one should get.