# Bundle card events

> The DOM events and Shopify customer events the AndOr bundle card sends, with payloads and listener examples, plus its data attributes and states.

Source: https://backtrackhq.com/docs/widgets/bundle/events/

This page is for theme developers. The bundle card host,
`<andor-bundle data-andor-widget="bundle">`, sends the shared widget
events. Its views, clicks and adds are also published as upsell offer
events for custom pixels.

All DOM events are `CustomEvent`s 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 host | the first pass that sees the card |
| `andor:widget:unmount` | the host and `document` | the first pass after the card left the page |
| `andor:display:change` | the host | the card's state changed since the last pass |
| `andor:offer_viewed` | customer events | the card was first seen, once per offer and placement per visit |
| `andor:offer_clicked` | customer events | a shopper clicked **Add bundle to cart** |
| `andor:offer_added` | customer events | bundle items were added to the cart |

Rules worth knowing:

- **No event on first paint.** The first pass sends
  `andor:widget:mount` and stores the state silently.
- **Deduped.** If nothing in the state changed, nothing is sent.
- To react to the bundle being applied, style or watch the host's
  `data-andor-progress` attribute. It reads `won` once checkout applies
  the bundle.

## Payloads

`andor:widget:mount`, `andor:widget:unmount` and
`andor:display:change` carry `event.detail.resource`:

| Field | Value for this widget |
|---|---|
| `widgetType` | `"bundle"` |
| `widgetId` | the block id (`data-andor-widget-id`) |
| `productId` | `null` (the card has no `data-andor-product-id`) |

`andor:display:change` adds `previous` and `current` state objects. The
bundle host 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 card shows |
| `discountId`, `kind`, `mode`, `endsAt` | `null` |
| `priceCents`, `originalCents` | `null` |

The `andor:offer_*` events carry `event.customData`:

| Field | Type | Meaning |
|---|---|---|
| `offerId` | string (digits) | the upsell offer |
| `placement` | `"product_page"` | where the offer showed |
| `valueCents` | number | adds only: the value of what was added, in cents |

No customer data, cart token or product ids are sent. The value is an
estimate for your reports.

## Examples

Log when a bundle card mounts:

```js
document.addEventListener("andor:widget:mount", (event) => {
  const { widgetType, widgetId } = event.detail.resource;
  if (widgetType === "bundle") {
    console.log("bundle card on the page, block", widgetId);
  }
});
```

Optional: count bundle adds in a custom pixel:

```js
// Shopify admin: Settings > Customer events > Add custom pixel
analytics.subscribe("andor:offer_added", (event) => {
  const { offerId, placement, valueCents } = event.customData;
  console.log("bundle add", offerId, placement, valueCents);
});
```

## Events the widget listens for

**Add bundle to cart** adds lines with the hidden line property
`_andor_offer_id`, then opens the theme's cart. The card re-reads the
cart on `shopify:cart:lines-update`, so a theme that sends that event
keeps the card in step. See [Cart updates](https://backtrackhq.com/docs/developers/cart-updates/).

## Data attributes and states

| Attribute or class | On | Meaning |
|---|---|---|
| `data-andor-ready` | host | drawn. Before that, it shimmers |
| `data-andor-kept="note"` | host | the card went away after it was applied. Only the line shows |
| `.andor-bundle__img--off` | picture | its row is unticked |

The Buy X get Y banner and the gift banner on the product page use the
same attributes.

For the attributes every widget shares, like `data-andor-state` and
`data-andor-progress`, see
[Data attributes and states](https://backtrackhq.com/docs/developers/data-attributes/).
