woocommerce Case study
A2 Offcanvas Cart
Adding a product used to send the customer to the cart page and out of the browsing flow. This is the drawer that replaced that jump: it opens in place, updates through WooCommerce's own fragment system, and stays out of the way when the customer is still shopping.
The business problem
The default add-to-cart path is a page load, which on mobile means losing your place in a long catalog. The usual drawer plugins solve that but bring their own cart state, which drifts from WooCommerce's, and they break under aggressive JavaScript optimization. I needed the interaction without a second source of truth for the cart.
What I delivered
- a2-cart-offcanvas.php, a self-contained MU plugin at version 1.0.23 with its own shortcodes for the toggle, badge and item count.
- Fragment-based updates through woocommerce_add_to_cart_fragments, so the drawer renders from WooCommerce's cart rather than a copy of it.
- Open-on-add behavior driven by a short-lived cookie set in the woocommerce_add_to_cart hook, so the drawer opens after a real add and not on every page view.
- Redirect suppression on two levels: the cart-redirect option is filtered off, and woocommerce_add_to_cart_redirect is forced back to the current URL at a very late priority.
- AJAX endpoints for item removal and fragment refresh, registered for both logged-in and guest users.
- Toman formatting that normalizes Persian and Arabic digits before parsing, because the price HTML arriving from the theme is not consistently in one numeral system.
- Explicit LiteSpeed exclusions so the drawer script is never deferred, delayed or combined.
Technical approach
- The drawer holds no cart state. Every render is WooCommerce's own fragment output, which means it cannot disagree with the cart page.
- GET-based add-to-cart requests are intercepted at wp_loaded before WooCommerce processes them, so a shared or bookmarked URL cannot silently add items.
- The add parameters are stripped from the URL after the fact, which keeps a reload from repeating the add.
- Assets are versioned from the file modification time rather than a hardcoded string, so a CSS change cannot be served stale.
- There is a printed fallback for both the stylesheet and the script, so the drawer still works if the asset files cannot be reached.
Result and evidence
The drawer is live on the store and add-to-cart no longer moves the customer off the page they were browsing. I have not run a controlled test of its effect on conversion, so the claim I will stand behind is the interaction one: the purchase path lost a full page load, and the drawer has stayed consistent with the cart page because it never had its own copy of the state.
Commercial value
Mobile is where most of this store's traffic is, and a page load in the middle of browsing is the most expensive kind of friction. Building on Woo's fragments rather than around them is what keeps it maintainable through WooCommerce updates.
Readable implementation brief
implementation_brief {
project: "A2 Offcanvas Cart"
file: "mu-plugins/a2-cart-offcanvas.php (653 lines, v1.0.23)"
state: "none of its own; renders Woo cart fragments"
open_trigger: "short-lived cookie set in woocommerce_add_to_cart"
redirect: "cart-redirect option filtered off + late redirect
filter forcing the current URL"
guards: "GET add-to-cart intercepted at wp_loaded;
add params stripped from the URL"
ajax: "remove item + refresh fragments, priv and nopriv"
assets: "filemtime versioning, inline fallback, LiteSpeed
excluded from defer/delay/combine"
money: "Persian/Arabic digits normalized before parsing"
}What this project shows
The LiteSpeed exclusions and the digit normalization are the parts I would point at. Neither is interesting design work, and both are the difference between a demo and something that survives on a real Persian store behind an aggressive optimizer.
Choosing not to hold cart state was the decision that made the rest cheap. Most drawer bugs I have seen are really synchronization bugs.