Want to track your habits in Notion? You’re in luck – and you have options.
In this post, I’ll show you how to can build a habit tracker in Notion at five different levels of complexity.
We’ll start from the absolute basics, building a habit tracker that uses nothing but checkboxes. From there, we’ll slowly add more of Notion’s different blocks to add new features – first adding a Button to create new habit journal entries in a single click, and then branching into Notion databases to add extra features.
In this article, I’ll give a brief explanation of how each level works. If you’d like to build one of them for yourself, you can follow along step-by-step with me in the video above.
Free Habit Tracker Template
In addition to this tutorial, I’ve also put together a free Notion template containing each of the five habit trackers. I’ve also included some bonus resources, including a database of alternative habit-tracking apps, along with links to some Notion chart tools you can optionally connect to your habit tracker.
You can get the template for free and join my Notion Tips newsletter below – once you sign up, I’ll also send you all of my other free Notion templates, along with other cheat sheets and resources.
Level 1: Habit Checklist
At Level 1, we have the simplest “habit tracker” possible – it’s just a checklist!
I’ve included this level because my friend Matt D’Avella actually uses reusable checklists in his life. He opens up a saved checklist, checks off the items as he does them, and then unchecks the whole list manually once he’s done.
(I once made a video with a Hollywood-level intro sequence just to convince him to move to Level 2).
If you’d like to keep things as simple as Matt, it’s easy to do in Notion:
- Create a Checkbox block with
/checkbox
, or with the shortcut[]
(type aspace
afterward) - Make as many checkboxes as you need
The downside of this method is that, like Matt, you have to manually uncheck the boxes to re-use them. I think we can do better, so let’s head up to Level 2.
P.S. – Not sure what a block is? In a sense, nearly everything in Notion is made up of blocks – so they’re important! Check out my guide to them:
Level 2: Habit Journal Button
Notion’s Button block can add useful buttons to your workspace that can trigger automations when you click them. A Button can:
- Insert blocks in the current page
- Add pages to a database
- Edit existing database page properties
- Show a confirmation message
- Open a specific page
That first capability gets us to Level 2. Inside a Button, you can add a collection of blocks that makes up a daily habit log entry.
Each day, you can click the button to create a new entry on the current page. Then you can check off the habits as you do them.
Unlike Level 1, this method gives you a historical record of your habit-tracking efforts. This method is also very simple and easy to maintain. Want to add a new habit? Just open the Button settings and add it to the checklist. You’ll it included each time you click the Button from then on.
However, there are still a couple of downsides to this method:
- You have to remember to click the Button each day. If you don’t, you simply won’t have a log for that day – so you won’t know for sure whether you did each habit, or skipped it.
- There’s no way to track stats over time using this method. It’s a simple page, filled with checklists that are separated by date headers.
We can eliminate these downsides, at the cost of some additional setup complexity, by moving up to Level 3.
Level 3: Habits Database
We’re now abandoning the Checkbox blocks in favor of something a bit more capable – Notion databases.
By building your Level 3 habit tracker with a database, you gain a few new advantages. Most importantly, you can now use Repeating Templates in our database to ensure a new habit journal entry gets created every day. It’ll happen automatically, on a schedule, so you don’t even have to remember to do it!
Using a database also means you can now used Linked Database Views to show your habit tracker anywhere else in your Notion workspace – e.g. you could embed a view of it on a daily planning dashboard, like the one that comes built into Ultimate Brain.
Finally, setting up a database sets you up for the additional features you can add at Level 4 and Level 5.
Here’s a brief overview of how you can set up a Notion database for habit-tracking:
- Create a Checkbox property for each habit
- Show each of those Checkbox properties in whichever database layout you choose to use (I recommend either Table or Gallery)
- Create a database template for each day’s log, then set that template to repeat daily
- Each day, you’ll see a new entry. Check off your habits as you complete them.
I’ve linked to a few reference pages and sections on my site for some of these features, but you can also see exactly how I set them up in the video above.
Level 4: Adding a Day Score
At Level 4, we continue building upon the database structure from Level 3.
The only thing we’re adding here is a Day Score property, which will show you each day’s habit completeion percentage.
It even includes a cool-looking progress bar!
You can add this by creating a Formula property in your database, naming it Day Score. This property will create a score by getting the average of all your habits, assuming a checked-off habit is worth 1 point, and an unchecked habit is worth 0 points.
Remember the method for getting the average (or mean) from a group of numbers:
\(\text{Average} = \frac{{\text{Sum of all data points}}}{{\text{Number of data points}}}\)We can get the average of all the habit scores by:
- Convert each habit Checkbox property’s boolean (e.g. true/false) value to a number (e.g. 1/0)
- Add all those numbers up
- Divide by the total number of habits
- Round the answer to get a nice percentage
Here’s an example formula, using the habit properties that are present in Level 4 of my free habit-tracking template (linked above):
round((
prop("Protein Shake").toNumber() +
prop("Go for a Run").toNumber() +
prop("Read 20 Mins").toNumber() +
prop("Close Apple Watch rings").toNumber() +
prop("Drink Water").toNumber() +
prop("Cook Dinner").toNumber()
) / 6 * 100) / 100
Code language: JavaScript (javascript)
Keep in mind that this formula will only work in your database if you have Checkbox properties that match these names!
I’m also using the round()
function, along with a trick to round the answer to two decimal places. You can learn how that trick works in my round function reference.
Want to learn Notion formulas from scratch? My team and I have written the internet’s most comprehensive guide on them:
Level 5: Streak Tracking
In the previous level, we added a Day Score property that gives you an average score for each day. Now, let’s take things to the next level and add streak tracking for your individual habits.
This is only natively possible in Notion now that they’ve released their new Formulas 2.0 language, which adds several new data types and a massive number of new functions to the formula language.
These new functions can access the properties of pages within a database Relation, manipulate Lists (e.g. arrays), and more – everything we need to track habit streaks.
Here’s a quick rundown of how you can actually build streak tracking into your Notion habit tracker. First, you need to create a secondary database – in the video above, I create on called Stats.
Within Stats, I added a single database page, also called Stats. These names don’t matter, but what does matter is that you create a Relation between this database and your Habits database, and then make sure every Habit page is related to the Stats page.
In doing this, you set up the Stats page to act as what I call an aggregator.
An aggregator is a page that is Related to every page in another database; this relation allows you to write formulas that can pull information from any or all of those pages.
This is, essentially, a trick that lets you write database queries in Notion. You could also think of it like doing a range calculation in Excel. Outside of using the Notion API to build an external integration, this is the only method of writing queries against a Notion database.
To ensure that all new Habit pages are related to this aggregator page, you can set up filters in your Habit database views to act as forcing functions, auto-applying the page relation. You can also also set up a database template that has the relation already set, then set that template as the default template in your Habits database. As noted in Level 3, I also recommend setting this template to repeat on a daily basis.
Once this aggregator setup is complete, you can add a Formula property for each habit to the aggregator page in the Stats database.
Here’s a look at the formula I built to show the streaks from my Drink Water habit. I’ve added comments explaining what each part of the formula does; if you’d like to understand it even further, I recommend watching the Level 5 section of the video tutorial above!
/* lets() sets multiple variables. We'll use it to get all of the streaks, then the current and longest streak, then set formatting variables. */
lets(
streaks,
/* Access the Habits Relation-type property to get all related pages from the Habits database. Sort them by their Date property. Reverse the sorted List so the latest date is first. Next, map through all the Habit rows in the sorted List to export a new List that contains the Checkbox (Boolean) values of the "Drink Water" property. Slice the List to exclude the latest date. Map through the List to convert the Boolean values to Numbers. Join the List into a single String. Split the String by "0" to create a List of Strings. Map through the List to get the length of each String. */
prop("Habits").sort(current.prop("Date"))
.reverse().map(current.prop("Drink Water"))
.slice(1)
.map(current.toNumber())
.join("")
.split("0")
.map(current.length()),
currentStreak,
/* Get the first element of the List of streaks. */
streaks.first(),
longestStreak,
/* Get the maximum value of the List of streaks. */
streaks.max(),
csFormat,
/* Ifs statement to determine the formatting variables for the Current streak. Sets both the color of the streak and plurality of the word "day(s)". */
ifs(
currentStreak < 1,
["red"," days"],
currentStreak == 1,
["blue", " day"],
currentStreak > 1,
["green", " days"]
),
lsFormat,
/* Get the same formatting variables for the Longest Streak. */
ifs(
longestStreak < 1,
["red"," days"],
longestStreak == 1,
["blue", " day"],
longestStreak > 1,
["green", " days"]
),
/* Construct a final string, which displays the streak counts with styleing, and which will be returned from the lets() function. */
"💧 Water: " + (
"Current: " + currentStreak + csFormat.at(1)).style(csFormat.at(0), csFormat.at(0) + "_background", "c", "b"
) + " " + (
"Longest: " + longestStreak + lsFormat.at(1)).style(lsFormat.at(0), lsFormat.at(0) + "_background", "c", "b"
)
)
Code language: JavaScript (javascript)
I’ve also created a Notion Formulas 2.0 masterclass video that you can use to understand Notion’s formula language even better:
If you don’t want to miss new Notion tutorial videos when I publish them, you can subscribe to my channel!
Finally, I’d recommend grabbing the free template above, duplicating it, and simply playing around with the formula properties in the Level 5 habit tracker if you’d like to truly understand them. Here’s a good challenge: How would you return the total number of times you’ve missed the habit?
In truth, using database properties to represent individual habits is not the way you’d do things if you were building a habit tracker app, using actual code and an underlying database.
Instead, you’d create a structure involving at least two unique database tables. I’ll call these:
- Habits
- Habit Log
The Habits database table would contain a list of each habit you wanted to track, e.g.:
- Drink Water
- Lift Weights
- Read for 20 Minutes
You’d then created a Habit Log table, where each entry represents a single habit being done on a single day. So if you have three habits in your Habits table, you’d have three entries per day in the Habit Log database.
This database’s properties would be (at minimum):
- ID (primary key)
- Habit (foreign key relation to the Habits table for the habit being tracked)
- Done (boolean)
- Date
With this structure in place, you’d be able to write database queries and build UI in order to create a habit tracker that has all the features you’d expect.
It’d be much easier to add new habits and delete old ones, and you’d also have an easier time creating reports – such as a report showing your completion data for the previous week.
Technically, you can create a setup like this in Notion. I’ve set up a proof-of-concept page that you can duplicate, which does just that.
Unfortunately, Notion just doesn’t give us the final pieces of the puzzle needed to make this type of setup work really well. As you’ll see in the proof-of-concept, the structure is there – but all the stat-tracking is necessarily separated from the Habit Log. Streaks are off in the Habits table, while Day Scores are only visible in the Journal. We could technically bring streaks to the Habit Log, but there’s not really a feasible way to bring the Day Score over.
You could almost fix this if you upgraded to a paid Notion account and used database automations feature within the Journal database. It’d work like this:
- When a new Journal entry is created for the current date, automations would kick in to create a new Habit Log row for each habit. These would be related not only to their page from the Habits database, but to the new Journal entry as well.
- The Habit Log row would pull the date from the related Journal entry, rather than having its own Date property.
- This would allow the Journal entry page to show the current day’s habits in a linked view.
But there’s a big snag; database automations currently don’t trigger in response to pages created by repeating templates, so the Habit Log entries wouldn’t be created. If automations did trigger in this way, I think that would mostly solve the problem… but only for people using paid accounts.
These are the kinds of problems that keep me up at night 🙃
I could write more about this problem than the rest of the aritcle’s length would take up, so I’ll restrain myself and end this little exploration here. The bottom line is that I don’t think Notion is ready for this type of habit-tracking setup. Once it is, this setup will be the ideal one.
More Resources
Habit-tracking isn’t the only thing you can do with Notion – in fact, it’s not even Notion’s strongest use case. I find Notion to be even better for managing tasks, taking notes, and organizing resources I collect from the web.
You can easily add all of these powerful workflows to your own Notion workspace with my Ultimate Brain template. It’s a complete, done-for-you system with a task manager, note-taking system, goal tracker, and more – plus useful dashbaords for daily planning and quick-capture.
Want to turn Notion into a complete productivity system? Ultimate Brain includes all the features from Ultimate Tasks - and combines them with notes, goals, and advanced project management features.
In our customer community, you’ll even find a tutorial for integrating the free habit tracking templates I shared above into Ultimate Brain – so you have the option of tracking habits in it as well!
For even more Notion tutorials and tricks, check out these guides: