# Event Taxonomy (/docs/sdk/events)



Every event the SDK sends has the same anatomy (simplified — the full
schema is what the ingest endpoint validates against):

```json
{
  "event": "purchase_success",
  "event_id": "uuid-...",
  "timestamp": "2026-04-19T12:00:00.000Z",
  "app_id": "app_xxx",
  "app_user_id": "user_42",
  "install_id": "inst_...",
  "session_id": "sess_...",
  "environment": "production",
  "platform": "ios",
  "os_version": "17.4",
  "app_version": "1.2.3",
  "device_model": "iPhone 15 Pro",
  "locale": "en-US",
  "properties": { "revenue": 9.99, "currency": "USD" }
}
```

## Required fields (accepted by the ingest endpoint) [#required-fields-accepted-by-the-ingest-endpoint]

The client SDK populates all of these automatically. You typically only
touch `event` and `properties` in application code.

| Field                                                 | Notes                                                                         |
| ----------------------------------------------------- | ----------------------------------------------------------------------------- |
| `event`                                               | Any non-empty string. See [standard events](/docs/sdk/standard-events).       |
| `timestamp`                                           | ISO 8601. SDK generates automatically.                                        |
| `app_id`                                              | From your Project → Layers SDK page; injected from `init({ appId })`.         |
| `environment`                                         | `development`, `staging`, or `production`.                                    |
| `platform`                                            | `ios`, `android`, `react-native`, `web`, `node`, `flutter`, `macos`, `unity`. |
| `os_version`, `app_version`, `device_model`, `locale` | Device metadata, auto-populated.                                              |

## Optional fields [#optional-fields]

| Field                                                                     | Notes                                                                               |
| ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `event_id`                                                                | UUID. SDK generates one if you don't pass it; used for Meta / TikTok deduplication. |
| `app_user_id`                                                             | Set via `setAppUserId()`.                                                           |
| `install_id`                                                              | Generated on first launch.                                                          |
| `session_id`                                                              | Started on first launch, regenerated via `startNewSession()`.                       |
| `properties`                                                              | Arbitrary JSON object with your event-specific fields.                              |
| `idfa`, `idfv`, `att_status`                                              | iOS-only. `idfa` only forwarded when ATT is `authorized`.                           |
| `utm_source` / `utm_medium` / `utm_campaign` / `utm_content` / `utm_term` | Marketing attribution params.                                                       |

The ingest endpoint uses `looseObject` validation — extra fields are
accepted and persisted.

## Naming conventions [#naming-conventions]

* `snake_case` event names.
* Verb-noun: `purchase_attempt`, `sign_up`, `paywall_show`.
* Lowercase.

## Why `event_id` matters [#why-event_id-matters]

The relay forwards `event_id` as Meta's `event_id` and TikTok's
`event_id`. Both platforms dedupe against it. If you also have a
client-side Pixel firing the same conversion, passing the **same
event\_id** in both places prevents double-counting.

## Reserved property names [#reserved-property-names]

The relay looks for these property keys when building the CAPI payload:

| Property                             | Meaning                                                                                                  |
| ------------------------------------ | -------------------------------------------------------------------------------------------------------- |
| `revenue`, `price`                   | Forwarded as Meta `custom_data.value` and TikTok `properties.value`.                                     |
| `currency`                           | ISO 4217, forwarded alongside value. Defaults to `USD` if missing.                                       |
| `email`, `phone`                     | Hashed and forwarded as advanced-matching fields (see [advanced matching](/docs/sdk/advanced-matching)). |
| `content_id`, `product_id`           | Forwarded as TikTok `contents[].content_id`.                                                             |
| `content_type`                       | Forwarded as TikTok `properties.content_type`.                                                           |
| `_fbp`, `_fbc`, `$fbclid`, `$ttclid` | Click-ID passthrough for CAPI.                                                                           |
| `email_hash`, `phone_hash`           | Pre-hashed PII (skip server-side hashing).                                                               |

## Reading events [#reading-events]

Browse events as they arrive in the [Events page](/docs/events/feed).

## Next [#next]

* [Standard events](/docs/sdk/standard-events) — the list of events the
  relay forwards to Meta and TikTok by default.
* [Custom events](/docs/sdk/custom-events) — what happens when you
  invent your own name.
* [User identity](/docs/sdk/user-identity) — install\_id, app\_user\_id.
