---
title: PostHog for LLM Apps with Langfuse (open source)
sidebarTitle: PostHog
logo: /images/integrations/posthog_icon.svg
description: Display your Langfuse metrics in Posthog dashboards.
---

# PostHog Integration

[PostHog](https://posthog.com) is a popular choice for OSS product analytics. While Langfuse offers [analytics](/docs/analytics) out of the box, many of our users have asked for a way to **integrate their LLM related metrics that they capture with Langfuse into their PostHog dashboards**.

We've built an integration to make it easy to answer questions like:

- _"Are my most active users also the ones who are most engaged with my LLM content?"_
- _"Does interacting with the LLM feature relate to higher retention rates?"_
- _"How does the LLM feature impact my conversion rates?"_
- _"Does the user feedback that I capture in Langfuse correlate with the user behavior that I see in PostHog?"_

## Get started

<Steps>

### Enable the integration

Configure this integration in your Langfuse project settings. You will need to provide your PostHog Hostname and API key.

  ![Posthog Integration Settings](/images/docs/posthog-settings.png)

### Build a dashboard in PostHog

Once integrated, you can build a dashboard in PostHog to visualize your Langfuse metrics (see [reference below](#details)). Use the _AI Metrics_ template to get started with a pre-built dashboard that includes the most common metrics from Langfuse.

  ![PostHog Dashboard Template](/images/docs/posthog-template.png)

</Steps>

## Example PostHog Dashboard

## Integration details [#details]

On an hourly schedule, Langfuse batches aggregated events and metrics to your PostHog instance.

### Metadata matching

Matching of metadata helps to join the data from Langfuse with the data from PostHog:

| Langfuse                                    | PostHog        | Notes                                                                               |
| ------------------------------------------- | -------------- | ----------------------------------------------------------------------------------- |
| `user_id`                                   | `$distinct_id` |                                                                                     |
| `observation.start_time`, `score.timestamp` | `timestamp`    | For [legacy events](#export-source): `trace.timestamp` and `generation.started_at`. |
| `trace.metadata.$posthog_session_id`        | `$session_id`  | Optional, you need to add the PostHog session id to your Langfuse traces.           |

### User properties

We send the following user properties via `'$set'`:

- `langfuse_user_url`: Deeplink to the [user profile](/docs/tracing-features/users) in Langfuse.

### Events [#events]

The integration sends one `langfuse observation` event per observation and one `langfuse score` event per score.

Is there any additional information that would be helpful? You can request more events or properties [here](/ideas).

  Projects using a legacy export source receive different events — see [Legacy
  export sources](#export-source) below.

#### Event: `langfuse observation` [#event-observation]

One event per observation, covering every observation type.

| Property                       | Description                                                                                                                           |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| `timestamp`                    | The start time of the observation.                                                                                                    |
| `langfuse_observation_name`    | The name of the observation.                                                                                                          |
| `langfuse_type`                | The observation type: `GENERATION`, `SPAN`, `EVENT`, `AGENT`, `TOOL`, `CHAIN`, `RETRIEVER`, `EVALUATOR`, `EMBEDDING`, or `GUARDRAIL`. |
| `langfuse_trace_name`          | Name of the trace related to the observation.                                                                                         |
| `langfuse_trace_id`            | The unique identifier of the trace related to the observation.                                                                        |
| `langfuse_url`                 | The URL of the observation on the host platform.                                                                                      |
| `langfuse_user_url`            | Deeplink to the user profile in Langfuse.                                                                                             |
| `langfuse_id`                  | Unique identifier of the observation.                                                                                                 |
| `langfuse_cost_usd`            | Computed total cost of the observation.                                                                                               |
| `langfuse_input_units`         | Number of tokens utilized in prompting (for LLM calls).                                                                               |
| `langfuse_output_units`        | Number of tokens produced (for LLM calls).                                                                                            |
| `langfuse_total_units`         | Total number of tokens consumed (for LLM calls).                                                                                      |
| `langfuse_session_id`          | The session ID associated with the trace of the observation.                                                                          |
| `langfuse_project_id`          | The ID of the project where the observation happened.                                                                                 |
| `langfuse_project_name`        | The name of the project where the observation happened.                                                                               |
| `langfuse_user_id`             | The user ID that started the trace linked to the observation. In case it's unavailable, it defaults to `langfuse_unknown_user`.       |
| `langfuse_latency`             | The observed latency of the observation.                                                                                              |
| `langfuse_time_to_first_token` | The time taken to generate the first token when streaming.                                                                            |
| `langfuse_release`             | Release information of the trace attached with the observation.                                                                       |
| `langfuse_version`             | The versioning info about the observation.                                                                                            |
| `langfuse_model`               | The model used (for LLM calls).                                                                                                       |
| `langfuse_level`               | The level associated with the observation.                                                                                            |
| `langfuse_tags`                | Any tags attached to the trace of the observation.                                                                                    |
| `langfuse_environment`         | The environment associated with the observation.                                                                                      |
| `langfuse_event_version`       | The integration version with Langfuse.                                                                                                |

#### Event: `langfuse score` [#event-score]

One event per score.

| Property                      | Description                                                                                                             |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `timestamp`                   | The time when the score event occurred.                                                                                 |
| `langfuse_score_name`         | The name associated with the score.                                                                                     |
| `langfuse_score_value`        | The value of the score.                                                                                                 |
| `langfuse_score_string_value` | The string value of the score. For BOOLEAN and CATEGORICAL scores, this will be the string representation of the value. |
| `langfuse_score_data_type`    | The data type of the score (NUMERIC, BOOLEAN, CATEGORICAL).                                                             |
| `langfuse_score_comment`      | Any comments attached with the score.                                                                                   |
| `langfuse_score_metadata`     | Any metadata attached with the score.                                                                                   |
| `langfuse_score_entity_type`  | The entity the score is attached to: `trace`, `session`, `dataset_run`, or `unknown`.                                   |
| `langfuse_dataset_run_id`     | The unique identifier of the dataset run, for scores attached to a dataset run.                                         |
| `langfuse_trace_name`         | The name of the trace associated with the score.                                                                        |
| `langfuse_trace_id`           | The unique identifier of the trace associated with the score.                                                           |
| `langfuse_user_url`           | Deeplink to the user profile in Langfuse.                                                                               |
| `langfuse_id`                 | The unique identification of the score.                                                                                 |
| `langfuse_session_id`         | The session identification related to the score's trace.                                                                |
| `langfuse_project_id`         | The project identification linked with the score's trace.                                                               |
| `langfuse_project_name`       | The name of the project linked with the score's trace.                                                                  |
| `langfuse_user_id`            | The user ID that triggered the trace tied with the score. If not available, defaults to `langfuse_unknown_user`.        |
| `langfuse_release`            | The release information of the trace associated with the score.                                                         |
| `langfuse_tags`               | Any tags related to the trace of the score.                                                                             |
| `langfuse_environment`        | The environment associated with the score.                                                                              |
| `langfuse_event_version`      | The integration version with Langfuse.                                                                                  |

## Legacy export sources [#export-source]

Cloud projects created before 2026-05-20 and self-hosted deployments have an `Export Source` selector in the integration settings (introduced with the Langfuse v4 preview). Cloud projects created on or after 2026-05-20 always use `Enriched observations (recommended)` — the schema documented [above](#events) — and can skip this section.

Available options:

- `Enriched observations (recommended)`: sends the [`langfuse observation`](#event-observation) events documented above. Provides significantly better export performance and covers every observation type.
- `Traces and observations (legacy)`: sends the [`langfuse trace`](#event-trace) and [`langfuse generation`](#event-generation) events documented below.
- `Traces and observations (legacy) and enriched observations`: sends all of the above. This creates duplicate records by design, as a validation aid during migration.

[`langfuse score`](#event-score) events are always sent, regardless of the selected export source.

`Traces and observations (legacy)` sources may be deprecated in the future. All new export jobs should use `Enriched observations (recommended)`, and existing legacy jobs are strongly recommended to upgrade.

### Migrating from the legacy export source [#migrate-export-source]

New integrations default to `Enriched observations (recommended)`; existing integrations continue to use `Traces and observations (legacy)` until changed.

  November 16, 2026 (2026-11-16) is the Langfuse Cloud v4 cutover. If you have not switched
  by then, remaining legacy exports switch to `Enriched observations`
  automatically. Migrate on your own schedule beforehand to avoid an
  unannounced hard cliff in your event stream. If you are self-hosting, the
  switch happens automatically once you run the v4 server in `events_only`
  mode.

PostHog is a schemaless event store, so no setup is needed on the PostHog side — the new event name and properties appear automatically once you switch. All migration effort goes into the assets built on top of the events: insights, dashboards, funnels, cohorts, alerts, and warehouse syncs.

Keep in mind:

1. **Nothing is backfilled.** The sync is watermark-based: the old event streams stop at the switch date and the new one starts. Dashboards keyed on the old event names show a hard cliff — add a PostHog annotation at the cutover date and keep old dashboards around for lookback.
2. **Queries need rewriting, not re-pointing.** Insights on `langfuse generation` become insights on `langfuse observation` filtered by `langfuse_type = 'GENERATION'`. Per-trace metrics (total cost, observation count, latency) must be recomputed by aggregating observation events over `langfuse_trace_id`, since there is no trace-summary event anymore — see [changes from legacy to enriched events](#legacy-vs-enriched).
3. **The combined mode double-counts by design.** With `Traces and observations (legacy) and enriched observations`, a generation is exported both as a `langfuse generation` and as a `langfuse observation` event. PostHog does not deduplicate across event names, so metrics that sum cost or tokens across both event types double-count during migration. Use this mode only to build and validate new dashboards side by side.
4. **The switch is effectively one-way.** Once legacy writes are off, the legacy sources can no longer be selected.

To migrate:

1. Switch to `Traces and observations (legacy) and enriched observations`.
2. Duplicate your dashboards and insights onto the `langfuse observation` event: filter by `langfuse_type`, use `langfuse_observation_name`, and rebuild per-trace metrics as aggregations over `langfuse_trace_id`.
3. Validate the new numbers against the old ones side by side. Expect intentional coverage differences: the enriched source includes all observation types, not just generations.
4. Switch to `Enriched observations (recommended)` and annotate the cutover date on any legacy dashboards you keep.

For rollout details, see the [enriched observations default changelog](/changelog/2026-05-20-blob-storage-enriched-default).

### Changes from legacy to enriched events [#legacy-vs-enriched]

- **`langfuse generation` is replaced by `langfuse observation`.** The two events are field-for-field identical, with two exceptions: `langfuse_generation_name` is renamed to `langfuse_observation_name`, and a new `langfuse_type` property carries the observation type.
- **Coverage expands to all observation types.** The legacy source only exports generations; the enriched source exports every observation type. Expect a higher event volume after switching — PostHog bills per event. Filter on `langfuse_type` = `GENERATION` to reproduce the legacy scope.
- **No standalone trace event.** Trace context is available on every observation event via `langfuse_trace_id` and `langfuse_trace_name`. The trace-level rollup properties have no enriched equivalent: `langfuse_count_observations`, the trace-level `langfuse_cost_usd` and `langfuse_latency` aggregates, and the trace-scoped `langfuse_url`. To approximate them, aggregate observation events by `langfuse_trace_id`.
- **Score events are identical** in both sources.
- **Identity and deduplication are unchanged**: the distinct id is still derived from `langfuse_user_id`, `$session_id` handling is the same, and `langfuse_event_version` remains `1.0.0` for all events.

### Event: `langfuse trace` [#event-trace]

Sent only by the legacy export sources. There is no enriched equivalent — see [changes from legacy to enriched events](#legacy-vs-enriched).

| Property                      | Description                                                                       |
| ----------------------------- | --------------------------------------------------------------------------------- |
| `timestamp`                   | The time the event occurred.                                                      |
| `langfuse_trace_name`         | The name of the trace.                                                            |
| `langfuse_url`                | The URL of the trace.                                                             |
| `langfuse_user_url`           | Deeplink to the user profile in Langfuse.                                         |
| `langfuse_id`                 | The unique identification of the trace.                                           |
| `langfuse_cost_usd`           | The total cost associated with the trace.                                         |
| `langfuse_count_observations` | The number of observations in the trace.                                          |
| `langfuse_session_id`         | The session ID related to the event.                                              |
| `langfuse_project_id`         | An ID associated with the project related to the event.                           |
| `langfuse_project_name`       | The name of the project related to the event.                                     |
| `langfuse_user_id`            | User ID related to the event. If it's null, it's marked as langfuse_unknown_user. |
| `langfuse_latency`            | The latency of the event.                                                         |
| `langfuse_release`            | Information relating to the event release.                                        |
| `langfuse_version`            | The version of the event.                                                         |
| `langfuse_tags`               | Any tags associated with the event.                                               |
| `langfuse_environment`        | The environment associated with the trace.                                        |
| `langfuse_event_version`      | The integration version of Langfuse.                                              |

### Event: `langfuse generation` [#event-generation]

Sent only by the legacy export sources. Only covers observations of type generation; replaced by [`langfuse observation`](#event-observation) in the enriched source.

| Property                       | Description                                                                                                                    |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| `timestamp`                    | The start time of the generation.                                                                                              |
| `langfuse_generation_name`     | The name of the generation.                                                                                                    |
| `langfuse_trace_name`          | Name of the trace related to the generation.                                                                                   |
| `langfuse_trace_id`            | The unique identifier of the trace related to the generation.                                                                  |
| `langfuse_url`                 | The URL of the generation on the host platform.                                                                                |
| `langfuse_user_url`            | Deeplink to the user profile in Langfuse.                                                                                      |
| `langfuse_id`                  | Unique identifier of the generation.                                                                                           |
| `langfuse_cost_usd`            | Computed total cost of the generation.                                                                                         |
| `langfuse_input_units`         | Number of tokens utilized in prompting the generation.                                                                         |
| `langfuse_output_units`        | Number of tokens produced by the generation.                                                                                   |
| `langfuse_total_units`         | Total number of tokens consumed in the generation process.                                                                     |
| `langfuse_session_id`          | The session ID associated with the trace of the generation.                                                                    |
| `langfuse_project_id`          | The project identification where the generation happened.                                                                      |
| `langfuse_project_name`        | The name of the project where the generation happened.                                                                         |
| `langfuse_user_id`             | The user ID that started the trace linked to the generation. In case it's unavailable, it defaults to `langfuse_unknown_user`. |
| `langfuse_latency`             | The observed latency of the generation.                                                                                        |
| `langfuse_time_to_first_token` | The time taken to generate the first token when streaming.                                                                     |
| `langfuse_release`             | Release information of the trace attached with the generation.                                                                 |
| `langfuse_version`             | The versioning info about the generation.                                                                                      |
| `langfuse_model`               | The model used during this generation's process.                                                                               |
| `langfuse_level`               | The level associated with the generation.                                                                                      |
| `langfuse_tags`                | Any tags attached to the trace of the generation.                                                                              |
| `langfuse_environment`         | The environment associated with the generation.                                                                                |
| `langfuse_event_version`       | The integration version with Langfuse.                                                                                         |

## Troubleshooting

**Missing data in PostHog?** Please check that you have correctly entered the PostHog hostname and API key in your Langfuse project settings. Also, if you use the PostHog free-tier, please make sure that you have not exceeded the event limits as PostHog drops events when the limit is reached. Reach out to us if you encounter any other issues with the integration.

<!-- agent-instructions -->

---

## Agent Instructions

This page is part of the [Langfuse](https://langfuse.com) documentation, published as plain Markdown for AI agents. Every page is available as Markdown by appending `.md` to its URL, or by sending an `Accept: text/markdown` header. This page: `https://langfuse.com/integrations/analytics/posthog.md`.

### Querying these docs

If the answer is not on this page, query the documentation instead of guessing:

- **Semantic search** across all Langfuse docs, returning an answer with the relevant pages and excerpts. Ask a specific, self-contained question:

  ```bash
  curl -sG "https://langfuse.com/api/search-docs" --data-urlencode "query=How do I trace a LangGraph agent?"
  ```

- **Index of every page**: <https://langfuse.com/llms.txt>, with per-section indexes [llms-docs.txt](https://langfuse.com/llms-docs.txt), [llms-integrations.txt](https://langfuse.com/llms-integrations.txt), and [llms-self-hosting.txt](https://langfuse.com/llms-self-hosting.txt).

### Before writing Langfuse code

- **Install the [Langfuse Agent Skill](https://langfuse.com/docs/api-and-data-platform/features/agent-skill).** It encodes Langfuse's own best practices for instrumentation, prompt management, and evaluation, and materially improves results.
- **Read [What does a good trace look like?](https://langfuse.com/docs/observability/best-practices.md)** before instrumenting an application.
- **Verify endpoints, parameters, and response fields** against the [API reference](https://api.reference.langfuse.com) instead of inferring them from code examples.
- **Use the [Langfuse CLI](https://langfuse.com/docs/api-and-data-platform/features/cli)** (`npx langfuse-cli api <resource> <action>`) to read or write traces, prompts, datasets, and scores from the terminal.

Found an error in these docs? Please open an issue at <https://github.com/langfuse/langfuse-docs/issues>.
