diff --git a/src/posts/2023/popular-posts-widget-using-eleventy-plausible.md b/src/posts/2023/popular-posts-widget-using-eleventy-plausible.md new file mode 100644 index 00000000..b9a42597 --- /dev/null +++ b/src/posts/2023/popular-posts-widget-using-eleventy-plausible.md @@ -0,0 +1,81 @@ +--- +date: '2023-07-12' +title: 'Building a popular posts widget in Eleventy using Plausible analytics' +draft: false +tags: ['Eleventy', 'development'] +--- +I took some time last week to build out a popular posts widget after seeing [Zach's](https://www.zachleat.com) implementation using Google Analytics. + +[Plausible offers access to an API to query and return stats collected from visitors to your site](https://plausible.io/docs/stats-api). + +My request to Plausible's API looks like this: + +```javascript +const EleventyFetch = require('@11ty/eleventy-fetch') + +module.exports = async function () { + const API_KEY_PLAUSIBLE = process.env.API_KEY_PLAUSIBLE + const url = + 'https://plausible.io/api/v1/stats/breakdown?site_id=coryd.dev&period=6mo&property=event:page&limit=30' + const res = EleventyFetch(url, { + duration: '1h', + type: 'json', + fetchOptions: { + headers: { + Authorization: `Bearer ${API_KEY_PLAUSIBLE}`, + }, + }, + }).catch() + const pages = await res + return pages.results.filter((p) => p.page.includes('posts')).splice(0, 5) +} +``` + +This is then passed to a custom filter ([based on code I originally stole from Zach](https://github.com/zachleat/zachleat.com/blob/bcce001529b7a08eadf752f62f2d8fc08798999f/_11ty/analyticsPlugin.js#L10)): + +```javascript +getPopularPosts: (posts, analytics) => { + return posts + .filter((post) => { + if (analytics.find((p) => p.page === post.url)) return true + }) + .sort((a, b) => { + const visitors = (page) => analytics.filter((p) => p.page === page.url).pop().visitors + return visitors(b) - visitors(a) + }) +}, +``` + +And rendered using a liquid template: +{% raw %} + +```liquid +{% assign posts = posts | getPopularPosts: analytics %} +
+

+ {% heroicon "outline" "fire" "Popular" "height=28" %} +
Popular posts
+

+ +
+``` + +{% endraw %} + +This can then be rendered just about anywhere using the following: +{% raw %} + +```liquid +{% render "partials/popular-posts.liquid", posts: collections.posts, analytics: analytics %} +``` + +{% endraw %} +[And can be seen on my handy, dandy 404 (or search or any post page)](https://coryd.dev/404).