All Articles

Yet Another Solution to Related Posts in Jekyll

Pages linked by a chain

When are two posts really related?

Wouldn’t it be nice for a reader landing up on a post on your website, to be able to graze and read more?

Related posts are posts that you would like to cue up for the reader to read next.

Jekyll support

Jekyll does support related posts, but it’s complicated.

For a page being processed by Jekyll, the variable site.related_posts holds up to 10 related posts. But the catch is that you need to turn on Latent Semantic Indexing (LSI) either on the command line

jekyll build --lsi

or via the _config.yml.

lsi: true

If LSI is not turned on, then site.related_posts just contains the ten most recent posts (which may or may not be related to the current post at all).

Problems

Now, if you are hosting on Github Pages, you have a problem. Github Pages does not support LSI, and in fact, overrides any settings in your _config.yml to lsi: false.

If you are hosting elsewhere, then you may have options, although site build times do increase significantly when LSI is enabled.

But there is another catch. If you have organised any content on your website, using the Jekyll collections feature, then you are out of luck. On documents in a collection, the variable site.related_posts is not defined.

Solution

Fortunately, there are several solutions available. For example, one solution uses recent posts in the same category as the current post, while another solution uses the number of common tags and/or categories between posts to suggest related posts. Both of these can be adapted to work with collections as well.

I adapted the former solution, but instead of recent posts, I use a random sample of posts from the same collection. Here’s how it works:

{% assign posts = site[page.collection] | sample:4 %}
{% for post in posts %}
  {% include archive-single.html type="grid" %}
{% endfor %}

The include parameters archive-single.html and type="grid" are just used to render the post teaser image and excerpt. You can replace that by an equivalent include of your own.

But this can result in suggesting the current page itself, as related. To prevent this from happening, you just need to check if a candidate post is the same as the current page or not, before adding it to the list of related posts.

{% assign posts = site[page.collection] | sample:5 %}
{% assign relatedCount = 0 %}
{% for post in posts %}
  {% if post.url != page.url %}
    {% include archive-single.html type="grid" %}
    {% assign relatedCount = relatedCount | plus: 1 %}
    {% if relatedCount >= 4 %}
      {% break %}
    {% endif %}
  {% endif %}
{% endfor %}

By replacing site[page.collection] by site.categories[page.categories[0]], this can be adapted to work with categories too.

That concludes how I rolled out yet another solution for related posts in Jekyll.