跳到主要内容

数据模型

四个基元构成引擎。其余一切都建立在它们之上。

事件

用户做的一件事,在发生时被捕获。事件是引擎折叠进状态的原始信号。

FieldWhat it carries
distinct_idWho did it: the identifier your code knows the user by
event_nameWhat happened, as a lowercase dotted name (order.completed); a leading $ marks a name the platform owns
propertiesAnything else about the moment, as a JSON object; three reserved keys mutate user state (below)
timestampWhen it happened, stamped by the sender
session_idThe visit it belongs to: the web SDK mints one and rotates it after thirty minutes idle or twenty-four hours; replay shares it
contextWhere 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:

KeyEffect on the profile
$setOverwrites each named property with the new value
$set_onceSets each named property only where none exists yet
$unsetRemoves the listed properties
JSON
{
  "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.

How the four pillars connectEventUser stateDecisionAction