How to build Close sales dashboards in Metabase
Close is an inside-sales CRM where your leads, opportunities, and outreach live. Metabase is where you turn that activity into shared, trustworthy sales dashboards. This guide covers two complementary paths: a lightweight MCP + CLI route that pulls live data with a managed Close MCP server and loads a CSV into Metabase with the Metabase CLI for quick analysis, and a durable pipeline route that syncs Close into a database so you can build pipeline, win-rate, and conversion dashboards anyone can read.
How do you connect Close to Metabase?
Most teams combine both routes: use the managed Close MCP server and Metabase CLI route to pull live data and stand up a quick analysis, and the pipeline route for the sales dashboards the team depends on.
Live data in, quick analysis out
Connect Close through a managed MCP server (Pipedream) to read live leads, opportunities, and activities, then pair it with the Metabase CLI, whose upload command loads a CSV into Metabase as a ready-to-query table and model.
- Quick lookups like "which opportunities are stuck in active?"
- Loading a Close CSV export into Metabase in seconds
- Spot-checks and one-off analyses without a warehouse
- Great for exploration, not governed reporting
- Scope the managed connector tightly to avoid unintended writes
- CSV uploads are snapshots — refresh or move to the pipeline for history
Durable dashboards with history
Sync Close into a database or warehouse with dlt, a managed connector, or the Close API, then point Metabase at it.
- Pipeline, win-rate, and conversion dashboards the whole team relies on
- Sales cycle and status-conversion trends over quarters
- Joining CRM data with product usage, billing, or support data
- Requires a destination database and a sync to maintain
- You own the won/lost and status definitions and the refresh schedule
- Capture opportunity status changes if you want accurate velocity metrics
What can you analyze from Close data in Metabase?
- Pipeline — active opportunity value by status, user, and pipeline, plus coverage against target
- Win rate — opportunities won vs. closed, by pipeline, source, and status
- Sales cycle length — created to won, with median and p90
- Status conversion — where opportunities advance and where they stall
- Deal size — average and median value, plus mix by pipeline
- Outreach — calls, emails, and SMS by rep and opportunity
- Connect rate — reached calls and talk time
Which Close dashboards should you build in Metabase?
Pipeline
The open book of business, right now.
- Active opportunities by status (funnel)
- Pipeline value by user and pipeline (bar)
- Coverage vs. target for the period (number)
- Stale opportunities with no recent activity (table)
Conversion
Where opportunities advance and where they stall.
- Status-to-status conversion (funnel)
- Win rate by pipeline and lead source (bar)
- Opportunities created vs. won by week (dual line)
- Lost reasons breakdown (bar)
Velocity
How fast opportunities close.
- Median sales cycle length (number + trend)
- Time-in-status by status (bar)
- Deal velocity: value / cycle time (number)
- Aging of active opportunities (table)
Outreach activity
Effort and coverage, not surveillance.
- Calls, emails, and SMS by rep (bar)
- Activities per active opportunity (number)
- Connect rate and talk time (number)
- First-touch response time (line)
How do you use the Close MCP server with the Metabase CLI?
Connect Close through a managed Close MCP server (Pipedream) and pair it with the Metabase CLI for fast, hands-on analysis. The Close MCP looks up current leads, opportunities, and activities; the Metabase CLI's upload command loads a CSV into Metabase and creates a ready-to-query table and model. Scope the managed connector tightly.
Example workflow
- Ask the Close MCP which active opportunities have no call or email in the last week, or a lead's opportunities and recent outreach.
- Export the opportunities or activity you want to keep as a CSV.
- 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
- The Close MCP is great for live lookups — not for scheduled or audited pipeline reporting.
- A CSV upload is a point-in-time snapshot; refresh it with
mb upload replaceor move to the pipeline for real history — sales cycle and status conversion still need synced opportunity history. - The managed connector acts with the permissions of the connected Close account; scope it tightly.
mb upload csvneeds an uploads database configured under Admin → Settings → Uploads.
How do you set up the Close MCP server and the Metabase CLI?
Close MCPmanaged
- Provider
- Pipedream (managed connector)
- Endpoint
https://mcp.pipedream.net/v2- Auth
- Connect your Close account in Pipedream (OAuth)
- Note
- No official first-party Close MCP server yet
Metabase CLIofficial
- Install
npm install -g @metabase/cli- Auth
mb auth login(browser OAuth on v62+, or an API key)- Load data
mb upload csv --file data.csv- Requires
- An uploads database (Admin → Settings → Uploads)
{
"mcpServers": {
"close": {
"url": "https://mcp.pipedream.net/v2"
}
}
}# 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 Close CSV export — creates a table AND a model
mb upload csv --file close-opportunities.csv --collection root
# Refresh that same table later from a new export
mb upload replace <table-id> --file close-opportunities.csvClose doesn't publish a first-party MCP server, so the practical path is a managed connector: connect your Close account in Pipedream, then use its static MCP URL. Because a third party brokers access, scope the connection tightly and review what the connector can read and write. The Metabase CLI stores its credentials securely after mb auth login.
Can you generate a Close dashboard with AI?
Yes. Use the prompt below with any assistant that can run the Close MCP server and the Metabase CLI. It works end to end: if Close tables already exist in Metabase it analyzes those; otherwise it pulls the data over the Close MCP, loads it with mb upload csv, then builds the dashboard — defining "won" and "closed" and skipping metrics the data can't support instead of faking them.
Create a polished Metabase dashboard for Close sales analytics.
Work end to end: get the data into Metabase if it isn't there yet, then build.
Goal: Help sales leaders understand pipeline, win rate, conversion, sales cycle,
and outreach activity from Close CRM data.
Step 1 — Find or load the data:
- First, check what already exists in Metabase (search for Close tables and
models). If durable Close data is already present — synced from a warehouse or
uploaded earlier — use it and skip to Step 2.
- If nothing is there, pull it with the Close MCP server (via the managed
Pipedream connector): leads, opportunities, pipelines/statuses, activities, and
users. 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:
Close CSV exports are usually flat and pre-aggregated (one row per opportunity,
lead, or activity, with columns like status, value, and dates). Warehouse tables
are raw and can carry status-change history for velocity metrics. Note that Close
opportunity value is stored in cents. Inspect the actual tables and column names
first; do not assume exact names or that status history exists.
Important:
- Build on whatever data is present; don't claim Metabase connects natively to
Close — it reads a database or CLI-uploaded tables.
- Only recompute rates over the correct base (e.g. win rate) when raw counts are
available; if the data already provides a rate, chart it directly.
- Define "won" and "closed" once (status_type = won vs. won/lost) and reuse them.
- For win rate, state the denominator explicitly (won / closed vs. won / created)
and hold the cohort fixed.
- Report sales cycle length and deal size as medians (p50) and p90, never plain
averages — both are right-skewed.
- If opportunity status-change history is missing, do not calculate sales cycle
length, time-in-status, or status conversion. Use a caveat instead.
- Convert all amounts to a single reporting currency; caveat any mix.
- Only build a card if its underlying column/metric exists 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: Close Sales Overview
Sections:
1. Executive summary (KPI cards): Open pipeline; Coverage vs. target; Win rate
(last 90 days); Median sales cycle length; Average and median deal size;
Opportunities closing this period.
2. Pipeline: Active opportunities by status; value by user and pipeline; stale
opportunities.
3. Conversion: Status-to-status conversion; win rate by pipeline and source; lost
reasons.
4. Velocity: Median cycle length; time-in-status; deal velocity; aging.
5. Activity: Calls/emails/SMS by rep; activities per opportunity; connect rate.
Filters: Pipeline, Status, User, Lead source, Date range.
Reuse the models Metabase auto-created from uploaded CSVs, or (for a warehouse)
create reusable models: modeled_close_opportunities, modeled_close_status_history,
modeled_close_leads, modeled_close_contacts, and modeled_close_activities.
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. Reconcile totals against
Close's own reporting. Keep it practical, dense, and executive-readable. Avoid
vanity metrics.How do you sync Close data into a database or warehouse?
For dashboards that need history and reliability, land Close data in a database first, then connect Metabase to that database.
Connector options
- Close API (raw) — the source of truth; pull leads, opportunities, activities, and status definitions, and capture status changes for history.
- dlt (code) — write a Python pipeline against the Close API for full control of schema and incremental loads.
- Managed ETL (Airbyte / Fivetran) — check the connector catalogs for a Close source; where one exists it can land opportunities and activities on a schedule.
- Reverse-ETL / webhooks — Close webhooks can stream opportunity and activity changes so you don't lose transitions between syncs.
Notes
- Land raw tables first, then build clean models on top.
- Close opportunities carry a
status_type(active / won / lost) and astatus_labelwithin a pipeline — use both. - Capture status changes (webhooks or the activity log) for cycle length, time-in-status, and conversion.
- Opportunity
valueis stored in cents — divide by 100 and note the currency.
How should you model Close data in Metabase?
Core tables
| Table | Grain | Key columns |
|---|---|---|
opportunities | one row per opportunity | id, lead_id, status_type, status_label, pipeline_id, value, value_currency, date_created, date_won, user_id |
opportunity_status_history | one row per change | opportunity_id, status_label, changed_at |
leads | one row per lead | id, status_label, source, date_created |
contacts | one row per contact | id, lead_id |
activities | one row per activity | id, lead_id, type (call/email/sms),direction, duration, user_id, date_created |
users | one row per user | id, name |
Modeling advice
- Build a
modeled_close_opportunitiestable with cleanstatus_type,status_label,value(dollars, one currency), andclosed_at(date_won or date_lost). - Derive
modeled_close_status_historyfrom webhooks or the activity log for time-in-status and cycle length. - Normalize status labels to an ordered funnel so conversion charts stay stable.
- Convert
valuefrom cents and to a single reporting currency. - Reconcile modeled pipeline and win rate against Close's own reporting before anyone trusts the numbers.
Which Close metrics should you track in Metabase?
| Metric | Definition | Notes |
|---|---|---|
| Open pipeline | Sum of value for active opportunities. | Segment by status, user, pipeline. |
| Win rate | Won ÷ closed opportunities in a cohort. | Fix the denominator (closed vs. created) before comparing. |
| Sales cycle length | Created → won, in days. | Report median and p90; it's right-skewed. |
| Status conversion | Opportunities reaching status N+1 ÷ reaching status N. | Needs status-change history. |
| Average deal size | Won value ÷ won opportunities. | Report the median too; outliers distort the mean. |
| Connect rate | Reached calls ÷ call attempts. | Read alongside pipeline, not alone. |
What SQL powers Close dashboards in Metabase?
These assume the modeled tables above (PostgreSQL dialect). Adjust identifiers to match your warehouse.
Won as a share of closed opportunities over the last 12 months.
SELECT
date_trunc('month', o.closed_at) AS month,
COUNT(*) FILTER (WHERE o.status_type = 'won') AS won,
COUNT(*) FILTER (WHERE o.status_type IN ('won', 'lost')) AS closed,
ROUND(
100.0 * COUNT(*) FILTER (WHERE o.status_type = 'won')
/ NULLIF(COUNT(*) FILTER (WHERE o.status_type IN ('won', 'lost')), 0),
1
) AS win_rate_pct
FROM modeled_close_opportunities o
WHERE o.status_type IN ('won', 'lost')
AND o.closed_at >= CURRENT_DATE - INTERVAL '12 months'
GROUP BY 1
ORDER BY 1;The current funnel — active opportunities and value by status.
SELECT
o.status_label,
COUNT(*) AS active_opps,
ROUND(SUM(o.value / 100.0), 2) AS active_value
FROM modeled_close_opportunities o
WHERE o.status_type = 'active'
GROUP BY o.status_label
ORDER BY active_value DESC;Days from created to won; medians beat averages here.
-- Median days from created to won, by month closed
SELECT
date_trunc('month', o.closed_at) AS month,
percentile_cont(0.5) WITHIN GROUP (
ORDER BY EXTRACT(EPOCH FROM (o.closed_at - o.date_created)) / 86400.0
) AS median_cycle_days,
percentile_cont(0.9) WITHIN GROUP (
ORDER BY EXTRACT(EPOCH FROM (o.closed_at - o.date_created)) / 86400.0
) AS p90_cycle_days
FROM modeled_close_opportunities o
WHERE o.status_type = 'won'
GROUP BY 1
ORDER BY 1;