Display Plausible Statistics in Your 11ty Blog
How to display popular and trending blog posts using Plausible Analytics and 11ty. Follow this step-by-step guide for seamless API integration.
# Introduction
Highlighting your most popular and trending posts is a great way to engage readers and showcase your best content. In this guide, I’ll walk you through how I implemented this feature for my blog using the privacy-friendly Plausible Analytics.
# Table of Contents
# Why Use Plausible Analytics?
- Data Privacy: Unlike other analytics platforms, Plausible values privacy, ensuring compliance with GDPR, CCPA, and other regulations.
- API-Driven: Its developer-friendly API provides easy access to site metrics such as page views.
- Lightweight Integration: Ideal for static site generators like Eleventy, allowing minimal overhead.
I have been using Plausible since 2020 so I have 4 years of analytics in one place.
# Steps to Display Popular and Trending Posts
# Calling the Plausible API
To fetch statistics from Plausible, you'll need:
- API Key: Obtain this from your API Settings page.
- Site ID: This corresponds to the domain name you registered with Plausible (e.g.,
jjude.com
).
I opted to use the 11ty Fetch plugin to cache the results. Below is the function to fetch stats from Plausible (plausible.mjs
file):
async function fetchPlausibleData(params) {
const PLAUSIBLE_API_KEY = process.env.PLAUSIBLE_API_KEY;
const SITE_ID = process.env.PLAUSIBLE_SITE_ID;
const PLAUSIBLE_API = 'https://plausible.io/api/v2/query';
const options = {
fetchOptions: {
method: 'POST',
headers: {
'Authorization': `Bearer ${PLAUSIBLE_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ ...params, site_id: SITE_ID })
}
};
try {
return await EleventyFetch(`${PLAUSIBLE_API}`, options);
} catch (error) {
console.error(`Error fetching data: ${error.message}`);
return { results: [] };
}
}
Use environment variables to keep your API key and site ID secure. Add these to your .env
file:
PLAUSIBLE_API_KEY=
PLAUSIBLE_SITE_ID=
# Fetch All-Time Popular Posts
You can fetch the top 10 posts with the following parameters:
const allTimeData = await fetchPlausibleData({
metrics: ["pageviews"],
dimensions: ["event:page"],
date_range: "all",
order_by: [["pageviews", "desc"]],
pagination: { "limit": 10 }
});
# Creating an 11ty Collection
To dynamically link post slugs to titles, we can create an 11ty Collection. This allows us to loop through all posts, filter the results, and maintain a mapping of slugs to titles. Add the following to your plausibleStats
collection in .eleventy.js
:
eleventyConfig.addCollection("plausibleStats", async (collectionApi) => {
let slugToFileMap = {};
// Map slugs to post titles
collectionApi.getAll().forEach(item => {
const slug = item.data.slug || slugifyFilter(item.fileSlug);
slugToFileMap[slug] = item.data.title || slug;
});
const data = await getPlausibleStats(slugToFileMap); // Fetch stats
return data;
});
# Mapping Slugs to Titles
Since the Plausible API provides URLs but not titles, a custom mapping is required. For example:
/blog/intro-to-cloud
→ "Introduction to Cloud"/travel/beach-trip
→ "Beach Trip Highlights"
Use the following utility function to transform results (in plausible.mjs
):
const transformResults = (results) => {
return results.map(result => {
const pagePath = result.dimensions[0];
// get the last segment
const slug = pagePath.split('/').filter(Boolean).pop();
return {
title: slugToFileMap[slug] || slug,
slug: pagePath,
pageviews: result.metrics[0]
};
}).filter(item => item.title);
};
let allTime = transformResults(allTimeData.results);
If you want to fetch other stats like for past 7 days, you can do that too. Here I've shown only for allTime
popular posts.
# Displaying Posts with Templates
To render the fetched data on your blog, insert the statistics into your Nunjucks template:
<ul>
{% for post in collections.plausibleStats.allTime | limit(5) %}
<li>
<a href="{{ post.slug }}">
<strong>{{ post.title }}</strong> ({{ post.pageviews }} views)
</a>
</li>
{% endfor %}
</ul>
This will display the top 5 posts with clickable links and their respective page views.
# Limitations
- Build-Time Updates: The data fetch happens only during the build process, so statistics won’t refresh in real-time.
- Error Handling: I've not shown error handling in these blocks of code. Handle errors appropriately.
Under: #11ty , #code