mcpField
A
analytics

analytics

github.com/growthbookData & databases2553 installsUpdated 4w ago
Repository

About analytics

A workflow router for GrowthBook Product Analytics, dashboards, and the metric catalog. It directs metric discovery, charting, dashboard changes, and SQL requests to separate workflows, while distinguishing reads from configuration writes.

Key features

  1. 01Route metric search and analysis workflows
  2. 02Create and edit analytics dashboards
  3. 03Browse fact metrics and fact tables
  4. 04Separate queries from configuration writes

Use cases

  1. 01Find metrics available for charting
  2. 02Run an analysis and inspect results
  3. 03Create or revise an analytics dashboard
  4. 04Use SQL when existing analytics cannot answer a question

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/growthbook/skills --skill analytics

After installing, type/analyticsin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
analytics-explore.md
dashboard-create.md
dashboard-edit.md
metric-create.md
metric-search.md
sql-query.md

Details

From the project README

analytics

Domain router for GrowthBook Product Analytics, Analytics dashboards, and the metric catalog. The workflows live in references/. Read this router, pick one, then read that file and follow it.

Analytics uses the v1 API — /api/v1/product-analytics/search, /columns, and /column-values for discovery, the metric, fact-table, data-source, and funnel /api/v1/product-analytics/*-exploration endpoints for charts, /api/v1/product-analytics/explorations/:id for polling, /dashboards for saved pages of charts (except create, which is POST /api/v2/dashboards; the v1 create is deprecated), and /fact-metrics and /fact-tables for the catalog. The API also exposes SQL explorations, but this skill does not construct or execute arbitrary SQL exploration payloads.

All API calls go through the bundled helper. Under the Claude Code plugin install, it lives at ${CLAUDE_PLUGIN_ROOT}/scripts/gb-call (the plugin root). Under npx skills install, it lives at scripts/gb-call relative to this skill's directory. Resolve that path once and substitute it whenever a reference example says gb-call; do not assume gb-call is on PATH. It reads GB_API_KEY from the environment first, then falls back to ~/.config/growthbook/.env (written by gb-setup); environment variables take precedence.

When a workflow needs to construct a GrowthBook UI link from a root-relative path, a shell-capable runtime should call gb-call app-origin once per conversation, retain the returned trusted origin across workflow and domain handoffs, and prepend it to each path. If the origin is already in context, reuse it; do not call the command once per link. Embedded or MCP adapters that already know their trusted app origin may resolve paths directly. Never derive an app origin from GB_API_URL; if app-origin refuses because self-hosted configuration is incomplete, route to gb-setup. API-returned explorationUrl values are already complete and must be used unchanged.

Pick a workflow

Read thisWhen the user wants to
references/metric-search.mdBrowse, find, or audit metrics and fact tables — inventory, a specific definition, or "what can I chart" triage (read-only)
references/metric-create.mdCreate a fact metric, creating its underlying fact table first when necessary (writes configuration)
references/analytics-explore.mdActually run a chart and report the numbers plus a deep link
references/dashboard-create.mdBuild a new dashboard — several charts saved together on one page (writes a dashboard)
references/dashboard-edit.mdChange a dashboard that already exists: add or remove a chart, swap a metric, change the timeframe, rename it
references/sql-query.mdRun ad-hoc SQL against the warehouse when no metric or exploration can answer the question (last resort)

When the user names a metric you have not resolved yet, read metric-search.md first. It hands analytics-explore or metric-create a stable definition. When they already named something concrete and just want the numbers, go straight to analytics-explore.md.

One chart or several? A single question gets one chart from analytics-explore. "Track", "monitor", "reporting", or two or more things to watch together means a dashboard. Route on whether the dashboard exists: no id yet is dashboard-create, an id is dashboard-edit.

Use sql-query.md only when the question can't be answered with existing metrics or the exploration config — custom joins, unmodeled tables, or aggregations the exploration can't express.

Shared conventions

  • Only fact metrics chart. fact__... ids work in Product Analytics; legacy met_... metrics from /api/v1/metrics are valid experiment metrics but cannot be charted. Never promise a chart for one.
  • Explorations are datasource-scoped, and the datasource must be a SQL warehouse. Mixpanel and Google Analytics datasources can't run explorations.
  • Pass ids, not display names, between workflows. Names aren't unique. Fact metric ids always start fact__; fact table ids default to ftb_... but can be custom, so don't filter on that prefix.
  • Every id comes from a lookup or from the user's @ mention — never construct one. Some are readable (fact__demo-d7-purchase-retention) and invite a guess like fact__AverageOrderValue; those resolve to nothing, and the failure surfaces late and obscurely.
  • Discover before constructing. Use Product Analytics search and columns, and call column-values before using any concrete filter or breakdown value. Never guess a value.
  • Check before creating. Prefer an existing official: true metric over adding a duplicate with the same meaning.
  • A 200 from an exploration POST is not necessarily success. Branch on exploration.status; poll running explorations by id, surface error, and note that cache=required can return exploration: null.
  • Handle workflow-endpoint 404s conservatively. A 404 from /product-analytics/search means the server predates these endpoints. On /columns, /column-values, or /explorations/:id, it can also mean the resource is missing or inaccessible. Surface the failure and stop; never probe around access checks, substitute an undocumented endpoint, or re-POST a running exploration.
  • Use the returned full result rows for numeric insights. Do not infer values from a chart preview, truncated summary, or config.
  • Run at most one successful chart per user turn. Discovery, polling, and one empty-result retry are allowed; once one non-empty exploration succeeds, answer from it unless the user explicitly asks for another chart in a later turn.
  • Always set unit explicitly on every dataset.values[] entry — that is the only level that takes one; a unit on the config itself is rejected. For metrics, follow /columns exactly: when metrics[].needsUnit is true, choose a returned userIdTypes entry; when it is false, default to null. A unit is an identifier type, never a value format such as currency. The server does not backfill a missing unit.
  • A date range's predefined is a closed list, everywhere one appears: today, yesterday, last7Days, last30Days, last90Days, last12Months, lastCalendarYear, customLookback, customDateRange. Any other name is rejected, so every window outside the list is customLookback with lookbackValue and lookbackUnit (hour, day, week, month).
  • dimensionType is a closed set, and "dimension" is not in it: date, dynamic, static, slice. Only the first two are supported — a date axis is { "dimensionType": "date", "column": null, "dateGranularity": "auto" } and a breakdown by column is { "dimensionType": "dynamic", "column": "browser", "maxValues": 5 }. Naming the field after what you want to group by is the guess the validator rejects.
  • Never re-send a rejected call unchanged. A 400 is deterministic: the same body gets the same error, so a retry that has not changed the field the message names only spends the user's turn. Read body.message, fix exactly what it names, and send it once more. If the message does not say what a valid value would be, or the same field is rejected twice, stop there — say which field failed and what you tried, and ask the user rather than guessing a third time. Ask about that field: a validation error names the field it rejected, and a question about a different one (a column name, a metric choice) cannot resolve it, so the answer arrives and the same call fails again.
  • Restyling a chart is free. Cache matching ignores chartType, so a different chart type on the same query is a cache hit. Never re-query just to restyle.
  • A dashboard's chart blocks carry a config, not a result. The create and update calls run every chart server-side, so never POST an exploration first just to get an id for a tile.
  • An update replaces a dashboard's whole block list. Read the dashboard in the same turn you write it, and list every tile being kept — but carry an unchanged one as { "id": "dshblk_…" } rather than copying it back in full, and list each id at most once.
  • A dashboard's owner changes only when the user asks. Create on POST /api/v2/dashboards without owner, which defaults to the API key's user, unless the user names someone else. Never put owner or ownerEmail in an update body unless the user asked to reassign the dashboard. For an admin, a stray owner silently hands the dashboard to someone else.
  • Dashboards are not scoped to a datasource the way metrics and explorations are, but every chart on one is.

Read-only vs. write

metric-search is strictly read-only. analytics-explore runs warehouse queries but changes no GrowthBook configuration — it does not create metrics, fact tables, or dashboards. sql-query is similar: it never mutates warehouse data, but it executes potentially costly queries and persists a GrowthBook exploration object from the results. metric-create writes organization-visible fact-table and fact-metric definitions, and dashboard-create / dashboard-edit write dashboards; all three must summarize the change in plain language and get confirmation before each write.

Note that explorations execute real warehouse queries, so they cost the user money and time even though they write nothing — and a dashboard write runs one per chart block. Scope them the way the reference files describe rather than fanning out speculatively.

Handoffs

  • The experiments skill — when the question is an A/B test readout, or when a chart surfaces something worth testing.
  • The feature-flags skill — when the user pivots to shipping or gating the thing the data is about.
  • gb-setup — when gb-call reports a missing or invalid GB_API_KEY.

Comments

Markdown supported