Skip to main content

App Events in Analytics

App Events in Analytics lets merchants query supported app-reported activity in Shopify Analytics. Declare the events that your app sends and send matching events through the App Events API. Merchants can then use ShopifyQL to report on the activity using FROM app_events.

Use Shopify-defined standard events, define custom analytics events (app-defined events declared with kind = "custom"), or use both. You can also add custom attributes and metrics to standard events.

Event kindWhen to use it
StandardA registry event describes your app's activity. Shopify supplies its standard attributes and metrics.
CustomYour app needs its own event definition, attributes, and metrics.

An event is available in Shopify Analytics only when all of the following are true:

Use the same full event handle in your declaration and in the API request:

Event kindDeclaration (name)API event_handle
Standardshopify.marketing.email_sentshopify.marketing.email_sent
Customexample-app.workflow_completedexample-app.workflow_completed

The shopify. prefix is reserved for Shopify-defined standard events. Custom events use your app handle as the prefix. Shopify doesn't add either prefix for you.


Anchor to Step 1: Declare your eventsStep 1: Declare your events

Choose an event from the standard event registry that accurately describes the activity that your app reports, and then declare its full handle. Shopify supplies the event's label, category, attributes, and metrics. You don't need to declare those fields yourself.

Set kind = "custom" and define a label and category. Replace example-app with your app handle.

You can declare both kinds of event in one extension. Add an [[extensions.events]] block for each event:

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

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

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

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

[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" }

You declare attributes under dimensions and send them in the API request's attributes object. Metrics summarize the events: count counts events, and sum adds values from a numeric attribute. You don't send metrics in the payload. For custom fields on standard events, see Extend a standard event.


Anchor to Step 2: Deploy the configurationStep 2: Deploy the configuration

Deploy your app configuration with the Shopify CLI app deploy command:

shopify app deploy

By default, app deploy creates an app version and releases it. If you deploy with --no-release, then release the app version before you send events that depend on it.

Shopify validates the declaration during deployment, including event names, types, metric sources, and compatibility with your released configuration. If validation fails, then update the configuration based on the returned error and deploy it again.

Common validation errors include:

  • The standard registry handle isn't recognized.
  • The configuration contains fields that aren't supported.
  • The configuration removes or changes a previously released event.

Anchor to Step 3: Send matching eventsStep 3: Send matching events

Use the exact declared name as the API event_handle. For a standard event, include every required attribute from its registry entry:

{
"shop_id": "gid://shopify/Shop/23423423",
"event_handle": "shopify.marketing.email_sent",
"timestamp": "2026-10-02T14:30:00Z",
"idempotency_key": "email_message_55667788_sent",
"attributes": {
"campaign_id": 100472895,
"message_type": "campaign"
}
}

For the custom event above, send the attributes that you declared:

{
"shop_id": "gid://shopify/Shop/23423423",
"event_handle": "example-app.workflow_completed",
"timestamp": "2026-10-02T14:30:00Z",
"idempotency_key": "workflow_run_1042_completed",
"attributes": {
"workflow_type": "inventory_sync",
"items_processed": 12
}
}

Replace the example values with your app's handle and actual event data. For authentication and headers, see Using App Events.

A 202 Accepted response confirms receipt. Analytics validation is asynchronous, so an event can appear in the Dev Dashboard without being queryable in Shopify Analytics.

A Checkout or Customer Account UI extension can send the same declared standard event with shopify.appEvents.emit(). Use the declared handle as the first argument and include every required attribute.

An extension event doesn't include shop_id, timestamp, or idempotency_key. Shopify adds the app and shop. For the emit() parameters and consent behavior, refer to the API reference for Checkout UI extensions and Customer Account UI extensions.

Caution

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.

For an event attribute with type money, declare the event's currency and send an integer in minor units:

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

With currency = "USD", this request reports an offer worth USD 12.99:

{
"shop_id": "gid://shopify/Shop/23423423",
"event_handle": "shopify.checkout.offer_shown",
"timestamp": "2026-10-02T14:30:00Z",
"idempotency_key": "offer_1042_impression_1",
"attributes": {
"offer_id": 1042,
"offer_type": "upsell",
"offer_value": 1299
}
}

Anchor to Step 4: Query the activityStep 4: Query the activity

After Shopify accepts events for analytics, merchants can query them through FROM app_events.

Standard events expose shared metric names. This query compares email counts by app:

FROM app_events
SHOW emails_sent
GROUP BY app_name
TIMESERIES day
SINCE -7d
UNTIL today

For custom events, use event. followed by the full event name declared in your configuration, then the field handle. Quote name segments that contain hyphens:

FROM app_events
SHOW event."example-app".workflow_completed.workflows_completed,
event."example-app".workflow_completed.total_items_processed
GROUP BY event."example-app".workflow_completed.workflow_type
SINCE -7d
UNTIL today

For apps setting up App Events for the first time, custom fields added to standard events use event.<app_handle>.<short_event_name>.<field_handle>, such as event."example-app".email_sent.total_processing_seconds. Standard fields, such as emails_sent, are queried directly by name. See Extend a standard event for the naming rules and an example.

Your labels appear in results and CSV exports. You use the event. prefix only in queries. It isn't part of the declared event name or API handle.

Shopify supplies app_name from the sending app. You don't need to include it in the payload.


Anchor to Limits and retentionLimits and retention

App Events in Analytics follows the App Events API requirements:

  • Each request contains one event. Batch requests aren't supported.
  • shop_id, event_handle, timestamp, idempotency_key, and attributes are required.
  • attributes can contain up to 15 keys.
  • Attribute values must be strings, numbers, or booleans. Arrays and nested objects aren't supported.
  • Events must not include personal data or data that can identify a natural person.

You must declare standard and custom events before they can be available in Shopify Analytics. See the configuration limits for declaration limits.

Events that a UI extension sends with shopify.appEvents.emit() follow the emit() parameter rules for Checkout UI extensions and Customer Account UI extensions.

Attributes are available for filtering and grouping for 30 days. Count and sum metrics remain available in hourly summaries for up to 365 days, without attribute breakdowns. Query app_events on its own. You can't combine it with another dataset in the same query.


ProblemWhat to check
An event appears in the Dev Dashboard but not in Shopify AnalyticsThe app is installed, the event is declared in a released configuration, and the handle and attributes match the declaration.
A custom name is rejectedUse your app's handle as the prefix and follow the naming rules.
A metric is rejectedCheck its source event, numeric source field for sums, and metric rules.
Field isn't in the schemaThe app is installed, the event is declared and released, and the field is a standard field or one of your declared attributes or metrics.
Query uses the wrong field nameFor custom events, use event. followed by the full declared event name and the field handle. For custom fields on standard events, follow the naming rules.
Attribute filter or breakdown fails for older datesAttributes are available for 30 days. Use a date range within that window.
A money value fails validationDeclare a currency on the event and send an integer in minor units.
Deployment rejects currencyThe event has a money attribute, and the code is a supported uppercase currency code.


Was this page helpful?