---
title: App Events API
description: >-
  Send events about how buyers use your extension to Shopify, where they appear
  in the Dev Dashboard and, for declared standard events, in Shopify Analytics.
api_version: 2027-01
source_url:
  html: >-
    https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/target-apis/platform-apis/app-events-api
  md: >-
    https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/target-apis/platform-apis/app-events-api.md
api_name: checkout-ui-extensions
---

# App Events API

The App Events API sends [app events](https://shopify.dev/docs/apps/build/app-events) from your extension to Shopify. Shopify adds your app and the shop to each event, so your extension doesn't need network access, an access token, or a shop ID. Events appear in the [Dev Dashboard](https://shopify.dev/docs/apps/build/dev-dashboard/monitoring-and-logs) with the events that your app backend sends.

### Use cases

* **Measure extension engagement**: Send a custom event when a buyer interacts with your extension, such as accepting an offer or choosing a delivery option.
* **Report standard events for Shopify Analytics**: Send a [standard event](https://shopify.dev/docs/apps/build/app-events/analytics/standard-event-registry) that your app has declared, so merchants can query it with ShopifyQL.
* **Skip a backend round trip**: Report what happened in checkout without sending a request from the extension to your app's backend.

### Support Targets (33)

### Supported targets

* [purchase.​address-autocomplete.​format-suggestion](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/address#format-a-selected-suggestion-)
* [purchase.​address-autocomplete.​suggest](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/address#suggest-address-completions-)
* [purchase.​checkout.​actions.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/navigation#navigation-target)
* [purchase.​checkout.​block.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/block#block-target)
* [purchase.​checkout.​cart-line-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/order-summary#line-item-targets)
* [purchase.​checkout.​cart-line-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/order-summary#checkout-cart-line-list-)
* [purchase.​checkout.​chat.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/web-components/overlays/chat)
* [purchase.​checkout.​contact.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/information#information-target)
* [purchase.​checkout.​delivery-address.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/shipping#render-after-delivery-address-)
* [purchase.​checkout.​delivery-address.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/shipping#delivery-address-targets)
* [purchase.​checkout.​footer.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/footer#footer-target)
* [purchase.​checkout.​header.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/header#header-target)
* [purchase.​checkout.​payment-method-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/payment#render-after-payment-methods-)
* [purchase.​checkout.​payment-method-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/payment#payment-targets)
* [purchase.​checkout.​pickup-location-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/local-pickup#render-after-pickup-locations-)
* [purchase.​checkout.​pickup-location-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/local-pickup#location-list-targets)
* [purchase.​checkout.​pickup-location-option-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/local-pickup#location-option-item-target)
* [purchase.​checkout.​pickup-point-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/pickup-points#render-after-pickup-points-)
* [purchase.​checkout.​pickup-point-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/pickup-points#pickup-points-targets)
* [purchase.​checkout.​reductions.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/order-summary#checkout-reductions-after-)
* [purchase.​checkout.​reductions.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/order-summary#reductions-targets)
* [purchase.​checkout.​shipping-option-item.​details.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/shipping#shipping-option-item-targets)
* [purchase.​checkout.​shipping-option-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/shipping#render-after-shipping-option-)
* [purchase.​checkout.​shipping-option-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/shipping#render-after-shipping-options-)
* [purchase.​checkout.​shipping-option-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/checkout/shipping#shipping-option-list-targets)
* [purchase.​thank-you.​announcement.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/thank-you/announcement#thank-you-announcement-)
* [purchase.​thank-you.​block.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/thank-you/block#block-target)
* [purchase.​thank-you.​cart-line-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/thank-you/order-summary#line-item-targets)
* [purchase.​thank-you.​cart-line-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/thank-you/order-summary#thank-you-cart-line-list-)
* [purchase.​thank-you.​chat.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/web-components/overlays/chat)
* [purchase.​thank-you.​customer-information.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/thank-you/information#information-target)
* [purchase.​thank-you.​footer.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/thank-you/footer#footer-target)
* [purchase.​thank-you.​header.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc/targets/thank-you/header#header-target)

### Properties and methods

The [`shopify` global object](https://shopify.dev/docs/api/checkout-ui-extensions/2027-01-rc#target-apis-define-what-your-extension-does) provides the app events interface for the current checkout. Call `shopify.appEvents.emit()` with an event handle and optional attributes. The promise resolves with `{success: true}` when checkout accepts the event, or `{success: false, error}` when it doesn't send it. The promise doesn't reject.

* **app​Events**

  **AppEvents**

  **required**

  Reports events to Shopify for this app.

### AppEvents

Reports events to Shopify for this app.

* emit

  Reports one occurrence of an app-defined event.

  ```ts
  (eventHandle: string, attributes?: AppEventAttributes) => Promise<AppEventEmitResult>
  ```

### AppEventAttributes

Attributes related to an app event.



### AppEventAttributeValue

A value attached to an app event.

```ts
string | number | boolean
```

### AppEventEmitResult

The outcome of an \`emit\` call. \`success: true\` means the host accepted the event. It does not confirm delivery. \`success: false\` means the event was not sent. \`error\` describes why.

```ts
{readonly success: true} | {readonly success: false; readonly error: string}
```

### Examples

* #### Send a custom event

  ##### Description

  Send a custom event when the buyer adds a bundle. This example checks the result and logs the reason when checkout doesn't send the event.

  ##### jsx

  ```jsx
  import '@shopify/ui-extensions/preact';
  import {render} from 'preact';

  export default function extension() {
    render(<Extension />, document.body);
  }

  function Extension() {
    async function handleClick() {
      const result = await shopify.appEvents.emit(
        'bundle_added',
        {
          bundle_id: 'summer_bundle',
          placement: 'order_summary',
        },
      );

      if (!result.success) {
        console.warn(result.error);
      }
    }

    return (
      <s-button onClick={handleClick}>
        Add the summer bundle
      </s-button>
    );
  }
  ```

* #### Send a declared standard event

  ##### Description

  Send a standard event for Shopify Analytics. This example sends \`shopify.checkout.offer\_shown\` with its required attributes when the offer renders. Your app must declare the event first.

  ##### jsx

  ```jsx
  import '@shopify/ui-extensions/preact';
  import {render} from 'preact';
  import {useEffect} from 'preact/hooks';

  export default function extension() {
    render(<Extension />, document.body);
  }

  function Extension() {
    useEffect(() => {
      // Declare shopify.checkout.offer_shown in your app's
      // Analytics App Events configuration first. Use the
      // full handle and include every required attribute.
      shopify.appEvents.emit('shopify.checkout.offer_shown', {
        offer_id: 1234,
        offer_type: 'upsell',
        placement: 'order_summary',
      });
    }, []);

    return (
      <s-banner heading="Add a gift box for $5" />
    );
  }
  ```

***

## Best practices

* **Call `emit()` once for each occurrence**: Events from UI extensions have no `timestamp` or `idempotency_key`. Shopify records the time that it receives each event, and each call creates a separate event.
* **Check the result**: When `success` is `false`, `error` describes why the event wasn't sent, such as invalid attributes or an exceeded rate limit.
* **Don't send personal data**: Don't include any data in `attributes` that, alone or in combination with other data, could identify an individual. This includes names, email addresses, phone numbers, and customer IDs.
* **Use the full handle for standard events**: To send a standard event, use the handle that you declared in your app's [Analytics App Events configuration](https://shopify.dev/docs/apps/build/app-events/analytics/toml-configuration), including the `shopify.` prefix, and include every required attribute.

***

## Limitations

* Checkout sends events only when the buyer has allowed analytics processing. Events wait on the page until consent is given, and are discarded if the buyer declines or leaves the page.
* Each extension can send a burst of up to 20 events, then 2 events per second. Over the limit, `emit()` returns `{success: false}`.
* Event handles have a maximum of 128 characters. `attributes` has a maximum of 15 keys, and values must be strings, numbers, or booleans.
* Events from UI extensions aren't processed for billing. To report usage for Shopify App Pricing, send a billing event from your app backend through the [App Events API](https://shopify.dev/docs/api/app-events).
* Events aren't sent from the checkout editor or from checkouts in the Shop app.

***
