Buy X get Y events
On this page
This page is for theme developers. The Buy X get Y banner host,
<andor-bundle data-andor-widget="bxgy">, sends the shared widget
events. The banner and the cart claim row also publish upsell offer
events for custom pixels.
All DOM events are CustomEvents that bubble, so you can listen on
document. The andor:offer_* events are not DOM events. Subscribe to
them in a custom pixel.
Note A custom pixel is optional. AndOr counts offers without one. Add a pixel only if you want the
andor:offer_*events in your own tools.
Events
| Event | Sent on | When |
|---|---|---|
andor:widget:mount |
the banner | the first pass that sees it |
andor:widget:unmount |
the banner and document |
the first pass after it left the page |
andor:display:change |
the banner | its state changed, for example it hid or showed again |
andor:offer_viewed |
customer events | the offer is first seen, once per offer and placement per visit |
andor:offer_clicked |
customer events | a shopper presses Claim |
andor:offer_added |
customer events | the claimed item was added to the cart |
Rules worth knowing:
- No event on first paint.
andor:display:changefires only when the state really changed. - Up to one second late. Treat a change event as a notice, not as the exact moment.
- The cart claim row is not a widget host. It sends no DOM events,
only the
andor:offer_*events.
Payloads
andor:widget:mount, andor:widget:unmount and
andor:display:change carry event.detail.resource:
| Field | Value for this widget |
|---|---|
widgetType |
"bxgy" |
widgetId |
the block id, or "pasted" for a pasted tag |
productId |
null (the banner carries no product id) |
andor:display:change adds previous and current state objects
(previous is null on the first change after mount). The banner
carries no discount, kind, mode, date or price attributes, so the useful
field is visible:
| State field | Value for this widget |
|---|---|
visible |
true while the banner shows |
discountId, kind, mode, endsAt |
null |
priceCents, originalCents |
null |
The andor:offer_* events carry event.customData:
| Field | Type | Meaning |
|---|---|---|
offerId |
string | the offer id (digits) |
placement |
string | "product_page" (banner), "cart_page" or "cart_drawer" (claim row) |
valueCents |
number | adds only: the value of what was added (full price times units), in cents |
No customer data, cart token or product ids are sent.
Examples
React when the banner hides:
document.addEventListener("andor:display:change", (event) => {
const { widgetType, previous, current } = event.detail.resource;
if (widgetType !== "bxgy") return;
if (previous?.visible && !current.visible) {
console.log("Buy X get Y banner hid");
}
});Optional: count claims in a custom pixel:
// Shopify admin: Settings > Customer events > Add custom pixel
analytics.subscribe("andor:offer_added", (event) => {
const { offerId, placement, valueCents } = event.customData;
console.log("upsell add", offerId, placement, valueCents);
});Events the widget listens for
The banner and claim row redraw when your theme sends these Shopify events, so a theme that sends them gets the redraw for free:
shopify:cart:lines-update: the cart changed. The widget reads it again.shopify:cart:view: the cart drawer opened.shopify:section:load: the theme editor re-rendered a section.
If you swap product markup with your own Ajax code, call
AndOrDisplay.refresh() and AndOrEvents.refresh() afterwards. See
JavaScript API.
Data attributes and states
Product page banner
The banner uses the same attributes as the bundle card. See Bundle card events.
Cart claim rows
| Attribute or class | On | Meaning |
|---|---|---|
data-andor-state="unlocked" |
box | the claim row: X is met |
data-andor-state="off" |
box | claimed, another discount won |
data-andor-ready |
host | drawn from the cart. Before that, boxes shimmer |
data-andor-place |
host | cart_page or cart_drawer |
Inside the claim host, the boxes use data-andor-state for their own
progress, because no other script writes it there.
For the attributes every widget shares, like data-andor-state and
data-andor-progress, see
Data attributes and states.
See it in action