> Part of the walkerOS documentation. Project overview and full index: <https://www.walkeros.io/llms.txt>

# PostHog

<!-- -->

[Web](#)[ ](https://github.com/elbwalker/walkerOS/tree/main/packages/web/destinations/posthog)

<!-- -->

[Source code](https://github.com/elbwalker/walkerOS/tree/main/packages/web/destinations/posthog)[ ](https://www.npmjs.com/package/@walkeros/web-destination-posthog)

<!-- -->

[Package](https://www.npmjs.com/package/@walkeros/web-destination-posthog)

[PostHog](https://posthog.com/) is an open-source product analytics platform with session replay, feature flags, A/B testing, surveys, and heatmaps. This destination forwards walkerOS events to PostHog via the official [`posthog-js`](https://www.npmjs.com/package/posthog-js) SDK, translating events into `posthog.capture(...)` calls, resolving identity and group assignments, and handling consent opt-in/opt-out. All built-in PostHog features (session replay, feature flags, surveys, heatmaps, exception capture) are available through SDK init passthrough.

<!-- -->

Where this fits

PostHog is a **web destination** in the walkerOS flow:

## Installation[​](#installation "Direct link to Installation")

```
npm install @walkeros/web-destination-posthog
```

* Integrated
* Bundled

```
import { startFlow } from '@walkeros/collector';
import { destinationPostHog } from '@walkeros/web-destination-posthog';

await startFlow({
  destinations: {
    posthog: {
      code: destinationPostHog,
      config: {
        settings: {
          apiKey: 'phc_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
          api_host: 'https://eu.i.posthog.com',
        },
      },
    },
  },
});
```

Add to your `flow.json` destinations:

```
"destinations": {
  "posthog": {
    "package": "@walkeros/web-destination-posthog",
    "config": {
      "settings": {
        "apiKey": "phc_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "api_host": "https://eu.i.posthog.com"
      }
    }
  }
}
```

[See bundled mode setup](https://www.walkeros.io/docs/getting-started/modes/bundled.md) | [CLI reference](https://www.walkeros.io/docs/apps/cli.md)

## Configuration[​](#configuration "Direct link to Configuration")

This <!-- -->destination<!-- --> uses the standard <!-- -->destination<!-- --> config wrapper (consent, data, env, id, ...). For the shared fields see [destination<!-- --> configuration](https://www.walkeros.io/docs/destinations.md#configuration). Package-specific fields live under `config.settings` and are listed below.

## Settings[​](#settings "Direct link to Settings")

| Property                    | Type                               | Description                                                                                                                                                        | More |
| --------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---- |
| `apiKey*`                   | `string`                           | Your PostHog project API key (starts with "phc\_"). Find it in your PostHog project settings under "Project API Key" (like phc\_a1b2c3d4e5f6789012345678abcdef12). |      |
| `api_host`                  | `string`                           | PostHog API host. Defaults to https\://us.i.posthog.com. Use https\://eu.i.posthog.com for the EU region.                                                          |      |
| `ui_host`                   | `string`                           | URL of the PostHog UI host, used by toolbar and replay player. Default: null.                                                                                      |      |
| `persistence`               | `'localStorage+cookie' \| 'cooki`  | Where to persist user identity. Default: "localStorage+cookie".                                                                                                    |      |
| `person_profiles`           | `'always' \| 'never' \| 'identifi` | When to create person profiles. "identified\_only" (default) creates profiles only after identify() is called.                                                     |      |
| `autocapture`               | `boolean`                          | Enable PostHog's autocapture of clicks, form submits, and pageviews. Default: false (walkerOS sources handle capture).                                             |      |
| `capture_pageview`          | `boolean \| string`                | Whether PostHog should auto-capture pageview events. Default: false (walkerOS sources handle this).                                                                |      |
| `capture_pageleave`         | `boolean \| string`                | Whether PostHog should auto-capture pageleave events. Default: false.                                                                                              |      |
| `capture_heatmaps`          | `boolean`                          | Enable heatmap data capture. Default: true (PostHog default).                                                                                                      |      |
| `capture_exceptions`        | `boolean`                          | Enable automatic exception capture. Default: false.                                                                                                                |      |
| `disable_surveys`           | `boolean`                          | Disable PostHog surveys. Default: false.                                                                                                                           |      |
| `disable_session_recording` | `boolean`                          | Disable session recording. Default: false.                                                                                                                         |      |
| `advanced_disable_flags`    | `boolean`                          | Disable feature flag loading. Default: false.                                                                                                                      |      |
| `cookieless_mode`           | `'always' \| 'on_reject'`          | "always" never uses cookies/localStorage. "on\_reject" falls back to cookieless when consent is rejected.                                                          |      |
| `debug`                     | `boolean`                          | Enable PostHog SDK debug logging. Default: false.                                                                                                                  |      |
| `session_recording`         | `any`                              | Session Replay options (SessionRecordingOptions). Masking, blocking, sampling. See PostHog docs for full list.                                                     |      |
| `bootstrap`                 | `any`                              | SSR bootstrap data. { distinctID?, featureFlags? } — pre-populates identity and flag values to avoid first-render flicker.                                         |      |
| `identify`                  | `any`                              | walkerOS mapping value resolving to an identity object. Keys: distinctId, $set, $set\_once. Resolved on first push and re-fired when distinctId changes.           |      |
| `group`                     | `any`                              | walkerOS mapping value resolving to a group object. Keys: type, key, properties. Resolved on first push and re-fired when type/key changes.                        |      |

\* Required fields

## Mapping[​](#mapping "Direct link to Mapping")

Per-event rules under `config.mapping`. For the standard rule fields (consent, condition, data, batch, name, policy) see [mapping](https://www.walkeros.io/docs/mapping.md).

| Property   | Type  | Description                                                                                                                                                                | More |
| ---------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| `identify` | `any` | Per-event identity mapping. Resolves to an object with any of: distinctId, $set, $set\_once. Omitting distinctId routes to setPersonProperties() (no identity change).     |      |
| `group`    | `any` | Group assignment. Resolves to { type, key, properties? } → posthog.group(type, key, properties).                                                                           |      |
| `reset`    | `any` | Logout trigger. Resolves to a truthy value → posthog.reset() (clears distinctId and regenerates an anonymous one). Typically used with silent: true on a user logout rule. |      |

## Examples

### Consent granted

A walker consent command with analytics granted calls posthog.opt\_in\_capturing to resume capture.

Event

```
{
  "analytics": true
}
```

Out

```
posthog.opt_in_capturing()
```

### Consent revoked

A walker consent command with analytics denied calls posthog.opt\_out\_capturing to stop capture and replay.

Event

```
{
  "analytics": false
}
```

Out

```
posthog.opt_in_capturing();

posthog.opt_out_capturing()
```

### Default capture

A walker event becomes a PostHog capture call with the event name and empty properties.

Event

```
{
  "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": "63700b9b24aaa0aa",
  "trigger": "load",
  "entity": "product",
  "action": "view",
  "timestamp": 1700000100,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Out

```
posthog.capture("product view", {})
```

### Destination identify

Destination-level identify calls posthog.identify with the user id before firing the default capture.

Event

```
{
  "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"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "2406fbb9a0e3f477",
  "trigger": "load",
  "entity": "page",
  "action": "view",
  "timestamp": 1700000104,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Out

```
posthog.identify("us3r");

posthog.capture("page view", {})
```

### Include data

Destination-level include flattens the event data section into prefixed PostHog capture properties.

Event

```
{
  "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": "30851eefb680c0c3",
  "trigger": "load",
  "entity": "product",
  "action": "view",
  "timestamp": 1700000102,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Out

```
posthog.capture("product view", {
  "data_id": "ers",
  "data_name": "Everyday Ruck Snack",
  "data_color": "black",
  "data_size": "l",
  "data_price": 420
})
```

### Group assignment

A company update assigns the user to a PostHog group and sets group properties via posthog.group.

Event

```
{
  "name": "company update",
  "data": {
    "company_id": "company_123",
    "company_name": "Acme",
    "plan": "enterprise",
    "size": 50
  },
  "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": "319c588d88945819",
  "trigger": "test",
  "entity": "company",
  "action": "update",
  "timestamp": 1700000108,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "silent": true,
  "settings": {
    "group": {
      "map": {
        "type": {
          "value": "company"
        },
        "key": "data.company_id",
        "properties": {
          "map": {
            "name": "data.company_name",
            "plan": "data.plan",
            "employee_count": "data.size"
          }
        }
      }
    }
  }
}
```

Out

```
posthog.group("company", "company_123", {
  "name": "Acme",
  "plan": "enterprise",
  "employee_count": 50
})
```

### Order complete

An order complete captures order data and globals as prefixed properties for revenue analysis in PostHog.

Event

```
{
  "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": "3291f37124ff33eb",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000109,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "include": [
    "data",
    "globals"
  ]
}
```

Out

```
posthog.capture("order complete", {
  "data_id": "0rd3r1d",
  "data_currency": "EUR",
  "data_shipping": 5.22,
  "data_taxes": 73.76,
  "data_total": 555,
  "globals_pagegroup": "shop"
})
```

### Set person properties

A profile update calls setPersonProperties to enrich the PostHog profile without changing identity.

Event

```
{
  "name": "profile update",
  "data": {
    "name": "Jane Doe",
    "avatar_url": "https://example.com/avatar.png"
  },
  "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": "8563200064238772",
  "trigger": "test",
  "entity": "profile",
  "action": "update",
  "timestamp": 1700000106,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "settings": {
    "identify": {
      "map": {
        "$set": {
          "map": {
            "name": "data.name",
            "avatar": "data.avatar_url"
          }
        }
      }
    }
  }
}
```

Out

```
posthog.setPersonProperties({
  "name": "Jane Doe",
  "avatar": "https://example.com/avatar.png"
}, null);

posthog.capture("profile update", {})
```

### Rule include overrides

A per-rule include replaces the destination-level include so this event forwards only globals.

Event

```
{
  "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": "a4335aa20f972c44",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000103,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "include": [
    "globals"
  ]
}
```

Out

```
posthog.capture("order complete", {
  "globals_pagegroup": "shop"
})
```

### User login identify

A user login fires PostHog identify with $set and $set\_once person properties, skipping the capture.

Event

```
{
  "name": "user login",
  "data": {
    "user_id": "new-user-123",
    "email": "user@acme.com",
    "plan": "premium",
    "company": "Acme",
    "source": "organic"
  },
  "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": "7413505e9fcd4321",
  "trigger": "test",
  "entity": "user",
  "action": "login",
  "timestamp": 1700000105,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "silent": true,
  "settings": {
    "identify": {
      "map": {
        "distinctId": "data.user_id",
        "$set": {
          "map": {
            "email": "data.email",
            "plan": "data.plan",
            "company": "data.company"
          }
        },
        "$set_once": {
          "map": {
            "first_login": "timestamp",
            "signup_source": "data.source"
          }
        }
      }
    }
  }
}
```

Out

```
posthog.identify("new-user-123", {
  "email": "user@acme.com",
  "plan": "premium",
  "company": "Acme"
}, {
  "first_login": 1700000105,
  "signup_source": "organic"
})
```

### User logout reset

A user logout calls posthog.reset to clear the distinct id and generate a new anonymous one.

Event

```
{
  "name": "user logout",
  "data": {
    "string": "foo",
    "number": 1,
    "boolean": true,
    "array": [
      0,
      "text",
      false
    ]
  },
  "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": "b5ce1815312803a8",
  "trigger": "test",
  "entity": "user",
  "action": "logout",
  "timestamp": 1700000107,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "silent": true,
  "settings": {
    "reset": true
  }
}
```

Out

```
posthog.reset()
```

## Built-in features[​](#built-in-features "Direct link to Built-in features")

All these PostHog features work via standard `posthog-js` init options, with no destination wiring required:

* **Session replay**: `settings.session_recording: { maskAllInputs: true, ... }`
* **Feature flags**: `settings.bootstrap: { featureFlags: { ... } }` for SSR
* **Surveys**: automatic; `settings.disable_surveys: true` to opt out
* **Heatmaps**: `settings.capture_heatmaps: true`
* **Exception capture**: `settings.capture_exceptions: true`
* **Cookieless mode**: `settings.cookieless_mode: 'always' | 'on_reject'`
* **Person profiles**: `settings.person_profiles: 'identified_only'` (PostHog default, privacy-friendly) or `'always'`

walkerOS sets three defaults that differ from PostHog's built-ins: `autocapture: false`, `capture_pageview: false`, `capture_pageleave: false`, because walkerOS sources handle event capture. Override them explicitly if you want PostHog's autocapture on.

## Related[​](#related "Direct link to Related")

* [PostHog documentation](https://posthog.com/docs)
* [`posthog-js` SDK reference](https://posthog.com/docs/libraries/js)
