kestra-io / kestra-io/plugin-posthog

Implement PostHog plugin — Capture events, identify users, evaluate feature flags

Open
#3 1 comment 0 reactions 0 assignees View on GitHub
area/plugin good first issue
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.