For AI agents: a Markdown version of this page is at https://docs.snowplow.io/docs/events/identifiers.md. The index of all documentation pages is at https://docs.snowplow.io/llms.txt, and the index for this section is at https://docs.snowplow.io/docs/cdi/llms.txt.
User and session identifiers
Snowplow tracks several identifiers to help you understand user behavior across sessions and devices. These include tracker-generated IDs stored on the client, server-generated IDs from the Collector, and business user IDs you set in your app.
Understanding how these identifiers work enables you to build a complete picture of user journeys, whether through real-time identity resolution with Snowplow Identities, or identity stitching in your data models.
This page also covers which identifiers each tracker lets you set, session timeouts, and the client session entity.
User identifiers
For identifiers in cookies, consider using the Cookie Lifetime Extension service to prevent identifier loss due to browser restrictions.
Tracker-generated
This on-device user identifier is generated by the tracker. It takes the form of a UUID, and is tracked differently on web or mobile.
It's the default identifier used in our dbt packages to identify users. The Unified Digital package coalesces the domain_userid and the userId property into a single user_identifier field, to make it easier to work with. The value can come from either place.
| Web | Mobile | |
|---|---|---|
| Event field | domain_userid | userId |
| Location in event | Atomic event property | Client session entity |
| Persistance mechanism | Browser cookies | App user settings storage |
| Unified Digital field | user_identifier | user_identifier |
In mobile apps, there are additional on-device identifiers provided by the platform: advertising ID (IDFA) and vendor ID (IDFV, app set ID). These can be tracked in the mobile entity.
Server-generated
The Snowplow Collector generates the network_userid user identifier. It's a UUID that's returned in the Collector's HTTP response to the tracker, as the sp cookie in a Set-Cookie header.
Whether the network_userid persists between events or sessions depends on the tracker:
| Tracker | Persists within session | Persists across sessions | Mechanism |
|---|---|---|---|
| Web | ✅ | ✅ | Stored in sp cookie |
| iOS | ✅ | ✅ | Stored using HTTPCookieStorage |
| Android | ✅ | ✅ | Stored using SharedPreferences |
| React Native | ✅ | ✅ | Depends on platform used |
| Flutter | ✅ | ✅ | Depends on platform used |
| Roku | ❌ | ❌ | |
| Node.js | ❌ | ❌ | |
| Golang | ❌ | ❌ | |
| .NET | ❌ | ❌ | |
| Java | ✅ | ❌/✅ | Stored in memory by default; configure a CollectorCookieJar to persist the network_userid across sessions |
| Python | ❌ | ❌ | |
| Scala | ❌ | ❌ | |
| Ruby | ❌ | ❌ | |
| Rust | ❌ | ❌ | |
| PHP | ❌ | ❌ | |
| C++ | ✅ | ❌/✅ | Stored in memory by default; configure a cookie_file to persist the network_userid across sessions |
| Unity | ❌ | ❌ | Set all properties. |
| Lua | ❌ | ❌ | Set user_id only. |
| Google Tag Manager | ✅ | ✅ | Same as for the web tracker: stored in sp cookie |
Some trackers also allow you to set your own network_userid value.
Business-generated
The business-generated user identifier is an external identifier given to the tracker by the application. Most commonly it's the username or email address of the logged in user e.g. jane.doe@email.com.
It's tracked as the atomic user_id field. All Snowplow trackers have an API to set this identifier.
Set identifiers in your tracking code
These properties can be assigned using most Snowplow trackers: user_id, domain_userid, network_userid, domain_sessionid, domain_sessionidx, and user_ipaddress.
Some trackers set certain user properties automatically, while others require you to set them manually using the tracker's API.
If you don't manually set an IP address or network_userid, the event Collector will automatically add them to the event based on the request HTTP headers and the Collector cookie. You can turn this feature off using server-side anonymization.
Values set in your tracking code will take precedence over values added by the Collector or enrichments.
| Tracker | Supported | Since version | Notes |
|---|---|---|---|
| Web | ✅ | 0.1.0 | Set user_id only. Tracker sets the domain_userid, network_userid, domain_sessionid, and domain_sessionidx automatically from cookies. |
| iOS | ✅ | 0.5.0 | Set all properties except domain_sessionid and domain_sessionidx. |
| Android | ✅ | 0.1.0 | Set all properties except domain_sessionid and domain_sessionidx. |
| React Native | ✅ | 0.1.0 | Set all properties. |
| Flutter | ✅ | 0.1.0 | Set user_id only on web. Set user_id, domain_userid, network_userid, and user_ipaddress on mobile. |
| Roku | ✅ | 0.2.0 | Set user_id and network_userid only. You can automatically populate domain_userid, domain_sessionid, and domain_sessionidx by configuring sessionAsCookies. |
| Node.js | ✅ | 0.8.0 | Set all properties. |
| Golang | ✅ | 1.0.0 | Set all properties. |
| .NET | ✅ | 0.1.0 | Set all properties. |
| Java | ✅ | 0.10.0 | Set all properties except domain_sessionidx. |
| Python | ✅ | 0.13.0 | Set all properties. |
| Scala | ✅ | 0.6.0 | Set all properties except domain_sessionid and domain_sessionidx. |
| Ruby | ✅ | 0.3.0 | Set all properties. |
| Rust | ✅ | 0.1.0 | Set all properties except domain_sessionidx. |
| PHP | ✅ | 0.1.0 | Set all properties. |
| C++ | ✅ | 0.1.0 | Set user_id and user_ipaddress only. |
| Unity | ✅ | 0.1.0 | Set all properties. |
| Lua | ✅ | 0.1.0 | Set user_id only. |
| Google Tag Manager | ❌ | Set using custom configuration. |
Snowplow ID
If you use Snowplow Identities, each event will receive a Snowplow ID from the resolved user profile. The ID is added in an identity entity. You can configure Identities to stitch together any identifiers for identity resolution.
IP address
Snowplow events also contain the IP address of the user. The value is stored in the atomic user_ipaddress property.
We don't recommend using the IP address as a primary identifier: multiple users can share an IP address, and a user's IP address can change frequently. However, it can be useful for certain use cases such as bot detection or geolocation.
Session identifiers
The main Snowplow session identifiers are the session ID and session index:
- Session ID: a UUID generated by the tracker at the start of the session
- Session index: the index of the session for the current user, based on the
domain_useridoruserIdtracker-generated user identifier
They're tracked differently depending on the tracker. On web, they're tracked as the domain_sessionid and domain_sessionidx atomic event fields. In other trackers, they're part of the client session entity, which also includes other session-related information. Note that the web trackers can also track the client session entity, but not all trackers support session tracking.
Session timeouts
A session is a period of time in which a user interacts with your application. A new session starts the first time an event is tracked after the previous session's timeout has elapsed.
There's no maximum session duration, but sessions do have a configurable inactivity timeout. If there's no user activity for the specified time, the session ends. A new one will start when the user returns.
For most trackers, the timeout is based on the gap between the last tracked event and the current event. Mobile trackers have two session timeout settings, allowing you to specify different timeouts if the app is in the foreground or background.
| Tracker | Foreground timeout, min | Background timeout, min | Notes |
|---|---|---|---|
| Web | 30 | - | Page pings from activity tracking will keep a session alive |
| iOS | 30 | 30 | |
| Android | 30 | 30 | |
| React Native | 30 | 30 | |
| Flutter | 30 | 30 | |
| Roku | 30 | - | |
| .NET | 10 | 5 | Uses a timer so it can expire a session independently of a new tracked event |
| C++ | 30 | 30 | |
| Google Tag Manager | 30 | - |
Session entity
Some trackers can track an entity containing information about the current session.
This table shows the support for client_session entity tracking across the main Snowplow tracker SDKs:
| Tracker | Supported | Since version | Auto-tracking |
|---|---|---|---|
| Web | ✅ | 3.5.0 | ✅ |
| iOS | ✅ | 0.5.0 | ✅ |
| Android | ✅ | 0.5.0 | ✅ |
| React Native | ✅ | 1.0.0 | ✅ |
| Flutter | ✅ | 0.2.0 | ✅ |
| Roku | ✅ | 0.3.0 | ✅ |
| Node.js | ❌ | ||
| Golang | ❌ | ||
| .NET | ✅ | 1.0.0 | ✅ |
| Java | ❌ | ||
| Python | ❌ | ||
| Scala | ❌ | ||
| Ruby | ❌ | ||
| Rust | ❌ | ||
| PHP | ❌ | ||
| C++ | ✅ | 1.0.0 | ✅ |
| Unity | ❌ | ||
| Lua | ❌ | ||
| Google Tag Manager | ✅ | v4 | ✅ |
The client_session entity contains data such as the session identifier and session index, as well as information about the previous session to help analysis.
The userId property is the device ID.
client_session
Eventiglu:com.snowplowanalytics.snowplow/client_session/jsonschema/1-0-2Example data
{
"sessionIndex": 7,
"sessionId": "bca0fa0e-853c-41cf-9cc4-15048f6f0ff5",
"previousSessionId": "fa008142-c427-4289-8424-6fb2b6576692",
"userId": "7a62ec9d-2aa0-4426-b014-eba2d0dcfebb",
"firstEventId": "1548BE58-4CE7-4A32-A5E8-2696ECE941F4",
"eventIndex": 66,
"storageMechanism": "SQLITE",
"firstEventTimestamp": "2022-01-01T00:00:00Z"
}
Properties and schema
- Table
- Complete JSON schema
| Property | Description |
|---|---|
userIdstring | Required. An identifier for the user of the session. It is set on app install. |
sessionIdstring | Required. An identifier for the session |
sessionIndexinteger | Required. The index of the current session for this user |
eventIndexnull | Optional. Optional index of the current event in the session |
previousSessionIdnull | Required. The previous session identifier for this user |
storageMechanismstring | Required. The mechanism that the session information has been stored on the device Must be one of: SQLITE, COOKIE_1, COOKIE_3, LOCAL_STORAGE, FLASH_LSO |
firstEventIdnull | Optional. The optional identifier of the first event for this session |
firstEventTimestampnull | Optional. Optional date-time timestamp of when the first event in the session was tracked |
{
"$schema": "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#",
"description": "Schema for a client-generated user session",
"self": {
"vendor": "com.snowplowanalytics.snowplow",
"name": "client_session",
"format": "jsonschema",
"version": "1-0-2"
},
"type": "object",
"properties": {
"userId": {
"type": "string",
"pattern": "^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$|^[0-9a-f]{16}$",
"maxLength": 36,
"description": "An identifier for the user of the session. It is set on app install."
},
"sessionId": {
"type": "string",
"format": "uuid",
"description": "An identifier for the session"
},
"sessionIndex": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647,
"description": "The index of the current session for this user"
},
"eventIndex": {
"type": [
"null",
"integer"
],
"minimum": 0,
"maximum": 2147483647,
"description": "Optional index of the current event in the session"
},
"previousSessionId": {
"type": [
"null",
"string"
],
"format": "uuid",
"description": "The previous session identifier for this user"
},
"storageMechanism": {
"type": "string",
"enum": [
"SQLITE",
"COOKIE_1",
"COOKIE_3",
"LOCAL_STORAGE",
"FLASH_LSO"
],
"description": "The mechanism that the session information has been stored on the device"
},
"firstEventId": {
"type": [
"null",
"string"
],
"format": "uuid",
"description": "The optional identifier of the first event for this session"
},
"firstEventTimestamp": {
"description": "Optional date-time timestamp of when the first event in the session was tracked",
"type": [
"null",
"string"
],
"format": "date-time"
}
},
"required": [
"userId",
"sessionId",
"sessionIndex",
"previousSessionId",
"storageMechanism"
],
"additionalProperties": false
}
Warehouse query
- Snowflake
- BigQuery
- Databricks
- Redshift & Postgres
select
unstruct_event_com_snowplowanalytics_snowplow_client_session_1 client_session_1
from
atomic.events
where
events.collector_tstamp > getdate() - interval '1 hour'
and events.event = 'unstruct'
and events.event_name = 'client_session'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
select
unstruct_event_com_snowplowanalytics_snowplow_client_session_1_0_2
from
PIPELINE_NAME.events events
where
events.collector_tstamp > timestamp_sub(current_timestamp(), interval 1 hour)
and events.event = 'unstruct'
and events.event_name = 'client_session'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
select
unstruct_event_com_snowplowanalytics_snowplow_client_session_1
from
atomic.events events
where
events.collector_tstamp > timestampadd(HOUR, -1, current_timestamp())
and events.event = 'unstruct'
and events.event_name = 'client_session'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
and unstruct_event_com_snowplowanalytics_snowplow_client_session_1 is not null
select
"client_session_1".*
from
atomic.events events
join atomic.com_snowplowanalytics_snowplow_client_session_1 "client_session_1"
on "client_session_1".root_id = events.event_id and "client_session_1".root_tstamp = events.collector_tstamp
where
events.collector_tstamp > getdate() - interval '1 hour'
and "client_session_1".root_tstamp > getdate() - interval '1 hour'
and events.event = 'unstruct'
and events.event_name = 'client_session'
and events.event_vendor = 'com.snowplowanalytics.snowplow'
Identity resolution
Identity resolution is the process of taking various user identifiers and combining them into a single user identifier, to better identify and track users throughout their journey on your site or app. It allows you to attribute logged-in and non-logged-in sessions back to a single user.
Snowplow offers two approaches to identity resolution:
- Snowplow Identities resolves identity in real time during enrichment, attaching a unified Snowplow ID to each event. The Identities dbt package then builds mapping tables for use in downstream models.
- Identity stitching in the Unified Digital dbt package resolves identity at modeling time by stitching the business user ID with tracker-generated user identifiers. This is available to all customers.
We recommend setting the business user identifier, where possible, when using either approach.
Reset generated identifiers on web
If you're not using Identities, there's a risk of attributing sessions to the wrong user when multiple users share the same browser or device.
If this is a problem for you, the JavaScript tracker allows you to clear all user data. If you call this function when a user logs out, the tracker will generate new user and session identifiers for subsequent events. This feature is only available for the JavaScript tracker.
Anonymous tracking
The user and session identifiers, along with the IP address, are considered personal identifiable information (PII). Snowplow also allows you to track data without these identifiers: check out the anonymous tracking overview page.