Skip to main content

JavaScript Events Reference

Wonder Theme fires JavaScript events throughout the shopping experience that you can listen to for custom integrations, analytics, third-party apps, and custom functionality.

There are two event systems:

  1. Pub/Sub Events - Theme's internal event bus (lightweight, in-memory)
  2. DOM Custom Events - Standard browser events dispatched on elements

Pub/Sub Events

Wonder uses a lightweight publish/subscribe system for core theme events. The global functions subscribe() and publish() are available on every page.

Subscribing to Events

// Subscribe - returns an unsubscribe function
const unsubscribe = subscribe("cart-update", (data) => {
console.log("Cart updated:", data);
});

// Unsubscribe when no longer needed
unsubscribe();

Available Events

cart-update

Fired when the cart contents change (item added, removed, or quantity updated).

subscribe("cart-update", (data) => {
// data.source - what triggered the update ("product-form", "cart-items", etc.)
// data.productVariantId - the variant ID that was added/changed
// data.cartData - full cart response from Shopify API
console.log("Item added:", data.productVariantId);
console.log("Cart total:", data.cartData.total_price);
});
PropertyTypeDescription
sourcestringComponent that triggered the update
productVariantIdstringVariant ID involved
cartDataobjectFull Shopify cart JSON response

cart-error

Fired when a cart operation fails (e.g., item sold out, quantity exceeds inventory).

subscribe("cart-error", (data) => {
// data.source - what triggered the error
// data.errors - error details from Shopify
// data.message - human-readable error message
console.log("Cart error:", data.message);
});
PropertyTypeDescription
sourcestringComponent that triggered the error
productVariantIdstringVariant ID involved
errorsstringError details from Shopify
messagestringHuman-readable error message

cart-drawer-open

Fired when the cart drawer opens.

subscribe("cart-drawer-open", () => {
console.log("Cart drawer opened");
});

cart-drawer-close

Fired when the cart drawer closes.

subscribe("cart-drawer-close", () => {
console.log("Cart drawer closed");
});

quick-buy-drawer-open

Fired when the Quick Add/Quick Buy modal opens on collection pages.

subscribe("quick-buy-drawer-open", (data) => {
console.log("Quick buy opened");
});

quick-buy-drawer-close

Fired when the Quick Add/Quick Buy modal closes.

subscribe("quick-buy-drawer-close", (data) => {
console.log("Quick buy closed");
});

variant-change

Fired when a customer selects a different product variant.

subscribe("variant-change", (data) => {
console.log("Variant changed:", data);
});

quantity-update

Fired when a line item quantity changes in the cart.

subscribe("quantity-update", () => {
console.log("Quantity updated");
});

Publishing Events

You can also publish events to trigger theme behavior:

// Trigger a cart update notification
publish("cart-update", {
source: "my-custom-integration",
cartData: responseFromShopifyAPI
});

DOM Custom Events

These are standard browser events dispatched on DOM elements using dispatchEvent(). Listen for them with addEventListener().

cart-drawer:refresh

Dispatched on the document to request a cart drawer content refresh. This is the most commonly used event for third-party integrations.

Listen for it:

document.addEventListener("cart-drawer:refresh", (e) => {
console.log("Cart drawer refreshing");
});

Dispatch it (e.g., after adding to cart via your own AJAX call):

document.dispatchEvent(new CustomEvent("cart-drawer:refresh"));

variantChangeStart

Dispatched on the variant-options element when a customer begins selecting a variant, before the UI updates.

document.addEventListener("variantChangeStart", () => {
console.log("Variant selection started");
});

variantChangeEnd

Dispatched on the variant-options element after the variant UI has fully updated.

document.addEventListener("variantChangeEnd", () => {
console.log("Variant selection complete - UI updated");
});

gallery:updated

Dispatched on the document when the product gallery slides change (e.g., after variant selection filters images).

document.addEventListener("gallery:updated", (e) => {
// e.detail.imageSelected - URL of the selected image
// e.detail.optionName - variant option name (e.g., "Color")
// e.detail.optionValue - variant option value (e.g., "Red")
console.log("Gallery updated for:", e.detail.optionValue);
});
PropertyTypeDescription
imageSelectedstringURL of the selected image
optionNamestringVariant option name
optionValuestringSelected option value

facets:change

Dispatched on the document when collection filters change.

document.addEventListener("facets:change", (e) => {
console.log("Filters changed:", e.detail);
});

modalClosed

Dispatched on document.body when any modal dialog closes.

document.body.addEventListener("modalClosed", () => {
console.log("A modal was closed");
});

wtSelectChange

Dispatched on custom-select elements when the selected value changes.

document.addEventListener("wtSelectChange", (e) => {
console.log("Previous:", e.detail.prevValue);
console.log("Current:", e.detail.currentValue);
});
PropertyTypeDescription
prevValuestringPrevious selected value
currentValuestringNew selected value

Event Summary Table

EventSystemFired When
cart-updatePub/SubCart contents change
cart-errorPub/SubCart operation fails
cart-drawer-openPub/SubCart drawer opens
cart-drawer-closePub/SubCart drawer closes
quick-buy-drawer-openPub/SubQuick buy modal opens
quick-buy-drawer-closePub/SubQuick buy modal closes
variant-changePub/SubVariant selected
quantity-updatePub/SubCart line item quantity changes
cart-drawer:refreshDOM EventCart drawer content refresh requested
variantChangeStartDOM EventVariant selection begins
variantChangeEndDOM EventVariant selection complete
gallery:updatedDOM EventProduct gallery slides change
facets:changeDOM EventCollection filters change
modalClosedDOM EventModal dialog closes
wtSelectChangeDOM EventCustom select value changes

Common Integration Examples

Refresh cart after external add-to-cart

If your app or custom code adds items to the cart via the Shopify AJAX API, trigger a cart drawer refresh so the UI stays in sync:

// Your custom add-to-cart call
fetch("/cart/add.js", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ id: variantId, quantity: 1 })
})
.then(response => response.json())
.then(data => {
// Refresh the cart drawer UI
document.dispatchEvent(new CustomEvent("cart-drawer:refresh"));
});

Track add-to-cart for analytics

subscribe("cart-update", (data) => {
if (data.source === "product-form") {
// Fire your analytics event
gtag("event", "add_to_cart", {
item_id: data.productVariantId
});
}
});

Run code after variant selection

document.addEventListener("variantChangeEnd", () => {
const selectedVariant = document.querySelector(
'variant-options [name="id"]'
);
console.log("Selected variant ID:", selectedVariant?.value);
});

Detect when cart drawer is toggled

subscribe("cart-drawer-open", () => {
// Pause background video, disable scroll, etc.
});

subscribe("cart-drawer-close", () => {
// Resume background video, enable scroll, etc.
});

note

The pub/sub system is in-memory only and does not persist across page navigations. Subscribers are cleared on each page load.