Skip to content

Terminal

Blueprint terminal ready. Run help to see available commands.

Press Tab to complete commands and paths

Keyboard shortcuts

6 min read

Standard events and actions: one contract every Liquid storefront now speaks

Different storefront structures converging through one shared interface

I have lost count of how many times I have opened a theme I did not build and spent the next hour tracing its cart code.

You find the function that updates a line item, work out which private custom event it fires, then read the result back from the DOM. Eventually it works, but only for that theme. Change the theme, move the integration to another store, or hand the project to somebody else and the whole thing can quietly fall apart.

Shopify's standard storefront events and actions replace that guesswork with a shared contract. I think this is one of the most important Liquid storefront updates in years.

The storefront finally has a shared language

The idea is simple when you look at it from both directions:

  • Events flow from the theme to an app or agent. The theme announces that a product was viewed, a variant was selected, the cart changed, or a search was refined.
  • Actions flow from an app or agent to the storefront. The app asks Shopify to read the cart, update it, or open it.

They ship together, so learning one side makes the other easier to understand. Themes talk. Apps and agents act.

The feature is live, not a developer preview. Shopify injects the standard cart actions into every Liquid storefront. Themes can adopt the standard events and configure actions to preserve their own interface behaviour.

Themes announce with standard events

Standard events are DOM events under a shopify: namespace. They bubble to document, which means an app can listen at the top level with plain JavaScript.

// Listen for cart line changes from a supporting theme
// or from the standard updateCart action.
document.addEventListener("shopify:cart:lines-update", (event) => {
  const { action, lines } = event;

  event.promise?.then(({ cart }) => {
    console.log(action, lines, cart.cost.totalAmount.amount);
  });
});

The initial contract covers eleven useful moments across page, product, cart, collection, and search experiences:

  • shopify:page:view
  • shopify:product:view and shopify:product:select
  • shopify:cart:view, line, note, discount, and error events
  • shopify:collection:view and shopify:collection:update
  • shopify:search:update

The payloads follow Storefront API shapes, so listeners can read useful data directly instead of parsing the DOM or making another request. Async events also expose a promise that settles when the underlying work completes.

Here is the part that makes the contract especially useful. If a theme implements standard cart events, the listener above can handle changes from the theme's own cart flow. If the theme configures updateCart, the action runtime emits the matching event after a successful change. One listener can cover both paths.

Apps and agents instruct with standard actions

Actions are functions on Shopify.actions. Three cart actions are available on every Liquid storefront:

  • Shopify.actions.getCart()
  • Shopify.actions.updateCart({ lines })
  • Shopify.actions.openCart()

An app or browser agent can add a product and open the cart without knowing whether the theme uses a drawer, a modal, or a cart page.

const result = await Shopify.actions.updateCart({
  lines: [
    {
      merchandiseId: "gid://shopify/ProductVariant/123",
      quantity: 1,
    },
  ],
});

if (!result.userErrors?.length) {
  await Shopify.actions.openCart();
}

Shopify's default handlers perform the cart work and then refresh or reveal the cart when possible. A theme can configure the same actions to update its own drawer, counter, or sections in place. The caller continues to use the same interface either way.

That separation is the important bit. The app states its intent. The theme remains responsible for how that intent appears in its interface.

Available everywhere, adopted progressively

There is an important distinction between actions and events.

Apps can call the standard cart actions on every Liquid storefront without first installing theme code. Existing theme behaviour continues to work, and Shopify provides the default action behaviour.

Event coverage depends on the theme implementing the relevant events. A theme also needs to configure an action if it wants to replace Shopify's default handling with its own interface update. This gives apps a universal action fallback now while allowing themes to adopt richer event coverage progressively.

A practical repository of examples

The official references describe the complete contract, but I wanted something smaller that makes the relationship between each side obvious. I created liquid-standard-events-actions-demos, a collection of focused, copy-pasteable examples for themes, apps, and agents.

The repository is deliberately not a full theme or app. Each file isolates one part of the contract:

  • Listen to events: subscribe to product, cart, collection, and search events and read their payloads.
  • Call actions: use updateCart, getCart, and openCart, including user error and warning handling.
  • Agent cart flow: read the current cart, add a line, and open the cart through the shared action interface.
  • Load and dispatch events: add Shopify's standard-events library to a Liquid theme and announce storefront interactions.
  • Configure actions: connect the standard action contract to a theme's own cart UI.

You can clone the repository and inspect the examples side by side:

git clone https://github.com/BillyNoyes/liquid-standard-events-actions-demos.git

For theme development, Shopify CLI can also expose the standard events inspector:

shopify theme dev --standard-events-inspector

The inspector validates event payloads during development and makes it much easier to see the contract working.

What this unlocks

A stable interface is only interesting if it lets us build something once and reuse it. A few possibilities stand out to me:

  • Analytics without private theme conventions. One set of listeners can follow product views, search refinements, and cart changes across supporting themes.
  • A live view of a shopper. Standard events can stream what somebody is doing during assisted shopping, a call, or a demo without polling the page.
  • Widgets that genuinely react. Bundles, upsells, and recommendations can respond to product or cart changes without learning a theme's private event system.
  • Carts that agents can drive. An agent can read, update, and open a cart on a Liquid storefront it has never seen before.
  • Theme changes with a smaller integration cost. Moving to another supporting theme no longer means rebuilding every storefront hook from scratch.

Why this is such a big Liquid update

Liquid themes have always been extensible, but storefront integrations have often depended on undocumented implementation details. The platform had shared commerce primitives, yet the last mile inside the browser was different everywhere.

Standard events and actions create that missing browser-level contract. They do not force every theme to look or behave the same. They separate intent from implementation, allowing an app to ask for a cart update while the theme decides how to present it.

That is a meaningful shift for app developers, theme developers, demo engineers, and anyone experimenting with browser agents. Less time reverse engineering a theme means more time building the actual experience.

Start with the example repository, then use Shopify's references for the full events and actions contracts.

Search suggestions are unavailable. Try again.

Loading...