Free data template
KPI dashboard notebook
Weekly revenue, orders, average basket and active customers, with a chart per KPI.
It opens with this template loaded and runs in your browser. You don't need an account to use it; a free account saves your work and exports it.
The job it does
For a weekly business review: the same KPIs every week from fresh data, instead of rebuilding a spreadsheet. It comes with its own checks, so after you change it you can see at a glance that it still does the job.
How to use it with your own data
Load your own CSV as a file called sales (columns date, orders, revenue, customers) to replace the sample.
What's inside
This is the template exactly as the Data Lab opens it, read-only. Open it to run it, change it and export it.
- 4 notebook cells
- Data: the retail sample database (Mangrove Market: stores, customers, orders, payments)
The weekly business review needs the same numbers every week: revenue, orders and average basket, this week against last week, with a chart for each. Run it on fresh data instead of rebuilding a spreadsheet.
The SQL cell reads 12 weeks of delivered orders from the sample; the notebook does the rest.
Your own data: load a CSV file called sales with the columns date, orders and revenue (one row per day) and Run: the notebook uses it instead of the sample.
- The notebook runs top to bottom without errors
- weekly has 2–520 rows
- kpis.change_pct has no empty values
- A line chart plots revenue
- Runs in 30 s or less
-- Delivered orders per day for the last 12 weeks (Monday 6 October to Sunday 28 December 2025)
select o.ordered_at::date as date,
count(distinct o.id)::int as orders,
(sum(i.qty * i.unit_price_cents) / 100.0)::float8 as revenue
from orders o
join order_items i on i.order_id = o.id
where o.status = 'delivered'
and o.ordered_at >= '2025-10-06' and o.ordered_at < '2025-12-29'
group by 1
order by 1# Your own data: load a CSV file called "sales" (columns date, orders, revenue) and it is used instead.
source = (sales if "sales" in globals() else daily).copy()
source["date"] = pd.to_datetime(source["date"])
# one row per week (weeks start on Monday)
weekly = (source.groupby(source["date"].dt.to_period("W-SUN").dt.start_time)[["orders", "revenue"]].sum()
.rename_axis("week").reset_index())
weekly["avg_basket"] = (weekly["revenue"] / weekly["orders"]).round(2)
weekly["revenue"] = weekly["revenue"].round(2)
weekly["week"] = weekly["week"].dt.strftime("%Y-%m-%d")
weekly# The KPIs for the review: this week, last week and the change
this, last = weekly.iloc[-1], weekly.iloc[-2]
kpis = pd.DataFrame({
"kpi": ["revenue", "orders", "avg_basket"],
"this_week": [this["revenue"], this["orders"], this["avg_basket"]],
"last_week": [last["revenue"], last["orders"], last["avg_basket"]],
})
kpis["change_pct"] = ((kpis["this_week"] - kpis["last_week"]) / kpis["last_week"] * 100).round(1)
kpischart(weekly, x="week", y="revenue", kind="line", title="Revenue per week")
chart(weekly, x="week", y="orders", kind="bar", title="Orders per week")
chart(weekly, x="week", y="avg_basket", kind="line", title="Average basket per week")The lesson behind it
Learn why it works, with a podcast and a quiz for each lesson.
More data templates
A/B test readout
Conversion per variant, the lift, a confidence interval and a plain-language verdict.
Simple forecast
A trend plus weekly pattern fitted to daily sales, the next 4 weeks forecast and a check against the last weeks.