数据模型
四个基元构成引擎。其余一切都建立在它们之上。
事件
用户做的一件事,在发生时被捕获。事件是引擎折叠进状态的原始信号。
| Field | What it carries |
|---|---|
| distinct_id | Who did it: the identifier your code knows the user by |
| event_name | What happened, as a lowercase dotted name (order.completed); a leading $ marks a name the platform owns |
| properties | Anything else about the moment, as a JSON object; three reserved keys mutate user state (below) |
| timestamp | When it happened, stamped by the sender |
| session_id | The visit it belongs to: the web SDK mints one and rotates it after thirty minutes idle or twenty-four hours; replay shares it |
| context | Where it came from: locale, OS, SDK and SDK version |
Events are immutable: nothing edits one after the fact, so the history stays trustworthy and everything current-state lives in user state instead. The exact wire rules, bounds and error codes are on the Ingest API page; the console browses the stream on Events.
用户状态
关于某用户已知的一切的实时、可查询投影(由其事件派生,并在新事件到达的瞬间更新)。这就是分析、开关和消息共享的真相来源。
The profile is cumulative, one per person, and any event may mutate it through three reserved property keys:
| Key | Effect on the profile |
|---|---|
| $set | Overwrites each named property with the new value |
| $set_once | Sets each named property only where none exists yet |
| $unset | Removes the listed properties |
{
"event_name": "plan.upgraded",
"distinct_id": "u_8f3a",
"properties": {
"$set": { "$email": "ada@example.com", "plan": "scale" },
"$set_once": { "first_seen_source": "organic" }
}
}Keys with a $ prefix are the platform’s: $email, $name, $avatar and $phone are the reserved traits the console renders as a person’s fields, and everything unprefixed is yours, rendered as a table. The distinction is deliberate: an unprefixed email stays a custom property and is never promoted to the person’s address, because your email may mean something else entirely. A malformed mutation is dropped and reported; the event itself is kept, because it genuinely happened.
Identity
Every event names a distinct_id, and a person may accumulate several: the anonymous id a browser minted before sign-up, the user id your backend knows. $identify (sent by SDKs, or POST /v1/identify) declares two ids the same person; the engine merges them to one canonical person, folds their profiles together, and every id keeps working. $group associates a person with a group and its traits, so state can be carried by an account as well as an individual. The merged people are what People shows and cohorts select over.
决策
针对用户状态评估的规则:谁在某群组中、谁获得某开关、谁符合某消息的条件。由于决策读取实时状态,它们永不过时。
Concretely: a flag rule, a cohort definition and a message audience are all predicates over the same live profile, which is why a person who upgrades is in the new cohort, the new rollout and the new audience the moment the $set lands, with no sync between three products.
行动
当决策触发时引擎所做的事:开放某功能、发送某消息、触发某工作流。
Actions close the loop: a message lands, a workflow runs, a feature turns on, and each of those produces events of its own for the next decision to read.