Express
Turn-key HTTP event collection server with Express.js. Runs standalone or embeds inside an existing Express app, handles JSON POST events, pixel tracking via GET with a 1x1 transparent GIF, and configurable CORS.
The Express source is a server source in the walkerOS flow:
It receives events via HTTP (POST/GET) and forwards them to configured destinations.
Installation
npm install @walkeros/server-source-expressThe path setting has been renamed to paths (array). The old path still works but is deprecated and will be removed in the next major version.
// Before (deprecated)
settings: { path: '/events' }
// After
settings: { paths: ['/events'] }
- Integrated
- Bundled
Standalone server
import { startFlow } from '@walkeros/collector';
import { sourceExpress } from '@walkeros/server-source-express';
const { collector } = await startFlow({
sources: {
express: {
code: sourceExpress,
config: {
settings: {
port: 8080,
cors: true,
},
},
},
},
destinations: {
// Your destinations
},
});
// Server running at http://localhost:8080
// POST /collect - JSON event ingestion
// GET /collect - Pixel trackingApp-only mode
const { collector } = await startFlow({
sources: {
express: {
code: sourceExpress,
config: {
settings: {
// No port = app only mode
paths: ['/events'],
},
},
},
},
});
// Access Express app for custom integration
const app = collector.sources.express.app;
app.use(yourAuthMiddleware);
app.listen(3000);Add to your flow.json sources:
"sources": {
"express": {
"package": "@walkeros/server-source-express",
"config": {
"settings": {
"port": 8080,
"cors": true
}
}
}
}Server sources require platform-specific handlers. For containerized deployments, see Docker.
Configuration
This source uses the standard source config wrapper (consent, data, env, id, ...). For the shared fields see source configuration. Package-specific fields live under config.settings and are listed below.
Settings
| Property | Type | Description | More |
|---|---|---|---|
port | integer | HTTP server port to listen on. Use 0 for random available port. If not provided, server will not start (app only mode) | |
path | string | Deprecated: use paths instead | |
paths | Array<any> | Route paths to register. String shorthand registers GET+POST. RouteConfig allows per-route method control. | |
cors | boolean | object | CORS configuration: false = disabled, true = allow all origins (default), object = custom configuration |
Mapping
This package does not define custom rule-level settings. For the standard rule fields (consent, condition, data, batch, name, policy) see mapping.
Examples
Pixel GET
An Express GET to /collect with query parameters is parsed into an elb event payload for pixel tracking.
{
"method": "GET",
"path": "/collect",
"query": {
"e": "page view",
"d": "{\"title\":\"Home\"}"
}
}elb({
"e": "page view",
"d": "{\"title\":\"Home\"}"
})POST event
An Express POST to /collect with a JSON body becomes a single walker elb event.
{
"method": "POST",
"path": "/collect",
"body": {
"name": "page view",
"data": {
"title": "Home",
"url": "https://example.com/"
}
}
}elb({
"name": "page view",
"data": {
"title": "Home",
"url": "https://example.com/"
}
})HTTP methods
| Method | Endpoint | Description |
|---|---|---|
| POST | /collect | JSON event ingestion |
| GET | /collect | Pixel tracking (returns 1x1 GIF) |
| OPTIONS | /collect | CORS preflight |
Health check endpoints (/health and /ready) are provided by the runner, not by individual sources. This means health checks work regardless of which source type you use.
Ingest metadata
Extract request metadata (IP, user agent, headers) and forward it through the pipeline to transformers and destinations.
config.ingest must use the map operator. Keys are output field names; values are direct field paths on the request scope (no req. prefix). A bare object like { ip: 'ip' } is silently inert: without the map operator the source passes the whole request through and no field is extracted.
import { startFlow } from '@walkeros/collector';
import { sourceExpress } from '@walkeros/server-source-express';
const { collector } = await startFlow({
sources: {
express: {
code: sourceExpress,
config: {
settings: { port: 8080 },
ingest: {
map: {
ip: { key: 'ip' },
ua: { key: 'headers.user-agent' },
origin: { key: 'headers.origin' },
referer: { key: 'headers.referer' },
},
},
},
},
},
});Available ingest paths
| Path | Description |
|---|---|
ip | Client IP address |
headers.* | HTTP headers (user-agent, origin, referer, etc.) |
protocol | Request protocol (http/https) |
method | HTTP method (GET, POST, etc.) |
hostname | Request hostname |
url | Full request URL |
Advanced mapping
Use walkerOS mapping features for complex extraction:
ingest: {
map: {
// Simple path
ip: { key: 'ip' },
// Custom function
country: { fn: (req) => geoip.lookup(req.ip)?.country },
// Conditional extraction
devMode: {
key: 'headers.x-debug',
condition: (req) => req.hostname === 'localhost',
},
// Nested structure
request: {
map: {
ua: { key: 'headers.user-agent' },
origin: { key: 'headers.origin' },
},
},
},
}Example request
curl -X POST http://localhost:8080/collect \
-H "Content-Type: application/json" \
-d '{"event":"page view","data":{"title":"Home"}}'