Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"displayName": "PostHog",
"source": "./",
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from your AI coding tool. Optionally capture Claude Code sessions to PostHog LLM Analytics.",
"version": "1.1.60",
"version": "1.1.61",
"author": {
"name": "PostHog",
"email": "hey@posthog.com",
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "posthog",
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from your AI coding tool. Optionally capture Claude Code sessions to PostHog LLM Analytics.",
"version": "1.1.60",
"version": "1.1.61",
"author": {
"name": "PostHog",
"email": "hey@posthog.com",
Expand Down
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "posthog",
"version": "1.0.58",
"version": "1.0.59",
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from Codex",
"author": {
"name": "PostHog",
Expand Down
2 changes: 1 addition & 1 deletion .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "posthog",
"displayName": "PostHog",
"version": "1.1.54",
"version": "1.1.55",
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from Cursor",
"author": {
"name": "PostHog",
Expand Down
2 changes: 1 addition & 1 deletion gemini-extension.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "posthog",
"version": "1.0.56",
"version": "1.0.57",
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from Gemini CLI",
"mcpServers": {
"posthog": {
Expand Down
16 changes: 16 additions & 0 deletions skills/instrument-error-tracking/references/fingerprints.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,22 @@ You can find details about how issue grouping works in the [issues and exception

Fingerprints can be manually set during exception capture. This is a very useful way to group exceptions that are not related to each other. You can find examples of how to do this in the [custom issue grouping](/docs/error-tracking/grouping-issues.md#option-2-client-side-fingerprint) section.

When you set a custom fingerprint, you can also name the resulting issue with the `$issue_name` and `$issue_description` properties:

JavaScript

PostHog AI

```javascript
posthog.captureException(error, {
$exception_fingerprint: "MyCustomGroup",
$issue_name: "Checkout failures",
$issue_description: "Payment provider timeouts during checkout",
})
```

PostHog uses these two properties only on the event that creates the issue, and truncates each to 255 characters. Later events on the same fingerprint keep the existing name and description. When you do not set them, PostHog uses the exception type as the name and the exception message as the description.

You can also learn more about grouping issues using rules in the [grouping issues](/docs/error-tracking/grouping-issues.md) guide.

### Still have questions?
Expand Down
12 changes: 9 additions & 3 deletions skills/instrument-integration/references/flutter.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,9 @@ Future<void> main() async {

#### Web setup

For Web, add your `Web snippet` (which you can find in [your project settings](https://us.posthog.com/settings/project#snippet)) in the `<header>` of your `web/index.html` file:
If your project has a `web/` directory, this step is required. `Posthog().setup()` is a no-op on web, so a web build without the snippet below captures nothing.

Add your `Web snippet` (which you can find in [your project settings](https://us.posthog.com/settings/project#snippet)) in the `<header>` of your `web/index.html` file. Write your project token into the snippet as a literal string. It's public, the same token ships to every visitor, and it needs no build-time or deploy-time injection:

web/index.html

Expand Down Expand Up @@ -292,12 +294,16 @@ PostHog autocapture automatically tracks the following events for you:
- **Application Backgrounded** - when the app is sent to the background by the user
- **Application Installed** - when the app is installed.
- **Application Updated** - when the app is updated.
- **$screen** - when the user navigates (if using [navigatorObservers](https://docs.flutter.dev/ui/navigation) or [go\_router](https://pub.dev/packages/go_router). You'd need to set up the `PosthogObserver` manually.)
- **$screen** - when the user navigates, once you add the `PosthogObserver`
- **$exception** - when the app throws exceptions.

### Capturing screen views

> Note: Your routes should be named. Otherwise, they won't be recorded.
Screen views aren't captured automatically. Add the `PosthogObserver` to your app yourself. Without it, your app sends no `$screen` events at all.

This works with any routing package, not just the plain `Navigator` API. Add the observer wherever your router takes navigator observers, as shown below for `MaterialApp` and `go_router`.

> Note: Screen names come from each route's `RouteSettings.name`. Most routing packages set this for you. If yours doesn't, name your routes so `$screen` events are readable.

#### Using `navigatorObservers`

Expand Down
6 changes: 3 additions & 3 deletions skills/instrument-integration/references/posthog-node.md
Original file line number Diff line number Diff line change
Expand Up @@ -1011,13 +1011,13 @@ await client.enable()

Evaluate all feature flags for a user in a single call and return a snapshot. Branch on `.isEnabled()` / `.getFlag()`, then pass the same snapshot to `capture()` via the `flags` option so the captured event carries the exact flag values the code branched on.
Prefer this over repeated `isFeatureEnabled()` / `getFeatureFlag()` calls and over `capture({ sendFeatureFlags: true })` — it consolidates flag evaluation into a single `/flags` request per incoming request.
**Local evaluation is transparent.** When the poller can resolve a flag from cached definitions, no network call is made and the snapshot's `$feature_flag_called` events are tagged `locally_evaluated: true`.
**Trim the request.** Pass `flagKeys` to scope the underlying `/flags` request to a subset of flags — useful when you only need a few flags and want to reduce the response payload.
**Local evaluation is transparent.** When the poller can resolve a flag from cached definitions, no network call is made and the snapshot's `$feature_flag_called` events are tagged `locally_evaluated: true`. A requested key missing from local definitions is included in a `/flags` fallback unless `onlyEvaluateLocally` is true. Locally resolved values remain authoritative when remote results are merged.
**Trim the request.** Pass `flagKeys` to scope local evaluation, the underlying `/flags` request, and the returned snapshot to a subset of flags. Remote evaluation responses are not cached, so a key missing both locally and remotely costs one `/flags` request per `evaluateFlags()` call.
**Trim the event payload.** Use `flags.only([...])` or `flags.onlyAccessed()` to filter which flags get attached to a captured event without re-fetching.

### Parameters

- **`options?`** (`AllFlagsOptions`) - Optional configuration for flag evaluation. Supports the same fields as `getAllFlags()`, including `flagKeys` to scope the `/flags` request.
- **`options?`** (`AllFlagsOptions`) - Optional configuration for flag evaluation. Supports the same fields as `getAllFlags()`. `flagKeys` scopes local evaluation, the `/flags` request, and the returned snapshot. `onlyEvaluateLocally` prevents fallback and leaves unresolved keys absent.

### Returns

Expand Down
9 changes: 5 additions & 4 deletions skills/instrument-integration/references/posthog-python.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# PostHog Python SDK

**SDK Version:** 7.39.2
**SDK Version:** 7.44.1

Integrate PostHog into any python application.

Expand Down Expand Up @@ -76,6 +76,7 @@ Initialize a new PostHog client instance.
- **`secret_key`** (`any`) - A Personal API Key or Project Secret API Key, used to authenticate local feature flag evaluation, remote config payloads, and decrypted flag payloads. Example:: posthog.Client(project_api_key, secret_key="phx_...")
- **`metrics?`** (`dict`)
- **`enable_full_ai_capture`** (`bool`) - Route PostHog AI wrapper events through the dedicated AI capture endpoint and capture full AI content: skips string truncation and passes media (base64/data URIs) through unredacted. ``privacy_mode`` always wins. Defaults to False.
- **`capture_trace_context`** (`bool`) - When OpenTelemetry is installed and a valid span is active at capture time, add its trace and span IDs as ``$trace_id`` and ``$span_id`` properties to events captured with ``capture()`` and ``capture_ai()``, so they can be correlated with backend traces. Explicit ``$trace_id``/``$span_id`` values passed in ``properties`` win. Exception events (``capture_exception``) always attach these IDs regardless of this setting. Defaults to False.
- **`_use_ai_lane`** (`bool`)
- **`_enable_multimodal_capture`** (`bool`)

Expand Down Expand Up @@ -320,7 +321,7 @@ Evaluate all feature flags for a user in a single call and return a :class:`Feat
- **`group_properties?`** (`dict[str, dict[str, Any]]`) - Group properties keyed by group type.
- **`only_evaluate_locally`** (`bool`) - If True, never fall back to remote evaluation — flags that can't be evaluated locally are simply omitted from the snapshot.
- **`disable_geoip?`** (`bool`) - Whether to disable GeoIP lookup.
- **`flag_keys?`** (`list[str]`) - Optional list of flag keys to scope the underlying ``/flags`` request to a subset.
- **`flag_keys?`** (`list[str]`) - Optional list that scopes local evaluation, the underlying ``/flags`` request, and the returned snapshot. When omitted or ``None``, all flags are evaluated. An empty list returns an empty snapshot without evaluating flags. A requested key absent from loaded local definitions is included in one remote fallback per ``evaluate_flags`` call unless ``only_evaluate_locally`` is True. If the server also does not know the key, it is omitted from the snapshot.
- **`device_id?`** (`str`) - Optional device ID override. If not provided, falls back to the context device_id (which may be set via tracing headers). Used by experience-continuity flags to match users across distinct_id changes.

### Returns
Expand Down Expand Up @@ -1166,9 +1167,9 @@ Evaluate all feature flags for a user in a single call and return a :class:`Feat
- **`groups?`** (`Mapping[str, Union[str, int]]`) - Mapping of group type to group key.
- **`person_properties?`** (`dict[str, Any]`) - Person properties to use for evaluation.
- **`group_properties?`** (`dict[str, dict[str, Any]]`) - Group properties keyed by group type.
- **`only_evaluate_locally`** (`bool`) - If ``True``, never fall back to remote evaluation.
- **`only_evaluate_locally`** (`bool`) - If ``True``, never fall back to remote evaluation and omit flags that cannot be evaluated locally.
- **`disable_geoip?`** (`bool`) - Whether to disable GeoIP lookup.
- **`flag_keys?`** (`list[str]`) - Optional list of flag keys. When provided, only these flags are evaluated — the underlying ``/flags`` request asks the server for just this subset, which makes the response smaller and the request cheaper. Use this when you only need a handful of flags out of many.
- **`flag_keys?`** (`list[str]`) - Optional list that scopes local evaluation, the underlying ``/flags`` request, and the returned snapshot. When omitted or ``None``, all flags are evaluated. An empty list returns an empty snapshot without evaluating flags. A requested key absent from loaded local definitions is included in one remote fallback per ``evaluate_flags`` call unless ``only_evaluate_locally`` is ``True``. If the server also does not know the key, it is omitted from the snapshot.
- **`device_id?`** (`str`) - Optional device ID override. If not provided, falls back to the context device_id (which may be set via tracing headers). Used by experience-continuity flags to match users across distinct_id changes.

### Returns
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ When PostHog calculates costs automatically, it sets the following metadata prop

These properties are useful for debugging cost discrepancies or understanding which pricing was applied when using model aliases or custom configurations.

You can find the code for this on [GitHub](https://github.com/PostHog/posthog/tree/master/plugin-server/src/ingestion/ai-costs).
You can find the code for this on [GitHub](https://github.com/PostHog/posthog/tree/master/nodejs/src/ingestion/pipelines/ai/costs).

### Still have questions?

Expand Down
4 changes: 4 additions & 0 deletions skills/instrument-llm-analytics/references/manual-capture.md
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,10 @@ Skip the manual setup — run this in your project and the wizard installs the S
| [Spans](/docs/ai-observability/spans.md) | Review spans and their role in representing individual operations. |
| [Anaylze LLM performance](/docs/ai-observability/dashboard.md) | Learn how to create dashboards to analyze LLM performance. |

## Large events

For large events, use the dedicated AI ingestion path – see [capturing large AI events](/docs/ai-observability/large-events.md).

### Still have questions?

Ask PostHog AI
Expand Down
4 changes: 3 additions & 1 deletion skills/instrument-logs/references/flutter.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,9 @@ The PostHog Flutter SDK has built-in support for capturing structured Logs from

#### Web setup

For Web, add your `Web snippet` (which you can find in [your project settings](https://us.posthog.com/settings/project#snippet)) in the `<header>` of your `web/index.html` file:
If your project has a `web/` directory, this step is required. `Posthog().setup()` is a no-op on web, so a web build without the snippet below captures nothing.

Add your `Web snippet` (which you can find in [your project settings](https://us.posthog.com/settings/project#snippet)) in the `<header>` of your `web/index.html` file. Write your project token into the snippet as a literal string. It's public, the same token ships to every visitor, and it needs no build-time or deploy-time injection:

web/index.html

Expand Down
12 changes: 9 additions & 3 deletions skills/instrument-product-analytics/references/flutter.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,9 @@ Future<void> main() async {

#### Web setup

For Web, add your `Web snippet` (which you can find in [your project settings](https://us.posthog.com/settings/project#snippet)) in the `<header>` of your `web/index.html` file:
If your project has a `web/` directory, this step is required. `Posthog().setup()` is a no-op on web, so a web build without the snippet below captures nothing.

Add your `Web snippet` (which you can find in [your project settings](https://us.posthog.com/settings/project#snippet)) in the `<header>` of your `web/index.html` file. Write your project token into the snippet as a literal string. It's public, the same token ships to every visitor, and it needs no build-time or deploy-time injection:

web/index.html

Expand Down Expand Up @@ -292,12 +294,16 @@ PostHog autocapture automatically tracks the following events for you:
- **Application Backgrounded** - when the app is sent to the background by the user
- **Application Installed** - when the app is installed.
- **Application Updated** - when the app is updated.
- **$screen** - when the user navigates (if using [navigatorObservers](https://docs.flutter.dev/ui/navigation) or [go\_router](https://pub.dev/packages/go_router). You'd need to set up the `PosthogObserver` manually.)
- **$screen** - when the user navigates, once you add the `PosthogObserver`
- **$exception** - when the app throws exceptions.

### Capturing screen views

> Note: Your routes should be named. Otherwise, they won't be recorded.
Screen views aren't captured automatically. Add the `PosthogObserver` to your app yourself. Without it, your app sends no `$screen` events at all.

This works with any routing package, not just the plain `Navigator` API. Add the observer wherever your router takes navigator observers, as shown below for `MaterialApp` and `go_router`.

> Note: Screen names come from each route's `RouteSettings.name`. Most routing packages set this for you. If yours doesn't, name your routes so `$screen` events are readable.

#### Using `navigatorObservers`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# PostHog Python SDK

**SDK Version:** 7.39.2
**SDK Version:** 7.44.1

Integrate PostHog into any python application.

Expand Down Expand Up @@ -76,6 +76,7 @@ Initialize a new PostHog client instance.
- **`secret_key`** (`any`) - A Personal API Key or Project Secret API Key, used to authenticate local feature flag evaluation, remote config payloads, and decrypted flag payloads. Example:: posthog.Client(project_api_key, secret_key="phx_...")
- **`metrics?`** (`dict`)
- **`enable_full_ai_capture`** (`bool`) - Route PostHog AI wrapper events through the dedicated AI capture endpoint and capture full AI content: skips string truncation and passes media (base64/data URIs) through unredacted. ``privacy_mode`` always wins. Defaults to False.
- **`capture_trace_context`** (`bool`) - When OpenTelemetry is installed and a valid span is active at capture time, add its trace and span IDs as ``$trace_id`` and ``$span_id`` properties to events captured with ``capture()`` and ``capture_ai()``, so they can be correlated with backend traces. Explicit ``$trace_id``/``$span_id`` values passed in ``properties`` win. Exception events (``capture_exception``) always attach these IDs regardless of this setting. Defaults to False.
- **`_use_ai_lane`** (`bool`)
- **`_enable_multimodal_capture`** (`bool`)

Expand Down Expand Up @@ -320,7 +321,7 @@ Evaluate all feature flags for a user in a single call and return a :class:`Feat
- **`group_properties?`** (`dict[str, dict[str, Any]]`) - Group properties keyed by group type.
- **`only_evaluate_locally`** (`bool`) - If True, never fall back to remote evaluation — flags that can't be evaluated locally are simply omitted from the snapshot.
- **`disable_geoip?`** (`bool`) - Whether to disable GeoIP lookup.
- **`flag_keys?`** (`list[str]`) - Optional list of flag keys to scope the underlying ``/flags`` request to a subset.
- **`flag_keys?`** (`list[str]`) - Optional list that scopes local evaluation, the underlying ``/flags`` request, and the returned snapshot. When omitted or ``None``, all flags are evaluated. An empty list returns an empty snapshot without evaluating flags. A requested key absent from loaded local definitions is included in one remote fallback per ``evaluate_flags`` call unless ``only_evaluate_locally`` is True. If the server also does not know the key, it is omitted from the snapshot.
- **`device_id?`** (`str`) - Optional device ID override. If not provided, falls back to the context device_id (which may be set via tracing headers). Used by experience-continuity flags to match users across distinct_id changes.

### Returns
Expand Down Expand Up @@ -1166,9 +1167,9 @@ Evaluate all feature flags for a user in a single call and return a :class:`Feat
- **`groups?`** (`Mapping[str, Union[str, int]]`) - Mapping of group type to group key.
- **`person_properties?`** (`dict[str, Any]`) - Person properties to use for evaluation.
- **`group_properties?`** (`dict[str, dict[str, Any]]`) - Group properties keyed by group type.
- **`only_evaluate_locally`** (`bool`) - If ``True``, never fall back to remote evaluation.
- **`only_evaluate_locally`** (`bool`) - If ``True``, never fall back to remote evaluation and omit flags that cannot be evaluated locally.
- **`disable_geoip?`** (`bool`) - Whether to disable GeoIP lookup.
- **`flag_keys?`** (`list[str]`) - Optional list of flag keys. When provided, only these flags are evaluated — the underlying ``/flags`` request asks the server for just this subset, which makes the response smaller and the request cheaper. Use this when you only need a handful of flags out of many.
- **`flag_keys?`** (`list[str]`) - Optional list that scopes local evaluation, the underlying ``/flags`` request, and the returned snapshot. When omitted or ``None``, all flags are evaluated. An empty list returns an empty snapshot without evaluating flags. A requested key absent from loaded local definitions is included in one remote fallback per ``evaluate_flags`` call unless ``only_evaluate_locally`` is ``True``. If the server also does not know the key, it is omitted from the snapshot.
- **`device_id?`** (`str`) - Optional device ID override. If not provided, falls back to the context device_id (which may be set via tracing headers). Used by experience-continuity flags to match users across distinct_id changes.

### Returns
Expand Down