How to build Shopify dashboards in Metabase
Shopify powers millions of online stores and holds the record of every order, product, and customer. Metabase is where you turn that activity into shared, trustworthy dashboards. This guide covers two complementary paths: a lightweight MCP + CLI route that pulls live data with the Shopify MCP and loads a CSV into Metabase with the Metabase CLI for quick analysis, and a durable pipeline route that syncs Shopify into a database so you can build dashboards anyone can read.
How do you connect Shopify to Metabase?
Most teams combine both routes: use the Shopify MCP and Metabase CLI route to pull live data and stand up a quick analysis, and the pipeline route for the dashboards people depend on.
Live data in, quick analysis out
Pair a Shopify MCP server (to read live store data — orders, products, customers) with the Metabase CLI, whose upload command loads a CSV into Metabase as a ready-to-query table and model.
- Quick lookups like "top products by revenue this week?"
- Loading a Shopify CSV export into Metabase in seconds
- Spot-checks and one-off analyses without a warehouse
- Great for exploration, not governed reporting
- Use read-only mode on the Shopify MCP to avoid accidental writes
- CSV uploads are snapshots — refresh or move to the pipeline for history
Durable dashboards with history
Sync Shopify into a database or warehouse with a managed connector, dlt, or the Admin API, then point Metabase at it.
- Sales, AOV, and cohort dashboards leaders depend on
- Joining orders with marketing, support, and finance data
- Peak-season comparisons across quarters and years
- You own the refresh schedule and the data model
- Reconcile refunds, taxes, and discounts to report net revenue
- Capture line items to analyze product and basket behavior
What can you analyze from Shopify data in Metabase?
- Sales — net revenue, orders, and AOV over time
- Repeat purchase — how many buyers come back, and how fast
- Product performance — top sellers, units, and refund rate
- Discounts & margin — discount depth and its effect on revenue
- Refunds & returns — where and why revenue comes back
- Customer cohorts — revenue by acquisition month and channel
- Cart abandonment — if you sync abandoned-checkout data
Which Shopify dashboards should you build in Metabase?
Store overview
The daily pulse of sales and demand.
- Net revenue vs. prior period (number + trend)
- Orders per day (line)
- Average order value (number + trend)
- New vs. returning customer revenue (bar)
Product performance
What's selling, what's stuck.
- Top products by net revenue (bar)
- Units sold by variant (table)
- Refund rate by product (bar)
- Inventory on hand vs. sell-through (table)
Customers & repeat purchase
Are buyers coming back?
- Repeat-purchase rate by cohort (line)
- Orders per customer distribution (bar)
- Time between first and second order (histogram)
- Revenue by acquisition month (cohort table)
Fulfillment & margin
From cart to delivered, and what's left.
- Discount depth as % of gross sales (line)
- Refunds and returns by week (line)
- Shipping vs. fulfillment time (table)
- Cart abandonment rate (number, if checkout data synced)
How do you use the Shopify MCP server with the Metabase CLI?
Pair a Shopify MCP server with the Metabase CLI for fast, hands-on analysis. Shopify's official Dev MCP is oriented toward the developer docs, GraphQL schema, and API tooling; for live store data (orders, products, customers) most teams connect the Admin API through a managed MCP such as Pipedream. The Metabase CLI's upload command then loads a CSV into Metabase and creates a ready-to-query table and model. For analysis, connect Shopify in read-only mode.
Example workflow
- Ask the Shopify MCP which products drove the most revenue this week.
- Export the orders or product performance 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 Shopify MCP is great for live lookups — not for scheduled or audited reporting.
- A CSV upload is a point-in-time snapshot; refresh it with
mb upload replaceor move to the pipeline for real history. - Use a read-only option so analysis can't trigger writes; the official Dev MCP is docs/tooling focused, so store-data reads typically run through a managed connector.
mb upload csvneeds an uploads database configured under Admin → Settings → Uploads.
How do you set up the Shopify MCP server and the Metabase CLI?
Shopify Dev MCPofficial
- Command
npx -y @shopify/dev-mcp@latest- Transport
- stdio (local process)
- Scope
- Docs, GraphQL schema, and API tooling
- Note
- In Cursor you can also run
/add-plugin shopify.
Shopify store data managed
- Endpoint
https://mcp.pipedream.net/v2- Transport
- Streamable HTTP
- Auth
- Connect Shopify inside Pipedream, then use the URL
- Scope
- Admin API actions — orders, products, customers
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": {
"shopify-dev": {
"command": "npx",
"args": ["-y", "@shopify/dev-mcp@latest"]
}
}
}# 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 Shopify CSV export — creates a table AND a model
mb upload csv --file shopify-orders.csv --collection root
# Refresh that same table later from a new export
mb upload replace <table-id> --file shopify-orders.csvThis example wires the official Dev MCP; for live store data, add a Pipedream (or equivalent) Shopify server alongside it and connect your store first. The Metabase CLI stores its credentials securely after mb auth login.
Can you generate a Shopify dashboard with AI?
Yes. Use the prompt below with any assistant that can run the Shopify MCP server and the Metabase CLI. It works end to end: if Shopify tables already exist in Metabase it analyzes those; otherwise it pulls the data over the Shopify MCP, loads it with mb upload csv, then builds the dashboard — reporting net revenue and skipping cards it has no data for (including cart abandonment if no checkout data is present).
Create a polished Metabase dashboard for Shopify ecommerce analytics.
Work end to end: get the data into Metabase if it isn't there yet, then build.
Goal: Help store operators understand sales, average order value, repeat purchase,
product performance, and discounts/refunds from Shopify data.
Step 1 — Find or load the data:
- First, check what already exists in Metabase (search for Shopify tables and
models). If durable Shopify 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 Shopify MCP server in read-only mode:
orders, order line items, products, customers, and refunds (and abandoned
checkouts if available). 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:
Shopify CSV exports are usually flat and pre-aggregated (one row per order, with
columns like total price, discounts, and financial status). Warehouse tables are
raw and order-grained (orders, order_line_items, products, customers, refunds).
Inspect the actual tables and column names first; do not assume exact names or that
a given table (e.g. abandoned checkouts) exists.
Important:
- Build on whatever data is present; don't claim Metabase connects natively to
Shopify — it reads a database or CLI-uploaded tables.
- 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.
- Report NET revenue: subtract refunds, discounts, and (per your policy) taxes and
shipping. State the definition on the dashboard.
- Use order-level grain for AOV; do not average line-item prices.
- Only build cart-abandonment cards if abandoned-checkout data is actually present.
- Define a "repeat customer" once (2+ paid orders) and reuse it everywhere.
Dashboard title: Shopify Store Overview
Sections:
1. Executive summary (KPI cards): Net revenue last 30 days; Orders; AOV; Repeat-
purchase rate; Refund rate; Cart abandonment (only if checkout data exists).
2. Sales & demand: Net revenue by day; Orders by day; AOV trend; New vs returning
revenue.
3. Product performance: Top products by net revenue; Units by variant; Refund rate
by product.
4. Customers & retention: Repeat-purchase rate by cohort; Orders per customer;
Revenue by acquisition month.
5. Discounts & margin: Discount depth over time; Refunds by week.
Filters: Date range, Sales channel, Product type, Discount code, Customer type.
Reuse the models Metabase auto-created from uploaded CSVs, or (for a warehouse)
create reusable models: modeled_shopify_orders, modeled_shopify_line_items,
modeled_shopify_products, modeled_shopify_customers, and modeled_shopify_refunds.
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. Keep it practical, dense,
and executive-readable. Avoid vanity metrics.How do you sync Shopify data into a database or warehouse?
For dashboards that need history and reliability, land Shopify data in a database first, then connect Metabase to that database.
Connector options
- Managed ETL — Shopify is a first-class source for connectors like Fivetran and Airbyte, which land orders, customers, and products into your warehouse on a schedule. The quickest route if you already run a warehouse.
- dlt (code) — write a Python pipeline against the Shopify Admin API for full control over tables and refresh.
- Shopify Admin GraphQL API (raw) — the source of truth; paginate orders, line items, products, and customers and upsert on a schedule.
- Store alongside adjacent data — sync ad spend, support (e.g. Gorgias), and finance so you can join orders to acquisition and service.
Notes
- Land raw tables first, then build clean models on top.
- Capture refunds and discounts so you can report net — not gross — revenue.
- Sync abandoned checkouts separately if you want cart-abandonment metrics.
How should you model Shopify data in Metabase?
Core tables
| Table | Grain | Key columns |
|---|---|---|
orders | one row per order | id, customer_id, created_at, total_price, total_discounts, financial_status |
order_line_items | one row per line | order_id, product_id, variant_id, quantity, price |
products | one row per product | id, title, product_type, vendor |
customers | one row per customer | id, email, created_at, orders_count |
refunds | one row per refund | order_id, amount, created_at |
Modeling advice
- Define net revenue once (gross − discounts − refunds; decide on taxes and shipping) and reuse it everywhere.
- Compute AOV at the order grain, not by averaging line prices.
- Filter to paid orders (
financial_status) so tests and draft orders don't inflate sales. - Treat line items as the bridge between orders and products for basket analysis.
- Define a "repeat customer" (2+ paid orders) once and reuse it.
Which Shopify metrics should you track in Metabase?
| Metric | Definition | Notes |
|---|---|---|
| Net revenue | Gross − discounts − refunds. | State whether taxes/shipping are included. |
| Average order value (AOV) | Net revenue ÷ orders. | Compute at order grain; segment by channel. |
| Repeat-purchase rate | Customers with 2+ paid orders ÷ all. | Pick a fixed window; watch by cohort. |
| Refund rate | Refunded amount ÷ gross. | Break out by product to find problem SKUs. |
| Cart abandonment | Abandoned ÷ started checkouts. | Needs abandoned-checkout data synced. |
| Discount depth | Discounts ÷ gross sales. | Rising depth can mask soft demand. |
What SQL powers Shopify dashboards in Metabase?
These assume the modeled tables above (PostgreSQL dialect). Adjust identifiers to match your warehouse.
Gross-after-discount and refunds by day over the last 30 days.
SELECT
date_trunc('day', o.created_at) AS day,
COUNT(*) AS orders,
SUM(o.total_price - COALESCE(o.total_discounts, 0)) AS gross_after_discount,
SUM(COALESCE(r.refunded_amount, 0)) AS refunds
FROM orders o
LEFT JOIN (
SELECT order_id, SUM(amount) AS refunded_amount
FROM refunds
GROUP BY order_id
) r ON r.order_id = o.id
WHERE o.created_at >= CURRENT_DATE - INTERVAL '30 days'
AND o.financial_status IN ('paid', 'partially_refunded')
GROUP BY 1
ORDER BY 1;AOV computed at the order grain, on paid orders.
SELECT
date_trunc('week', o.created_at) AS week,
COUNT(*) AS orders,
ROUND(
SUM(o.total_price - COALESCE(o.total_discounts, 0)) / NULLIF(COUNT(*), 0),
2) AS aov
FROM orders o
WHERE o.financial_status IN ('paid', 'partially_refunded')
GROUP BY 1
ORDER BY 1;Share of customers with two or more paid orders.
WITH customer_orders AS (
SELECT
customer_id,
COUNT(*) AS paid_orders
FROM orders
WHERE financial_status IN ('paid', 'partially_refunded')
AND customer_id IS NOT NULL
GROUP BY customer_id
)
SELECT
ROUND(
100.0 * COUNT(*) FILTER (WHERE paid_orders >= 2) / NULLIF(COUNT(*), 0),
2) AS repeat_purchase_rate_pct
FROM customer_orders;Units and gross revenue by product over 90 days.
SELECT
p.title AS product,
SUM(li.quantity) AS units,
SUM(li.quantity * li.price) AS gross_revenue
FROM order_line_items li
JOIN orders o ON o.id = li.order_id
JOIN products p ON p.id = li.product_id
WHERE o.created_at >= CURRENT_DATE - INTERVAL '90 days'
AND o.financial_status IN ('paid', 'partially_refunded')
GROUP BY p.title
ORDER BY gross_revenue DESC
LIMIT 20;