Skip to content
notionsolutions

A practical library for building,
organizing and working in Notion.

Workflow guides

Notion KPI Tracker: Two Databases, Formulas and a Trend Chart

Keep one page per KPI and one row per reading. Formulas give each KPI its latest value, progress and status, a line chart shows the trend, and your plan decides how many charts you get and whether a Dashboard view is available.

Published
A row of thin white ceramic cards standing in date order on a steel rail, the newest one electric blue, beside a frosted-glass marker set at a target height
Each reading gets its own row; the newest one, set against the target, becomes the status.

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:

Example KPIs for a freelancer or small agency, with the five decisions made (targets are yours to set)
KPIUnitDirectionTypeCadenceWhere the number comes from
Revenue this month$Higher is betterFlowWeeklyPayments received that week, from your bank or invoicing tool
New leadsCountHigher is betterFlowWeeklyInquiries that reached your inbox or CRM that week
Billable utilization%Higher is betterSnapshotMonthlyBillable hours divided by available hours, from your time log
Average first-response timeHoursLower is betterSnapshotWeeklyYour help desk report, or the week's client emails
Active clientsCountHigher is betterSnapshotMonthlyClients 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

Properties for the KPIs database
PropertyTypeWhat it holds
NameTitleThe KPI, such as New leads
TargetNumberThe value you're aiming for; keep it above 0
UnitSelect$, %, Count, Hours
DirectionSelectHigher is better, Lower is better
TypeSelectFlow, Snapshot
CadenceSelectWeekly, Monthly
OwnerPersonWho logs the reading
MeasurementsRelationEvery reading of this KPI

Measurements: one row per reading

Properties for the Measurements database
PropertyTypeWhat it holds
NameTitleA short label such as Leads, week 2; optional
DateDateThe day the reading covers; for a period total, the period's last day
ValueNumberThe reading itself
KPIRelationThe one KPI this reading belongs to
NoteTextAnything 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:

  1. In KPIs, add a new property, search for Relation and choose the Measurements database.
  2. 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.
  3. Click Add relation.
  4. 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.

Diagram of a KPIs database (Target, Direction, Type, Owner) linked by a two-way relation to a Measurements database (Date, Value, KPI), with Latest, Progress and Status on KPIs
One page per KPI, one row per reading; the KPI page computes Latest, Progress and Status from its readings.

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.

The computed properties on each KPI page
PropertyKindReturns
LatestFormulaThe Value of the newest reading
This monthFormulaThe total of this month's readings
CurrentFormulaThis month for flows, Latest for snapshots
ProgressFormulaA ratio where 1 means the target is met
StatusFormulaNo data, On track, Watch or Off track
Last loggedRollupThe date of the newest reading
StaleFormulaTrue 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.

Flow diagram: the newest Measurements reading becomes Latest, Latest or the This month total for flows becomes Current, Current divided by Target gives Progress, and Progress sets Status to No data, On track, Watch or Off track
A status comes from the newest reading, or this month's total for flows, measured against the target.

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.

  1. Open Measurements, click + next to the database or view name and select Chart. On a separate page, the /chart command lets you pick a chart type and link the existing database.
  2. 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.
  3. Under X axis, set What to show to Date and sort it ascending.
  4. Under Y axis, set What to show to Value and Group by to None.
  5. 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:

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

What each Notion plan allows for the parts of a KPI tracker
FeatureFreePlusBusinessEnterprise
Charts1UnlimitedUnlimitedUnlimited
Database automationsSlack notifications onlyYesYesYes
ButtonsYes; some actions are paid-onlyYesYesYes
Dashboard viewNoNoYesYes

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

Common KPI tracker problems, their usual cause and the fix
What you seeUsual causeFix
The chart won't offer your rollupChart axes can't show rollupsChart Measurements directly, or use a single-number formula on KPIs
Current shows a total or the highest valueLatest was built as a rollup set to Sum or MaxReplace it with the Latest formula
Latest shows an old or blank readingA reading without a Date, two readings on one date, or a scheduled page still emptyGive every reading a Date and Value; delete empty pages for periods with nothing to log
A rollup total doesn't match your recordsA missing relation or the wrong calculationReconcile it with the rollup sum checklist
Progress is far above 1 on a lower-is-better KPIDirection is empty or doesn't match "Lower is better" exactlySet Direction; the select option has to match the text in the formula
A flow KPI reads Off track early in the monthThis month restarts every monthRead flow statuses at the end of the period
Some KPIs are missing from the Progress chartThey're sub-itemsShow sub-items as a Flattened list; see chart missing sub-items
You can't add a second chartFree includes one chartSwitch the existing chart's filter, delete it to make another, or upgrade
No Dashboard option under Add a new viewDashboard view needs Business or EnterpriseUse a plain page with a KPIs table and your charts
A teammate's dashboard filter disappearedView mode filters are stored locallyChoose Save for everybody (needs edit permissions)
The chart loads slowlyA large database or a relation-based formulaFilter the chart by Date; chart Measurements fields rather than KPI formulas
Older points are missing from a daily chartThe 200-group capFilter 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:

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.

Review the numbers