A Notion KPI tracker works best as two related databases: a KPIs database with one page per metric and its target, and a Measurements database with one row per reading. Formulas on each KPI page pull the latest reading, compare it with the target and return a status you can read in a second, while a line chart on Measurements shows the trend. I'd build it this way rather than typing the current number into each KPI page, because a typed number overwrites last month's value and Notion charts can't plot rollups, while a log keeps every reading and charts cleanly. Your plan shapes the layout: Free gives you one chart, and the Dashboard view needs Business or Enterprise.
For a solo freelancer on Free, build the two databases, the formulas and one chart for the KPI you'd act on first. For a small team on Plus, add a chart per KPI and an automation that reminds people to log. On Business or Enterprise, finish with a Dashboard view that puts the KPI table and its charts side by side. Whichever plan you're on, values arrive the same way: someone types them in, or an integration you run yourself writes them. Nothing in this setup pulls numbers from your invoicing or analytics tools.
Which KPIs should the tracker hold?
Pick three to seven numbers you'd change a decision over. A number you only glance at is a report, and a tracker full of reports stops getting updated. If you work with SMART goals, the measurable and time-bound parts become two properties here: a target and a cadence.
For each KPI, settle five things before you open Notion:
- Unit. Dollars, a count, a percent or hours. It tells you how to read the value, and it's the reason each KPI gets its own chart.
- Direction. Higher is better for revenue; lower is better for response time or churn. The progress formula flips on this one.
- Type. A flow is several readings that add up over a period, such as weekly payment totals or weekly lead counts. A snapshot stands on its own: a level, a rate, or a period total you log once when the period ends.
- Cadence. Weekly or monthly. It sets the logging routine and the staleness check.
- Owner. The person who logs the reading. On a team, the KPI without an owner is the one that goes quiet.
| KPI | Unit | Direction | Type | Cadence | Where the number comes from |
|---|---|---|---|---|---|
| Revenue this month | $ | Higher is better | Flow | Weekly | Payments received that week, from your bank or invoicing tool |
| New leads | Count | Higher is better | Flow | Weekly | Inquiries that reached your inbox or CRM that week |
| Billable utilization | % | Higher is better | Snapshot | Monthly | Billable hours divided by available hours, from your time log |
| Average first-response time | Hours | Lower is better | Snapshot | Weekly | Your help desk report, or the week's client emails |
| Active clients | Count | Higher is better | Snapshot | Monthly | Clients with work in progress on the last day of the month |
These are examples to adapt, not benchmarks. I'd start with three of them and use the tracker for one full month before adding more, because the first month shows which numbers you'll really log on time. Adding a KPI later takes a minute; reviving a tracker nobody updates takes much longer.
How do you set up the KPIs and Measurements databases?
Create two full-page databases. KPIs holds the definition of each metric and its formulas; Measurements holds the numbers. Because each reading is its own row, the history stays intact and a chart can plot it.
KPIs: one page per metric
| Property | Type | What it holds |
|---|---|---|
| Name | Title | The KPI, such as New leads |
| Target | Number | The value you're aiming for; keep it above 0 |
| Unit | Select | $, %, Count, Hours |
| Direction | Select | Higher is better, Lower is better |
| Type | Select | Flow, Snapshot |
| Cadence | Select | Weekly, Monthly |
| Owner | Person | Who logs the reading |
| Measurements | Relation | Every reading of this KPI |
Measurements: one row per reading
| Property | Type | What it holds |
|---|---|---|
| Name | Title | A short label such as Leads, week 2; optional |
| Date | Date | The day the reading covers; for a period total, the period's last day |
| Value | Number | The reading itself |
| KPI | Relation | The one KPI this reading belongs to |
| Note | Text | Anything that explains an odd number |
Keep Value a plain number. Notion's database properties reference says a Number property can be formatted as currency or a progress bar, but that format belongs to the whole property, and one Measurements database holds dollars, percents and hours side by side. The Unit select on the KPI page tells you how to read each value.
Then connect the two databases:
- In KPIs, add a new property, search for Relation and choose the Measurements database.
- Switch on the toggle that says Show on Measurements. Notion's guide to relations and rollups notes that relations between two different databases are one-way by default, so this toggle is what gives every reading a KPI property.
- Click Add relation.
- In Measurements, limit the KPI relation to 1 page, so a reading can't belong to two metrics.
If relations are new to you, the walkthrough of relations and rollups on a client database covers the same menus step by step. The structure handles the bookkeeping; deciding what counts as one reading stays with you. Write the rule on each KPI page, for example "payments received Monday to Sunday," so two people log the same thing the same way.

Which formulas turn readings into a status?
A KPI needs its most recent value, and the rollup menu doesn't offer one. The relations guide lists every rollup calculation: the number-only ones are Sum, Average, Median, Min, Max and Range, and Latest date exists only for Date properties. None of them returns the value of the newest related page, so the tracker gets its latest value from a formula and its latest date from a rollup. According to Notion's formulas help, you add a formula through the slider icon at the top of the database: Edit properties → New property → Formula → Edit formula. Open the editor from a KPI row and it shows a live preview for that row, which is the quickest way to check each result against a number you already know.
| Property | Kind | Returns |
|---|---|---|
| Latest | Formula | The Value of the newest reading |
| This month | Formula | The total of this month's readings |
| Current | Formula | This month for flows, Latest for snapshots |
| Progress | Formula | A ratio where 1 means the target is met |
| Status | Formula | No data, On track, Watch or Off track |
| Last logged | Rollup | The date of the newest reading |
| Stale | Formula | True when the newest reading is older than your cutoff |
Latest: the newest reading
prop("Measurements").sort(current.prop("Date")).last().prop("Value")
This sorts the related readings by Date, takes the last one and returns its Value. Thomas Frank's formula reference shows sort() ordering related pages by a date property in ascending order, and last() returning the final item of a list, so the newest reading comes out at the end. Because the order comes from Date alone, every reading needs a date, and one reading per date per KPI keeps "latest" unambiguous. Latest is the number snapshot KPIs report.
This month: the running total for flows
sum(prop("Measurements").filter(formatDate(current.prop("Date"), "YYYY-MM") == formatDate(today(), "YYYY-MM")).map(current.prop("Value")))
filter() keeps the readings dated in the current month, map() turns them into their values, and sum() adds them up. Notion's formula syntax reference lists "YYYY" for the year and "MM" for the month as formatDate() codes, so both sides become the same year-month text when a reading falls in this month. The guide to map() and filter() on related pages explains this kind of chain in more depth.
Current: one number for every KPI
if(prop("Type") == "Flow", prop("This month"), prop("Latest"))
Flows report the month's total, snapshots report the newest reading, and the remaining formulas only look at Current. If you log a flow once a month as a finished total, set its Type to Snapshot: its newest reading already is the total.
Progress: how close you are to the target
if(prop("Measurements").length() == 0, 0, if(prop("Direction") == "Lower is better", if(prop("Current") == 0, 1, prop("Target") / prop("Current")), prop("Current") / prop("Target")))
Progress is a ratio: 1 means the target is met and 0.8 means 80% of the way there. Higher-is-better KPIs divide Current by Target. Lower-is-better KPIs flip it to Target divided by Current, so a 6-hour response time against a 4-hour target reads 0.67 instead of 1.5. A reading of 0 on a lower-is-better KPI counts as met, and every Target has to be above 0 for the division to mean anything.
The first check counts readings with length() rather than testing Current with empty(), on purpose. The formula syntax reference says empty() treats 0, an empty string and an empty list as empty, so a week with zero new leads would look like a week with nothing logged. Counting the related readings keeps "logged a zero" apart from "logged nothing." To display Progress as a bar, the progress bar guide compares Notion's built-in bar display with a text bar drawn by the formula.
Status: the word you read first
ifs(prop("Measurements").length() == 0, "No data", prop("Progress") >= 1, "On track", prop("Progress") >= 0.8, "Watch", "Off track")
ifs() returns the value for the first condition that's true, so order matters: the no-data case goes first, then the thresholds from high to low. The 0.8 line between Watch and Off track is a starting point, not a standard; move it to where you'd start acting. For color, wrap a label in style(), such as style("Off track", "red"); the syntax reference lists colors from gray to red plus "_background" versions. The if() and ifs() guide covers condition order and the mistakes that send every row to the last value.
Read flow statuses at the end of the period. On the 3rd of the month, This month has barely started filling up, so a flow KPI can show Off track while it's on pace. The formula reports the ratio; whether a Watch month calls for action is your call.
Last logged and Stale: catch the KPI nobody updated
Add a Rollup property to KPIs and name it Last logged: choose the Measurements relation, the Date property and the Latest date calculation. Then add one more formula, Stale:
dateBetween(today(), prop("Last logged"), "days") > 35
It returns true when the newest reading is more than 35 days old, which suits a monthly KPI; a weekly one might use 10. today() goes first so the gap counts up as the last reading ages, and the guide to date difference formulas covers argument order and units. Both cutoffs are yours to pick. The formula can only tell you a KPI went quiet; whether it still earns its place on the page is a human decision.

How do you chart each KPI's trend?
Build trend charts on Measurements, because that's where the history lives: KPIs has one row per metric, Measurements has one row per reading. It also keeps you clear of a hard limit. Notion's charts help says the X and Y axes "won't be able to show rollups, buttons, unique IDs, files and media, or formulas resulting in a list of outputs," and that formulas based on relations and rollups may make charts slower to load. Plain dates and numbers avoid both problems.
- Open Measurements, click + next to the database or view name and select Chart. On a separate page, the
/chartcommand lets you pick a chart type and link the existing database. - In the settings menu at the top right, choose Line chart under chart type. X and Y axis settings exist only for bar and line charts.
- Under X axis, set What to show to Date and sort it ascending.
- Under Y axis, set What to show to Value and Group by to None.
- Filter the chart view to one KPI. Each KPI gets its own chart because units differ: dollars and hours on one axis make both lines unreadable.
For a flow, the Cumulative option turns the line into a running total; it appears when the chart shows Count or Sum and the X axis is sorted ascending. The style settings add data labels, a smooth line, a gradient area or grid lines. If you'd rather see one big figure than a line, Number chart sits among the five types next to vertical bar, horizontal bar, line and donut.
Three limits from the same help page shape how you use these charts:
- A chart displays up to 200 groups and 50 subgroups at a time, and Notion's own example is 200 days on the X axis. Daily readings reach that in a little over six months; weekly or monthly readings take years. Filter the view by Date to the period you review.
- You can't edit entries from a chart view. Clicking into a chart opens the underlying entries as a table, and ••• → Save as view in keeps that table.
- In a large database, a chart can be slower to update.
On Free you get one chart. The charts help says Free members "can try one chart for free," and you can delete it to create another; a template with several charts shows only one of them on Free. I'd spend that chart on the KPI you'd act on first and change its KPI filter when you want to look at another, rather than deleting and rebuilding. Notion's views and filters guide explains that a filter you don't save for everyone applies only to you, so switching it won't change what a teammate sees.
On a paid plan, one extra chart on KPIs compares every metric on a single scale: a bar chart with each KPI's name on the X axis and Progress on the Y axis. Progress returns one number per KPI, so the chart can use it, though a formula built on a relation may load a little slower.
Put the tracker on one page
| Feature | Free | Plus | Business | Enterprise |
|---|---|---|---|---|
| Charts | 1 | Unlimited | Unlimited | Unlimited |
| Database automations | Slack notifications only | Yes | Yes | Yes |
| Buttons | Yes; some actions are paid-only | Yes | Yes | Yes |
| Dashboard view | No | No | Yes | Yes |
Notion's pricing page lists 1 chart on Free and unlimited charts on every paid plan, with custom database automations starting on Plus. Per Notion's dashboards help, the Dashboard view is available on Business and Enterprise: open a database, select + Add a new view → Dashboard, or type /dash on a page. Each widget shows a database view, one dashboard can mix widgets from several databases, and it holds up to 4 widgets per row and 12 in total. For a KPI tracker, I'd put the KPIs table across the top and one line chart per KPI below it, because Status is the first thing you read and the charts explain it. Filter each chart to the months you review so it loads less data.
Two dashboard details catch teams out. Filters set in View mode stay local unless someone with edit permissions chooses "Save for everybody." A global filter only affects widgets whose views include the property you're filtering on.
On Free or Plus, a plain page does the same job: a table view of KPIs with your chart under it. In the table, use Property visibility to show Name, Current, Target, Progress, Status and Stale, and hide Latest and This month so each KPI reads in one line. For the page layout and a review habit to go with it, the project dashboard and weekly review guide shows how to arrange panels that lead to a decision.
Keep the readings coming in
A KPI tracker is only as current as its last reading, so the logging routine decides whether it works. Notion can create the reading page and remind people; typing the number stays a human job. I'd use a repeating template for weekly and monthly KPIs and a button for numbers that arrive at odd times, because a scheduled empty page is harder to forget than a reminder.
A repeating template per KPI
In Measurements, open the dropdown next to New, select + New template, and make one template per KPI with its KPI relation already filled in. Notion's database templates help warns against filling in a relation "unless you want every page you create with that template to relate to the same existing page(s)." In a KPI log, that's the goal: every New leads reading should point at the New leads KPI.
To schedule it, open the dropdown next to New, select ••• next to the template, and open the dropdown next to Repeat. Templates can repeat daily, weekly, monthly or yearly, with an interval, a start date and a time. Each cycle drops a new reading page into Measurements for the owner to fill in. Fill in its Date and Value as soon as it appears, or delete it if the period had nothing to log, because an empty page still counts as a reading for the formulas.
A button for readings that arrive whenever
A button suits KPIs you log when a number lands rather than on a schedule. Type / on the tracker page, select Button, and add the Add page to action. Notion's buttons help says this action "will add a page to a database of your choosing, and edit the properties of that page," so one button per KPI can set the KPI relation for you. In the action's fields, @ inserts a date and ∑ opens a formula, which is where today() can fill in the Date. Whoever clicks it must be an editor of Measurements. Buttons work on every plan; the actions the help page reserves for paid plans include Send mail to and Send webhook. If you're weighing a button against an automation for a given step, buttons vs database automations sorts out which trigger fits.
Reminders and notifications on paid plans
On a paid plan, click the lightning-bolt icon at the top of Measurements and choose New automation. Notion's database automations help lists the pieces a KPI log needs: a Page added or Property edited trigger, an Every {frequency} trigger for a recurring reminder, and a Send notification to action that reaches up to 20 people in your workspace. On Free, only Slack-notification automations are available.
One catch decides which logging route pairs with automations. Pages created by a repeating template don't trigger database automations, while a page created by someone clicking a button does; the automations help gives both as examples. If you want a notification each time a reading lands, log through a button, or with templates set the trigger to Property edited on Value so it fires when a person types the number in. The reasons behind the template behavior are covered in why a repeating template doesn't trigger your automation.
Fix the problems that show up first
| What you see | Usual cause | Fix |
|---|---|---|
| The chart won't offer your rollup | Chart axes can't show rollups | Chart Measurements directly, or use a single-number formula on KPIs |
| Current shows a total or the highest value | Latest was built as a rollup set to Sum or Max | Replace it with the Latest formula |
| Latest shows an old or blank reading | A reading without a Date, two readings on one date, or a scheduled page still empty | Give every reading a Date and Value; delete empty pages for periods with nothing to log |
| A rollup total doesn't match your records | A missing relation or the wrong calculation | Reconcile it with the rollup sum checklist |
| Progress is far above 1 on a lower-is-better KPI | Direction is empty or doesn't match "Lower is better" exactly | Set Direction; the select option has to match the text in the formula |
| A flow KPI reads Off track early in the month | This month restarts every month | Read flow statuses at the end of the period |
| Some KPIs are missing from the Progress chart | They're sub-items | Show sub-items as a Flattened list; see chart missing sub-items |
| You can't add a second chart | Free includes one chart | Switch the existing chart's filter, delete it to make another, or upgrade |
| No Dashboard option under Add a new view | Dashboard view needs Business or Enterprise | Use a plain page with a KPIs table and your charts |
| A teammate's dashboard filter disappeared | View mode filters are stored locally | Choose Save for everybody (needs edit permissions) |
| The chart loads slowly | A large database or a relation-based formula | Filter the chart by Date; chart Measurements fields rather than KPI formulas |
| Older points are missing from a daily chart | The 200-group cap | Filter the view to the period you review |
Should you start from a template?
Notion's template gallery has a whole KPI tracker category, and a template saves setup time if it already works the way described here. Before you duplicate one, check four things:
- Readings live in their own database, one row per reading, related to the KPI.
- The current value is calculated, not typed into the KPI page.
- On Free, it doesn't rely on several charts, since you'll see only one of them.
- If it's built around a Dashboard view, you're on Business or Enterprise.
Some guides add a third Goals database above the KPIs. For a freelancer or a small team, the Target property already does that job. I'd add Goals only when several KPIs serve one shared goal that has its own owner and deadline, because that's the point where a goal needs a page of its own.
Where to start
Build the log first and the dashboard last. Two databases, six formulas, one rollup and one chart cover what a freelancer or a small team needs from a KPI tracker, and upgrading only changes the chart count, the automations and the Dashboard view sitting on top of them. Your first step: create Measurements, log last month's numbers for your top three KPIs, add the Latest formula and check it against a number you already know. If it matches, the rest is setup. If it doesn't, you've found the problem while the log holds a few rows instead of a few hundred.