Appearance
Theme events overview ​
Note
This documentation is provided for developers looking to build on top of our theme. We assume advanced knowledge of JavaScript, CSS and Liquid. Please note that while we welcome feedback, we are not able to provide support for anything described here.
JavaScript theme events allow you to build on top of our themes in a predictable and reliable way.
The theme dispatches events at key points in its lifecycle, like when a product is added to the cart or when the current variant is changed. Theme events also provide relevant data directly from theme components.
Additionally, the theme listens to events that allow you to control theme elements, for example, refreshing all sections that show cart state.
Target ​
Events from the theme are dispatched to document
.
Product root ​
The product root element is an element that contains the variant selectors and the product form. It is also the primary Alpine.js component for the product section.
The product root is identified by its [x-data]
attribute but it also has a data-product-root
attribute to make it easier to select. The value of the attribute is the section’s ID as generated by Shopify ({{ section.id }}
).
HTML
<div
id="shopify-section-template--14962412257369__main"
class="shopify-section"
>
<section
id="template--14962412257369__main"
x-data="Product({ /* … */ })"
data-product-root="template--14962412257369__main"
></section>
</div>
<div
id="shopify-section-template--14962412257369__main"
class="shopify-section"
>
<section
id="template--14962412257369__main"
x-data="Product({ /* … */ })"
data-product-root="template--14962412257369__main"
></section>
</div>
JavaScript
const productRootEl = document.querySelector(
`[data-product-root="${shopifySectionId}"]`
);
// or:
const productRootEl = document
.querySelector(`.shopify-section-${shopifySectionId}`)
.querySelector('[data-product-root]');
// or:
const productRootEl = productFormEl.closest(
'[data-product-root]'
);
// etc.
const productRootEl = document.querySelector(
`[data-product-root="${shopifySectionId}"]`
);
// or:
const productRootEl = document
.querySelector(`.shopify-section-${shopifySectionId}`)
.querySelector('[data-product-root]');
// or:
const productRootEl = productFormEl.closest(
'[data-product-root]'
);
// etc.
Alpine.js ​
Our theme events can be listened to from Alpine.js as well as plain JavaScript. Here’s an example implementation of a theme:variant:change
event listener in both JavaScript and Alpine.js.
JavaScript ​
JavaScript
document.addEventListener('theme:variant:change', (e) => {
const {
productRootEl,
formEl,
variant,
previousVariant,
product,
} = e.detail;
});
document.addEventListener('theme:variant:change', (e) => {
const {
productRootEl,
formEl,
variant,
previousVariant,
product,
} = e.detail;
});
Alpine.js ​
Liquid
<div
x-data="{ variantId: null }"
@theme:variant:change.document="variantId = $event.detail.variant.id"
>
The variant ID is <span x-text="variantId"></span>
</div>
<div
x-data="{ variantId: null }"
@theme:variant:change.document="variantId = $event.detail.variant.id"
>
The variant ID is <span x-text="variantId"></span>
</div>
Proxies ​
Sometimes, properties returned in detail
objects can be JavaScript Proxies, because they are reactive properties from an Alpine.js data scope. While they should behave just like their underlying value in most cases, you can use Alpine.raw()
to unwrap them should you need to, for example:
JavaScript
document.addEventListener('theme:variant:change', (e) => {
console.log('Variant Proxy', e.detail.variant);
console.log(
'Unwrapped variant object',
Alpine.raw(e.detail.variant)
);
});
document.addEventListener('theme:variant:change', (e) => {
console.log('Variant Proxy', e.detail.variant);
console.log(
'Unwrapped variant object',
Alpine.raw(e.detail.variant)
);
});
Logging theme events in the console ​
Theme events are logged to the console inside the theme editor. If you'd like to log events outside the theme editor, set window.themeEventsDebugMode
to true
before the theme-events.js
script is evaluated.
Naming convention ​
Theme events start with theme:
, for example theme:variant:change
.
Note
Events that don’t start with theme:
are internal and are subject to change at any time.
Control events ​
Control events dispatched to the theme take the form of a command, with a verb in the second slot.
Theme event | Control event |
---|---|
theme:variant:change is dispatched by the theme when the current variant has changed | theme:change:variant can be dispatched to the theme to change the current variant |
Events list ​
Theme events ​
theme:variant:change
theme:product:add
theme:line-item:change
theme:cart:change
theme:cart:update
theme:cart-drawer:opening
theme:cart-drawer:open
theme:cart-drawer:closing
theme:cart-drawer:closed
Error events ​
theme:product:error:add-to-cart
theme:line-item:error
theme:cart:error:other
theme:cart:error
Control events ​
These are events that the theme listens to.
theme:change:variant
theme:update:cart
theme:open:cart-drawer
theme:close:cart-drawer
Theme support ​
You can check window.theme.events.version
to see if a theme supports theme events.
Theme | Theme events support |
---|---|
Exhibit | Coming soon |
Shapes v3.0.0 | v1.0 |
Baseline v3.1.0 | v1.0 |
Cascade | Coming soon |
Label | Coming soon |