PostHog
Server-side event delivery to PostHog for product analytics, identity resolution, group analytics, and feature flags via the official posthog-node SDK.
PostHog is a server destination in the walkerOS flow:
Sends events server-side to PostHog's ingestion API, translating walkerOS events into `capture`, `identify`, and `groupIdentify` calls with full control over identity and group resolution.
Installation
npm install @walkeros/server-destination-posthog- Integrated
- Bundled
import { startFlow } from '@walkeros/collector';
import { destinationPostHog } from '@walkeros/server-destination-posthog';
await startFlow({
destinations: {
posthog: {
code: destinationPostHog,
config: {
settings: {
apiKey: 'phc_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
host: 'https://eu.i.posthog.com',
},
},
},
},
});Add to your flow.json destinations:
"destinations": {
"posthog": {
"package": "@walkeros/server-destination-posthog",
"import": "destinationPostHog",
"config": {
"settings": {
"apiKey": "phc_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"host": "https://eu.i.posthog.com"
}
}
}
}Configuration
This destination uses the standard destination config wrapper (consent, data, env, id, ...). For the shared fields see destination configuration. Package-specific fields live under config.settings and are listed below.
Settings
| Property | Type | Description | More |
|---|---|---|---|
apiKey | string | PostHog project API key (starts with "phc_"). Find it in PostHog project settings. | |
host | string | PostHog API host. Defaults to https://us.i.posthog.com. Use https://eu.i.posthog.com for EU or your self-hosted URL. | |
flushAt | number | Number of events queued before auto-flush. Default: 20. | |
flushInterval | number | Milliseconds between periodic flushes. Default: 10000. | |
personalApiKey | string | Personal API key (phx_...) for local feature flag evaluation. | |
featureFlagsPollingInterval | number | Milliseconds between feature flag definition polls. Default: 30000. | |
disableGeoip | boolean | Disable GeoIP lookups globally. Useful for GDPR compliance. | |
debug | boolean | Enable PostHog SDK debug logging. Default: false. | |
identify | any | walkerOS mapping value resolving to an identity object. Keys: distinctId, $set, $set_once. Resolved on every push (server is stateless). | |
group | any | walkerOS mapping value resolving to a group object. Keys: type, key, properties. Resolved on every push. | |
include | Array<string> | Event sections to flatten into capture() properties (e.g. ["data", "globals"]). |
Mapping
Per-event rules under config.mapping. For the standard rule fields (consent, condition, data, batch, name, policy) see mapping.
| Property | Type | Description | More |
|---|---|---|---|
identify | any | Per-event identity mapping. Resolves to { distinctId, $set?, $set_once? }. Fires client.identify() when $set/$set_once present. | |
group | any | Group assignment. Resolves to { type, key, properties? }. Fires client.groupIdentify() when properties present, adds groups to capture(). |
Examples
Capture with group
A destination-level group mapping attaches the resolved group context to every PostHog capture call.
{
"name": "page view",
"data": {
"domain": "www.example.com",
"title": "walkerOS documentation",
"referrer": "https://www.walkeros.io/",
"search": "?foo=bar",
"hash": "#hash",
"id": "/docs/"
},
"context": {
"dev": [
"test",
1
]
},
"globals": {
"pagegroup": "docs",
"company_id": "company_123"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "child",
"data": {
"is": "subordinated"
}
}
],
"consent": {
"functional": true
},
"id": "0f8019ecc755c2de",
"trigger": "load",
"entity": "page",
"action": "view",
"timestamp": 1700000104,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}client.capture({
"distinctId": "us3r",
"event": "page view",
"properties": {},
"groups": {
"company": "company_123"
}
})Capture with include
Destination-level include flattens data and globals sections into prefixed PostHog event properties.
{
"name": "order complete",
"data": {
"id": "0rd3r1d",
"currency": "EUR",
"shipping": 5.22,
"taxes": 73.76,
"total": 555
},
"context": {
"shopping": [
"complete",
0
]
},
"globals": {
"pagegroup": "shop"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "product",
"data": {
"id": "ers",
"name": "Everyday Ruck Snack",
"color": "black",
"size": "l",
"price": 420
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
},
{
"entity": "product",
"data": {
"id": "cc",
"name": "Cool Cap",
"size": "one size",
"price": 42
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
},
{
"entity": "gift",
"data": {
"name": "Surprise"
},
"context": {
"shopping": [
"complete",
0
]
},
"nested": []
}
],
"consent": {
"functional": true
},
"id": "09073abf930d0f48",
"trigger": "load",
"entity": "order",
"action": "complete",
"timestamp": 1700000101,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}client.capture({
"distinctId": "us3r",
"event": "order complete",
"properties": {
"data_id": "0rd3r1d",
"data_currency": "EUR",
"data_shipping": 5.22,
"data_taxes": 73.76,
"data_total": 555,
"globals_pagegroup": "shop"
}
})Consent granted
A walker consent command with analytics granted calls client.enable on the PostHog client.
{
"analytics": true
}client.enable()Consent revoked
A walker consent command with analytics denied calls client.disable on the PostHog client.
{
"analytics": false
}client.enable();
client.disable()Default capture
A walker event becomes a PostHog capture call with the user id as distinctId and no extra properties.
{
"name": "product view",
"data": {
"id": "ers",
"name": "Everyday Ruck Snack",
"color": "black",
"size": "l",
"price": 420
},
"context": {
"shopping": [
"detail",
0
]
},
"globals": {
"pagegroup": "shop"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [],
"consent": {
"functional": true
},
"id": "8730a13ed7b3a8f2",
"trigger": "load",
"entity": "product",
"action": "view",
"timestamp": 1700000100,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}client.capture({
"distinctId": "us3r",
"event": "product view",
"properties": {}
})Group identify
A company update fires PostHog groupIdentify with group type, key, and associated group properties.
{
"name": "company update",
"data": {
"company_id": "company_123",
"company_name": "Acme",
"plan": "enterprise"
},
"context": {
"dev": [
"test",
1
]
},
"globals": {
"lang": "elb"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "child",
"data": {
"is": "subordinated"
}
}
],
"consent": {
"functional": true
},
"id": "dc910f7e333fd738",
"trigger": "test",
"entity": "company",
"action": "update",
"timestamp": 1700000103,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"group": {
"map": {
"type": {
"value": "company"
},
"key": "data.company_id",
"properties": {
"map": {
"name": "data.company_name",
"plan": "data.plan"
}
}
}
}
}
}client.groupIdentify({
"groupType": "company",
"groupKey": "company_123",
"properties": {
"name": "Acme",
"plan": "enterprise"
}
})Identify with $set
A user login fires PostHog identify with $set and $set_once person properties and skips the capture.
{
"name": "user login",
"data": {
"user_id": "new-user-123",
"email": "user@acme.com",
"plan": "premium"
},
"context": {
"dev": [
"test",
1
]
},
"globals": {
"lang": "elb"
},
"custom": {
"completely": "random"
},
"user": {
"id": "us3r",
"device": "c00k13",
"session": "s3ss10n"
},
"nested": [
{
"entity": "child",
"data": {
"is": "subordinated"
}
}
],
"consent": {
"functional": true
},
"id": "198e984bcae96d14",
"trigger": "test",
"entity": "user",
"action": "login",
"timestamp": 1700000102,
"timing": 3.14,
"source": {
"count": 1,
"trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"type": "collector",
"schema": "4"
}
}{
"silent": true,
"settings": {
"identify": {
"map": {
"distinctId": "data.user_id",
"$set": {
"map": {
"email": "data.email",
"plan": "data.plan"
}
},
"$set_once": {
"map": {
"first_login": "timestamp"
}
}
}
}
}
}client.identify({
"distinctId": "new-user-123",
"properties": {
"$set": {
"email": "user@acme.com",
"plan": "premium"
},
"$set_once": {
"first_login": 1700000102
}
}
})