Popular Posts
I’ve gone back and forth about whether adding analytics to my blog for a while now. Recently I added a privacy focused analytics solution with Umamai that allowed me to add a new feature to my site.
Personally, I think website analytics have gotten a bad rap. At their core, analytics are a way to get feedback on the performance and reach of our sites. We spend a lot of time building these sites and their content, it’s only natural that we’d want to know if anyone else is interacting with them.
If I was going to add analytics, they need to satisfy a few requirements:
- Respect my reader’s privacy
- Free of cookie banner requirements
- Open-source and maintainable
- API to access the data
- Easy to setup
Fortunately, Umamai meets all of these needs quite nicely.
Setup
Setup with Umamai is pretty easy. There is a self-hosted open source solution or a reasonably priced cloud solution. Since this is only a hobby project, the free tier of cloud hosting worked for me.
Once our account is setup, we get access the the dashboard. Setting up a website
will give us access to a website ID that we’ll need for adding website tracking.
Drop the little script into your <head>
and we’ll soon be seeing metrics in
our website dashboard.
<script
defer
src="https://cloud.umami.is/script.js"
data-website-id="xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
></script>
Page Stats
Now that we have the metrics in place, it would be nice to have a way to download the website metrics for use with our site. Fortunately, Umamai has an API that allows us to do just that.
I use a Makefile locally to handle various project related tasks but the same strategy could be applied with other methods.
# Get the timestamp for now in milliseconds
endAt = $(shell echo $$(( $(shell date +%s) * 1000 )))
# Get the timestamp for 30 days ago in milliseconds
startAt = $(shell echo $$(( $(endAt) - 2592000000 )))
.PHONY: stats
stats:
curl -H "Accept: application/json" -H "x-umami-api-key: ${UMAMI_API_KEY}" \
"https://api.umami.is/v1/websites/${UMAMI_WEBSITE_ID}/metrics?startAt=$(startAt)&endAt=$(endAt)&type=url" \
> assets/data/stats.json
With this added to a local Makefile I can simply type make stats
and it will
drop my stats for the last 30 days right into my site’s data folder.
[
{ "x": "/blog/great-sanddunes/", "y": 75 },
{ "x": "/blog/unplugged/", "y": 66 },
{ "x": "/", "y": 23 },
{ "x": "/blog/", "y": 3 },
{ "x": "/blog/indieweb/", "y": 1 },
{ "x": "/subscribe/", "y": 1 }
]
Popular Posts
Now that the page metrics are in place, we can use them to generate a list of popular posts for people to read. I use Hugo for my site so here is an example of mapping the metrics to the blog pages and displaying the top 3 most popular links.
{{- $data := dict }}
{{- $path := "data/stats.json" }}
{{- with resources.Get $path }}
{{- with . | transform.Unmarshal }}
{{- $data = . }}
{{- end }}
{{- else }}
{{- errorf "Unable to get page stats resource %q" $path }}
{{- end -}}
<h2>Popular Posts</h2>
<ul>
{{- range $index, $entry := $data }}
{{- if le $index 3 }}
{{- $matches := strings.FindRE `\/blog\/.+\/` $entry.x }}
{{- if gt (len $matches) 0 }}
{{- with site.GetPage $entry.x }}
<li><a href="{{ .Permalink }}">{{ .Title }}</a></li>
{{- end }}
{{- end }}
{{- end }}
{{- end }}
</ul>
Now we can include this partial anywhere we want to get a list of popular posts for my site. You can see it in action at the bottom of this post.
Updating the List
My blog is a static site, so the popular post list will only update when I update my site. If I posted more regularly, I could probably rely on updating the metrics on every build. Since I tend to post infrequently, I’ll probably look into setting up a job to perform a site build once a day to keep things fresh.