context-aware related posts in jekyll using liquid
Why Contextual Related Posts Improve Engagement
Most "Related Posts" systems simply match by tags or categories. While this works in many cases, it can feel too broad. A more intelligent approach is to show posts that are related based on the user's context or the post’s core theme. This increases reader retention and keeps your content experience focused.
We’ll use Jekyll’s powerful Liquid syntax to achieve context-sensitive recommendations.
Core Idea Behind Context-Aware Related Posts
Instead of relying solely on tags or categories, you can:
- Define a primary topic for each post
- Group related posts by
series,pillar, ortype - Set up fallback logic if no strong match exists
This way, you can recommend:
- Other parts of a tutorial series
- Posts targeting the same user intent
- Posts with the same use case (e.g. Jekyll for documentation)
Step-by-Step: Smarter Related Posts
Step 1: Define Contextual Fields
In your post front matter, add fields that describe context:
---
title: "Optimizing Jekyll Templates"
category: jekyll
series: "template-performance"
pillar: "layout"
type: "tutorial"
---
Repeat this for any post you want to be part of a logical group.
Step 2: Build Context Matching in Layout
We’ll match posts by series, falling back to pillar if no match is found. In your _layouts/post.html, insert:
{% assign context_series = page.series %}
{% assign context_pillar = page.pillar %}
{% assign related_series = site.posts | where: "series", context_series | where_exp: "post", "post.url != page.url" %}
{% assign related_pillar = site.posts | where: "pillar", context_pillar | where_exp: "post", "post.url != page.url" %}
{% if related_series.size > 0 %}
<div class="related-posts">
<h3>More from this series</h3>
<ul>
{% for post in related_series limit:3 %}
<li><a href="{{ post.url }}">{{ post.title }}</a></li>
{% endfor %}
</ul>
</div>
{% elsif related_pillar.size > 0 %}
<div class="related-posts">
<h3>Related posts on this topic</h3>
<ul>
{% for post in related_pillar limit:3 %}
<li><a href="{{ post.url }}">{{ post.title }}</a></li>
{% endfor %}
</ul>
</div>
{% endif %}
Step 3: Add Optional Filtering by Type
You can go further and match by a third context like post type:
{% assign related_type = site.posts | where: "type", page.type | where_exp: "post", "post.url != page.url" %}
Use this as a final fallback.
Visual Variations Based on Context
You can also dynamically change the heading or section style:
{% if page.series %}
<h3>Continue the "{{ page.series | capitalize }}" series</h3>
{% elsif page.pillar %}
<h3>Explore more on "{{ page.pillar | capitalize }}"</h3>
{% else %}
<h3>You may also like</h3>
{% endif %}
This makes the related section more personalized and relevant.
Case Study: A Jekyll Knowledge Base
Let’s say you are running a technical documentation site with categories like api-reference, tutorials, and guides. Each post can be grouped by:
- product area: auth, payment, analytics
- series: onboarding, setup, advanced
With the system above, you can easily recommend relevant articles without needing a plugin, database, or even search engine.
Advantages of This Approach
- Zero JavaScript – Works at build time, not runtime
- Highly customizable using front matter
- Works on GitHub Pages without any plugins
- More relevant suggestions for readers
Tips for Long-Term Maintenance
- Define a consistent set of
seriesandpillarvalues across posts - Use `_data/context.yml` to manage your series or topics
- Apply the same layout logic to collections (e.g. `docs`, `guides`, etc.)
Conclusion
By going beyond basic tag-matching and building a layered context-based system, you give your Jekyll blog or documentation a much more powerful user experience. It's simple, clean, and works entirely within the GitHub Pages ecosystem—no plugins or search libraries required.
In the next article, we’ll build on this and explore how to use a **centralized YAML data file** to control related post groupings across your entire Jekyll site.
