> ## Documentation Index
> Fetch the complete documentation index at: https://discountkit.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Events

> The event <dkl-order-goal> emits

`<dkl-order-goal>` recomputes its progress on every cart update and emits a single custom
event when the cart total crosses a tier boundary. To run your own logic on a tier change,
listen for it — see [Reacting to changes](/components/order-goal/web-component#reacting-to-changes)
and the examples on the [web component](/components/order-goal/web-component#examples) page.

## Emits

<Note>
  **`widgetId`.** The **app block's id** — `null` on a web component. `discountId` identifies which order goal a
  concurrent instance tracks.
</Note>

<ParamField body="discount-kit-live:order-goal:tier-change" type="CustomEvent">
  Fired when the cart total crosses a tier boundary. The initial render establishes the
  baseline silently — the event fires only on a subsequent change, in either direction
  (unlocking a tier, or dropping below one when items are removed). The detail carries
  `resource`:

  ```ts theme={null}
  resource: {
    widgetId: string | null
    widgetType: 'order-goal'
    discountId: string
    previousTier: OrderGoalTier | null
    currentTier: OrderGoalTier | null
    cartTotalCents: number
  }

  // previousTier / currentTier are null below the first tier
  type OrderGoalTier = {
    tierLevel: number
    minSpendCents: number
    discountAmount: number     // raw config value: percent, or CENTS for fixedAmount
    discountType: 'percentage' | 'fixedAmount'
    message: string
  }
  ```

  Note `currentTier.discountAmount` is the raw config value — a percent, or **cents** for
  `fixedAmount`.
</ParamField>

A full example payload — the cart crossing from tier 1 into tier 2:

```js theme={null}
// event.detail.resource on tier-change
{
  widgetId: 'a1b2c3d4',        // the app block's id (null on a web component)
  widgetType: 'order-goal',
  discountId: 'discount-1478638797012',
  previousTier: {
    tierLevel: 1,
    minSpendCents: 5000,
    discountAmount: 10,
    discountType: 'percentage',
    message: 'Save 10%'
  },
  currentTier: {
    tierLevel: 2,
    minSpendCents: 10000,
    discountAmount: 15,        // percent — or CENTS when discountType is 'fixedAmount'
    discountType: 'percentage',
    message: 'Save 15%'
  },
  cartTotalCents: 11000
}
```

### Lifecycle

Each Order Goal instance also emits **mount** and **unmount** events as its behaviour
attaches and tears down — handy for wiring up (and cleaning up) custom integrations per
instance. Both **bubble** and carry a `DklWidgetEventDetail` resource. Order goals are
order-level, so the payload is just `widgetType` and `widgetId` (no product/variant).

<ParamField body="discount-kit-live:widget:mount" type="CustomEvent">
  Fired once the controller has attached its behaviour to the (already server-rendered)
  element, after the baseline tier is established. `resource`: `{ widgetType, widgetId }`.
</ParamField>

<ParamField body="discount-kit-live:widget:unmount" type="CustomEvent">
  Fired when the instance tears down — e.g. the element is removed, or the theme editor
  re-renders the section. Same `resource` shape. Use it to detach any listeners or observers
  you set up on mount.
</ParamField>

```js theme={null}
// event.detail.resource on widget:mount / widget:unmount
{
  widgetType: 'order-goal',
  widgetId: 'a1b2c3d4'         // the app block's id (null on a web component)
}
```

## Next steps

<CardGroup cols={2}>
  <Card title="Web Components" icon="code" href="/components/order-goal/web-component">
    Listener and payload examples for reacting to tier changes.
  </Card>

  <Card title="Order Goal overview" icon="circle-info" href="/components/order-goal/overview">
    What the component does, and how it reads the cart total.
  </Card>
</CardGroup>
