Events & properties
Events are immutable
Section titled “Events are immutable”An event freezes its properties at capture time. Nothing rewrites it afterwards — not identity merges, not trait updates, not enforcement decisions. If a person’s plan changes, their person changes; the events they sent while on the old plan keep saying the old plan. That’s the split: events are history, persons are state.
Every event carries:
| Field | What it is |
|---|---|
uuid |
Client-generated UUID v7. The idempotency key: the pipeline deduplicates by it, which is why retries at every layer are safe |
event |
The name. Your names are free-form; $-prefixed names are the system’s |
distinct_id |
Who did it, as known at capture time |
properties |
Arbitrary JSON. Kilden never validates or types it — the envelope is typed, the payload is yours by design |
timestamp |
When it happened (client-supplied, corrected for clock skew using the batch’s sent_at) |
The $ namespace
Section titled “The $ namespace”Names starting with $ — events and properties — are reserved for the system. The SDK warns in debug mode if you track() one, but still delivers it: the namespace is a convention, never a reason to drop your data.
System events you’ll see in your stream:
| Event | Emitted by |
|---|---|
$pageview, $pageleave |
SDK, automatically (including SPA route changes) |
$autocapture |
Autocapture: clicks, submits, changes, described by $event_type and $elements |
$identify |
identify() — carries $anon_distinct_id for identity linking |
$set, $set_once |
Person trait updates |
$feature_flag_called |
First flag read per session — $flag_key, $flag_value (exposures) |
$session_recording_started |
Replay recording start |
$email_sent, $email_delivered, $email_opened, $email_clicked, $email_bounced, $email_complained |
Campaigns and the email provider’s webhooks |
Context properties stamped on every SDK event: $current_url, $referrer, $session_id, $device_type, $screen_width, $screen_height, $lib, $lib_version, $utm_source, $utm_medium, $utm_campaign, $utm_term, $utm_content.
One write path
Section titled “One write path”Every event — browser, backend, email webhook, even Kilden’s own internal events — enters through the same capture endpoint and the same pipeline. There are no side doors, which is what makes the guarantees (dedup, identity resolution, trust levels) hold for everything uniformly.
Sessions
Section titled “Sessions”The SDK maintains $session_id (UUID v7) on every event, rotating it after 30 minutes of inactivity. Sessions tie together events, feature-flag exposure dedupe and session replay — a recording is always joinable 1:1 with its session’s events.