kestra-io / kestra-io/plugin-posthog
Implement PostHog plugin — Capture events, identify users, evaluate feature flags
- Dominant language
- Java
- Stars
- 1
- Forks
- 0
- Avg merge
- 5d 10h
- Merged PRs (30d)
- 3
Description
## Summary
Implement the `plugin-posthog` Kestra plugin using the official [PostHog Java SDK](https://posthog.com/docs/libraries/java) to allow workflows to capture analytics events, identify users, evaluate feature flags, and track group behaviors directly from Kestra flow tasks — without any custom scripting or shell tasks.
## Motivation
Product and data engineering teams currently capture PostHog events from backend processes through ad-hoc Python scripts or custom HTTP tasks, losing the observability and re-use benefits of structured Kestra tasks. A dedicated plugin will let teams instrument ETL pipelines, data migrations, and automation workflows with PostHog analytics natively — correlating workflow execution with product usage data.
Key beneficiaries: growth engineers instrumenting experiment pipelines, data engineers tagging pipeline runs with feature flag state, and platform teams emitting lifecycle events from infrastructure flows.
## Context
The repository `kestra-io/plugin-posthog` already exists as a scaffold. This issue tracks the full implementation of the plugin tasks.
Reference implementation to model after: [`plugin-core` HTTP tasks](https://github.com/kestra-io/kestra/tree/develop/core/src/main/java/io/kestra/plugin/core/http) for task structure and `Property` usage patterns.
Note: `package-info.java` currently uses `PluginCategory.DATA` — this should be updated to `PluginCategory.BUSINESS` as part of this implementation.
## API Reference
- **Official docs**: https://posthog.com/docs/libraries/java
- **Authentication — two key types**:
- `Capture`, `Identify`, `Alias`, `Group`, `EvaluateFeatureFlag` use the **project API key** (starts with `phc_`). Configured via `PostHogConfig.builder().apiKey(...).host(...).build()`.
- `NewEvent` trigger (REST API reads via `GET /api/projects/:projectId/events/`) requires a **personal API key** (Settings → Personal API keys) plus the numeric `projectId`. These are separate from the `phc_` key and must be exposed as distinct task/trigger fields.
- **Base URL pattern**: `https://us.i.posthog.com` (US Cloud) or `https://eu.i.posthog.com` (EU Cloud) or custom self-hosted URL
- **SDK / client library**: `com.posthog.java:posthog:3.19.0` (Maven Central)
## Gradle Dependencies
Add to `build.gradle`:
```groovy
// PostHog server-side Java SDK
implementation "com.posthog.java:posthog:3.19.0"
```
> Use the latest stable version available on Maven Central (`com.posthog.java:posthog`).
## Plugin Structure
- **Repository**: `plugin-posthog`
- **Namespace**: `io.kestra.plugin.posthog`
- **Sub-plugins**: none (flat structure)
- **Categories**: `BUSINESS`
## Suggested Tasks
1. Implement `AbstractPosthogTask` — abstract base class with `apiKey` and `host` `Property` fields, shared `PostHog` client initialization, and `flush()`/`close()` lifecycle
2. `Capture` — send a custom analytics event for a `distinctId` with optional event properties and timestamp
3. `Identify` — set or update person properties for a user identified by `distinctId`
4. `Alias` — create an alias mapping a new distinct ID to an existing one (e.g. anonymous → authenticated user)
5. `Group` — send a group analytics event associating a `distinctId` with a named group type/key and optional group properties
6. `EvaluateFeatureFlag` — evaluate a feature flag for a given `distinctId`, returning the flag value (boolean or string variant) as a task output
7. Add polling trigger `NewEvent` that queries the PostHog REST API (`GET /api/projects/:projectId/events/`) periodically for new events matching configurable filters (event name, properties). Use a **personal API key** (not the `phc_` project key) for authentication. Be mindful of PostHog's REST API rate limits when setting the polling `interval` — prefer `PT5M` or longer for production flows.
8. Write unit + integration tests (mock PostHog server or use PostHog's test mode)
9. Update `package-info.java` — change `PluginCategory.DATA` to `PluginCategory.BUSINESS`
10. Add `metadata/index.yaml` and plugin icon SVG
11. Add YAML examples and plugin documentation
## YAML Examples
### Example 1 — Capture a custom event when a pipeline completes
```yaml
id: pipeline_completed_event
namespace: company.analytics
inputs:
- id: user_id
type: STRING
- id: pipeline_name
type: STRING
tasks:
- id: capture_completion
type: io.kestra.plugin.posthog.Capture
apiKey: "{{ secret('POSTHOG_API_KEY') }}"
host: "https://us.i.posthog.com"
distinctId: "{{ inputs.user_id }}"
event: "pipeline_completed"
properties:
pipeline_name: "{{ inputs.pipeline_name }}"
kestra_execution_id: "{{ execution.id }}"
environment: "production"
```
### Example 2 — Identify a user and capture an onboarding event
```yaml
id: user_onboarding_tracking
namespace: company.growth
inputs:
- id: user_id
type: STRING
- id: plan
type: STRING
tasks:
- id: identify_user
type: io.kestra.plugin.posthog.Identify
apiKey: "{{ secret('POSTHOG_API_KEY') }}"
host: "https://us.i.posthog.com"
distinctId: "{{ inputs.user_id }}"
properties:
plan: "{{ inputs.plan }}"
onboarding_completed: true
- id: capture_onboarding
type: io.kestra.plugin.posthog.Capture
apiKey: "{{ secret('POSTHOG_API_KEY') }}"
host: "https://us.i.posthog.com"
distinctId: "{{ inputs.user_id }}"
event: "onboarding_completed"
properties:
plan: "{{ inputs.plan }}"
- id: log_result
type: io.kestra.plugin.core.log.Log
message: "Tracked onboarding for user {{ inputs.user_id }} on plan {{ inputs.plan }}"
```
### Example 3 — Trigger a flow when a specific PostHog event appears
```yaml
id: react_to_posthog_event
namespace: company.analytics
triggers:
- id: on_new_signup_event
type: io.kestra.plugin.posthog.triggers.NewEvent
apiKey: "{{ secret('POSTHOG_API_KEY') }}"
host: "https://us.i.posthog.com"
projectId: "{{ secret('POSTHOG_PROJECT_ID') }}"
eventName: "user_signed_up"
interval: PT5M
tasks:
- id: handle_signup
type: io.kestra.plugin.core.log.Log
message: "New signup event detected: {{ trigger.distinctId }} at {{ trigger.timestamp }}"
```
## Acceptance Criteria
- [ ] `AbstractPosthogTask` with `apiKey` and `host` `Property` fields implemented
- [ ] `Capture`, `Identify`, `Alias`, `Group`, and `EvaluateFeatureFlag` tasks implemented
- [ ] At least one polling trigger (`NewEvent`) implemented
- [ ] All `Property` fields support Kestra expression language (template rendering)
- [ ] Unit + integration tests pass (`./gradlew test`)
- [ ] `package-info.java` updated from `PluginCategory.DATA` to `PluginCategory.BUSINESS`
- [ ] `metadata/index.yaml` and plugin icon SVG present
- [ ] Build passes with `./gradlew build`
## Repository Setup Checklist
### 1. Add to Sanity check page
Add this plugin to the [Sanity check Notion page](https://www.notion.so/kestra-io/32736907f7b580cbb00dc7c061e624b1?v=32736907f7b58002ac2b000ccc63d8a2).
### 2. Run scoped Terraform apply
Run the following from `infra/terraform/github`:
```bash
terraform apply \
-target='github_repository.repo["plugin-posthog"]' \
-target='github_issue_labels.plugins["plugin-posthog"]' \
-target='github_repository_ruleset.branch["plugin-posthog"]'
```
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the existing scaffold, build.gradle, package-info.java, and the plugin-core HTTP task structure referenced in the issue. Implement the listed tasks and NewEvent trigger, then add unit/integration tests, metadata, icon, examples, and documentation. Done means ./gradlew test and ./gradlew build pass and all acceptance criteria are satisfied.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- analytics, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100