メインコンテンツへスキップ

データモデル

4 つのプリミティブがエンジンを構成します。他のすべてはその上に構築されます。

イベント

ユーザーが行った 1 つのこと。発生した瞬間に捕捉されます。イベントは、エンジンが状態に集約する生のシグナルです。

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