When a Shopify promotion breaks at checkout, the cause is almost always the same: the cart and the checkout are separate systems. Your cart is theme and app territory, where JavaScript can draw any deal it likes — “buy 2, save 15%”, a free gift, a bundle price. Checkout is Shopify’s own environment, and it recalculates every total from scratch. If the offer isn’t enforced server-side, checkout doesn’t trust the cart’s number. So it drops the discount, keeps a gift the shopper no longer qualifies for, or charges a different total. The offer looked perfect one screen earlier. The fix isn’t a better cart script — it’s moving enforcement to checkout with a Shopify Function.
Diagnosis: the cart and checkout are separate systems
The mental model that fixes most of these bugs is this: the cart is a suggestion; checkout is the source of truth. Anything a theme or app renders in the cart — a struck-through price, a “free” line, a bundle total — is cosmetic until something enforces it at checkout.
A JavaScript-only promotion works by rewriting what the cart displays. It has no authority over what Shopify charges. When the shopper moves to checkout, Shopify re-evaluates the line items against the discounts and functions that are actually installed. If the deal lives only in cart JavaScript, there’s nothing for checkout to honor — so the number changes.
That single gap explains every failure mode below. The promotion isn’t “buggy” in the cart; it was never real anywhere except the cart.
Why it matters: lost sales and silent margin leaks
A promotion that breaks at checkout fails in two directions, and both are expensive.
The loud failure is a lost sale. The shopper saw a discount, committed, and reached the payment step — the most fragile moment in the funnel — only for the total to jump. That reads as bait-and-switch, and they abandon. You paid to acquire that click and lost it at the finish line.
The quiet failure is worse because nobody reports it: a silent margin leak. If checkout keeps a gift the shopper stopped qualifying for, or applies a bundle discount twice, you win the order but ship it below margin. No complaint, no ticket, no signal — just a leak that runs on every order until someone audits it. That’s why this deserves a real trace, not a patch. If you’d rather have someone follow it end to end, that’s what a free profit audit is for.
The real failure modes
These are the ways a cart-only offer comes apart at checkout — the ones worth reproducing deliberately.
Cart edits after the offer applies. The offer qualifies at “2 items”, the script draws the deal, then the shopper changes quantity to 1 or removes a qualifying product. The cart JavaScript may not re-run its eligibility check, so it keeps showing the deal. Checkout recalculates against the current cart and either drops it or charges wrong.
Currency and Markets changes. Under Shopify Markets, prices convert and round per currency. A discount computed in theme JavaScript against the home-currency price can land on a value that checkout — working from the market’s own converted price — recalculates differently. The deal that was exact in USD is off by more than rounding elsewhere.
Accelerated checkout that skips the cart. Shop Pay, Apple Pay, Google Pay and “Buy now” buttons jump straight from the product page to checkout. Any promotion that only applies in the cart never runs — the shopper bypasses the one screen where the deal existed. The offer silently vanishes for exactly the highest-intent buyers.
Eligibility changes mid-session. A minimum-spend threshold, a “spend $75 for a free gift” progress bar, a first-order condition — if these are evaluated once in the cart and not re-checked at checkout, a shopper can dip below the threshold and still carry the reward, or qualify and lose it.
App conflicts. Two apps both touch the cart — an upsell app, a bundle app, a discount app — and each assumes it owns pricing. One rewrites a line the other already changed, and checkout inherits an incoherent cart. Cart apps that fight over the same line items are a classic source of totals that only reconcile (badly) at checkout.
Two offers colliding. A code plus an automatic discount, or a bundle price plus a site-wide sale. Whether they combine, replace each other, or stack twice is decided by Shopify’s combination rules at checkout — not by whatever the cart drew. If your stacking logic lives in the cart, checkout will overrule it. The mechanics of legitimate stacking are covered in how to run multiple discounts on Shopify.
How to test it: try to break the offer
Don’t test a promotion by confirming it looks right — test it by attacking it. Reproduce the offer, then run this adversarial checklist and watch checkout, not the cart:
- Edit the cart after qualifying. Drop a qualifying item’s quantity, then remove it. Does the deal correctly disappear at checkout — or linger?
- Switch currency and country. Repeat the offer under each active market. If the discount value drifts beyond a rounding cent, it isn’t enforced consistently.
- Use accelerated checkout. Hit “Buy now” / Shop Pay / Apple Pay from the product page and skip the cart entirely. Does the promotion still apply?
- Cross the eligibility threshold both ways. Qualify, then fall below it. Then the reverse. Confirm checkout matches the final cart state, not an earlier one.
- Stack a second offer. Add a code on top of an automatic discount. Confirm it combines exactly once, the way you intended.
- Age the cart. Leave it open, change the promotion in admin, return. Checkout should use the current rule, not the stale one.
If any of these changes the outcome unexpectedly, the promotion isn’t enforced at checkout — it was only ever a cart illusion.
The fix: enforce the promotion with a Shopify Function
Every reliable fix is the same idea: what the shopper sees must be what checkout charges, and only checkout can guarantee that. On Shopify, the tool that makes that guarantee is a Shopify Function — server-side code that re-evaluates the cart at checkout and applies exactly the offer the shopper earned, regardless of how they got there.
Because the Function runs inside checkout, cart edits, currency conversion, accelerated checkout, threshold changes and app ordering can’t route around it. It recalculates against the real, final cart every time. If you want the deeper mechanics, see what are Shopify Functions, and for the build-vs-buy trade-off read Shopify Functions vs discount apps. Building that enforcement is exactly what our custom apps and Shopify Functions work delivers.
What to look for in an offer app
If you’re choosing an app rather than building, the one question that matters is where the offer is enforced. Ask directly:
- Is the discount applied by a Shopify Function, or only drawn in cart JavaScript?
- Does it survive accelerated checkout — Shop Pay, Apple Pay, “Buy now”?
- Does it re-check eligibility at checkout, not just once in the cart?
- How does it behave under Shopify Markets across currencies?
- What happens when it meets another discount — does it respect combination rules?
An app that only answers “it looks great in the cart” is telling you where the offer lives, and it isn’t checkout. Our own AOV Bundle app is built Function-first for exactly this reason: the bundle, quantity break or free gift is enforced at checkout, not painted in the cart.
Common mistakes
- Testing by confirming, not attacking. A promotion that “looks right” proves nothing — break it on purpose.
- Trusting the cart display. The cart is a suggestion; only checkout charges.
- Ignoring accelerated checkout. Your highest-intent buyers skip the cart, and cart-only offers skip them.
- Forgetting Markets. A promotion that’s exact in one currency can misfire in another.
- Letting two apps own pricing. Overlapping cart apps produce totals that only reconcile, badly, at checkout.
- Patching the cart number. Rewriting the display to match checkout hides the leak instead of enforcing the right price.
Promotions breaking at checkout? If your offers live only in the cart, you’re leaking sales and margin. We build checkout-safe promotions with Shopify Functions. See Custom Apps & Shopify Functions or get a free profit audit.