Vitally × Metabase

How to build Vitally customer success dashboards in Metabase

Vitally is a customer success platform popular with mid-market B2B SaaS teams — accounts and users, multiple named health scores, conversations, notes, tasks, and NPS, with a clean REST API. Metabase is where you turn that record into shared, trustworthy customer success dashboards. This guide covers two complementary paths: a lightweight API + CLI route that pulls live data via the Vitally REST API and loads a CSV into Metabase with the Metabase CLI, and a durable pipeline route that lands Vitally data in a database so you can build dashboards anyone can read.

Heads up: Metabase connects to databases and warehouses — it does not ship a native Vitally connector. The good news: account and health data is small and tabular, and it becomes far more useful the moment it sits next to product usage and billing. Land it in a database, define the metrics once, and every dashboard downstream inherits the same definitions.

How do you connect Vitally to Metabase?

Most teams combine both routes: quick answers through API exports and CLI uploads first, then recurring reporting on a warehouse-backed model.

1 · API + CLI route (AI-assisted)

Live answers in, quick analysis out

Script a scoped export against the Vitally REST API, write the result to CSV, then load it into Metabase as a ready-to-query table and model. No vendor MCP server exists for Vitally, so the export script is the fast route.

Best for
  • Quick questions such as "show me health score distribution across the account base"
  • Loading Vitally exports into Metabase in seconds
  • Spot-checks and one-off investigations without pipeline work
Trade-offs
  • Great for exploration, not the governed numbers a QBR runs on
  • Use read-only credentials or scoped API keys wherever supported
  • CSV uploads are snapshots — refresh or move to the pipeline for history
2 · Pipeline route (warehouse-backed)

Durable dashboards with history

Land Vitally data in a database or warehouse — via connector or scheduled API pulls — then point Metabase at it.

Best for
  • Vitally dashboards CS and finance both trust
  • Joining health data with product usage, support, and billing
  • Long-run trends for health score distribution across the account base and score movers: accounts improving and declining
Trade-offs
  • You own the refresh schedule and the snapshot grain
  • Re-derive health score components once, in the warehouse layer
  • Current-state fields need dated snapshots or history never exists

What can you analyze from Vitally data in Metabase?

These all come from the same core objects — accounts and their health scores, plus the users, conversations and notes, tasks and playbooks your sync exposes:

  • Health score distribution across the account base
  • Score movers: accounts improving and declining
  • NPS by segment and its trend
  • CSM workload and task completion
  • Health score vs. product usage reality check

Which Vitally customer success dashboards should you build in Metabase?

For: CS leadership

Health overview

The distribution behind the average.

  • Accounts by risk tier (bar)
  • MRR by risk tier (bar)
  • Median health score by segment (bar)
  • Accounts that changed tier this month (table)
For: CSMs

Score movers

The accounts that moved, not the ones that sat still.

  • Biggest score gains and drops this month (table)
  • Score trend for the top 10 accounts by MRR (line)
  • Accounts crossing into the at-risk tier (table)
  • Days since last conversation, by account (bar)
For: CS leadership, product

Voice of the customer

NPS read next to health, not on its own.

  • NPS by segment (bar)
  • NPS trend by quarter (line)
  • Survey response rate (number + trend)
  • Detractors with an open task (table)
For: CS ops

Workload

Whether coverage matches the book of business.

  • Accounts and MRR per CSM (bar)
  • Open tasks by owner and age (table)
  • Task completion rate (number + trend)
  • Conversations per account per month (line)

How do you use the Vitally REST API with the Metabase CLI?

Pair the Vitally REST API with the Metabase CLI for fast, hands-on analysis. With no vendor MCP server available, scripted API exports do the pulling here; the Metabase CLI's upload command loads CSV data into Metabase and creates a ready-to-query table and model.

Example workflow

  • Ask the API for every account with its current health scores and MRR, one row per account per named score.
  • Export the result as CSV, keeping stable IDs, owners, statuses, and dates — and hashing or dropping any personal contact fields.
  • Run mb upload csv to load it into Metabase as a table and model, then build questions and dashboards on top.

Be honest about the limits

  • Scripted API exports are excellent for exploration, not scheduled reporting.
  • A CSV upload is a snapshot; refresh it with mb upload replace or move to the pipeline for real history.
  • The API returns current score values, so a trend needs repeated extracts appended over time — one export is a single point in time.
  • mb upload csv needs an uploads database configured under Admin → Settings → Uploads.

How do you set up Vitally exports and the Metabase CLI?

Vitally REST APIcommunity

Transport
No vendor server; community projects run locally over stdio
Auth
HTTP Basic with your Vitally API key as the username
Best for
Live scoped account 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)
ShellExample scripted export
# No vendor MCP server exists. Export directly from the REST API:
curl -s "https://$SUBDOMAIN.rest.vitally.io/resources/accounts?limit=100" \
  -u "$VITALLY_API_KEY:" \
  | jq -r '.results[] | [.id, .name, .mrr, .createdAt,
      (.traits.segment // "")] | @csv' \
  > vitally-accounts.csv

Vitally publishes no MCP server (verified July 2026), and its own API documentation doesn't mention MCP at all — so this guide leads with a scripted export. Community options exist, but read the fine print before adopting one: the most complete, fiscaltec/vitally-mcp, is published by FISCAL Technologies, a company unaffiliated with Vitally, under a proprietary license with a hosted endpoint aimed at its own customers. It is not a first-party server despite how the name reads. If Vitally ships an official server later, only route 1's export step changes.

TerminalLoad a Vitally CSV with the Metabase CLI
# 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 accounts export — creates a table AND a model
mb upload csv --file vitally-accounts.csv --collection root

# Refresh that same table later from a new export
mb upload replace <table-id> --file vitally-accounts.csv

Can you generate a Vitally dashboard with AI?

Yes. Use the prompt below with any assistant that can run shell commands (for the API export) and the Metabase CLI. It works end to end: if Vitally tables already exist in Metabase it analyzes those; otherwise it pulls scoped, summarized data, loads it with mb upload csv, then builds the dashboard and caveats any metric that needs missing history.

Prompt for creating a Vitally Customer Success Overview dashboard
Create a polished Metabase dashboard for Vitally customer success analytics.
Work end to end: get the data into Metabase if it isn't there yet, then build.

Goal: Help customer success and revenue leaders understand health score distribution, the accounts moving most, NPS by segment, and CSM workload from Vitally data.

Step 1 — Find or load the data:
- First, check what already exists in Metabase (search for vitally tables and
  models). If durable Vitally data is already present — a warehouse sync or
  an earlier upload — use it and skip to Step 2.
- If nothing is there, pull a scoped, summarized export by scripting the Vitally REST API:
  accounts and their health scores, plus users, conversations and notes, tasks and playbooks.
  Prefer one row per account per snapshot date over raw activity
  feeds. 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 fields, owners,
segments, statuses, and date ranges before creating trend cards.

Important:
- Build on whatever data is present; don't claim Metabase connects natively to
  Vitally — it reads a database or CLI-uploaded tables.
- State which health score a card uses and when it was captured. Vendor scores
  are opaque composites and get redefined without notice.
- A single CSV is a point-in-time snapshot: health scores, phases, and renewal
  dates are current-state fields, so only build trend cards once several dated
  snapshots exist.
- Reconcile ARR against billing data, not against the Vitally record — CS
  platforms hold a projection of CRM, billing, and product data.
- Only compute retention where subscription or license values exist. Gross
  revenue retention excludes expansion and can never exceed 100%; net revenue
  retention includes it and can.

Dashboard title: Vitally Customer Success Overview

Sections:
1. Executive summary: Accounts by risk tier; MRR at risk; Median health
   score; NPS; Accounts with no conversation in 30 days.
2. Health: Risk tier distribution; MRR by tier; median score by segment.
3. Movers: Biggest gains and drops; accounts crossing into at risk.
4. Voice of the customer: NPS by segment; NPS trend; response rate.
5. Workload: Accounts and MRR per CSM; open tasks by age; completion rate.

Filters: Date range, CSM owner, Segment, Risk tier, Lifecycle stage.

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 Vitally data into a database or warehouse?

For dashboards that need history and reliability, land Vitally data in a database first, then connect Metabase to that database.

Connector options

  • Managed ETL — use a connector when one covers the objects you need, and read its support level and sync mode before you rely on it.
  • Custom pipeline — use the Vitally REST API for control over snapshot grain, fields, and refresh cadence.
  • API + CSV — use this for quick exploration and one-off slices.

Both major ETL vendors cover Vitally, with caveats. Airbyte's <code>source-vitally</code> (Marketplace support level) syncs accounts, admins, conversations, notes, NPS responses, tasks, and users — but it is <strong>full-refresh only</strong>, so every sync re-reads the whole account base and deletions never propagate as deletions. Fivetran offers an Application Lite connector. Scripting the API yourself is well-supported: cursor pagination with a 100-record page limit, sorting by <code>createdAt</code> or <code>updatedAt</code> for genuine incremental pulls, and a generous 1,000 requests per minute.

Notes

  • Decide the snapshot grain first (one row per account per day, or per account per week) — it drives storage and every trend card.
  • Land raw tables first, then build clean Metabase models on top.
  • Normalize account-id, csm-owner, segment, snapshot-date, score-name, and score-value fields.

How should you model Vitally data in Metabase?

Core tables

TableGrainKey columns
cs_accountsone row per accountaccount_id, name, mrr, created_at, segment, csm_owner, churned_at, traits
account_health_scoresone row per account per named score per snapshot dateaccount_id, snapshot_date, score_name, score_value, grade, category
cs_activitiesone row per conversation, note, or taskactivity_id, account_id, type, subject, created_at, completed_at, owner

Modeling advice

  • Build a clean cs_accounts model with common columns across CS tools, so multi-source dashboards don't fork definitions.
  • Re-derive the health score components in the warehouse and keep the vendor's score beside your own as a separate, labeled column. Vendor scores are opaque composites, and they get redefined without anyone telling the analytics team.
  • Snapshot renewal forecasts into a renewal_forecast_snapshots table frozen at period start — accuracy cannot be measured against a forecast that keeps moving.
  • Model gross and net revenue retention separately: gross excludes expansion and can never exceed 100%, net includes it and can.
  • Reconcile ARR against billing rather than the CS platform. What a CS tool holds is a projection of CRM, billing, and product data, and projections drift.

Which Vitally customer success metrics should you track in Metabase?

MetricDefinitionNotes
Customer health scoreThe named score you have chosen as the account's headline.Pick one named score and say which one on the card.
Churn rateAccounts or MRR lost in a period over the opening base.Logo churn and revenue churn tell different stories.
Net revenue retentionRetained plus expansion revenue from an existing cohort.Unlike GRR, this one can and should exceed 100%.
Time to valueDays from signup to the first realized customer outcome.Product usage data, not the CS record, defines it.

What SQL powers Vitally customer success dashboards in Metabase?

These assume a cleaned analytical model in a warehouse (PostgreSQL dialect). Adjust table and column names to match your pipeline.

Health score distribution by risk tierPostgreSQL

One named score, bucketed, with annualized MRR per tier.

WITH latest AS (
  SELECT DISTINCT ON (account_id)
    account_id,
    score_value
  FROM account_health_scores
  WHERE score_name = 'Overall Health'
  ORDER BY account_id, snapshot_date DESC
)
SELECT
  CASE
    WHEN l.score_value >= 80 THEN 'healthy'
    WHEN l.score_value >= 60 THEN 'watch'
    ELSE 'at risk'
  END AS risk_tier,
  COUNT(*) AS accounts,
  ROUND(SUM(a.mrr) * 12, 0) AS annualized_mrr
FROM latest l
JOIN cs_accounts a ON a.account_id = l.account_id
WHERE a.churned_at IS NULL
GROUP BY 1
ORDER BY MIN(l.score_value);
Accounts whose score moved most month over monthPostgreSQL

Month-end values compared, ranked by absolute change.

WITH month_end AS (
  SELECT DISTINCT ON (account_id, date_trunc('month', snapshot_date))
    account_id,
    date_trunc('month', snapshot_date) AS month,
    score_value
  FROM account_health_scores
  WHERE score_name = 'Overall Health'
  ORDER BY account_id, 2, snapshot_date DESC
),
movement AS (
  SELECT
    account_id,
    month,
    score_value,
    LAG(score_value) OVER (PARTITION BY account_id ORDER BY month)
      AS prior_value
  FROM month_end
)
SELECT
  a.name,
  a.csm_owner,
  a.mrr,
  mv.prior_value,
  mv.score_value AS current_value,
  ROUND((mv.score_value - mv.prior_value)::numeric, 1) AS score_change
FROM movement mv
JOIN cs_accounts a ON a.account_id = mv.account_id
WHERE mv.month = date_trunc('month', CURRENT_DATE)
  AND mv.prior_value IS NOT NULL
  AND a.churned_at IS NULL
ORDER BY ABS(mv.score_value - mv.prior_value) DESC
LIMIT 25;
Health score against real product usagePostgreSQL

The reality check: does the score match what accounts actually do?

WITH latest AS (
  SELECT DISTINCT ON (account_id)
    account_id,
    score_value
  FROM account_health_scores
  WHERE score_name = 'Overall Health'
  ORDER BY account_id, snapshot_date DESC
),
usage AS (
  SELECT
    account_id,
    COUNT(*) FILTER (WHERE active_users > 0) AS active_days_30d,
    AVG(active_users) AS avg_daily_active_users
  FROM product_usage_daily
  WHERE usage_date >= CURRENT_DATE - INTERVAL '30 days'
  GROUP BY account_id
)
SELECT
  CASE
    WHEN l.score_value >= 80 THEN 'healthy'
    WHEN l.score_value >= 60 THEN 'watch'
    ELSE 'at risk'
  END AS risk_tier,
  COUNT(*) AS accounts,
  ROUND(AVG(COALESCE(u.active_days_30d, 0))::numeric, 1) AS avg_active_days_30d,
  ROUND(AVG(COALESCE(u.avg_daily_active_users, 0))::numeric, 1) AS avg_dau
FROM latest l
JOIN cs_accounts a ON a.account_id = l.account_id
LEFT JOIN usage u ON u.account_id = l.account_id
WHERE a.churned_at IS NULL
GROUP BY 1
ORDER BY MIN(l.score_value);

What are common mistakes when analyzing Vitally in Metabase?

Treating the vendor health score as a metric definition.→ It is an opaque composite, and it gets reweighted or redefined without the analytics team hearing about it. Re-derive the components in the warehouse, and keep the vendor score beside yours as a labeled column rather than as the source of truth.
Letting a full-refresh sync stand in for history.→ The Airbyte source replaces tables wholesale, so yesterday's values are gone and deletions never appear as deletions. Snapshot each sync into a dated table if you want to answer any question about movement.
Comparing several named health scores as if they were one.→ Vitally supports multiple named scores per account, and teams accumulate them. Pick the one your retention and renewal views run on, name it on the card, and keep the others clearly labeled.
Building dashboards from one-off API exports only.→ A scripted export is a snapshot. Durable dashboards need a database-backed model with history behind them.

Related analytics

Related dashboards

Related integrations

FAQ

Does Metabase connect natively to Vitally?
No. Metabase reads databases and warehouses. Land Vitally data in a database first — via connector or API pipeline — or upload a CSV with the Metabase CLI, then build Metabase models and dashboards on top.
Should Metabase replace Vitally?
No — they answer different questions. Vitally is the system of action: playbooks, alerts, workflows, and the CSM's daily queue. Metabase is where you build governed, shareable reporting for the whole company, and join that data with product usage, support, and billing to answer questions no single tool holds the data for.
Is there a Vitally MCP server?
Not from Vitally — verified July 2026, and its own API documentation doesn't mention MCP at all. That is why this guide leads with a scripted REST export. Community servers exist, and the most complete of them, fiscaltec/vitally-mcp, is published by FISCAL Technologies — a company unaffiliated with Vitally — under a proprietary license, with a hosted endpoint aimed at its own customers. It is not a first-party server despite how the name reads. If Vitally ships an official one later, only the export step of route 1 changes.
Can I sync Vitally with Airbyte?
Yes, with one caveat worth designing around. source-vitally sits at Marketplace support level and syncs accounts, admins, conversations, notes, NPS responses, tasks, and users — but it is full-refresh only, so every sync re-reads the whole account base and deletions never propagate as deletions. If you need genuine incremental pulls, script the REST API instead: cursor pagination with a 100-record page limit, sorting by createdAt or updatedAt, and a generous 1,000 requests per minute. Fivetran offers an Application Lite connector.