Using App Events
With the App Events API, you can send events from your app to Shopify. All events are shown in the Dev Dashboard, and events with handles that match a Shopify App Pricing billing meter are automatically processed as billable usage. For a step-by-step guide to setting up billing events, see Build a billing event.
In this tutorial, you'll build an end-to-end tracking flow using onboarding as the example. The same pattern applies to any custom event — define your event handles, structure your attributes, send them through the API, and analyze the data in the Dev Dashboard.
Anchor to What you'll learnWhat you'll learn
In this tutorial, you'll learn how to do the following tasks:
- Authenticate with the App Events API
- Define event handles and design attribute structures for your use case
- Send custom events to the App Events API
- Include structured attribute data to track meaningful metrics
- Use the Dev Dashboard to monitor trends and troubleshoot issues
Anchor to RequirementsRequirements
- A Partner account
- A development store
- An app
- An API key
Anchor to Step 1: Authenticate with the App Events APIStep 1: Authenticate with the App Events API
The App Events API uses JWT tokens for authentication. Generate a token using your app's client credentials from the Dev Dashboard.
Use your app's client ID and client secret to request an access token:
https://api.shopify.com/auth/access_token
The response includes an access_token, the granted scope, and an expires_in value in seconds:
{} Response
Store this token securely in your app. Tokens expire after 60 minutes — refresh them before they expire.
Anchor to Step 2: Plan your eventsStep 2: Plan your events
Before sending events, define what you want to track and how you'll structure the data. A well-planned event schema makes it easier to filter and analyze data in the Dev Dashboard.
Anchor to Define the event handlesDefine the event handles
Pick handles that clearly describe the event. For the onboarding example, you'll send two events that bookend the flow:
| Event handle | When to send | Purpose |
|---|---|---|
onboarding_started | The merchant opens your app's setup flow for the first time | Track when merchants begin onboarding and which version they see |
onboarding_completed | The merchant finishes all setup steps | Track completion rates, time-to-complete, and which steps merchants finish |
Together, these events let you calculate onboarding completion rates, identify where merchants drop off, and measure how long onboarding takes.
The same pattern works for other use cases. For example, if you're tracking errors, you might define a server_error handle that fires whenever your app returns a 500 to a merchant, with attribute fields like error_code, endpoint, and stack_trace. If you're tracking feature usage, you might define report_generated with fields like report_type and row_count.
Anchor to Design the attributes structureDesign the attributes structure
Custom event attributes are flexible JSON objects. Include data that helps you analyze behavior and troubleshoot issues.
Don't include any data that, alone or in combination with other data, could identify an individual. This includes any merchant or buyer information, such as name, email address, phone number, and other identifiable data points. Use anonymized identifiers and aggregated metrics instead.
Don't include any data that, alone or in combination with other data, could identify an individual. This includes any merchant or buyer information, such as name, email address, phone number, and other identifiable data points. Use anonymized identifiers and aggregated metrics instead.
Here's the attributes structure for the onboarding example:
onboarding_started attributes:
| Field | Type | Description |
|---|---|---|
onboarding_version | integer | The version of your onboarding flow, so you can compare changes over time |
total_steps | integer | The total number of steps in the onboarding flow |
source | string | Where the merchant entered onboarding from (for example, app_install, settings_page, welcome_link) |
onboarding_completed attributes:
| Field | Type | Description |
|---|---|---|
onboarding_version | integer | Matches the version from onboarding_started |
steps_completed | integer | How many steps the merchant actually finished |
total_steps | integer | The total number of steps available |
time_to_complete_seconds | integer | Seconds between onboarding_started and onboarding_completed |
Use a consistent naming convention for your event_handle values. Sticking with snake_case makes them easier to filter and search in the Dev Dashboard.
Use a consistent naming convention for your event_handle values. Sticking with snake_case makes them easier to filter and search in the Dev Dashboard.
Anchor to Step 3: Send the first eventStep 3: Send the first event
When a merchant opens your onboarding flow for the first time, send an onboarding_started event to record it.
Anchor to Create the reporting functionCreate the reporting function
Anchor to Integrate into your onboarding flowIntegrate into your onboarding flow
Call the reporting function when the merchant first lands on your onboarding page. Use the idempotency_key to prevent duplicates if the merchant refreshes the page:
app/routes/onboarding.jsx
The idempotency key onboard_start_{shopId}_v3 ensures that if the merchant visits the onboarding page multiple times, only the first visit is recorded. Update the version suffix when you change your onboarding flow.
Anchor to Step 4: Send a follow-up eventStep 4: Send a follow-up event
When a merchant finishes all the steps in your onboarding flow, send an onboarding_completed event with metrics about their experience. Pairing related events like this — a start and an end event — lets you measure conversion rates and time-to-complete for any flow.
Anchor to Create the reporting functionCreate the reporting function
Anchor to Integrate into your onboarding completion handlerIntegrate into your onboarding completion handler
Call the reporting function when the merchant completes the final step. Track the start time so you can calculate time_to_complete_seconds.
The code below reads startTime and stepsCompleted from the form submission. You'll need to store these values when the merchant begins onboarding — for example, save startTime (as a Unix timestamp from Date.now()) in a hidden form field or in the merchant's session when the onboarding page first loads, and increment stepsCompleted as the merchant progresses through each step.
app/routes/onboarding.complete.jsx
The time_to_complete_seconds field in the attributes lets you measure how long merchants take to finish onboarding. Compare this metric across onboarding versions to see whether your changes are making setup faster or slower.
Anchor to Step 5: Verify events in the Dev DashboardStep 5: Verify events in the Dev Dashboard
After sending both events, use the Dev Dashboard to confirm they're being recorded and inspect the data.
Anchor to Find your eventsFind your events
- Go to the Dev Dashboard and select your app.
- Click Logs in the sidebar.
- Set the Type filter to App Event to show only app events.
You should see your custom events in the list. In this example, you'd see both onboarding_started and onboarding_completed. Custom events are labeled as Non-billable since they don't match a billing meter.
Anchor to Inspect event detailsInspect event details
Click any event to see its full details:
- Event handle: The handle you defined (for example,
onboarding_started) - Shop: The merchant's shop domain
- Timestamp: When the event occurred
- Attributes: The full JSON attributes with all the fields you included
Verify that the attribute fields contain the values you expect. If any field is missing or incorrect, check your app's reporting logic.
Anchor to Filter by event typeFilter by event type
Use the search and filter options to focus on specific events:
- Filter by Shop to see a specific merchant's event history
- Search by event handle to find all instances of a specific event
- Compare timestamps between related events (like
onboarding_startedandonboarding_completed) for the same shop to verify calculated fields liketime_to_complete_seconds
Anchor to Step 6: Analyze event trendsStep 6: Analyze event trends
With events flowing into the Dev Dashboard, you can analyze behavior across your merchant base.
Anchor to Monitor event volumeMonitor event volume
Switch to the Monitoring tab to see aggregated event data. The event graph shows the volume of events over time, which helps you:
- Track adoption: See how many merchants trigger a given event each day or week
- Measure conversion: Compare the volume of paired events (like
onboarding_startedvs.onboarding_completed) to calculate completion rates - Spot issues: A sudden spike in
server_errorevents or a drop inonboarding_completedwhile starts remain steady might indicate a bug
Anchor to Spot-check attribute dataSpot-check attribute data
You can click into individual events in the Dev Dashboard to inspect their attribute fields. This is useful for debugging and verifying that your app is sending the right data for specific merchant journeys. For the onboarding example, you might check:
- Whether
steps_completedis less thantotal_steps, indicating the merchant abandoned onboarding before finishing - Whether a merchant has an
onboarding_startedevent but no correspondingonboarding_completed - Whether
time_to_complete_secondsseems unusually high for a particular merchant, suggesting a confusing step
Since the Dev Dashboard shows attribute data on individual event records, this approach works best for spot-checking and investigating specific merchants rather than analyzing aggregate trends. For broader analysis across your merchant base, you'd need to export or process the event data externally — for example, by querying the API programmatically and aggregating the results in your own analytics system.
Anchor to Iterate using version fieldsIterate using version fields
When you make changes to a flow, include a version field in your event attributes (like the onboarding_version in this example). This lets you compare metrics across versions in the Dev Dashboard:
- Filter by attribute values to compare version 3 against version 4
- Track whether your changes improved completion rates or reduced time-to-complete
- Identify regressions early by monitoring error patterns after a deploy
Learn more about monitoring in the Dev Dashboard.
Anchor to Next stepsNext steps
- Apply this pattern to other use cases — track feature usage, errors, support interactions, or any event that's meaningful to your app.
- Set up billing events to charge merchants based on usage.
- Review the App Events API reference for the complete API specification.
- Monitor your events in the Dev Dashboard.