Skip to content

Fields are used in where clauses, aggregations, group by, and sort. The available fields depend on the query source.

Core fields

Present on every event. Usable in all event-based queries.

FieldTypeDescription
event_typestringEvent name (e.g. signup, page_view)
user_idstringUser identifier set by your code
device_idstringAnonymous device identifier (auto-generated by JS SDK)
session_idstringSession identifier (auto-generated by JS SDK, 30-min timeout)
distinct_idstringStitched identity (see Identity below)
timedatetimeEvent timestamp (client-provided or server now())
insert_idstringDeduplication key (auto-generated if not provided)

System fields

Server-enriched from the User-Agent header and request metadata. Prefixed with _.

FieldTypeValuesDescription
_browserstringChrome, Firefox, Safari, …Browser name
_browser_versionstring120.0, 3.1, …Browser version
_osstringWindows, Mac OS X, Linux, Android, iOS, …Operating system
_os_versionstring14.2, 10, …OS version
_platformstringweb, android, iosPlatform (detected from UA)
_device_typestringdesktop, mobile, botDevice classification
_ipstringClient IP (may be anonymized per policy)
_librarystringwirelog-js/1.0, …SDK identifier

Examples:

# Events by platform
* | last 7d | count by _platform
# Mobile-only events
* | where _device_type = "mobile" | last 30d | count by event_type | top 10
# Filter by browser
page_view | where _browser = "Chrome" | last 7d | count

Event properties

Access nested properties sent in the event_properties object on track calls.

Syntax: event_properties.<KEY>

| where event_properties.page = "/pricing"
| sum event_properties.amount by day
| where event_properties.button contains "signup"

Property keys must match [a-zA-Z0-9_.\-]+ and be at most 256 characters.

Examples:

# Filter by a custom property
purchase | where event_properties.plan = "pro" | last 30d | count
# Sum a numeric property
purchase | last 30d | sum event_properties.amount by week
# P95 of a latency property
api_call | last 7d | p95 event_properties.duration_ms

User properties (on event)

Access user properties sent alongside the event in the user_properties object.

Syntax: user_properties.<KEY>

| where user_properties.plan = "enterprise"
| count by user_properties.role

These are the user properties attached at track time, not the latest profile state. For latest profile state, use user.<KEY>.

Profile fields

Access the user_profiles table for the latest user state. Populated by identify() calls.

Syntax: user.<KEY>

Built-in profile fields

FieldTypeDescription
user.emailstringEmail address (set via identify)
user.email_domainstringDomain extracted from email (e.g. acme.org)
user.first_seendatetimeTimestamp of first event
user.last_seendatetimeTimestamp of most recent event

Custom profile properties

Any key set via identify() user properties:

user.plan
user.company
user.role
user.acquisition_channel

These resolve to user_properties['<key>'] on the user_profiles table.

Availability by source:

Sourceuser.* fieldsNotes
Event queries (*, <event>)YesJoins user_profiles via stitched identity
user "<id>"YesJoins user_profiles for the specified user
usersYesQueries user_profiles directly
funnel, retention, paths, sessionsNoNot supported; use event queries with where user.* instead
formulaNoEvent-level metrics only

Examples:

# Events from enterprise users
* | where user.plan = "enterprise" | last 30d | count by event_type
# All events from a specific company
* | where user.email_domain = "acme.org" | last 12w | count by week
# User directory: list enterprise users
users | where user.plan = "enterprise" | list
# Count users by plan
users | count by user.plan | top 10

Identity

distinct_id is the stitched identity field:

coalesce(user_id, mapped_user_id, device_id)

Resolution order:

  1. user_id — explicitly set user identifier
  2. mapped_user_id — looked up from device_user_map (set by identify() binding a device_id to a user_id)
  3. device_id — anonymous device identifier (fallback)

Use unique distinct_id when you want unique user counts. This correctly deduplicates anonymous and identified events from the same user.

# Unique users per week
signup | last 12w | unique distinct_id by week
# Unique users by platform
* | last 30d | unique distinct_id by _platform

Pre-identify attribution: Events tracked before an identify() call are attributed retroactively. Once a device-to-user mapping exists in device_user_map, queries using distinct_id will include the anonymous events from that device.

Property type handling

Properties are normalized on ingest into typed storage buckets:

TypeStorageQuery behavior
Stringevent_properties / user_properties (canonical maps)Direct string comparison
Number*_num maps + canonical string mapNumeric aggregations (sum, avg, etc.) use numeric bucket first, fall back to toFloat64OrNull on string
Boolean*_bool maps + canonical string mapStored as 1/0 in bool bucket
Null*_null arrays + excluded from other mapsKey recorded in null array
Object/ArrayJSON-stringified in canonical string mapStored as string; queryable via string operators

Queries automatically check the correct typed bucket. You do not need to reference _num or _bool maps directly — the compiler handles this.

For numeric comparisons (>, <, >=, <=) with numeric literal values, the compiler uses the numeric bucket automatically. Non-numeric comparison values fall back to string semantics.

For exists/not exists on property fields, the compiler checks mapContains on the canonical map.