LuxeDocsv0.3.0
STOREFRONT APIStable

window.Luxe.cart and events

Place widgets in the Luxe cart drawer and react to what Luxe does. Display only: never a price, never billing data.

Getting the cart object

window.Luxe.cart exists as soon as luxe-root.js runs on a store that uses the Luxe cart drawer (with the theme's own cart it is undefined); register and hideLines calls made before the drawer loads are queued. Your script may run first:

function withLuxeCart(fn) {
  if (window.Luxe?.cart) fn(window.Luxe.cart);
  else document.addEventListener("luxe:ready", () => { if (window.Luxe?.cart) fn(window.Luxe.cart); }, { once: true });
}

Members

MemberSignatureWhat it does
register(zone, renderer) => unregistermount(host, ctx) once, update?(ctx) after each cart read, unmount?() on unregister
hideLines(predicate) => voidKeeps matching lines out of the list and count; they stay in every total
refresh() => voidReads /cart.js once
withLuxeCart((cart) => {
  const unregister = cart.register("checkout-before", {
    mount(host, ctx) {
      host.innerHTML = '<label><input type="checkbox"> Plant a tree (+' + ctx.money(100) + ')</label>';
    },
    update(ctx) {
      /* ctx.cart is Shopify's /cart.js object */
    },
  });
});

ctx is { cart, money(cents), locale }.

Zones and hosts

ZoneWhere
topBelow the header
lines-afterBelow the last line
checkout-beforeAbove the subtotal
checkout-afterUnder the checkout button
emptyIn place of the lines on an empty bag

Each widget gets a light-DOM host inside <luxe-cart-drawer> with data-luxe-slot, styled by your CSS. Hosts are never re-created. #luxe-checkout-anchor is a stable anchor inside the Route host, for Route's Checkout Button Selector.

Events

Every luxe:* event is dispatched on document and is cancelable.

EventWhenDetail
luxe:readyRuntime configured{ version }
luxe:cart:updatedAfter every cart read{ itemCount, totalPrice, lines }; lines is a string, "key:quantity,…"
luxe:kit:addedA set was added; with the theme's own cart, preventDefault() keeps the shopper on the page{ kitId, source }
luxe:drawer:open, closeLuxe drawer only{ source } on open
luxe:drawer:renderedAfter every render{ slots }
luxe:offer:shown, accepted, declinedCheckout offer{ offerId, placement }, { offerId, variantIds }, { offerId }: ids only, never prices or shopper data
luxe:warningTheme editor only{ element, message }

Listened for

EventEffect
luxe:drawer:request-openOpens the drawer
luxe:cart:request-refreshReads the cart once

B2B buyers

For company buyers with B2B buyers on (the default), no Luxe script loads and window.Luxe.b2b is true. Check window.Luxe?.cart first.

Rules

  • Keep optional charges opt-in. Luxe never changes another app's line.
  • Exclude protection, donations or memberships from the ladder with Excluded products, not a line property.
Was this page helpful?Last updated 4 October 2026