Home Developers JavaScript events

JavaScript events

Last updated on Sep 09, 2026

JavaScript events

The theme 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 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 the theme emits

Event Fires when
shopify:page:view every page load
shopify:product:view a product page loads, and each product card as it scrolls into view
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, and each set of search suggestions
shopify:cart:view the cart drawer opens, or the cart page loads
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.

Some of these fire more often than their names suggest. shopify:product:view fires once per product card as it scrolls into view, carrying a context of collection, search, or recommendation, so a collection page emits many of them. shopify:cart:view fires with a context of page on the cart page as well as when the drawer opens. Read the context field if you need to tell these surfaces apart.

shopify:search:update fires in two places: on the search results page when filters or sort change, and in the search overlay each time a set of suggestions is shown. One shopper typing a query therefore produces several. The overlay events carry the query and resolve their promise with the number of suggestions found, and they carry no product filters, because the page behind the overlay is unrelated to the query.

Driving the cart

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

// Add to cart. Updates the theme'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 the theme'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 }],
});
// The theme 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();
});