Custom Cart Discount Coordination Engine

Bridging Shopify’s cart/checkout logic to show trustworthy, combined discounts in the cart UI.

Role: Lead Developer Deployed to 8+ stores Stack: JS · Liquid · Rebuy · DOM

Summary

Shopify applies automatic discounts at checkout and allows us to handle manual codes at the cart layer. The two don’t natively combine in the cart, and the line item UI does not natively update to reflect the discount, leading to confusing subtotals and lost trust. I built a modular cart-layer system that detects both, allocates discounts proportionally, renders clear per-line price changes, and derives a truthful subtotal so the cart matches checkout expectations.

Client code is private. This case study documents architecture, approach, and redacted UI behaviour.

The Challenge

Solution · Built in Stages

  1. Callbacks for line items – dynamic UI based on quantity/changes. Not native behaviour in all Shopify themes
  2. Free gift handler – reads MOV/code/gift from Admin; adds/removes safely and dynamically depending on cart state
  3. Manual discount code UI adds – compare-at + sale classes; transparent pricing; saves original state for ease of code removal
  4. Proportional allocation – fixed / % discounts spread across line items, so subtotal is accurate.
  5. URL discount sync – detects Shopify’s discount_code cookie; applies same UI updates.
  6. 3-for-2 handler – cheapest eligible item goes to zero; visuals + math stay in sync. UI updates working in conjunction with native "Buy X Get Y" Shopify discount
  7. Auto-discount detection – listens for platform signals; mirrors expected checkout discounting in cart.
  8. Derived subtotal for combo scenarios – sums effective per-line sale prices; overwrites displayed subtotal with guardrails.
  9. Combination logic – manual + auto together with coherent UI and totals.
  10. Split/merge resilience – defensive regrouping; fails-safe to native display when needed.
  11. Event Manager → Coordinator (coming soon) – migrating to a single orchestrator (queue + debounce) for clean sequencing.
  12. State preservation (coming soon) – quick, safe reversion when codes/conditions change.

Technical Challenges

Ensuring proportional discount allocation across mixed cart items (percentage vs. fixed amounts) while maintaining subtotal accuracy required custom mathematical distribution algorithms that consistently matched Shopify's backend calculations. Some markets required different currency formatting while maintaining unified discount logic.

Getting the cart line item UI to accurately reflect combination situations - for example, a URL-based discount is applied by Shopify at checkout level, then manually entered codes are cart level (so essentially ignored by Shopify's frontend). Getting the line item discounting to accurately calculate the correct full discount, update the subtotal - which natively ONLY shows the Shopify-applied disocounting (so the checkout-level, not checkout+cart level) and having everything reliably accurate into the checkout.

Comprehensive debugging was essential given the system's complexity across multiple platforms and discount combinations. Each module includes extensive debug logging that can be enabled via browser console commands (window.CartCallbacks.debug(true)), providing real-time visibility into state changes, allocation calculations, and UI updates. This proved invaluable for troubleshooting edge cases and performance optimization across different international deployments.

Architecture (high level)

The upcoming DiscountCoordinator will replace the current event manager's broadcast approach with intelligent orchestration. Instead of multiple handlers reacting simultaneously to cart events, the Coordinator will analyze discount state first, then decide which handlers should run, in what order, and with what data. This prevents conflicts and race conditions while enabling more sophisticated discount combinations and cleaner debugging workflows.

Impact

Key Technical Learning

Sometimes the best engineering solution works around platform constraints rather than fighting them - building coordination layers often delivers better results than trying to force different systems to communicate natively.

What I’ll Do Next