Required fields
- orgId — your organization id (UUID).
- projectId — required. Identity is per-project.
- module — which product module the event belongs to (e.g.
analytics,links,billing). - eventType — dotted name describing what happened (e.g.
order.placed). - timestamp — ISO 8601, UTC.
Optional fields
- userId — identified user id (set after
identify()). - anonymousId — anonymous device id (auto-managed by the SDK).
- properties — free-form JSON for the event payload.
- context — auto-populated by the SDK:
userAgent,referrer,page,locale. IP is hashed (SHA-256, truncated) at write — never stored raw.
Example
{
"orgId": "5b8f1f4f-7b8e-4e9d-9d9b-...",
"projectId": "0a1b2c3d-...",
"module": "analytics",
"eventType": "order.placed",
"timestamp": "2026-05-01T12:00:00Z",
"userId": "u_123",
"anonymousId": "anon_xyz",
"properties": { "orderId": "ord_81", "amount": 4200, "currency": "USD" },
"context": {
"userAgent": "Mozilla/5.0 ...",
"referrer": "https://...",
"page": { "url": "...", "title": "..." }
}
}Identify (auto-upsert profile traits)
A special eventType: "identify" with context.traits lands the traits onto the profile row keyed by userId. Use it on signup and any time a customer-attribute changes.
{
"orgId": "...",
"projectId": "...",
"module": "profiles",
"eventType": "identify",
"timestamp": "2026-05-01T12:00:00Z",
"userId": "u_123",
"context": { "traits": { "email": "sam@acme.co", "plan": "growth" } }
}Why this shape
Because every module reads from and writes to the same envelope, analytics funnels, messaging templates, and support timelines all speak the same language. Add a new module, and it instantly has every event it needs — no pipeline to build.
Naming conventions
We recommend lowercase, dot-separated object.past_tense_verb: order.placed, session.started, link.clicked. Sendora Cloud doesn't enforce this — but it makes searching events easier.
Anonymous → identified
Use sendora.auth.signInAnonymously() to mint a stable user_id before signup. When the visitor signs up, sendora.auth.signUp() upgrades the same row in place — attached events stay bound. See Identity for the full lifecycle.