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

# Events

> Purchase-flow events and callbacks emitted by the SDK.

# Events

The SDK reports every step of the purchase flow as:

1. **DOM custom events** — bubble up from each `<khaime-*>` component, composed across Shadow DOM. Listen with `addEventListener`.
2. **SDK callbacks** — registered via `sdk.on({ … })`. Easier when you've initialized the SDK programmatically.

Both fire for the same underlying action. Pick whichever fits your integration.

## Two ways to listen

```javascript theme={null}
// Option A — callbacks (global)
sdk.on({
  onAddToCart: (product, quantity) => { /* … */ },
  onPaymentSuccess: (result) => { /* … */ },
});

// Option B — DOM events (per component)
document.addEventListener('khaime:payment-success', (e) => {
  console.log(e.detail.orderId);
});
```

Every event detail includes `timestamp` (ms since epoch) and `merchantId`.

## Purchase-flow events

### `khaime:product-click`

Fired when a customer clicks a product card or tile.

```typescript theme={null}
{
  product: Product;
  source: 'grid' | 'card' | 'detail';
  timestamp: number;
  merchantId: string | number;
}
```

Callback: `onProductClick(product)`

***

### `khaime:add-to-cart`

Fired when a customer adds an item to the cart.

```typescript theme={null}
{
  product: Product;
  quantity: number;
  variant?: { id: number; name: string };
  timestamp: number;
  merchantId: string | number;
}
```

Callback: `onAddToCart(product, quantity)`

***

### `khaime:cart-updated`

Fired on every cart mutation — add, remove, quantity change, clear, or hydrate from storage.

```typescript theme={null}
{
  items: LocalCartItem[];
  itemCount: number;
  subtotal: number;              // minor units
  action: 'add' | 'remove' | 'update' | 'clear' | 'hydrate';
  timestamp: number;
  merchantId: string | number;
}
```

Callback: `onCartUpdated(items, action)`

Use this to update a header badge, drawer count, or analytics.

***

### `khaime:cart-open` / `khaime:cart-close`

Fired when the cart drawer (or cart page) opens or closes.

Callbacks: `onCartOpen()`, `onCartClose()`

***

### `khaime:currency-change`

Fired when the customer picks a different currency from the switcher.

```typescript theme={null}
{
  previousCurrency: string;
  newCurrency: string;
  timestamp: number;
  merchantId: string | number;
}
```

Callback: `onCurrencyChange(newCurrency)`

***

### `khaime:checkout-init`

Fired right after the SDK creates a checkout session (before the payment modal opens).

```typescript theme={null}
{
  productId: number;
  amount: number;       // minor units
  currency: string;
  sessionToken?: string;
  timestamp: number;
  merchantId: string | number;
}
```

Callback: `onCheckoutInit(sessionToken)`

Use this to log checkout starts for funnel analysis.

***

### `khaime:payment-success`

Fired after the customer's payment is confirmed.

```typescript theme={null}
{
  sessionToken: string;
  orderId?: string;
  amount: number;                       // minor units
  currency: string;
  paymentMethod: 'stripe' | 'paystack';
  timestamp: number;
  merchantId: string | number;
}
```

Callback: `onPaymentSuccess(result)`

<Warning>
  This event confirms the **payment UI completed** — not that the charge settled. Always verify via a [webhook](/webhooks/overview) before fulfilling the order.
</Warning>

***

### `khaime:payment-error`

Fired when the payment fails (declined card, expired session, gateway error, etc.).

```typescript theme={null}
{
  error: string;          // human-readable message
  code?: string;          // gateway error code, if available
  sessionToken?: string;
  timestamp: number;
  merchantId: string | number;
}
```

Callback: `onPaymentError(error)`

## Full callback signature

All purchase-related callbacks accepted by `sdk.on(…)`:

```typescript theme={null}
sdk.on({
  onProductClick?:   (product: Product) => void;
  onAddToCart?:      (product: Product, quantity: number) => void;
  onCartUpdated?:    (items: LocalCartItem[], action: string) => void;
  onCartOpen?:       () => void;
  onCartClose?:      () => void;
  onCurrencyChange?: (newCurrency: string) => void;
  onCheckoutInit?:   (sessionToken: string) => void;
  onPaymentSuccess?: (result: PaymentSuccessEventDetail) => void;
  onPaymentError?:   (error: PaymentErrorEventDetail) => void;
});
```

Callbacks are additive — calling `sdk.on(...)` multiple times merges into the existing handler map (later calls override same-named keys).

## Analytics example

Wire every purchase step into your analytics tool:

```javascript theme={null}
sdk.on({
  onProductClick: (p) => analytics.track('Product Viewed', {
    productId: p.id, name: p.title, price: p.price,
  }),
  onAddToCart: (p, qty) => analytics.track('Product Added', {
    productId: p.id, quantity: qty, value: p.price * qty,
  }),
  onCheckoutInit: (sessionToken) => analytics.track('Checkout Started', {
    sessionToken,
  }),
  onPaymentSuccess: ({ orderId, amount, currency, paymentMethod }) => {
    analytics.track('Order Completed', { orderId, revenue: amount / 100, currency, paymentMethod });
  },
  onPaymentError: ({ error, code }) => analytics.track('Payment Failed', { error, code }),
});
```

## See also

* [Pay Button quickstart](/sdks/embedded/quickstart)
* [Storefront + Cart](/sdks/embedded/storefront-cart)
* [Webhooks](/webhooks/overview) for server-side order verification
