Skip to main content
Sessions group a user’s events into a single visit. Every event carries a session ID, so you can answer questions like “how many sessions included a purchase” or “what did this user do in their last session.”

How sessions work

A session starts when the SDK initializes (app launch, first page load) and ends when the user is inactive for longer than the session timeout (30 minutes by default) or exceeds the max session length (24 hours by default). On web, the session ID is persisted to localStorage so page navigations continue the same session. Every event sent during a session shares the same 16-byte session ID. When a session expires and the user returns, a new session ID is generated and all subsequent events are grouped under it. Sessions are tracked alongside a device ID — a persistent identifier for the physical device. The device ID stays the same across sessions; the session ID rotates.

Session lifecycle

On mobile (iOS, macOS, visionOS), the SDK observes app lifecycle events and sends context events at each transition:
TriggerContext eventWhat happens
App launchsession_startedNew session ID generated, full device context collected
App backgroundedapp_backgroundedTimestamp recorded, context event sent
App foregroundedapp_foregroundedIf background time < timeout, session continues
Background > timeoutsession_timeoutNew session ID generated, context event sent
App terminatedapp_terminatedFinal context event sent
Active/inactive transitions (e.g. pulling down notification center) update internal state but don’t generate context events — they happen too frequently to be useful.

Session timeout

The default timeout is 30 minutes. If a user backgrounds your app and returns within 30 minutes, the same session continues. If they return after 30 minutes, a new session starts. You can configure this at initialization:
try await Tell.shared.configure(
    apiKey: "YOUR_API_KEY",
    sessionTimeout: 15 * 60  // 15 minutes
)
tell.configure('YOUR_API_KEY', { sessionTimeout: 15 * 60 * 1000 }); // 15 minutes

Max session length

Sessions are capped at 24 hours by default to prevent zombie sessions from tabs left open indefinitely. When the max length is reached, the session rotates even if the user is still active.
tell.configure('YOUR_API_KEY', { maxSessionLength: 12 * 60 * 60 * 1000 }); // 12 hours

Context data

Each context event carries a snapshot of the device and app environment. On mobile SDKs, this is collected automatically — you don’t need to send it yourself.

Automatically collected properties

Device
PropertyExampleDescription
device_typemobile, tablet, desktop, tv, watch, vrDevice form factor
device_modeliPhone, Mac14,2Hardware model
operating_systemios, macos, visionosOS family
os_version18.2.0Semver OS version
App
PropertyExampleDescription
app_version2.1.0Bundle short version string
app_build42Build number
app_bundle_idcom.example.appBundle identifier
Screen
PropertyExampleDescription
screen_width1170Physical pixel width
screen_height2532Physical pixel height
screen_scale3.0Display scale factor
screen_logical_width390Logical point width
screen_logical_height844Logical point height
System
PropertyExampleDescription
memory_total6442450944Total physical memory (bytes)
memory_available104857600Resident memory usage (bytes)
storage_available48318382080Available disk space (bytes)
storage_total127989493760Total disk capacity (bytes)
battery_level0.85Battery charge 0.0–1.0 (iOS only)
battery_statechargingunplugged, charging, or full (iOS only)
Locale
PropertyExampleDescription
localeen_USDevice locale
timezoneAmerica/New_YorkDevice timezone
Session
PropertyExampleDescription
session_reasonsession_startWhy this context event was sent
app_stateactiveApp state at time of event
background_duration1847.5Seconds spent in background (if returning)

Adding custom context

Use super properties to attach custom context to every event:
tell.register({
    deployment: 'canary',
    app_version: '2.1.0',
    build_sha: 'a1b2c3d'
});
On the server side, pass context as event properties. There’s no fixed schema — the properties field accepts any key-value data, so you can enrich events with whatever is relevant to your application.

Device IDs

The device ID is a 16-byte UUID that persists across sessions and app updates.
PlatformStorageLifetime
iOS / visionOSKeychainSurvives app reinstalls
macOSKeychainSurvives app reinstalls
WeblocalStoragePer browser, cleared on storage wipe
ServerNot applicableUse user IDs directly
Mobile SDKs generate and store the device ID automatically. You never need to manage it yourself.

What gets attached to events

Every event (track, identify, group, revenue, alias) automatically gets:
  1. Device ID — from the session manager
  2. Session ID — from the session manager
  3. Minimal device contextdevice_type, operating_system, os_version, app_version (if device context enrichment is enabled)
  4. Timestamp — current time unless overridden
You don’t need to pass any of this manually. The SDK handles it.

Manual session control

You can force a new session at any time:
// Swift — starts new session with custom reason
await Tell.shared.sessionManager?.startNewSession(reason: "user_switched")
Call reset() to clear the current user, generate a new anonymous ID, and stop the current session. The next event starts a fresh session.
Tell.shared.reset()

What’s next