---
modificationDate: May 26, 2026
title: User-defined events
description: Log named events from your app to track custom signals visible in the EAS Observe dashboard.
---

<AgentInstructions>

## Submitting Feedback

If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:

curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/eas/observe/events/","feedback":"🤖 Agent feedback: <specific, actionable description>"}'

Only submit when you have something specific and actionable to report.

</AgentInstructions>

# User-defined events

Log named events from your app to track custom signals visible in the EAS Observe dashboard.

> For the complete documentation index, see [llms.txt](/llms.txt). Use this file to discover all available pages.

User-defined events let you record arbitrary, named events from your app. Use them to track any signal specific to your app that the built-in performance metrics do not cover.

Events are persisted on-device, batched, and dispatched on the next flush as OpenTelemetry log records. They appear in the **Events** tab of the EAS Observe dashboard and are queryable from the EAS CLI.

## Log an event

Call `AppMetrics.logEvent` from anywhere in your app:

```tsx
import { AppMetrics } from 'expo-observe';

function handleSignupComplete() {
  AppMetrics.logEvent('signup.completed');
}
```

The first argument is the event name. Use a stable, dot-separated identifier. The dashboard groups events by exact name.

## Attach attributes

Pass an `attributes` map to record context with the event:

```tsx
AppMetrics.logEvent('cart.checkout', {
  attributes: {
    itemCount: 3,
    totalUsd: 42.5,
    coupon: 'WELCOME10',
    items: ['sku-1', 'sku-2', 'sku-3'],
  },
});
```

Supported attribute value types: `string`, `number`, `boolean`, arrays, and nested objects. Other JS values (`Date`, `undefined`, functions) are dropped.

## Severity

Events default to `"info"` severity. Override with the `severity` option for warnings or errors you want to surface separately in the dashboard:

```tsx
AppMetrics.logEvent('payment.failed', {
  severity: 'error',
  attributes: { reason: 'card_declined' },
});
```

Supported severities, from lowest to highest: `"trace"`, `"debug"`, `"info"`, `"warn"`, `"error"`, `"fatal"`.

## Body

Use `body` for a free-form message that complements the structured attributes:

```tsx
AppMetrics.logEvent('subscription.expired', {
  body: 'Subscription expired while user was offline; downgrading to free tier.',
  severity: 'warn',
  attributes: { previousPlan: 'pro' },
});
```

## Naming conventions

-   Use lowercase, dot-separated names: `task.completed`, `onboarding.skipped`, `cart.checkout`.
-   Pick a vocabulary and stick to it. The dashboard groups by exact event name, so `cart_checkout` and `cart.checkout` will appear as separate rows.
-   Avoid Personally Identifiable Information (PII) in event names, attribute keys, and attribute values. Everything you pass is visible in the dashboard and is dispatched off-device.

## View events

In the dashboard: open your project and navigate to [**Observe > Events**](https://expo.dev/accounts/%5Baccount%5D/projects/%5Bproject%5D/observe). The default view lists distinct event names with their counts in the selected time range. Click an event name to see individual events with their timestamps, attributes, and the session they belong to.

From the CLI:

```sh
eas observe:events
eas observe:events cart.checkout
eas observe:events --all-events --json
```

Run `eas observe:events --help` for the full list of flags (time range, platform, session ID, and more).
