JavaScript - Community > genkitx-posthog
Plugin to integrate with PostHog for telemetry and analytics.

Firebase Genkit PostHog
PostHog LLM Analytics for Firebase Genkit
genkitx-posthog is the PostHog LLM analytics plugin for Firebase Genkit, originally developed and battle-tested at Orchestra.
It automatically captures AI/LLM telemetry data from your Genkit applications and sends it to PostHog for analysis.
Installation
Install the plugin in your project with your favorite package manager:
npm install genkitx-posthog
pnpm add genkitx-posthog
yarn add genkitx-posthog
Version Compatibility
| Plugin Version | Genkit Version |
|---|---|
| >= 0.1.0 | >= 1.0.0 |
Configuration
To use the plugin, you need to configure it with your PostHog API key:
import { genkit } from 'genkit';
import { googleAI } from '@genkit-ai/googleai';
import { enableTelemetry } from 'genkit/tracing';
import { getPostHogProcessor } from 'genkitx-posthog';
// 1. Initialize Genkit
const ai = genkit({
plugins: [googleAI()],
});
// 2. Create the PostHog span processor
const posthogProcessor = getPostHogProcessor({
apiKey: process.env.POSTHOG_API_KEY!,
host: 'https://us.i.posthog.com', // or 'https://eu.i.posthog.com'
genkitInstance: ai,
});
// 3. Add it to telemetry
enableTelemetry({
spanProcessors: [posthogProcessor],
});
The plugin accepts the following configuration options:
| Option | Type | Default | Description |
|---|---|---|---|
apiKey |
string |
required | PostHog project API key |
host |
string |
'https://us.i.posthog.com' |
PostHog API host URL |
debug |
boolean |
false |
Enable debug logging |
getContext |
ContextResolver |
undefined |
Custom function to resolve user context from spans |
genkitInstance |
GenkitInstanceMinimal |
undefined |
Genkit instance for currentContext() fallback |
logger |
Logger |
Console logger | Custom logger implementation |
flushAt |
number |
1 |
Batch size before automatic flush |
privacyMode |
boolean |
false |
Redact input/output content from events |
Usage
Basic Generation
Once configured, the plugin automatically captures all Genkit operations:
// Events are captured automatically
const response = await ai.generate({
model: 'googleai/gemini-2.0-flash',
prompt: 'Tell me a joke',
});
With User Context
To attribute events to specific users, pass context through Genkit or use a custom context resolver:
// Option 1: Pass context via Genkit's context option
await ai.generate({
model: 'googleai/gemini-2.0-flash',
prompt: 'Hello',
context: {
auth: { uid: 'user-123' },
sessionId: 'session-789',
},
});
// Option 2: Use a custom context resolver
const processor = getPostHogProcessor({
apiKey: process.env.POSTHOG_API_KEY!,
getContext: ({ traceId, spanAttributes, currentContext }) => {
return {
distinctId: currentContext?.userId as string || 'anonymous',
groupType: 'company',
groupId: currentContext?.organizationId as string,
sessionId: currentContext?.sessionId as string,
};
},
});
Within a Genkit Flow
import { defineFlow } from 'genkit';
const myFlow = ai.defineFlow(
{ name: 'myFlow', inputSchema: z.string(), outputSchema: z.string() },
async (input) => {
const response = await ai.generate({
model: 'googleai/gemini-2.0-flash',
prompt: input,
});
return response.text;
}
);
// Flow execution is automatically traced
const result = await myFlow('What is AI?');
Serverless Environments
In serverless environments (AWS Lambda, Cloud Functions), flush events before termination:
import { flushPostHog, shutdownPostHog } from 'genkitx-posthog';
export async function handler(event) {
// ... your Genkit operations
await flushPostHog(); // Ensure events are sent
return response;
}
// For graceful shutdown
process.on('SIGTERM', async () => {
await shutdownPostHog();
process.exit(0);
});
Features
Captured Events
The plugin captures these PostHog AI event types:
| Event | Description | Key Properties |
|---|---|---|
$ai_generation |
Model/LLM calls | $ai_model, $ai_provider, $ai_input_tokens, $ai_output_tokens |
$ai_embedding |
Embedder calls | $ai_model, $ai_provider, $ai_input |
$ai_trace |
Flows and root operations | $ai_trace_id, $ai_span_name, $ai_latency |
$ai_span |
Tools and nested operations | $ai_span_name, $ai_input_state, $ai_output_state |
All events include: $ai_framework ('genkit'), $ai_lib_version, $ai_trace_id, $ai_span_id, $ai_latency, $ai_is_error
Privacy Mode
Enable privacy mode to redact sensitive data:
const processor = getPostHogProcessor({
apiKey: process.env.POSTHOG_API_KEY!,
privacyMode: true, // Redacts input/output content
});
When enabled, $ai_input, $ai_output_choices, $ai_input_state, and $ai_output_state are replaced with '[REDACTED]'. Metadata like token counts and latency are still captured.
PostHog Groups
To use PostHog Groups for organization-level analytics:
const processor = getPostHogProcessor({
apiKey: process.env.POSTHOG_API_KEY!,
getContext: ({ currentContext }) => ({
distinctId: currentContext?.userId as string,
groupType: 'company', // Your PostHog group type
groupId: currentContext?.organizationId as string,
}),
});
API Reference
| Export | Type | Description |
|---|---|---|
getPostHogProcessor |
(options) => SpanProcessor |
Creates a span processor for PostHog integration |
posthog |
(options) => GenkitPlugin |
Genkit plugin (marker only) |
flushPostHog |
() => Promise<void> |
Flush pending events to PostHog |
shutdownPostHog |
() => Promise<void> |
Gracefully shutdown the exporter |
Troubleshooting
Events not appearing in PostHog
- Verify
POSTHOG_API_KEYis set correctly - Enable
debug: trueto see detailed logs - Call
flushPostHog()explicitly to force send events - Ensure correct host (
us.i.posthog.comvseu.i.posthog.com)
Missing user attribution
- Implement a custom
getContextresolver - Pass context via Genkit's
contextoption - Provide
genkitInstancefor automatic context extraction
Built & Maintained By
This plugin was originally built for internal use at Orchestra — the AI-Native productivity platform.
We couldn't find a ready-made way to track our Genkit workflows in PostHog, so we built and open-sourced it to help the Genkit community get better visibility into their AI apps.
Maintained by Miro K and the Orchestra Team.
Contributing
Contributions are welcome! See CONTRIBUTING.md for guidelines.
License
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.