Home Developers JavaScript events

JavaScript events

Last updated on Jun 26, 2026

JavaScript events

Reign implements Shopify's Standard Storefront Events and Actions: the cross-theme interface that apps, analytics tools, and AI agents use to read and drive the storefront. You integrate against the standard once. It works on Reign without forking theme files, parsing markup, or intercepting network requests. The same code keeps working on any other theme that implements the standard.

Two Shopify references define the contract:

Anything you find in the theme source that is not a shopify: event or a Shopify.actions call is internal wiring. It can change at any time, so do not depend on it.

Listening for events

Every event bubbles to document. Add a listener and read the event properties:

document.addEventListener('shopify:cart:lines-update', (event) => {
  console.log(event.action, event.lines); // "add", "update", or "remove"
  event.promise?.then(({ cart }) => {
    console.log(cart.totalQuantity, cart.cost.totalAmount.amount);
  });
});

Events that describe an operation in progress (the cart mutations, variant selection, and the collection or search refresh) carry a promise. It resolves once the operation commits and gives you the canonical result: the updated cart, the selected variant, or the new product count. Read the promise when you need the final state rather than the optimistic one.

Events Reign emits

Event Fires when
shopify:page:view every page load
shopify:product:view a product page loads
shopify:product:select the shopper changes a variant
shopify:collection:view a collection page loads
shopify:collection:update collection filters or sort change
shopify:search:update search filters or sort change
shopify:cart:view the cart drawer opens
shopify:cart:lines-update a line is added, updated, or removed
shopify:cart:note-update the cart note changes
shopify:cart:discount-update a discount is applied or removed
shopify:cart:error a cart operation fails

Payloads follow the Shopify Storefront GraphQL API shape: camelCase fields, and prices as money objects with amount and currencyCode. The full payload for each event is documented in Shopify's standard events reference linked above.

Driving the cart

Shopify injects a Shopify.actions object on every storefront. Reign configures it so your calls render in Reign's own drawer and header, with no page reload.

// Add to cart. Updates Reign's drawer and header in place, no reload.
const { cart, userErrors } = await Shopify.actions.updateCart({
  lines: [{ merchandiseId: 'gid://shopify/ProductVariant/123', quantity: 1 }],
});

await Shopify.actions.openCart();               // opens Reign's cart drawer
const { cart: current } = await Shopify.actions.getCart(); // reads the current cart

updateCart also emits the matching shopify:cart: events for you, so code that calls it does not need to dispatch them too. Always check userErrors before you use cart.

Common examples

Track add to cart in analytics

document.addEventListener('shopify:cart:lines-update', (event) => {
  if (event.action !== 'add') return;
  event.promise?.then(({ cart }) => {
    myAnalytics.addToCart(cart);
  });
});

Update the cart from your own code

await Shopify.actions.updateCart({
  lines: [{ merchandiseId: 'gid://shopify/ProductVariant/123', quantity: 1 }],
});
// Reign re-renders its cart drawer and header. No extra refresh call needed.

React when a shopper picks a variant

document.addEventListener('shopify:product:select', (event) => {
  event.promise?.then(({ variant }) => {
    if (variant) updateBadge(variant.availableForSale);
  });
});

Pause background media when the cart drawer opens

document.addEventListener('shopify:cart:view', () => {
  video.pause();
});