Storefront Drawer API
Kaching Cart is a Shopify app that adds a fully-featured cart drawer to a merchant’s storefront. This page documents the storefront drawer API — a browser-side JavaScript object attached to window.kachingCartApi that lets themes, page builders, and third-party apps drive the drawer: open and close it, read cart state, refresh data, and override the default checkout button behavior.
Prerequisites
Section titled “Prerequisites”- A Shopify store with the Kaching Cart app installed and enabled on the storefront
- The cart extension loaded on the page —
window.kachingCartApiis only available after Kaching Cart has booted
Accessing the API
Section titled “Accessing the API”Once the cart extension boots, the API is attached to the global window object:
window.kachingCartApiIn non-preview environments, opening the browser DevTools console will show a collapsed log group — 🛍️ Kaching Cart API Documentation — listing every available method along with its arguments and whether it returns a Promise. This is generated from the same source as this page and is the canonical reference at runtime.
TypeScript
Section titled “TypeScript”If you’re working in TypeScript, declare the global so the compiler knows about it:
declare global { interface Window { kachingCartApi?: KachingCartApi; }}
interface KachingCartApi { openCart: (options?: { refetchCart?: boolean }) => void; closeCart: () => void; refreshCart: () => Promise<void>; getCartData: () => CartData | undefined; updateTieredPromotionsBar: () => Promise<void>; getCheckoutButtonClickHandler: () => | ((event: MouseEvent) => boolean | Promise<boolean>) | null; setCheckoutButtonClickHandler: ( newHandler: (event: MouseEvent) => boolean | Promise<boolean>, ) => void;}kachingCartApi is typed as optional because it’s only present after the extension boots — always narrow before calling.
Methods
Section titled “Methods”openCart
Section titled “openCart”Opens the cart drawer.
window.kachingCartApi.openCart();openCart(options?: { refetchCart?: boolean }): void| Option | Type | Default | Description |
|---|---|---|---|
refetchCart | boolean | false | When true, the drawer refetches cart data as it opens. Use this after adding/updating items outside the drawer. |
Example — open after adding an item via the Shopify AJAX API:
await fetch("/cart/add.js", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ id: variantId, quantity: 1 }),});
window.kachingCartApi?.openCart({ refetchCart: true });closeCart
Section titled “closeCart”Closes the cart drawer.
window.kachingCartApi.closeCart();closeCart(): voidrefreshCart
Section titled “refreshCart”Refetches the cart data from Shopify and updates the drawer. Use after a mutation that happened outside Kaching Cart’s own controls — for example, an Add-to-Cart elsewhere on the page, or a third-party app that mutated the cart.
await window.kachingCartApi.refreshCart();refreshCart(): Promise<void>The returned Promise resolves once the refetch completes. If you need the drawer to reopen with the fresh data, prefer openCart({ refetchCart: true }) — it combines both operations.
getCartData
Section titled “getCartData”Returns the currently cached cart data synchronously. The shape follows Shopify’s Cart AJAX API response, with a few Kaching-specific extensions.
const cart = window.kachingCartApi.getCartData();
if (cart) { console.log(`Cart has ${cart.item_count} items, total ${cart.total_price}`);}getCartData(): CartData | undefinedReturns undefined if the cart hasn’t been fetched yet. Commonly used fields:
| Field | Type | Description |
|---|---|---|
token | string | Shopify cart token. |
item_count | number | Total quantity across all line items. |
total_price | number | Cart total in the store’s currency subunits (e.g. cents). |
total_discount | number | Total discount applied to the cart, in subunits. |
items_subtotal_price | number | Subtotal before discounts, in subunits. |
currency | string | ISO currency code, e.g. "USD". |
items | array | Line items in the cart. |
attributes | object | Cart-level custom attributes. |
note | string | Cart note. |
checkoutUrl | string? | Resolved checkout URL when available. |
updateTieredPromotionsBar
Section titled “updateTieredPromotionsBar”Recomputes the tiered promotions bar and applies any free gifts, automatic discounts, or upgrades that have become eligible. Useful when you’re about to redirect a customer to checkout after adding an item programmatically and want their cart-level promotions reflected before they leave the storefront.
await window.kachingCartApi.updateTieredPromotionsBar();updateTieredPromotionsBar(): Promise<void>If the tiered promotions bar is not active on the store, this is a no-op. Otherwise it fetches the latest cart state with promo operations resolved, then resumes normal cart interception.
Example — add an item then go straight to checkout with promos applied:
await fetch("/cart/add.js", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ id: variantId, quantity: 1 }),});
await window.kachingCartApi?.updateTieredPromotionsBar();window.location.href = "/checkout";getCheckoutButtonClickHandler
Section titled “getCheckoutButtonClickHandler”Returns the currently registered custom checkout button handler, or null if none has been set.
const handler = window.kachingCartApi.getCheckoutButtonClickHandler();getCheckoutButtonClickHandler(): | ((event: MouseEvent) => boolean | Promise<boolean>) | nullUse this if you want to compose with an existing handler — read it, wrap it, and pass the wrapped version back via setCheckoutButtonClickHandler.
setCheckoutButtonClickHandler
Section titled “setCheckoutButtonClickHandler”Overrides the default checkout button click handler with a function of your own. The handler runs when the customer clicks the checkout button inside the cart drawer.
window.kachingCartApi.setCheckoutButtonClickHandler((event) => { // run custom logic — analytics, validation, custom redirect, etc. return true; // allow the default redirect to proceed});setCheckoutButtonClickHandler( newHandler: (event: MouseEvent) => boolean | Promise<boolean>,): voidReturn value semantics:
| Returned value | Behavior |
|---|---|
true | Continue with the default checkout redirect. |
false | Cancel the default redirect. |
Promise<boolean> | Awaited — same semantics as the resolved value. |
| Anything else | Treated as “continue” — only false cancels. |
Example — redirect to a custom checkout page:
window.kachingCartApi.setCheckoutButtonClickHandler((event) => { event.preventDefault(); window.location.href = "/pages/my-custom-checkout"; return false; // cancel the default redirect});Example — run async validation before allowing checkout:
window.kachingCartApi.setCheckoutButtonClickHandler(async (event) => { const ok = await validateCartWithMyBackend();
if (!ok) { alert("Please resolve the issues in your cart before checking out."); return false; }
return true;});Example — compose with an existing handler:
const previous = window.kachingCartApi.getCheckoutButtonClickHandler();
window.kachingCartApi.setCheckoutButtonClickHandler(async (event) => { trackCheckoutClick();
if (previous) { return await previous(event); }
return true;});