Skip to main content

Woo Custom Events

Woo runtime events are browser CustomEvent objects. They bubble, so you can listen on a component, a nearby wrapper, or document.

Use events as the integration contract for work that happens after a Woo action. Do not use data-ome-state="success" as an integration contract; that state is visible UI feedback for the control that just finished an action.

Which Event Should I Use?

GoalEvent
Open a mini-cart, track an add-to-cart conversion, or inspect the product that was added.ome-woo:item-added
Refresh any cart-related integration after add, quantity update, or item removal.ome-woo:cart-updated
Track add-to-cart failures.ome-woo:add-to-cart-error
React to quantity changes or item removal with row-level detail.ome-woo:item-quantity-updated or ome-woo:item-removed
React to committed variable-product selection state inside a Product Provider.ome-woo:variation-selection-changed
Track checkout start, completion, and checkout errors.ome-woo:checkout-started, ome-woo:checkout-complete, ome-woo:checkout-error

ome-woo:item-added fires first for successful add-to-cart and includes product_id, quantity, and cart_summary. ome-woo:cart-updated follows when the integration only needs to know that the cart changed.

Event Summary

AreaEventDispatch targetDetail payload
Cart bootome-woo:cart-loadedFirst cart display root found, or document.body.{ cart_summary }
Product addome-woo:item-addedStandalone add button or submitted AddToCartForm.{ product_id, quantity, cart_summary }
Product addome-woo:cart-updatedSame target as the successful cart mutation.{ cart_summary }
Product addome-woo:add-to-cart-errorStandalone add button or submitted AddToCartForm.{ product_id, quantity, error }
Product selectionome-woo:variation-selection-changedNearest ProductProvider root.{ product_id, selection, selected_variation, current_product }
Cart item mutationome-woo:item-quantity-updatedCart item quantity input.{ key, quantity, cart_summary }
Cart item mutationome-woo:item-removedCart item remove button, or document.body if the button was detached first.{ key, cart_summary }
Cart item mutationome-woo:cart-errorCart item quantity input or remove button.{ action, key, quantity?, error }
Checkoutome-woo:checkout-loadedCheckout provider, checkout form, checkout notices, or document.body.{ checkout }
Checkoutome-woo:checkout-startedCheckout form.{}
Checkoutome-woo:checkout-completeCheckout form.{ checkout }
Checkoutome-woo:checkout-errorCheckout form.{ errors?, phase?, source?, error?, diagnostic? }

Shared Payload Shapes

cart_summary is the live cart summary after the mutation:

type WooCartSummary = {
item_count: number;
line_count: number;
};

error is a safe Woo error summary:

type WooErrorSummary = {
code: string;
message: string;
status: number;
field_keys?: string[];
};

checkout is the current Store API checkout response. It can include fields such as order_id, status, order_key, payment_method, payment_result, and __experimentalCart.

diagnostic is present on payment adapter failures when the adapter can provide a safe diagnostic object. It can include methodId, adapterId, provider, paymentType, fieldMode, phase, code, message, details, and sequence.

Product Selection Event

ome-woo:variation-selection-changed

ContractValue
Dispatch targetThe nearest OmeWooProductProvider root. Standalone AddToCartForm does not emit this event.
BubblesYes.
ComposedYes.
CancelableNo.
When it firesAfter Provider datasets and form mirrors have committed a new semantic variable-product selection state. Initialization emits only the final settled state. Recommitting the same state does not emit again. Simple products do not emit it.
Detail payload{ product_id, selection: { phase, attributes }, selected_variation, current_product }

selection.phase is base, partial, resolved, or invalid. selected_variation is the complete resolved variation object or null. current_product is the complete base product until resolution succeeds, then the complete resolved variation. Availability remains a field of the product or variation object; it is not encoded in the phase.

document.addEventListener("ome-woo:variation-selection-changed", (event) => {
const detail = (event as CustomEvent).detail;

if (detail.selection.phase === "resolved") {
console.log(detail.selected_variation);
}
});

Product Add Events

ome-woo:item-added

ContractValue
Dispatch targetThe standalone AddToCartButton, or the submitted AddToCartForm for form-submit buttons.
BubblesYes.
When it firesAfter Store API POST /cart/add-item succeeds and the runtime has a fresh cart summary.
Detail payload{ product_id, quantity, cart_summary: { item_count, line_count } }

Use this event when the integration needs the product and quantity that were just added.

ome-woo:cart-updated

ContractValue
Dispatch targetThe same element that dispatched the successful cart mutation event.
BubblesYes.
When it firesAfter add-to-cart, quantity update, or item removal succeeds.
Detail payload{ cart_summary: { item_count, line_count } }

Use this event when the integration only needs the latest cart count or line count.

Cart mutation scheduling is intentionally not a public event stream. There is no generic transaction-lifecycle event. For local visual progress, style data-ome-woo-mutation-phase; for business integrations, keep using the semantic events above.

ome-woo:add-to-cart-error

ContractValue
Dispatch targetThe standalone AddToCartButton, or the submitted AddToCartForm for form-submit buttons.
BubblesYes.
When it firesAfter Store API POST /cart/add-item fails.
Detail payload{ product_id, quantity, error: { code, message, status, field_keys? } }

Cart Item Events

ome-woo:cart-loaded

ContractValue
Dispatch targetFirst matching cart display root: [data-ome-woo-cart-count], [data-ome-woo-cart-total-field], [data-ome-woo-cart-items], [data-ome-woo-cart-notices], or document.body.
BubblesYes.
When it firesAfter Woo cart boot loads and cart display components are bound.
Detail payload{ cart_summary: { item_count, line_count } }

ome-woo:item-quantity-updated

ContractValue
Dispatch targetThe cart item quantity input.
BubblesYes.
When it firesAfter each real Store API quantity response is committed. Debounced-away, cancelled, and already-satisfied no-op targets do not emit it. An intermediate response still emits this semantic event, while control-local success waits for the latest target.
Detail payload{ key, quantity, cart_summary: { item_count, line_count } }

ome-woo:item-removed

ContractValue
Dispatch targetThe cart item remove button. If that button was detached before the request finished, the event is dispatched from document.body.
BubblesYes.
When it firesAfter Store API POST /cart/remove-item succeeds.
Detail payload{ key, cart_summary: { item_count, line_count } }

ome-woo:cart-error

ContractValue
Dispatch targetThe cart item quantity input for quantity failures, or the remove button for removal failures.
BubblesYes.
When it firesAfter Store API quantity update or item removal fails.
Detail payload{ action, key, quantity?, error: { code, message, status, field_keys? } }, where action is "update-item" or "remove-item".

Checkout Events

ome-woo:checkout-loaded

ContractValue
Dispatch targetFirst matching checkout root: [data-ome-woo-checkout-provider], form[data-ome-woo-checkout-form], [data-ome-woo-checkout-notices], or document.body.
BubblesYes.
When it firesAfter checkout boot loads and checkout components are bound.
Detail payload{ checkout }

ome-woo:checkout-started

ContractValue
Dispatch targetThe checkout form.
BubblesYes.
When it firesAfter local submit validation passes and before payment preparation or Store API checkout submission.
Detail payload{}

ome-woo:checkout-complete

ContractValue
Dispatch targetThe checkout form.
BubblesYes.
When it firesAfter Store API checkout succeeds. Redirect handling can happen after this event.
Detail payload{ checkout }

ome-woo:checkout-error

ContractValue
Dispatch targetThe checkout form.
BubblesYes.
When it firesAfter local validation, payment preparation, payment result handling, or Store API checkout fails.
Detail payloadLocal validation: { errors, phase, source: "local-validation" }. Runtime/payment failure: { error, diagnostic? }.

errors is an array of checkout field errors:

type WooCheckoutFieldError = {
field_key: string;
code: "required" | "invalid_email" | "invalid_country" | "invalid_state";
message: string;
};

phase is "submit" or "update". source is currently "local-validation" when the checkout form blocks submission before Store API checkout.

Example: Open A Mini-Cart Drawer After Add To Cart

Author the drawer and trigger normally:

Authored mini-cart drawer
<OmeDrawerTrigger
targeting='{{"targetDrawerId":"store-mini-cart"}}'
content='{{"label":"Cart"}}'
/>

<OmeDrawer
identity='{{"drawerId":"store-mini-cart"}}'
settings='{{"direction":"right","dismissible":true}}'
>
{#slot default}
<OmeDrawerTitle>Shopping bag</OmeDrawerTitle>
<OmeWooCartItems>
{#slot default}
<OmeWooCartItemImage />
<OmeWooCartItemTitle />
<OmeWooCartItemQuantity />
<OmeWooCartItemRemove />
{/slot}
{#slot empty}
Your cart is empty.
{/slot}
</OmeWooCartItems>
<OmeWooCartTotalsList />
<OmeDrawerClose>Close</OmeDrawerClose>
{/slot}
</OmeDrawer>

Then click the real trigger when ome-woo:item-added bubbles:

Open the drawer after add-to-cart
document.addEventListener("ome-woo:item-added", () => {
const trigger = document.querySelector(
'[data-ome-drawer-trigger][data-ome-target-drawer-id="store-mini-cart"]',
);

if (trigger instanceof HTMLButtonElement) {
trigger.click();
}
});

This keeps OmeDrawerTrigger and OmeDrawer as the drawer owners. The Woo event only decides when to open it.

Example: Track Add-To-Cart Analytics

Track product adds
document.addEventListener("ome-woo:item-added", (event) => {
if (!(event instanceof CustomEvent)) {
return;
}

const { product_id, quantity, cart_summary } = event.detail;

window.dataLayer?.push({
event: "add_to_cart",
product_id,
quantity,
cart_items: cart_summary.item_count,
});
});

Use ome-woo:item-added here because analytics usually needs the specific product and quantity.

Example: Refresh Cart Integrations

Refresh after any cart change
document.addEventListener("ome-woo:cart-updated", (event) => {
if (!(event instanceof CustomEvent)) {
return;
}

const { cart_summary } = event.detail;
document.documentElement.dataset.cartItems = String(cart_summary.item_count);
});

Use ome-woo:cart-updated when the integration does not care whether the cart changed because of add, quantity, or removal.

Example: Capture Checkout Errors

Listen for checkout errors
document.addEventListener("ome-woo:checkout-error", (event) => {
if (!(event instanceof CustomEvent)) {
return;
}

const { errors, error, diagnostic } = event.detail;

console.warn("Checkout failed", {
fieldErrors: errors,
error,
diagnostic,
});
});

Use this for logging, support tooling, or checkout instrumentation. Let CheckoutNotices remain responsible for visible customer messages.