How to build Ghost dashboards in Metabase
Ghost is an open-source publishing platform for newsletters and memberships, tracking subscribers, paid tiers, and MRR. Metabase is where you turn that site data into shared, trustworthy dashboards. This guide covers three complementary paths: a direct database connection to the MySQL 8 instance Ghost runs on, a lightweight MCP + CLI route that pulls live data with the Ghost MCP server (community) and loads a CSV into Metabase with the Metabase CLI, and a durable pipeline route that syncs Ghost stats into a database so you can build dashboards anyone can read.
How do you connect Ghost to Metabase?
Self-hosters should start with the database route; the MCP + CLI and pipeline routes cover hosted setups and cross-source joins.
Point Metabase at MySQL 8
Self-hosted Ghost runs on MySQL 8: members, members_paid_subscriptions, posts, and emails tables give you subscriber growth, MRR, and newsletter engagement with zero ETL.
- Self-hosted installs where you control the database
- Full history from day one — no sync to schedule
- Content, users, and commerce tables in one place
- Query a read replica, not the production primary
- Internal schemas can change across major upgrades
- Hosted plans without database access need another route
Live data in, quick analysis out
Pair the Ghost MCP server (community) with the Metabase CLI. Use MCP for live lookups, write a scoped result to CSV, then load it into Metabase as a ready-to-query table and model.
- Quick lookups such as "show me member growth: free vs. paid by week"
- Loading a Ghost export into Metabase in seconds
- Spot-checks and one-off analyses without a warehouse
- Great for exploration, not governed recurring reporting
- Use read-only or least-privilege credentials — CMS MCP servers often include write tools
- CSV uploads are snapshots — refresh or move to a durable route for history
Durable dashboards with history
Sync Ghost stats and entities into a database or warehouse with a connector, script, or API, then point Metabase at it.
- Ghost reporting that content and commerce teams depend on
- Joining Ghost data with analytics, search, and revenue data
- Long-run trends for member growth: free vs. paid by week and mrr trend and paid-conversion rate
- You own the refresh schedule and the rollup grain
- Platform APIs cap what's exposed — and sometimes how much history
- Hosted-plan rate limits shape how often you can sync
How do you connect Metabase directly to the Ghost database?
Self-hosted Ghost runs on MySQL 8: members, members_paid_subscriptions, posts, and emails tables give you subscriber growth, MRR, and newsletter engagement with zero ETL.
- Add the MySQL 8 instance under Admin → Databases in Metabase — use a read-only user, and prefer a read replica for busy production sites.
- Build Metabase models on top of the raw tables (filter out revisions, autosaves, and internal statuses once), and point every question at the models.
- Version-pin your expectations: CMS core upgrades can change internal schemas, so re-check models after major updates.
What can you analyze from Ghost data in Metabase?
- Member growth: free vs. paid by week — built from members and subscriptions and the related paid tiers, newsletter sends and engagement, posts data your connection exposes.
- MRR trend and paid-conversion rate — built from members and subscriptions and the related paid tiers, newsletter sends and engagement, posts data your connection exposes.
- Newsletter open and click engagement — built from members and subscriptions and the related paid tiers, newsletter sends and engagement, posts data your connection exposes.
- Top posts by member signups driven — built from members and subscriptions and the related paid tiers, newsletter sends and engagement, posts data your connection exposes.
- Churned members and cancellation reasons — built from members and subscriptions and the related paid tiers, newsletter sends and engagement, posts data your connection exposes.
Which Ghost dashboards should you build in Metabase?
Member growth
The audience the publication owns.
- New members by week: free vs. paid (stacked bar)
- Total members and paid share (combo)
- Signups by attribution source (table)
- Churned members by week (line)
Subscription revenue
Whether the paid tier compounds.
- MRR trend by day (line)
- Free-to-paid conversion rate (line)
- Members by tier (bar)
- ARPU trend (line)
Email engagement
How each send performs.
- Open and click rates by send (table)
- Engagement trend across sends (line)
- Unsubscribes per send (bar)
- Click rate by post type (bar)
Content that converts
Which posts grow the list.
- Signups attributed to posts (table)
- Posts by member-conversion rate (table)
- Publishing cadence vs. signups (combo)
- Top content for paid conversions (table)
How do you use the Ghost MCP server (community) with the Metabase CLI?
Pair the Ghost MCP server (community) with the Metabase CLI for fast, hands-on analysis. MCP is useful for scoped lookups and summarized exports; the Metabase CLI's upload command loads CSV data into Metabase and creates a ready-to-query table and model.
Example workflow
- Ask the MCP server for members and subscriptions with signup dates, status, and tier.
- Export the result as CSV, keeping stable IDs, statuses, and dates as columns.
- Run
mb upload csvto load it into Metabase as a table and model, then build questions and dashboards on top.
Be honest about the limits
- MCP lookups are excellent for exploration, not scheduled reporting.
- A CSV upload is a snapshot; refresh it with
mb upload replaceor move to a durable route for real history. - Member records carry their own created-at history, but MRR trends need daily snapshots — start capturing them before you need the chart.
mb upload csvneeds an uploads database configured under Admin → Settings → Uploads.
How do you set up Ghost MCP and the Metabase CLI?
Ghost MCP server (community)community
- Transport
- Local server over stdio
- Auth
- Ghost Admin API key (JWT-signed requests)
- Best for
- Live scoped lookup and export
Metabase CLIofficial
- Install
npm install -g @metabase/cli- Auth
mb auth login- Load data
mb upload csv --file data.csv- Requires
- An uploads database (Admin → Settings → Uploads)
{
"mcpServers": {
"ghost": {
"command": "npx",
"args": ["-y", "@fanyangmeng/ghost-mcp"],
"env": {
"GHOST_API_URL": "https://yoursite.ghost.io",
"GHOST_ADMIN_API_KEY": "your-admin-api-key"
}
}
}
}Ghost publishes no official MCP server as of mid-2026; this community server wraps the Admin API (posts, members, tiers, offers, newsletters) and targets Ghost 5.x — check compatibility notes against Ghost 6 sites before automating anything.
# Install the Metabase CLI
npm install -g @metabase/cli
# Log in (opens your browser; requires Metabase v62+)
mb auth login --url https://your-metabase.example.com
# Load a members-and-subscriptions export — creates a table AND a model
mb upload csv --file ghost-members-and-subscriptions.csv --collection root
# Refresh that same table later from a new export
mb upload replace <table-id> --file ghost-members-and-subscriptions.csvCan you generate a Ghost dashboard with AI?
Yes. Use the prompt below with any assistant that can run the Ghost MCP server (community) and the Metabase CLI. It works end to end: if Ghost tables already exist in Metabase it analyzes those; otherwise it pulls scoped, summarized data over MCP, loads it with mb upload csv, then builds the dashboard and caveats any metric that needs missing history.
Create a polished Metabase dashboard for Ghost membership analytics.
Work end to end: get the data into Metabase if it isn't there yet, then build.
Goal: Help site and content owners understand member growth, subscription revenue, newsletter engagement, and which posts convert readers into subscribers from Ghost data.
Step 1 — Find or load the data:
- First, check what already exists in Metabase (search for ghost tables and
models). If Metabase is already connected to the Ghost database, use those tables directly — that's the best route.
- If nothing is there, pull a scoped, summarized export with the Ghost MCP server (community):
members and subscriptions, plus paid tiers, newsletter sends and engagement, posts.
Write each result to a CSV, then load it with the Metabase CLI — run
"mb upload csv --file <export>.csv" so each upload creates a table and a
ready-to-query model. Use "mb upload replace <table-id> --file <export>.csv"
to refresh an existing table instead of creating duplicates.
Step 2 — Inspect before querying:
Do not assume exact table or column names. Inspect available content types,
statuses, dates, and whether daily history exists before creating trend cards.
Important:
- Build on whatever data is present; don't claim Metabase connects natively to
the Ghost API — it reads a database or CLI-uploaded tables.
- Exclude revisions, autosaves, and test entries from headline content counts.
- Only compute rates (conversion, open rate, paid share) when both numerator
and denominator exist in the data.
- A single CSV is a point-in-time snapshot: only build trend cards if there is
a usable date column or multiple periods have been uploaded.
Dashboard title: Ghost Membership Overview
Sections:
1. Executive summary: Total members; Paid members; MRR; Last send's open and
click rates.
2. Growth: New free and paid members by week; signups by attribution source.
3. Revenue: MRR trend; free-to-paid conversion; tier mix; churned members.
4. Newsletter: Open, click, and unsubscribe rates by send.
5. Content: Posts ranked by member signups and paid conversions.
Filters: Date range, Content type/Collection, Status, Author/Editor, Tier.
Output: Build the dashboard if you have permission; otherwise provide the exact
questions, SQL, model definitions, and layout. Include caveats for any metric
that cannot be calculated from the available data.How do you sync Ghost data into a database or warehouse?
Self-hosted installs may not need a sync at all — connect Metabase to the database. Sync when you're on a hosted plan, or when Ghost data should land next to analytics and revenue data in a shared warehouse.
Connector options
- Managed ETL — use a connector when one covers the objects you need.
- Custom pipeline — use the Ghost Admin API for control over grain, fields, and refresh cadence.
- MCP + CSV — use this for quick exploration and one-off slices.
No managed connector exists — script the Admin API for members, tiers, and newsletter stats. Ghost 6's native analytics (traffic, sources, growth) are served through the admin UI rather than a documented public API, so member and email data are the reliable warehouse objects.
Notes
- Land raw entity tables first, then build clean Metabase models on top.
- Normalize member status, tier, signup date, and MRR amount fields.
- Keep platform stats (views, sessions) separate from measured analytics tools' numbers — definitions differ, and gaps are normal.
How should you model Ghost data in Metabase?
Core tables
| Table | Grain | Key columns |
|---|---|---|
ghost_members | one row per member | member_id, created_at, status, status_at_signup, email_open_rate, tier, source |
ghost_mrr_daily | one row per day per currency | stat_date, currency, mrr, paid_members, free_members |
ghost_email_stats | one row per newsletter send | email_id, post_id, sent_at, email_count, opened_count, clicked_count, unsubscribed_count |
Modeling advice
- Build a clean
member_growth_dailymodel with consistent columns, so dashboards survive schema changes and plugin swaps. - Filter out revisions, autosaves, drafts-of-drafts, and internal test entries once, in the model — not in every question.
- Normalize URLs (lowercase, no protocol, no trailing slash) so CMS content joins cleanly to analytics and Search Console data.
- Store dates in UTC and convert at display time; CMS installs often run in site-local timezones.
Which Ghost metrics should you track in Metabase?
| Metric | Definition | Notes |
|---|---|---|
| MRR | Monthly recurring revenue from paid subscriptions. | Snapshot daily — member counts alone can't rebuild it. |
| Churn rate | Paid members lost divided by paid members at risk. | Separate cancellations from payment failures. |
| Click-through rate | Newsletter clicks divided by delivered emails. | The engagement number to trust over opens. |
| Free-to-paid conversion | Free members upgrading divided by free members. | Measure per signup cohort, not as one blended rate. |
What SQL powers Ghost dashboards in Metabase?
These run against Ghost's own MySQL 8 schema, shown in PostgreSQL dialect — MySQL needs minor changes such as DATE_FORMAT in place of date_trunc.
Signup-week cohorts by status at signup — not current status after upgrades.
SELECT
date_trunc('week', created_at) AS week,
COUNT(*) FILTER (WHERE status_at_signup = 'free') AS new_free_members,
COUNT(*) FILTER (
WHERE status_at_signup IN ('paid', 'comped')
) AS new_paid_members
FROM ghost_members
GROUP BY 1
ORDER BY 1;Subscription revenue from daily snapshots.
SELECT
stat_date,
mrr,
paid_members,
ROUND(1.0 * mrr / NULLIF(paid_members, 0), 2) AS arpu
FROM ghost_mrr_daily
WHERE currency = 'usd'
ORDER BY 1;Open, click, and unsubscribe rates per email.
SELECT
sent_at::date AS send_date,
email_count AS delivered,
ROUND(100.0 * opened_count / NULLIF(email_count, 0), 1) AS open_rate_pct,
ROUND(100.0 * clicked_count / NULLIF(email_count, 0), 2) AS click_rate_pct,
unsubscribed_count
FROM ghost_email_stats
ORDER BY sent_at DESC
LIMIT 20;What are common mistakes when analyzing Ghost in Metabase?
Related
Related analytics
Related dashboards
Related integrations
FAQ
Does Metabase connect natively to Ghost?
Should Metabase replace Ghost's built-in stats?
Can I get Ghost's traffic analytics into Metabase?
How do I track MRR history for a Ghost publication?
ghost_mrr_daily table. Cross-check totals against Stripe, which processes Ghost's payments and is the revenue source of truth.