name: walkeros-understanding-events description: Use when creating walkerOS events, understanding event structure, or working with event properties. Covers entity-action naming, event properties, statelessness, and vendor-agnostic design.
Understanding walkerOS Events
Overview
walkerOS events are self-describing, stateless, vendor-agnostic data structures. They capture user interactions in a standardized format that can be transformed for any destination.
Core principle: Events describe WHAT happened, not WHERE it goes. Stateless. Self-describing. Industry-agnostic.
Entity-Action Naming (Critical)
STRICT REQUIREMENT: All events use "entity action" format with space separation.
// Correct
'page view';
'product add';
'order complete';
'button click';
// Wrong
'page_view'; // underscore
'pageview'; // no separator
'purchase'; // no entity
'add_to_cart'; // wrong format
Parsing: const [entity, action] = event.split(' ')
- Entity: Noun (page, product, user, order, button)
- Action: Verb (view, add, complete, click, login)
Event Properties
See
packages/core/src/types/walkeros.ts
for canonical types (Event interface, plus event helpers in event.ts).
| Property | Type | Purpose | Example |
|---|---|---|---|
name |
string | "entity action" format | "product view" |
data |
object | Entity-specific properties | { id: "P123", price: 99 } |
context |
object | State/environment info (optional) | { stage: ["checkout", 1] } |
globals |
object | Global properties | { language: "en" } |
user |
object | User identification | { id: "user123" } |
nested |
array | Related entities (optional) | [{ entity: "product", data: {...} }] |
consent |
object | Consent states | { marketing: true } |
id |
string | W3C span_id, 16 lowercase hex chars, generated by collector | "0123456789abcdef" |
timestamp |
number | Auto-generated Unix ms | 1647261462000 |
entity |
string | Parsed from name | "product" |
action |
string | Parsed from name | "view" |
source.type |
string | Source kind (browser, dataLayer, cookiefirst, ...) |
"browser" |
source.platform |
string | Runtime platform (web, server) |
"web" |
source.schema |
string | Source-emitted schema/version (optional) | "datalayer-v2" |
source.trace |
string | Run-scoped W3C trace_id, shared by every event of a run | "0123...cdef" (32 hex) |
source.count |
number | Per-run emission sequence (1, 2, 3, ...) | 1 |
data Property
Entity-specific properties. Schema-free but consistent within entity type.
// product entity
data: { id: "P123", name: "Laptop", price: 999, currency: "USD" }
// page entity
data: { title: "Home", path: "/", referrer: "https://..." }
context Property
Hierarchical state information. Format: { name: [value, order] }. Optional.
context: {
stage: ["checkout", 1], // checkout stage, first step
test: ["variant-A", 0], // A/B test variant
group: ["premium", 2] // user segment
}
globals Property
Properties that apply to ALL events in the session.
globals: {
language: "en",
currency: "USD",
environment: "production"
}
nested Property
Related entities captured together. Optional.
// Order with line items
nested: [
{ entity: 'product', data: { id: 'P1', quantity: 2 } },
{ entity: 'product', data: { id: 'P2', quantity: 1 } },
];
user Property
User identification across sessions.
user: {
id: "user123", // Your user ID
device: "device456", // Device fingerprint
session: "sess789" // Session ID
}
source Property
Where the event came from. The collector enriches the event with source data
based on which source emitted it.
source: {
type: 'browser', // source kind (browser, dataLayer, cookiefirst, ...)
platform: 'web', // runtime: 'web' or 'server'
version: '4.0.0', // source package version
schema: 'datalayer-v2', // optional schema/version emitted by the source
trace: '0123...cdef', // run-scoped W3C trace_id, groups all events of a run
count: 1, // per-run emission sequence (1, 2, 3, ...)
url: 'https://...', // page URL (web only, set by web-context transformer)
referrer: '...', // page referrer (web only)
tool: 'cli', // tool that produced the event (optional)
command: 'simulate', // command name (optional)
}
CMP and other non-page sources do NOT set source.url/source.referrer -
that's the responsibility of a web-context transformer.
source.trace is the run grouping key: the collector mints a fresh run-scoped
trace_id on each run and stamps it (plus a per-run source.count) on every
event when absent. It is preserved unchanged when an event is forwarded from web
to server, so the whole pipeline shares one trace.
Migration from v3
If you have existing v3 events or configs, here is the v4 mapping:
| v3 | v4 |
|---|---|
event.id = "<ts>-<rnd>-<seq>" |
event.id = W3C span_id (16 lowercase hex chars) |
event.version |
removed - see source.version and source.schema |
event.group |
removed - use source.trace (run-scoped trace_id) for correlation |
event.count |
removed - use source.count (per-run emission sequence) |
event.source.id |
event.source.url (when it meant page URL) |
nested: [{ type, data }] |
nested: [{ entity, data }] (Entity.entity replaces .type) |
Design Principles
Statelessness
Events are immutable snapshots. They don't reference previous events or maintain state.
Self-Describing
Events contain all context needed to understand them. No external lookups required.
Vendor-Agnostic
Events use generic concepts (product, order) not vendor-specific (GA4 item, FB content).
Transformation to vendor formats happens in mapping, not in event creation.
Creating Events
import { elb } from '@walkeros/collector';
// Basic event
await elb('page view', { title: 'Home', path: '/' });
// With all properties
await elb(
'product add',
{ id: 'P123', price: 99 }, // data
{ stage: ['cart', 1] }, // context (optional)
{ currency: 'USD' }, // globals (optional)
);
Related Skills
- walkeros-understanding-mapping - Transform events for destinations
- walkeros-understanding-flow - Data flow architecture
Source Files:
- packages/core/src/types/walkeros.ts - Event types
- packages/core/src/schemas/ - Event schemas
Documentation:
- Website: Event Model - User-facing docs
- walkeros.io/docs - Public documentation