posthog

GitHub

PostHog插件通过REST API提供分析数据查询、事件与用户管理、功能标志及实验操作等功能。支持HogQL查询,需配置API密钥并识别US/EU区域以构建请求。

apps/browser/bundled/plugins/posthog/SKILL.md mereyabdenbekuly-ctrl/clodex-ide

触发场景

需要查询PostHog分析数据或运行HogQL查询 需要管理功能标志、实验、受众群体或调查 需要查找特定用户(Person)或查看事件详情

安装

npx skills add mereyabdenbekuly-ctrl/clodex-ide --skill posthog -g -y
更多选项

非标准路径

npx skills add https://github.com/mereyabdenbekuly-ctrl/clodex-ide/tree/main/apps/browser/bundled/plugins/posthog -g -y

不安装直接使用

npx skills use mereyabdenbekuly-ctrl/clodex-ide@posthog

指定 Agent (Claude Code)

npx skills add mereyabdenbekuly-ctrl/clodex-ide --skill posthog -a claude-code -g -y

安装 repo 全部 skill

npx skills add mereyabdenbekuly-ctrl/clodex-ide --all -g -y

预览 repo 内 skill

npx skills add mereyabdenbekuly-ctrl/clodex-ide --list

SKILL.md

Frontmatter
{
    "name": "posthog",
    "description": "Complete guide for the PostHog plugin — REST API access for querying analytics with HogQL, managing feature flags, inspecting events and persons, reading insights, experiments, cohorts, surveys, and more."
}

PostHog Plugin

This plugin provides access to the PostHog REST API on the user's behalf, using a stored Personal API Key (phx_...).

Capabilities:

  • Run arbitrary HogQL (SQL-like) queries against the analytics database
  • List, filter, and inspect events
  • Look up persons (users) by ID, email, or properties
  • Read saved insights (trends, funnels, retention, paths, etc.)
  • CRUD feature flags
  • Read and manage experiments (A/B tests)
  • Read cohorts, annotations, actions, dashboards, and surveys
  • Query web analytics stats

Authentication

Request the stored PostHog credential. The personalApiKey field is an opaque placeholder — the sandbox fetch proxy substitutes the real value automatically. Never decode or transform it.

const cred = await API.getCredential('posthog-pat');
if (!cred) {
  return 'PostHog credential is not configured. Ask the user to create a Personal API Key at Settings → Personal API Keys in their PostHog dashboard, then store it in Settings.';
}

Region & Base URL

PostHog Cloud has two regions. The agent must determine which one the user is on:

Region Base URL
US Cloud https://us.posthog.com
EU Cloud https://eu.posthog.com

How to determine the region:

  • Ask the user, OR
  • Look at any PostHog dashboard tab open in the browser — the URL hostname reveals the region.

Store the base URL in a variable and use it for all requests.


Making Requests

All API paths are relative to the region base URL. Always pass the key as a Bearer header:

const BASE = 'https://us.posthog.com'; // or https://eu.posthog.com

async function phGet(path) {
  const res = await fetch(`${BASE}${path}`, {
    headers: {
      Authorization: `Bearer ${cred.personalApiKey}`,
      'Content-Type': 'application/json',
    },
  });
  if (!res.ok) throw new Error(`PostHog API ${res.status}: ${await res.text()}`);
  return res.json();
}

async function phPost(path, body) {
  const res = await fetch(`${BASE}${path}`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${cred.personalApiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });
  if (!res.ok) throw new Error(`PostHog API ${res.status}: ${await res.text()}`);
  return res.json();
}

async function phPatch(path, body) {
  const res = await fetch(`${BASE}${path}`, {
    method: 'PATCH',
    headers: {
      Authorization: `Bearer ${cred.personalApiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });
  if (!res.ok) throw new Error(`PostHog API ${res.status}: ${await res.text()}`);
  return res.json();
}

async function phDelete(path) {
  const res = await fetch(`${BASE}${path}`, {
    method: 'DELETE',
    headers: {
      Authorization: `Bearer ${cred.personalApiKey}`,
      'Content-Type': 'application/json',
    },
  });
  if (!res.ok) throw new Error(`PostHog API ${res.status}: ${await res.text()}`);
  if (res.status === 204) return null;
  return res.json();
}

Identifying the Project

Most endpoints require a project ID — a numeric identifier visible in the PostHog dashboard URL:

https://us.posthog.com/project/{project_id}/...

If the user hasn't specified a project ID:

  1. Check any open PostHog dashboard tab in the browser — the project ID is in the URL path.
  2. Ask the user directly.

Key Endpoints

All paths below are relative to the base URL (e.g. https://us.posthog.com).

HogQL Queries (The Primary Analytical Tool)

Run a HogQL query POST /api/projects/{project_id}/query Body:

{
  "query": {
    "kind": "HogQLQuery",
    "query": "SELECT event, count() AS cnt FROM events WHERE timestamp > now() - interval 7 day GROUP BY event ORDER BY cnt DESC LIMIT 20"
  }
}

Response contains results (array of rows), columns (column names), and types (column types).

HogQL is a SQL-like query language on top of ClickHouse. It can query events, persons, sessions, groups, and more. This is the most powerful endpoint for analytics — prefer it over the REST list endpoints when aggregation or filtering is needed.

Run a web stats query POST /api/projects/{project_id}/query Body:

{
  "query": {
    "kind": "WebStatsTableQuery",
    "dateRange": { "date_from": "2025-01-01", "date_to": "2025-01-31" },
    "breakdownBy": "Page",
    "limit": 10
  }
}

Common HogQL Patterns

Top events in the last 7 days:

SELECT event, count() AS cnt
FROM events
WHERE timestamp > now() - interval 7 day
GROUP BY event
ORDER BY cnt DESC
LIMIT 20

Unique users in the last 30 days:

SELECT uniq(person_id) AS unique_users
FROM events
WHERE timestamp > now() - interval 30 day

Pageviews by path:

SELECT properties.$pathname AS path, count() AS views
FROM events
WHERE event = '$pageview'
  AND timestamp > now() - interval 7 day
GROUP BY path
ORDER BY views DESC
LIMIT 20

Daily active users trend:

SELECT toDate(timestamp) AS day, uniq(person_id) AS dau
FROM events
WHERE timestamp > now() - interval 30 day
GROUP BY day
ORDER BY day

Funnel analysis (pageview → signup):

SELECT
  uniq(person_id) AS total_users,
  uniqIf(person_id, event = '$pageview') AS step1,
  uniqIf(person_id, event = 'signed_up') AS step2
FROM events
WHERE timestamp > now() - interval 7 day

User sessions with duration:

SELECT
  session.session_id,
  min(timestamp) AS start,
  max(timestamp) AS end,
  dateDiff('second', min(timestamp), max(timestamp)) AS duration_s,
  count() AS event_count
FROM events
WHERE timestamp > now() - interval 1 day
  AND session.session_id IS NOT NULL
GROUP BY session.session_id
ORDER BY duration_s DESC
LIMIT 20

Events for a specific person:

SELECT event, timestamp, properties
FROM events
WHERE person_id = 'PERSON_UUID'
ORDER BY timestamp DESC
LIMIT 50

Events

List events GET /api/projects/{project_id}/events/ Query params: ?event=<event_name>, ?person_id=<id>, ?limit=<n>, ?after=<cursor> Returns paginated event list.

Get a single event GET /api/projects/{project_id}/events/{event_id}/

Persons

List persons GET /api/projects/{project_id}/persons/ Query params: ?search=<term>, ?email=<email>, ?limit=<n>

Get a specific person GET /api/projects/{project_id}/persons/{person_id}/

Insights (Saved Analytics)

List insights GET /api/projects/{project_id}/insights/ Query params: ?search=<term>, ?short_id=<id>, ?limit=<n> Returns saved trends, funnels, retention, paths, lifecycle, and stickiness queries.

Get a specific insight GET /api/projects/{project_id}/insights/{id}/ Returns the insight definition and its last-calculated results.

Feature Flags

List feature flags GET /api/projects/{project_id}/feature_flags/ Query params: ?search=<term>, ?active=true

Get a specific feature flag GET /api/projects/{project_id}/feature_flags/{id}/

Create a feature flag POST /api/projects/{project_id}/feature_flags/ Body:

{
  "name": "My Flag",
  "key": "my-flag-key",
  "description": "Enables the new onboarding flow",
  "filters": { "groups": [] },
  "active": true
}

Update a feature flag PATCH /api/projects/{project_id}/feature_flags/{id}/ Body: partial update (e.g. { "active": false } to disable).

Delete a feature flag DELETE /api/projects/{project_id}/feature_flags/{id}/

Experiments

List experiments GET /api/projects/{project_id}/experiments/

Get a specific experiment GET /api/projects/{project_id}/experiments/{id}/

Get experiment results GET /api/projects/{project_id}/experiments/{id}/results/

Cohorts

List cohorts GET /api/projects/{project_id}/cohorts/

Get a specific cohort GET /api/projects/{project_id}/cohorts/{id}/

Actions

List actions GET /api/projects/{project_id}/actions/

Get a specific action GET /api/projects/{project_id}/actions/{id}/

Annotations

List annotations GET /api/projects/{project_id}/annotations/

Create an annotation POST /api/projects/{project_id}/annotations/ Body:

{
  "content": "Deployed v2.1.0",
  "date_marker": "2025-03-15T12:00:00Z",
  "scope": "project"
}

Update an annotation PATCH /api/projects/{project_id}/annotations/{id}/

Delete an annotation DELETE /api/projects/{project_id}/annotations/{id}/

Dashboards

List dashboards GET /api/projects/{project_id}/dashboards/

Get a specific dashboard GET /api/projects/{project_id}/dashboards/{id}/

Surveys

List surveys GET /api/projects/{project_id}/surveys/

Get a specific survey GET /api/projects/{project_id}/surveys/{id}/


Common Patterns

Query top events for the past week

const cred = await API.getCredential('posthog-pat');
const BASE = 'https://us.posthog.com';
const projectId = 12345;

const result = await phPost(`/api/projects/${projectId}/query`, {
  query: {
    kind: 'HogQLQuery',
    query: `SELECT event, count() AS cnt FROM events WHERE timestamp > now() - interval 7 day GROUP BY event ORDER BY cnt DESC LIMIT 20`
  }
});
return { columns: result.columns, rows: result.results };

Look up a person by email

const cred = await API.getCredential('posthog-pat');
const BASE = 'https://us.posthog.com';
const projectId = 12345;

const persons = await phGet(`/api/projects/${projectId}/persons/?email=user@example.com`);
return persons.results;

List active feature flags

const cred = await API.getCredential('posthog-pat');
const BASE = 'https://us.posthog.com';
const projectId = 12345;

const flags = await phGet(`/api/projects/${projectId}/feature_flags/?active=true`);
return flags.results.map(f => ({
  id: f.id,
  key: f.key,
  name: f.name,
  active: f.active,
  rollout: f.rollout_percentage,
}));

Create a feature flag

const cred = await API.getCredential('posthog-pat');
const BASE = 'https://us.posthog.com';
const projectId = 12345;

const flag = await phPost(`/api/projects/${projectId}/feature_flags/`, {
  name: 'New Onboarding',
  key: 'new-onboarding',
  description: 'Enables the redesigned onboarding flow',
  filters: { groups: [{ properties: [], rollout_percentage: 50 }] },
  active: true,
});
return flag;

Get daily active users trend

const cred = await API.getCredential('posthog-pat');
const BASE = 'https://us.posthog.com';
const projectId = 12345;

const result = await phPost(`/api/projects/${projectId}/query`, {
  query: {
    kind: 'HogQLQuery',
    query: `SELECT toDate(timestamp) AS day, uniq(person_id) AS dau FROM events WHERE timestamp > now() - interval 30 day GROUP BY day ORDER BY day`
  }
});
return { columns: result.columns, rows: result.results };

List experiments and their status

const cred = await API.getCredential('posthog-pat');
const BASE = 'https://us.posthog.com';
const projectId = 12345;

const experiments = await phGet(`/api/projects/${projectId}/experiments/`);
return experiments.results.map(e => ({
  id: e.id,
  name: e.name,
  start_date: e.start_date,
  end_date: e.end_date,
}));

Read insights (saved analytics)

const cred = await API.getCredential('posthog-pat');
const BASE = 'https://us.posthog.com';
const projectId = 12345;

const insights = await phGet(`/api/projects/${projectId}/insights/?limit=10`);
return insights.results.map(i => ({
  id: i.id,
  name: i.name,
  short_id: i.short_id,
  filters: i.filters,
  last_refresh: i.last_refresh,
}));

Important Rules

  • Always call API.getCredential('posthog-pat') before any PostHog API call. If it returns null, prompt the user to configure it.
  • Always determine the user's region (US or EU) before making requests. Check open PostHog tabs or ask.
  • Always identify the target project ID (numeric). Check open PostHog tabs (it's in the URL path: /project/{id}/...) or ask.
  • Prefer HogQL queries (POST /api/projects/{id}/query) for analytical questions — they are far more flexible than REST list endpoints.
  • Use LIMIT clauses in HogQL queries to keep responses manageable.
  • When creating or modifying feature flags, confirm details with the user first.
  • When deleting resources (flags, annotations, etc.), always confirm with the user first.
  • Treat API keys as sensitive — never log or display them.
  • Paginated responses use next / previous URLs. Follow next to get more pages.
  • The PostHog API may rate-limit requests. Avoid tight loops; add short delays between batch requests.

版本历史

  • 0f01f5b 当前 2026-07-19 09:02

同 Skill 集合

apps/browser/bundled/plugins/figma/SKILL.md
apps/browser/bundled/plugins/github/SKILL.md
apps/browser/bundled/plugins/javascript-sandbox/SKILL.md
apps/browser/bundled/plugins/mini-apps/SKILL.md
apps/browser/bundled/plugins/open-code-review/SKILL.md
apps/browser/bundled/plugins/openmanus/SKILL.md
apps/browser/bundled/plugins/remotion/SKILL.md
apps/browser/bundled/plugins/supabase/SKILL.md
apps/browser/bundled/plugins/vercel/SKILL.md
apps/browser/bundled/skills/debug/SKILL.md
apps/browser/bundled/skills/learn-skill/SKILL.md
apps/browser/bundled/skills/plan/SKILL.md
apps/browser/bundled/skills/preview/SKILL.md
apps/browser/bundled/skills/implement/SKILL.md

元信息

文件数
0
版本
5244a17
Hash
c20dc4b5
收录时间
2026-07-19 09:02

首页 - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-07-22 08:24
浙ICP备14020137号-1 $访客地图$