/modeling-revenue-metrics
Build reusable revenue models — MRR, ARR, gross revenue, new/expansion/contraction/churn, ARPU, LTV, and per-customer/per-account revenue — on either PostHog data-warehouse views (HogQL) or an external dbt project. Use when the user wants to model, define, or compute recurring
Claude Code
$ npx -y skills add posthog/posthog --skill modeling-revenue-metrics --agent claude-code
Codex
$ npx skills add posthog/posthog --skill modeling-revenue-metrics -a codex -y
Cursor
$ npx skills add posthog/posthog --skill modeling-revenue-metrics -a cursor -y
Gemini CLI
$ npx skills add posthog/posthog --skill modeling-revenue-metrics -a gemini-cli -y
GitHub Copilot
$ npx skills add posthog/posthog --skill modeling-revenue-metrics -a github-copilot -y
OpenCode
$ npx skills add posthog/posthog --skill modeling-revenue-metrics -a opencode -y
Windsurf
$ npx skills add posthog/posthog --skill modeling-revenue-metrics -a windsurf -y
SKILL.md
modeling-revenue-metrics.SKILL.mdname: modeling-revenue-metrics
description: >
Build reusable revenue models — MRR, ARR, gross revenue, new/expansion/contraction/churn, ARPU, LTV, and
per-customer/per-account revenue — on either PostHog data-warehouse views (HogQL) or an external dbt
project. Use when the user wants to model, define, or compute recurring revenue, monthly/annual recurring
revenue, churn or retention of revenue, lifetime value, average revenue per user, or revenue by customer,
cohort, product, or currency. On PostHog, build on the managed *_revenue_view views (revenue_item,
mrr, customer, subscription, charge, product) fed by Stripe or custom revenue events — not raw Stripe
tables — and normalize money with convertCurrency(). In dbt, stage the payment source and compute
fct_mrr / fct_revenue_item / dim_customer marts with tests. Covers picking the right source, the
subscription-config gotcha that leaves MRR empty, currency handling, and linking revenue to persons/groups.
Read modeling-warehouse-foundations first for the view-vs-dbt mechanics.
Modeling revenue metrics
Turn payment/subscription data into durable revenue models. Read `modeling-warehouse-foundations` first for the view-vs-dbt decision, the `view-*` workflow, and `convertCurrency()`; this skill is the revenue-specific layer on top. Metric definitions live in [`references/revenue-metric-definitions.md`](references/revenue-metric-definitions.md); copy-paste recipes in [`references/posthog/`](references/posthog/) and [`references/dbt/`](references/dbt/).
Step 1 — find where revenue lives
Revenue reaches PostHog two ways; both feed the same **managed revenue views**:
- **A payment platform as a warehouse source** — Stripe today (Chargebee/Polar/RevenueCat coming). Best when
the business runs on a billing platform. Connect via `setting-up-a-data-warehouse-source`.
- **Custom revenue events** — you send events (e.g. `purchase_completed`) with a revenue property. Best when
there's no supported platform or you already track revenue in-product.
If neither exists yet, use `suggesting-data-imports` to recommend a source. In **dbt**, the equivalent is staging whichever billing tables landed in the warehouse.
Step 2 — model on the managed views, not raw tables
PostHog auto-generates a curated set of views per source. **Do not re-derive revenue from raw Stripe tables** — the managed views already handle deferred-revenue recognition, currency, and a stable schema.
Each source gets its own views. There is no cross-source view. Names depend on the source type:
- Warehouse source: `<source>.<prefix>.<kind>_revenue_view`, for example `stripe.prod.mrr_revenue_view`. The
`<prefix>.` part is absent when the source has no prefix.
- Custom revenue events: `revenue_analytics.events.<event_name>.<kind>_events_revenue_view`, where every
non-alphanumeric character in the event name becomes `_`.
`<kind>` is one of the managed views in the table below. Discover the exact names. Do not search for `revenue_analytics`, because it does not match warehouse source views:
SELECT table_name FROM system.information_schema.tables
WHERE position(table_name, 'revenue_view') > 0 ORDER BY table_name
If this returns nothing, the project has no revenue source configured yet. Check the governed `mrr` metric (`metric-list`) or discover warehouse billing tables, and read their columns before modeling. Do not guess view names.
| Managed view | Grain | Use for | | ------------------------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------- | | `revenue_item` (**start here**) | 1 / invoice line item | Gross revenue, monthly recurring revenue, revenue by product/customer/period. Implements deferred revenue + currency. | | `mrr` | 1 / (customer, subscription) | **Live snapshot** of current MRR — not a time series. | | `customer` | 1 / customer | `dim_customer`: email, country, cohort, metadata. | | `subscription` | 1 / subscription | Subscription state for churn/expansion logic. | | `charge` | 1 / charge | Raw charges; prefer `revenue_item` unless you specifically need charges. | | `product` | 1 / product | Product dimension. |
Key `revenue_item` columns: `amount` (already converted to the project **base currency**), `currency` (that base currency), `original_amount` / `original_currency` (as charged), `is_recurring`, `customer_id`, `subscription_id`, `product_id`, `group_0_key`…`group_4_key` (B2B account keys), `timestamp`.
Rules before you model (revenue gotchas)
1. **MRR is empty without a subscription config.** For event-based revenue, MRR only populates when a subscription property is configured. Empty MRR + populated gross revenue is **expected behaviour**, not a bug — say so instead of "fixing" it. 2. **The `mrr` managed view is a current snapshot**, not history ("MRR at the current time"). For MRR _over time_, sum recurring `amount` per month from `revenue_item` (see the recipe), or materialize a monthly snapshot of the `mrr` view on a schedule. 3. **`amount` is already in base currency.** Use it directly for reporting. Only call `convertCurrency(original_currency, 'XXX', original_amount, timestamp)` when you need a _different_ ta
Read more
name: modeling-revenue-metrics description: > Build reusable revenue models — MRR, ARR, gross revenue, new/expansion/contraction/churn, ARPU, LTV, and per-customer/per-account revenue — on either PostHog data-warehouse views (HogQL) or an external dbt project. Use when the user wants to model, define, or compute recurring revenue, monthly/annual recurring revenue, churn or retention of revenue, lifetime value, average revenue per user, or revenue by customer, cohort, product, or currency. On PostHog, build on the managed *_revenue_view views (revenue_item, mrr, customer, subscription, charge, product) fed by Stripe or custom revenue events — not raw Stripe tables — and normalize money with convertCurrency(). In dbt, stage the payment source and compute fct_mrr / fct_revenue_item / dim_customer marts with tests. Covers picking the right source, the subscription-config gotcha that leaves MRR empty, currency handling, and linking revenue to persons/groups. Read modeling-warehouse-foundations first for the view-vs-dbt mechanics.
Modeling revenue metrics
Turn payment/subscription data into durable revenue models. Read `modeling-warehouse-foundations` first for the view-vs-dbt decision, the `view-*` workflow, and `convertCurrency()`; this skill is the revenue-specific layer on top. Metric definitions live in [`references/revenue-metric-definitions.md`](references/revenue-metric-definitions.md); copy-paste recipes in [`references/posthog/`](references/posthog/) and [`references/dbt/`](references/dbt/).
Step 1 — find where revenue lives
Revenue reaches PostHog two ways; both feed the same **managed revenue views**:
- **A payment platform as a warehouse source** — Stripe today (Chargebee/Polar/RevenueCat coming). Best when
the business runs on a billing platform. Connect via `setting-up-a-data-warehouse-source`.
- **Custom revenue events** — you send events (e.g. `purchase_completed`) with a revenue property. Best when
there's no supported platform or you already track revenue in-product.
If neither exists yet, use `suggesting-data-imports` to recommend a source. In **dbt**, the equivalent is staging whichever billing tables landed in the warehouse.
Step 2 — model on the managed views, not raw tables
PostHog auto-generates a curated set of views per source. **Do not re-derive revenue from raw Stripe tables** — the managed views already handle deferred-revenue recognition, currency, and a stable schema.
Each source gets its own views. There is no cross-source view. Names depend on the source type:
- Warehouse source: `<source>.<prefix>.<kind>_revenue_view`, for example `stripe.prod.mrr_revenue_view`. The
`<prefix>.` part is absent when the source has no prefix.
- Custom revenue events: `revenue_analytics.events.<event_name>.<kind>_events_revenue_view`, where every
non-alphanumeric character in the event name becomes `_`.
`<kind>` is one of the managed views in the table below. Discover the exact names. Do not search for `revenue_analytics`, because it does not match warehouse source views:
SELECT table_name FROM system.information_schema.tables WHERE position(table_name, 'revenue_view') > 0 ORDER BY table_name
If this returns nothing, the project has no revenue source configured yet. Check the governed `mrr` metric (`metric-list`) or discover warehouse billing tables, and read their columns before modeling. Do not guess view names.
| Managed view | Grain | Use for | | ------------------------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------- | | `revenue_item` (**start here**) | 1 / invoice line item | Gross revenue, monthly recurring revenue, revenue by product/customer/period. Implements deferred revenue + currency. | | `mrr` | 1 / (customer, subscription) | **Live snapshot** of current MRR — not a time series. | | `customer` | 1 / customer | `dim_customer`: email, country, cohort, metadata. | | `subscription` | 1 / subscription | Subscription state for churn/expansion logic. | | `charge` | 1 / charge | Raw charges; prefer `revenue_item` unless you specifically need charges. | | `product` | 1 / product | Product dimension. |
Key `revenue_item` columns: `amount` (already converted to the project **base currency**), `currency` (that base currency), `original_amount` / `original_currency` (as charged), `is_recurring`, `customer_id`, `subscription_id`, `product_id`, `group_0_key`…`group_4_key` (B2B account keys), `timestamp`.
Rules before you model (revenue gotchas)
1. **MRR is empty without a subscription config.** For event-based revenue, MRR only populates when a subscription property is configured. Empty MRR + populated gross revenue is **expected behaviour**, not a bug — say so instead of "fixing" it. 2. **The `mrr` managed view is a current snapshot**, not history ("MRR at the current time"). For MRR _over time_, sum recurring `amount` per month from `revenue_item` (see the recipe), or materialize a monthly snapshot of the `mrr` view on a schedule. 3. **`amount` is already in base currency.** Use it directly for reporting. Only call `convertCurrency(original_currency, 'XXX', original_amount, timestamp)` when you need a _different_ ta
: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.
More skills from other plugins.
paddleocr-doc-parsing
Use this skill to extract structured Markdown/JSON from PDFs and document images—tables with cell-level precision, formulas as…
13c-metabolic-flux
Estimates intracellular metabolic fluxes from steady-state carbon-13 isotope-tracing measurements using validated atom maps,…
Questions about modeling-revenue-metrics.
- Which coding agents can use modeling-revenue-metrics?
- modeling-revenue-metrics 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.

