Sources
Sources are the entry points for event data in walkerOS. They capture events from different environments and formats, then transform them into standardized events that the collector can process.
How sources work
Sources capture events in their native format and send them to the collector:
Server source contracts
Every server source normalizes its platform's request into one shared shape before mapping, and accepts one shared set of POST body forms. Two pages define them:
- Request scope: the eight fields
config.ingestresolves against, identical on every server source. - Event envelope: how many events a request body carries, the batch cap, and the response contract.
Web and queue sources have no inbound request to adapt, so neither applies to
them: browser and dataLayer sources push directly, and config.ingest is inert
there.
Available sources
Web
Browser
Captures events from web pages using DOM attributes:
- DOM interactions (clicks, form submissions, visibility)
- Automatic session and pageview tracking
- Custom data attributes (
data-elb-*)
dataLayer
Integrates with existing analytics implementations:
- Works with GA4 and GTM dataLayer
- Event transformation and filtering
- Gradual migration support
Session
Session lifecycle detection, emitting session start and session end:
- Storage-backed session identity across page loads
- Configurable timeout and lifetime
- Feeds session context to every downstream event
Consent management
Consent state from a CMP, forwarded to the collector:
- CookieFirst, Usercentrics and CookiePro adapters
- Consent changes propagate to destinations at runtime
- Events queue until consent resolves
Server
Server sources accept HTTP requests containing walkerOS events and forward them to the collector.
Express
Turn-key HTTP event collection server with Express.js:
- Standalone or embedded: Start server automatically or integrate with existing Express app
- CORS support and health checks
- Pixel tracking with 1x1 transparent GIF
Fetch
Web Standard Fetch API source for edge and serverless platforms:
- Platform agnostic: Cloudflare Workers, Vercel Edge, Deno, Bun, Node.js 18+
- Web Standard
(Request) => Responsesignature - Batch processing and CORS support
AWS Lambda
AWS Lambda HTTP handler for event collection:
- Multi-platform: API Gateway REST (v1), HTTP API (v2), Function URLs
- Auto-detection of API Gateway version
- Pixel tracking and health checks
GCP Cloud Functions
Google Cloud Functions HTTP handler for event collection:
- Plug-and-play: Direct assignment to Cloud Functions handler
- Batches via the shared event envelope
- Configurable CORS
AWS SQS
Queue consumer for events delivered through Amazon SQS:
- Decouples ingestion from processing
- Batch record handling
- Retries and dead-letter handling stay with the queue
Google Pub/Sub
Pull subscriber and push webhook for Google Pub/Sub:
- Pull for long-running workers, push for HTTP endpoints
- Configurable decoders for the message payload
- Redelivery governed by the subscription
Basic setup
Sources are configured in startFlow:
import { startFlow } from '@walkeros/collector';
import { sourceBrowser } from '@walkeros/web-source-browser';
const { collector, elb } = await startFlow({
sources: {
browser: {
code: sourceBrowser,
config: {
settings: {
pageview: true,
session: true,
prefix: 'data-elb',
},
},
},
},
destinations: {
/* your destinations */
},
});
// elb is now browser.push (enhanced with DOM commands)
// Use elb for manual event tracking
await elb('product view', { id: 'P123', name: 'Laptop' });Primary source
startFlow returns an elb function based on your sources:
- With sources: Returns first source's
pushmethod (enhanced features) - Multiple sources: First source is primary by default
- No sources: Returns
collector.push(basic functionality)
Override primary source
const { elb } = await startFlow({
sources: {
browser: { code: sourceBrowser },
dataLayer: { code: sourceDataLayer, primary: true }, // Override
},
});
// elb is now dataLayer.push instead of browser.pushReactive event handling
Sources can react to collector events via the optional on method:
const mySource: Source.Init = async (config, env) => {
return {
type: 'custom',
config,
on: async (event, context) => {
if (event === 'consent') {
// React to consent changes
}
},
};
};Available Events:
consent- Consent state changessession- Session lifecycle eventsready- Collector ready staterun- Collector run events
Creating custom sources
See Create Your Own Source for a complete guide to building custom sources.
Configuration
These fields are available on every source, regardless of package. They wrap the
package-specific settings field, which is documented on each source's page.
| Property | Type | Description | More |
|---|---|---|---|
consent | WalkerOS.Consent | Required consent states to process any events | |
data | any | any | Global data transformation applied to all events | |
include | Array<string> | Event sections to flatten into context.data | |
mapping | Mapping.Rules | Entity-action specific mapping rules | |
policy | Mapping.Policy | Pre-processing policy rules applied before mapping | |
settings | Source.Settings | Implementation-specific configuration | |
credentials | Source.Credentials | Optional credentials (source-defined shape) | |
env | Source.BaseEnv | Environment dependencies (platform-specific) | |
id | string | Source identifier (defaults to source key) | |
primary | boolean | Mark as primary (only one can be primary) | |
require | Array<string> | Defer source initialization until these collector events fire (e.g., ["consent"]) | |
logger | Logger.Config | ||
async | boolean | object | Respond-first acknowledgement for response-producing server sources. When true the source responds 2xx ("accepted") before the event is delivered; when false it waits for delivery to settle and the response reflects the outcome. A record configures this per source-defined key: the express source keys it by HTTP method (GET/POST) and defaults to { GET: false, POST: true }. Browser/dataLayer sources have no HTTP response to defer and ignore it. A 2xx means accepted, not delivered. Defaults are per source type. | |
setup | boolean | object | One-time setup options applied during source registration (boolean enables defaults, object configures specifics) | |
ingest | any | any | Ingest metadata extraction mapping. Extracts values from raw request objects (Express req, Lambda event) using mapping syntax. | |
disabled | boolean | Completely skip this source (no init, no event capture) | |
state | State.Config | State.Config[] | Declarative store get/set operations applied around this source | |
init | boolean | Init lifecycle flag set by collector to true after Instance.init() runs |
Events and commands take different routes
A source has two ways out, and the pipeline fields above apply to only one of them:
- Events go through the source pipeline. This is where
before,next,mapping,cacheandstaterun, where the event picks up its per-source ingest, and what makes the source show up incollector.status.sources. walker *commands (walker consent,walker user,walker run, …) go straight to the collector. They are control signals, not data, so no mapping or chain applies to them.
This holds for every source on both platforms, web and server alike. So a
next chain declared on the browser or dataLayer source runs for the events it
captures, while a consent grant coming from a CMP source reaches the collector
untouched.
Next steps
- Browser source - DOM-based tracking
- DataLayer source - Legacy integration
- Create your own - Custom source guide