Skip to main content

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.


A handle is a text identifier. Your app, the Analytics App Events extension, and each event have their own handle:

HandleExampleWhere it's used
App handleexample-appIdentifies your app and is the prefix for custom event names.
Extension handleapp-eventsIdentifies the Analytics App Events extension within your app. Set it with handle under [[extensions]] in shopify.extension.toml.
Event handleexample-app.workflow_completedIdentifies 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:

[[extensions]]
type = "analytics_app_events"
handle = "app-events"

[[extensions.events]]
name = "shopify.marketing.email_sent"
kind = "standard"

[[extensions.events]]
name = "shopify.marketing.sms_sent"
kind = "standard"

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:

[[extensions]]
type = "analytics_app_events"
handle = "app-events"

[[extensions.events]]
name = "example-app.workflow_completed"
kind = "custom"
label = "Workflow completed"
category = "Inventory"

[extensions.events.dimensions.workflow_type]
label = "Workflow type"
type = "string"
optional = false

[extensions.events.dimensions.items_processed]
label = "Items processed"
type = "int"

[[extensions.metrics]]
handle = "workflows_completed"
label = "Workflows completed"
aggregation = "count"
source = { event = "example-app.workflow_completed" }

[[extensions.metrics]]
handle = "total_items_processed"
label = "Total items processed"
aggregation = "sum"
source = { event = "example-app.workflow_completed", field = "items_processed" }

Declare each attribute in [extensions.events.dimensions.<attribute_handle>]. Declare each metric in [[extensions.metrics]], with a source that identifies the event.


FieldRequiredDescription
typeYesMust be analytics_app_events.
handleYesIdentifies 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.
eventsYesOne or more standard or custom events.
metricsNoCustom 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.


FieldStandard eventCustom event
nameRequired full registry handle.Required app-qualified name.
kindstandard, the default when omitted.Must be custom.
labelInherited.Required readable label, up to 80 characters.
categoryInherited.Required supported category.
dimensionsOptional custom attributes.Optional attributes defined by your app.
currencySupported 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.

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.

Info

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:

  • Checkout
  • Claims and order protection
  • Demand
  • Discovery
  • Duties and tariffs
  • Experimentation
  • Fraud and risk
  • Fulfillment
  • Inventory
  • Lead capture
  • Loyalty
  • Marketing
  • Merchandising
  • Purchasing
  • Returns
  • Subscriptions
  • Support

Declare each attribute as [extensions.events.dimensions.<handle>] with a label and type. Send its value in the API request's attributes object.

TypeJSON value example
string"inventory_sync"
int12
float2.5
booleantrue
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:

[[extensions]]
type = "analytics_app_events"
handle = "app-events"

[[extensions.events]]
name = "shopify.marketing.email_sent"
kind = "standard"

[extensions.events.dimensions.processing_seconds]
label = "Processing seconds"
type = "float"

[[extensions.metrics]]
handle = "total_processing_seconds"
label = "Total processing seconds"
aggregation = "sum"
source = { event = "shopify.marketing.email_sent", field = "processing_seconds" }

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.

FROM app_events
SHOW emails_sent, event."example-app".email_sent.total_processing_seconds
GROUP BY app_name
SINCE -7d
UNTIL today

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.


FieldRequiredDescription
handleYesMetric identifier. Uses the same naming rules as attribute handles.
labelYesReadable label, up to 80 characters. Used in results and CSV exports.
aggregationYescount to count events, or sum to add numeric values.
source.eventYesExact name of an event declared in this extension.
source.fieldFor sumAn 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.


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:

[[extensions]]
type = "analytics_app_events"
handle = "app-events"

[[extensions.events]]
name = "shopify.checkout.offer_accepted"
kind = "standard"
currency = "USD"

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:

{
"shop_id": "gid://shopify/Shop/23423423",
"event_handle": "shopify.checkout.offer_accepted",
"timestamp": "2026-10-21T14:30:00Z",
"idempotency_key": "offer-accepted-123",
"attributes": {
"offer_id": 123,
"offer_type": "upsell",
"offer_value": 1299
}
}

Send amounts as integers in the currency's minor units:

CurrencyAmountoffer_value
USD12.991299
JPY12991299
KWD12.34512345

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:

[extensions.events.dimensions.offer_value]
label = "Offer value"
type = "int"
semantic_type = "money"

LimitValue
Custom events per app15
Unique custom attribute handles across the app's events64
Attributes per event15, including all of a standard event's required and optional attributes
Custom metrics per event16, subject to the metric rules above
Attribute or metric handle length64 characters
Custom event or field label length80 characters

Metrics don't count toward the payload's attribute limit.


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.


Was this page helpful?