Configure Analytics App Events
Use an analytics_app_events extension to declare the events that your app makes available in Shopify Analytics. You can use standard events, extend them with custom fields, and define custom analytics events.
Release the configuration before sending matching events through the App Events API.
Anchor to Understand handlesUnderstand handles
A handle is a text identifier. Your app, the Analytics App Events extension, and each event have their own handle:
| Handle | Example | Where it's used |
|---|---|---|
| App handle | example-app | Identifies your app and is the prefix for custom event names. |
| Extension handle | app-events | Identifies the Analytics App Events extension within your app. Set it with handle under [[extensions]] in shopify.extension.toml. |
| Event handle | example-app.workflow_completed | Identifies an event. Declare it as name and send it as the API event_handle. |
Find your app handle in the top-level handle field of shopify.app.toml or your named app configuration, such as shopify.app.production.toml. It also appears in your app's Shopify admin URL: https://admin.shopify.com/store/your-store/apps/<app_handle>/app. For more information, refer to App configuration.
The extension handle doesn't supply the custom event prefix. In the examples on this page, the app handle is example-app and the extension handle is app-events.
Anchor to Declare standard eventsDeclare standard events
Add the extension and event declaration to shopify.extension.toml.
Use the full handle from the standard event registry:
Shopify supplies each standard event's label, category, attributes, and metrics. Use those definitions without redeclaring them. Add an [[extensions.events]] block for each event.
Anchor to Declare custom eventsDeclare custom events
Set kind = "custom" and define the event's label, category, attributes, and metrics. Replace example-app with your app handle in the event name and metric sources. Keep handle = "app-events" as the separate extension identifier, or choose another unique extension handle.
In TOML, double brackets ([[...]]) add an entry to a list, such as an event or metric. Single brackets ([...]) group the settings for one named attribute. Use the bracket styles shown in the following example:
Declare each attribute in [extensions.events.dimensions.<attribute_handle>]. Declare each metric in [[extensions.metrics]], with a source that identifies the event.
Anchor to Extension fieldsExtension fields
| Field | Required | Description |
|---|---|---|
type | Yes | Must be analytics_app_events. |
handle | Yes | Identifies this extension within your app. Must be unique across the app's extensions. Up to 50 letters, numbers, or hyphens, without a leading or trailing hyphen. |
events | Yes | One or more standard or custom events. |
metrics | No | Custom metric declarations. Standard events inherit their standard metrics. |
Omit namespace from new configurations. If your released configuration already includes it, then keep its exact value in future versions.
Anchor to Event fieldsEvent fields
| Field | Standard event | Custom event |
|---|---|---|
name | Required full registry handle. | Required app-qualified name. |
kind | standard, the default when omitted. | Must be custom. |
label | Inherited. | Required readable label, up to 80 characters. |
category | Inherited. | Required supported category. |
dimensions | Optional custom attributes. | Optional attributes defined by your app. |
currency | Supported uppercase currency code for events with money attributes. Required before sending an amount. | Supported uppercase currency code for events with money attributes. Required before sending an amount. |
Anchor to Custom event namesCustom event names
Use <app_handle>.<local_event_handle>, such as example-app.workflow_completed. The prefix must exactly match the app handle from your app configuration. The extension's handle doesn't supply this prefix. The local handle must start with a lowercase letter and contain only lowercase letters, numbers, and underscores, up to 64 characters.
Use the full name in API requests. Shopify doesn't add a prefix for you. The shopify. prefix is reserved for standard events.
If your app has no assigned handle, then use its API key as the prefix. If your currently released configuration includes a namespace, then keep that field and its exact value in every future version. New configurations omit it. If your app's handle changes, then keep released event names unchanged and use the new handle for new events.
If your app configuration includes a namespace, use its value when querying custom fields added to standard events. For example, with namespace = "example-app", a custom processing_seconds field on shopify.marketing.email_sent is queried as event."example-app".email_sent.processing_seconds. Use the short event name, email_sent, without shopify.marketing.
For custom events, use event. followed by the full event name declared in your configuration, then the field handle. For example, a workflow_type field on example-app.workflow_completed is queried as event."example-app".workflow_completed.workflow_type. Don't add the namespace before the event name. Quote name segments that contain hyphens.
If your app has no assigned handle, then use its API key as the prefix. If your currently released configuration includes a namespace, then keep that field and its exact value in every future version. New configurations omit it. If your app's handle changes, then keep released event names unchanged and use the new handle for new events.
If your app configuration includes a namespace, use its value when querying custom fields added to standard events. For example, with namespace = "example-app", a custom processing_seconds field on shopify.marketing.email_sent is queried as event."example-app".email_sent.processing_seconds. Use the short event name, email_sent, without shopify.marketing.
For custom events, use event. followed by the full event name declared in your configuration, then the field handle. For example, a workflow_type field on example-app.workflow_completed is queried as event."example-app".workflow_completed.workflow_type. Don't add the namespace before the event name. Quote name segments that contain hyphens.
Anchor to Supported categoriesSupported categories
Custom events use the same categories as standard events. Set category to one of these values:
CheckoutClaims and order protectionDemandDiscoveryDuties and tariffsExperimentationFraud and riskFulfillmentInventoryLead captureLoyaltyMarketingMerchandisingPurchasingReturnsSubscriptionsSupport
Anchor to Custom attributesCustom attributes
Declare each attribute as [extensions.events.dimensions.<handle>] with a label and type. Send its value in the API request's attributes object.
| Type | JSON value example |
|---|---|
string | "inventory_sync" |
int | 12 |
float | 2.5 |
boolean | true |
datetime | "2026-10-02T14:30:00Z" |
int with semantic_type = "money" | 1299 for USD 12.99. Declare currency = "USD" on the event. |
Handles must start with a lowercase letter and contain only lowercase letters, numbers, and underscores, up to 64 characters. Labels must be nonempty, contain no control characters, and be no longer than 80 characters. String values are limited to 128 characters. Integers must fit within the signed 64-bit range.
Custom attributes default to optional. Set optional = false to require one. An event that's missing a required attribute fails Analytics validation. When present, attribute values must match the declared type. The same attribute handle must use the same type across your app's events. Standard attributes follow the registry's required and optional rules.
Don't include personal data in handles, labels, or values. See the App Events data requirements.
Anchor to Extend a standard eventExtend a standard event
Add custom attributes and metrics without redefining the standard fields. Standard events already include a count metric, so you can add custom attributes and sum metrics, but not another count metric. This example adds processing duration while retaining the standard emails_sent metric:
For apps setting up App Events for the first time, custom fields added to standard events use your app handle, the short standard event name, and the field handle:
event.<app_handle>.<short_event_name>.<field_handle>
For example, an app with the handle example-app queries its custom total_processing_seconds metric on shopify.marketing.email_sent as follows. The shared standard metric, emails_sent, is queried directly by name.
The app prefix stays the same if your app handle later changes. If your app has no handle, Shopify uses its API key as the prefix.
Anchor to Custom metricsCustom metrics
| Field | Required | Description |
|---|---|---|
handle | Yes | Metric identifier. Uses the same naming rules as attribute handles. |
label | Yes | Readable label, up to 80 characters. Used in results and CSV exports. |
aggregation | Yes | count to count events, or sum to add numeric values. |
source.event | Yes | Exact name of an event declared in this extension. |
source.field | For sum | An int or float attribute on the source event, including int attributes with semantic_type = "money". Omit for count. |
A sum can use a custom or standard numeric attribute.
Within an event, each metric handle must be unique and must differ from attribute handles and inherited metric handles. Each event can have one count metric and one sum per source attribute, including inherited standard metrics. You can reuse a metric handle on different events. Because every standard event has a count metric, only custom events can declare a count metric.
Anchor to MoneyMoney
Declare custom monetary attributes with type = "int" and semantic_type = "money". Standard monetary attributes are inherited from the registry. Set a supported uppercase currency code on the event before sending an amount. Only set currency on events that have a money attribute. Deployment fails if you set it on any other event.
Anchor to Declare money amountsDeclare money amounts
For a standard event with an optional money attribute, declare one supported, uppercase currency code for that event:
Send the amount as an int in the currency's minor units. For this USD declaration, the following App Events API request reports an accepted offer worth USD 12.99:
Send amounts as integers in the currency's minor units:
| Currency | Amount | offer_value |
|---|---|---|
| USD | 12.99 | 1299 |
| JPY | 1299 | 1299 |
| KWD | 12.345 | 12345 |
Don't send a decimal amount or add a currency attribute to the payload. Shopify uses the event declaration to attach trusted currency metadata.
An existing count-only declaration can continue omitting both currency and the optional amount. To start reporting amounts, add currency to the existing event declaration and deploy the configuration before sending amounts. You can still omit the amount after declaring a currency. Sending an amount without a currency declaration fails Analytics validation. Zero is a reported amount, not a missing value.
The currency applies to this event across all installations of your app. You can't change or remove it after release. Totals include only reported amounts in the declared currency. Shopify doesn't convert App Events money to the shop currency. Values in different currencies can't be combined in one result. If apps or events report different currencies, then merchants must filter or group by currency_code, such as WHERE currency_code = 'USD'. Review the money amount definitions before choosing a field. For a request example, refer to Send money values.
Anchor to Define custom money attributesDefine custom money attributes
For a custom event, set currency on the event and declare the attribute as follows:
Anchor to LimitsLimits
| Limit | Value |
|---|---|
| Custom events per app | 15 |
| Unique custom attribute handles across the app's events | 64 |
| Attributes per event | 15, including all of a standard event's required and optional attributes |
| Custom metrics per event | 16, subject to the metric rules above |
| Attribute or metric handle length | 64 characters |
| Custom event or field label length | 80 characters |
Metrics don't count toward the payload's attribute limit.
Anchor to Deploy and updateDeploy and update
Run shopify app deploy before sending events that use the configuration. By default, app deploy creates an app version and releases it. If you deploy with --no-release, then release the app version first. You can add events, attributes, and metrics within the limits. Released definitions must remain compatible:
- Keep event names and kinds unchanged.
- Keep existing attributes and their types. Don't make an optional attribute required.
- Keep existing metrics and their aggregations. Don't repoint a released metric to a different source.
- Keep any declared currency and existing namespace unchanged.
For an incompatible custom schema, use a new event name. You can update labels without renaming handles.
Continue with App Events in Analytics to send and query events.