Why do customers still get charged shipping when their order should qualify for free shipping?

When a cart splits across shipping profiles or fulfillment locations, Shopify's free-shipping minimum can apply to each piece separately instead of the whole order — here's why, and how to fix it.

shippingsplit-ordersfree-shippingfulfillment

What's going on

A customer adds enough to their cart to clear your "free shipping over $75" banner, gets to checkout, and finds one part of the order ships free while another line still carries a shipping charge — or the order splits into two separate shipments, each billed separately. The merchant didn't do anything wrong in the sense of a bug; this is how Shopify's shipping engine is designed to work once more than one shipping profile or fulfillment location is involved, but it reads as broken to the customer and generates support tickets and cart abandonment.

This shows up most often for stores that have a custom shipping profile for a subset of products — oversized furniture, fragile items, a dropshipped category, or anything shipped from a second warehouse. Shopify groups cart items by shipping profile (and by fulfillment location) and calculates a rate for each group independently at checkout. A free-shipping price condition set on a profile checks the subtotal of items assigned to that profile, not the customer's total cart value, so a full cart can still miss the free-shipping condition on the sub-group that holds the custom-profile items even though the storefront-wide progress bar shows the order as qualifying.

Why it happens

Shopify shipping rates are configured per shipping profile (Settings > Shipping and delivery > Manage rates), and every store starts with one General profile plus room for up to 99 custom ones. Any product not explicitly moved into a custom profile stays in General; once a cart contains items from two different profiles, or items fulfilled from two different locations, checkout groups them and calculates a separate rate — including any free-shipping price condition — for each group using only that group's subtotal.

A storefront's cart-page free-shipping progress bar is almost always driven by theme code that just compares the full cart total against a target number, because that is simple to build and looks reassuring. It has no visibility into how checkout will actually group and price the order, so it can promise something the shipping engine won't deliver once profiles or locations diverge.

5 ways to fix it

1

Consolidate products into one shipping profile whenever possible

If items are split into a custom profile for a reason that no longer matters much (an old vendor setup, a slightly different weight class), moving them back into the General profile is the cleanest native fix. With everything in one profile, Shopify evaluates your free-shipping price condition against the customer's full cart subtotal instead of a subtotal per group, so the number on your cart page banner matches what actually happens at checkout. Do this in Settings > Shipping and delivery > Manage rates, by dragging products back to the General profile.

2

Set the same free-shipping threshold on every profile that could apply

When you genuinely need separate profiles (different warehouse, different carrier, oversized items), open each profile's rate table and add a matching "Free shipping" rate at the same dollar threshold. This won't merge the shipments into one package, but it keeps the promise consistent: a customer who crosses your stated minimum won't get free shipping on one line item and a surprise charge on another. Check this under each profile's shipping zone, not just the General one — it's easy to set it in one place and forget the rest.

3

Use Shopify Functions (delivery customization) for order-wide logic, if you're on Plus or have dev resources

Shopify's Delivery Customization API lets you write a function that looks at the entire cart's value, regardless of how many shipping profiles or fulfillment groups it splits into, and hide or override rates accordingly — for example, zeroing out shipping cost on every group once the combined cart total clears your threshold. This is the only way to get true order-level free shipping when profiles split by design (e.g., fulfillment location). It requires custom development, not a checkout setting.

4

Add clear cart and product page messaging about split shipments and the threshold

Since checkout, not your theme, ultimately decides how many shipments and rates apply, don't let your cart page promise something checkout can't guarantee. Add a short note near your free-shipping bar ("Orders with [specific item type] may ship in a separate package with its own shipping rate") and, on the product page for items you know sit in a different profile, flag that up front. This is copy/theme work, not a setting, but it's the fastest way to stop the support tickets even before you fix the underlying profile setup.

5

Audit why the split exists in the first place

Splits usually come from one of three sources: a custom shipping profile, products stocked at different fulfillment locations, or an item marked for local delivery/pickup only. Go through Settings > Shipping and delivery and Settings > Locations to confirm which one is driving it — sometimes consolidating inventory into fewer locations or turning off an unused location removes the split entirely, which is a more permanent fix than layering on more messaging.

Bottom line

There's no single toggle that makes Shopify's free-shipping threshold apply cleanly across every possible split shipment — it's a byproduct of how shipping profiles and fulfillment locations are evaluated independently. Start with the free fix (consolidate profiles or align thresholds across them), add plain-language messaging so customers aren't surprised, and only reach for custom Shopify Functions development if you have a real business reason to keep multiple profiles and need true order-wide logic. No app is required to solve the core mismatch; a shipping-bar or cart-messaging app can help with the communication piece, but it won't change how checkout actually calculates the rate.

Still Stuck?

Browse the rest of the problem library, run a free storefront scan to catch issues like this automatically, or email us and we'll work out a custom solution for it.