How to build Clay enrichment dashboards in Metabase
Clay is where your list-building and enrichment run — tables of records enriched through a waterfall of data providers. Metabase is where you turn that into shared dashboards on coverage, provider performance, and credit cost. Clay isn't a deal-pipeline CRM, so this guide focuses on data quality and enrichment economics. It covers two complementary paths: a lightweight MCP + CLI route that pulls live data with the Clay MCP server and loads a CSV into Metabase with the Metabase CLI for quick analysis, and a durable warehouse route for reporting people depend on.
How do you connect Clay to Metabase?
Most teams combine both routes: use the Clay MCP server and Metabase CLI route to pull live data and stand up a quick analysis, and the warehouse route for the enrichment dashboards the team depends on.
Live data in, quick analysis out
Pair Clay's official local MCP server (to inspect tables and enrichment results) with the Metabase CLI, whose upload command loads a CSV into Metabase as a ready-to-query table and model.
- Quick lookups like "which enrichment column has the lowest hit rate?"
- Loading a Clay CSV export into Metabase in seconds
- Spot-checks and one-off analyses without a warehouse
- Great for exploration, not governed reporting
- The Clay MCP runs locally over stdio with your API key — scope it to lookups
- CSV uploads are snapshots — refresh or move to the warehouse for history
Durable dashboards with history
Push Clay tables to a database or warehouse (Clay's warehouse/HTTP export, or a webhook to your own pipeline), then point Metabase at it.
- Enrichment coverage and credit-usage dashboards the whole team relies on
- Provider hit-rate and cost trends over time
- Joining enriched lists with CRM pipeline and outbound outcomes
- Requires a destination database and an export to maintain
- You own the coverage and match definitions and the refresh schedule
- Snapshot runs over time if you want credit and cost trends
What can you analyze from Clay data in Metabase?
- Enrichment coverage — share of records with a value in each key field
- Provider performance — hit rate and cost by provider in the waterfall
- Credit usage — credits by table and week, and per usable contact
- List quality — verified vs. risky emails and duplicates vs. CRM
- ICP fit — share of enriched records that match your target profile
- List growth — records added and enriched over time
Which Clay dashboards should you build in Metabase?
Enrichment coverage
How complete the data is.
- Coverage by column: email, phone, LinkedIn (bar)
- Records fully vs. partially enriched (number)
- Coverage by source table (matrix)
- Records missing key fields (table)
Provider performance
Which sources actually resolve.
- Hit rate by provider in the waterfall (bar)
- First-provider vs. fallback resolution (number)
- Cost per resolved field by provider (bar)
- Provider errors over time (line)
Credits & cost
What enrichment costs.
- Credits used by table and week (line)
- Cost per enriched record (number)
- Credits per usable contact (number)
- Wasted credits on unresolved rows (number)
List quality
Whether the output is usable.
- Verified vs. risky emails (number)
- Duplicate rate vs. CRM (number)
- ICP-fit share of enriched records (number)
- List growth by week (line)
How do you use the Clay MCP server with the Metabase CLI?
Pair the Clay MCP server with the Metabase CLI for fast, hands-on analysis. Clay offers an official local MCP server that inspects tables and enrichment results; the Metabase CLI's upload command loads a CSV into Metabase and creates a ready-to-query table and model.
Example workflow
- Ask the Clay MCP which enrichment column has the lowest hit rate.
- Export the table records or enrichment results 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 Clay MCP is great for live lookups — not for scheduled or audited enrichment reporting.
- A CSV upload is a point-in-time snapshot; refresh it with
mb upload replaceor move to the warehouse for real history. - The Clay MCP runs locally over stdio with your API key — scope it to lookups.
mb upload csvneeds an uploads database configured under Admin → Settings → Uploads.
How do you set up the Clay MCP server and the Metabase CLI?
Clay MCPofficial local
- Transport
- Local stdio (npx package)
- Package
@clay-inc/mcp-server- Auth
- Clay API key in the environment
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": {
"clay": {
"command": "npx",
"args": ["-y", "@clay-inc/mcp-server"],
"env": { "CLAY_API_KEY": "your-clay-api-key" }
}
}
}# 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 Clay CSV export — creates a table AND a model
mb upload csv --file clay-records.csv --collection root
# Refresh that same table later from a new export
mb upload replace <table-id> --file clay-records.csvThe Clay MCP runs on your machine and reads live table state with your API key. Use it for enrichment lookups and workflow design — not governed reporting, which should run on warehouse-backed Metabase models. The Metabase CLI stores its credentials securely after mb auth login.
Can you generate a Clay dashboard with AI?
Yes. Use the prompt below with any assistant that can run the Clay MCP server and the Metabase CLI. It works end to end: if Clay tables already exist in Metabase it analyzes those; otherwise it pulls the data over the Clay MCP, loads it with mb upload csv, then builds the dashboard — keeping coverage and hit rate distinct and skipping cards it has no data for.
Create a polished Metabase dashboard for Clay enrichment analytics.
Work end to end: get the data into Metabase if it isn't there yet, then build.
Goal: Help RevOps and data teams understand enrichment coverage, provider
performance, credit usage, and list quality from Clay data.
Step 1 — Find or load the data:
- First, check what already exists in Metabase (search for Clay tables and
models). If durable Clay data is already present — exported from a warehouse or
uploaded earlier — use it and skip to Step 2.
- If nothing is there, pull it with the Clay MCP server: table records,
enrichment results (with the provider that resolved each field), credit/usage
events, and verification results. 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:
Clay CSV exports are usually flat and pre-aggregated (one row per record, with
enrichment columns and a resolving provider). Warehouse tables are rawer, often
with a separate row per field attempt. Inspect the actual tables and column
names first; do not assume exact names or that a per-attempt table exists.
Important:
- Build on whatever data is present; don't claim Metabase connects natively to
Clay — it reads a database or CLI-uploaded tables.
- Define enrichment "coverage" as the share of records with a non-null value in a
field, and "match/hit rate" as resolved attempts ÷ attempts — keep them
distinct.
- Attribute a resolved field to the provider that resolved it (waterfall) so
provider hit rate is meaningful.
- Report credits and cost with their denominators (per record, per usable
contact) visible.
- 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: Clay Enrichment Overview
Sections:
1. Executive summary (KPI cards): Records enriched; Coverage (key fields);
Provider hit rate; Credits used; Cost per enriched record; Verified email
share.
2. Coverage: By column; fully vs. partially enriched; by source table.
3. Providers: Hit rate by provider; first vs. fallback; cost per resolved field.
4. Credits & cost: Credits by table and week; cost per record; wasted credits.
5. List quality: Verified vs. risky; duplicates vs. CRM; ICP fit.
Filters: Table, Provider, Column, Date range.
Reuse the models Metabase auto-created from uploaded CSVs, or (for a warehouse)
create reusable models: modeled_clay_records, modeled_clay_enrichment_results,
modeled_clay_credit_events, and modeled_clay_verifications.
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
Clay's own usage views. Keep it practical, dense, and executive-readable.How do you send Clay tables into a database or warehouse?
For dashboards that need history and reliability, land Clay data in a database first, then connect Metabase to that database.
Export options
- Clay warehouse / HTTP export — push table rows to your warehouse or an endpoint on a schedule.
- Webhooks — stream enriched rows to your own pipeline as they complete, capturing the resolving provider.
- dlt (code) — receive Clay exports and load them incrementally with full schema control.
Notes
- Land raw rows first, then build clean models on top.
- Keep the resolving provider per field so provider hit rate stays meaningful.
- Snapshot credit/usage events over time so cost trends are possible.
- Keep verification status so list-quality metrics are honest.
How should you model Clay data in Metabase?
Core tables
| Table | Grain | Key columns |
|---|---|---|
records | one row per Clay record | id, source_table, email, email_status, phone, linkedin_url, created_at |
enrichment_results | one row per field attempt | record_id, field, provider, resolved, run_at |
credit_events | one row per credit charge | record_id, provider, credits, used_at |
verifications | one row per verification | record_id, status (valid/risky/invalid), verified_at |
Modeling advice
- Keep coverage (non-null share) and hit rate(resolved ÷ attempts) as distinct metrics.
- Attribute a resolved field to the provider that resolved it so waterfall analysis is fair.
- Model
credit_eventsso cost per record and per usable contact are easy to compute. - Join records to your CRM to measure duplicate rate and downstream use.
Which Clay metrics should you track in Metabase?
| Metric | Definition | Notes |
|---|---|---|
| Enrichment coverage | Records with a value in a field ÷ records. | Report per field. |
| Provider hit rate | Resolved attempts ÷ attempts, by provider. | Distinct from coverage. |
| Credits per usable contact | Credits used ÷ valid, usable contacts. | An efficiency signal, not a target. |
| Verified email share | Valid ÷ verified emails. | Drives deliverability downstream. |
| Duplicate rate | Records matching an existing CRM contact. | Keeps coverage honest. |
| List growth | New enriched records per period. | Read with quality, not alone. |
What SQL powers Clay dashboards in Metabase?
These assume the modeled tables above (PostgreSQL dialect). Adjust identifiers to match your warehouse.
Share of records with an email, phone, and LinkedIn, by source table.
-- Enrichment coverage by field, by source table
SELECT
r.source_table,
COUNT(*) AS records,
ROUND(100.0 * COUNT(r.email) / COUNT(*), 1) AS pct_with_email,
ROUND(100.0 * COUNT(r.phone) / COUNT(*), 1) AS pct_with_phone,
ROUND(100.0 * COUNT(r.linkedin_url) / COUNT(*), 1) AS pct_with_linkedin
FROM modeled_clay_records r
GROUP BY r.source_table
ORDER BY records DESC;Resolved attempts as a share of attempts, by provider.
-- Hit rate by enrichment provider
SELECT
e.provider,
COUNT(*) AS attempts,
COUNT(*) FILTER (WHERE e.resolved) AS resolved,
ROUND(100.0 * COUNT(*) FILTER (WHERE e.resolved)
/ NULLIF(COUNT(*), 0), 1) AS hit_rate_pct
FROM modeled_clay_enrichment_results e
GROUP BY e.provider
ORDER BY attempts DESC;Cost efficiency by week, using valid emails as the usable base.
-- Cost efficiency: credits per usable contact by week
SELECT
date_trunc('week', c.used_at) AS week,
SUM(c.credits) AS credits_used,
COUNT(DISTINCT r.id) FILTER (WHERE r.email IS NOT NULL AND r.email_status = 'valid') AS usable_contacts,
ROUND(SUM(c.credits)::numeric
/ NULLIF(COUNT(DISTINCT r.id) FILTER (WHERE r.email IS NOT NULL AND r.email_status = 'valid'), 0), 2)
AS credits_per_usable_contact
FROM modeled_clay_credit_events c
LEFT JOIN modeled_clay_records r ON r.id = c.record_id
GROUP BY 1
ORDER BY 1;