Skip to content
Data
Skill

/querying-canvas-data

Get PostHog data into a canvas correctly: the host-injected `ph` SDK (loadInsight, query, capture, state, connectors, openExternal, navigate), the data hierarchy (saved insights first, typed query nodes second, inline HogQL last), verifiability (insight-backed metrics link their

From plugin
posthog
41k172 skills11 agents2 commands3 MCP

Claude Code

$ npx -y skills add posthog/posthog --skill querying-canvas-data --agent claude-code

SKILL.md

querying-canvas-data.SKILL.md
name: querying-canvas-data
description: >
  Get PostHog data into a canvas correctly: the host-injected `ph` SDK (loadInsight, query,
  capture, state, connectors, openExternal, navigate), the data hierarchy (saved insights first, typed query nodes
  second, inline HogQL last), verifiability (insight-backed metrics link their saved insight in
  PostHog; ad-hoc queries expose the exact query that ran), per-insight-type result shapes,
  progressive per-query loading, date-range wiring, live third-party data through the viewer's own
  connections (ph.connectors), and event capture from a canvas. Use whenever a canvas shows
  metrics, charts, tables, any PostHog data, or data from GitHub or an MCP server, or needs to send
  analytics events.

Querying canvas data

The `ph` bridge is the only way a canvas talks to PostHog. Import it with `import { ph } from "@posthog/canvas-sdk"` — a platform-provided module, so it needs no `dependencies` entry. The same object is also installed as the `window.ph` global, which existing canvases use; prefer the import in new code. Its typed surface is [references/canvas-sdk.d.ts](references/canvas-sdk.d.ts). Never initialize it: credentials stay in the host, and `fetch()`, posthog-js, and hand-rolled clients cannot reach PostHog from the sandbox. External requests and resources require a non-PostHog origin declared in `capabilities.network.origins`, and work only in the published canvas — the edit-mode preview blocks all direct network access. This includes external stylesheets; remote scripts remain blocked.

Data hierarchy — back every metric with a saved insight

1. **Preferred — save an insight, load it by reference.** Use the PostHog MCP insight tools to create/save an insight that computes the metric with an insight query type (TrendsQuery, FunnelsQuery, RetentionQuery, PathsQuery, or the web-analytics kinds WebOverviewQuery / WebStatsTableQuery — not raw SQL). Confirm its numbers, note the `short_id`, and render it with `await ph.loadInsight(shortId, { dateRange })`. These are proven queries — numbers match the PostHog UI exactly (sessionization, unique users, breakdowns, bounce rate). Never fabricate a query or guess event/property names; discover and save them via MCP first. 2. **Secondary — an ad-hoc typed node**: `ph.query({ kind: "TrendsQuery", series: [...], dateRange: {...} })` when saving an insight genuinely doesn't fit. 3. **Last resort — inline HogQL**: `ph.query("SELECT …")`, only when no insight kind can express the metric; you then own the SQL and its date window.

For web-analytics boards specifically, use the web-analytics query kinds — raw HogQL subtly gets bounce rate, sessionization, channel attribution, and unique-visitor counts wrong.

Whatever tier you use, **declare it in the project's `capabilities`** before publishing: every `ph.loadInsight` short id in `capabilities.posthog.insights`, every `ph.capture` event name in `captureEvents`, and `inlineQueries: true` for any `ph.query` use. The host rejects undeclared calls at runtime, and validation fails on undeclared literals.

Verifiability — every claim must be checkable in PostHog

A number a viewer cannot verify is a number they cannot trust. Every data-backed figure a canvas shows — a KPI, a chart, a table, a stated conclusion — must carry the verification affordance for its tier:

1. **Insight-backed metrics link the real insight in PostHog.** For a metric loaded from a saved insight (the preferred tier), render a "View in PostHog" affordance that calls `ph.openExternal(insightUrl)` from a click. Mint the URL at authoring time with the `generate-app-url` MCP tool (path template `/insights/{id}` with the insight's short id) and bake the returned URL into the source verbatim — never hand-build one. `ph.openExternal` only opens `https://*.posthog.com` URLs and only from a user gesture, so wire it to a button or link, never to load or render. Do not also bake the insight's saved query text into the source: canvas source is readable by every canvas viewer, while access to the insight itself is enforced by PostHog — the link is where a viewer inspects the query, with their own permissions applied. 2. **Ad-hoc queries disclose the exact query that ran, viewable in place.** For a figure computed by `ph.query` (a typed node or inline HogQL), show the query behind it — the HogQL text, or the typed query node pretty-printed as JSON — in a modal or a collapsed disclosure attached to the card (a Quill `Dialog` or `Collapsible` in a React canvas, a `<details>` element in an HTML one). Render it from the same constant or builder you pass to `ph.query`, so the displayed query can never drift from the executed one. This discloses nothing beyond what the viewer already runs: `ph.query` executes as the signed-in viewer.

These are not optional polish: a canvas that presents PostHog data without them is incomplete. Keep the affordances compact — a small link icon per insight-backed card, a "View query" disclosure per ad-hoc card, or one shared modal listing every ad-hoc query the canvas runs, each labeled with the figure it backs.

For a status board, set `refresh` to the cache lifetime in seconds. Use a whole number from 30 to 86400 (one day); values outside that range, or fractional ones, fail at runtime:

await ph.loadInsight(shortId, { refresh: 30 })
await ph.query(queryNode, {}, { refresh: 30 })

Result shapes — read them correctly or every value renders 0

  • **Trends-style results** (insight query types, via `ph.loadInsight` or a typed node): `results`

is an array of **series objects**, not rows. Each series has `data: number[]` (per interval), `days: string[]` (ISO), `labels: string[]`, `count` (sum), `aggregated_value` (single-value total), `label`, and optional `compare_label: "current" | "previous"`. A KPI total is `results[0].count` (or `.aggregated_value`); a line chart plots `re

Read more
@posthog
Ships withposthog

:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.

41k172 skills11 agents3 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
40.7k
Star history of posthog/posthog on GitHub, a chart by star-history.com

Other skills on posthog.

mcp-servers

mcp-servers

Install, configure, authenticate, and troubleshoot MCP (Model Context Protocol) servers for this agent. Use when the user asks to…

@posthog@posthogInstall Skill
dynamic-workflows

dynamic-workflows

Designs and runs task-specific JavaScript harnesses with the `workflow` tool. Use for broad, long-running, highly structured, or…

@posthog@posthogInstall Skill
subagent-orchestration

subagent-orchestration

How and when to delegate work to subagents via the `subagent` tool (Explore, Plan, General). Use when a task involves codebase…

@posthog@posthogInstall Skill
checking-member-access

checking-member-access

Explains what a member or a role can do in a PostHog project, using the access control MCP tools. Use when the user asks what…

@posthog@posthogInstall Skill
analyzing-ai-citations

analyzing-ai-citations

Answer AI citation and answer engine optimization (AEO) questions in PostHog: whether AI answer engines (ChatGPT, Claude, and an…

@posthog@posthogInstall Skill
analyzing-expensive-users

analyzing-expensive-us…

Analyze the most expensive users in AI observability and explain why they cost so much. Use when the user asks about top…

@posthog@posthogInstall Skill

More skills from other plugins.

context-loader
Auto-invoked

context-loader

Search memories from earlier Pi sessions in this repository. Use it when earlier work may already explain the code, error,…

mem07d69k
@mem0ai@mem0aiInstall Skill
qmd

qmd

Search local markdown knowledge bases, notes, docs, and wikis with QMD. Use when users ask to find notes, retrieve documents,…

qmd4w31k
@tobi@tobiInstall Skill

Questions about querying-canvas-data.

Which coding agents can use querying-canvas-data?
querying-canvas-data installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.