TechHive.IO

Subscribe to TechHive Insights

Our blog is young but growing. Subscribe to our newsletter to receive bi-weekly insights on design, engineering, and the startup life in general.

close
toggle-menu

TechHive.IO

hero-image

Making your blog smarter - How to implement suggestions

How to add suggestions to your NextJs Blog, powered by Contentful

One of the most effective methods for promoting your business is content creation.

You can choose between various methods and mediums through which to publish your insights.

More often than not, you'll want to choose something simple that can get you going immediately, such as Medium.

However, there's one advantage to building the blog yourself, and that is it allows you to customize the user experience.

One of the critical elements that can define your readers' experience is how they discover your content.

To do that, you must be able to suggest relevant content for your readers. You want your readers to be fully engaged and benefit to the maximum from what you are offering.

In our previous blog post, we have explored how we can build a powerful blog with NextJs and Contentful, as well as how to integrate Google analytics and to enhance your meta tags.

In this piece, we explore how we can drive the blog forward by maximizing the value and knowledge ingested by our readers. We also do not want our readers to drop-off after reading one insight or article only.

This is why, in addition to creating great content, we enhance the user experience. To do so, we make suggestions at the end of every blog post to keep the user engaged.

User Experience

When reading a blog post, the reader is usually researching information that would enrich his know-how and his knowledge.

The user also, more often than that, is interested in knowing more about the topic he is researching and is directly related in content and essence to the article he is currently reading.

So the logical and straightforward way to suggest related content is by filtering our blog posts by tags and then displaying them.

Prerequisite

In this post, we are not walking through the basics of building the blog. This post will, however, expand on the logic that we have already implemented in our previous article.

So if you didn't go through our previous blog post, you should do so before moving to this one.

Let's get started!

The blog we've built utilizes the power of tags fully. We have already labelled every blog post with a set of tags that we define in our headless CMS.

If you haven't already, I highly encourage you to do so before resuming this article.

Fetching the Suggestions

To fetch the suggestions, let's modify our contentful.ts file to include our newest function:

For our use case, we want to fetch three suggestions per post and display them at the end of the article.

Contentful provides us with many efficient ways to query our posts; in our case, by tags.

As an important note, you want to make sure to exclude from your suggestions the current post you are reading.

In theory

Let's explore how our algorithm works:

1- User is reading blog post 1
2- We defined an empty suggestions set
3- Fetch blog post 1 tags on load
4- Find 3 blog posts with at least one matching tag
5- Append your result to the suggestions set
6- If you found less than 3 blog posts
7- Then, fetch (3 - result.length) random blog posts
8- Append to suggestions set
9- Return suggestions

Step number 7 is essential, as we do not want more than 3 suggestions per post.

In implementation

To fetch each post's suggestions:

Many things are happening above.

Remember that in our previous article, we've already included filtering by tags.

Our current goal is to find at least one matching tag across all our articles and display those.

'fields.tags.sys.id[in]': tags.length ? tags.join(',') : undefined

The [in] allows us to do so, but since Contentful allows us to query by reference in our case, we need to include the ids of the tags that Contentful generates. Those can be found until the fields.tags.sys field.

What happens if we have less than 3 posts to display in the suggestions? 

In other words, if the blog post is not related to any other subject you have previously published, or you do not have enough content to display, then it is initially safe to suggest a random set of posts that the user could browse.

In this case, we query our entire posts collection randomly and append them to the original array.

Let's start off by excluding the current article (the one we want to fetch the suggestions for), from being fetched again:

'fields.slug[ne]': currentArticleSlug, // exclude current article

You also want to exclude fetching suggestions that you already fetched by tag.

'fields.slug[nin]': slugsToExclude, // exclude slugs already fetched

Finally, we append the random posts with the posts that we fetched by suggestions:

entries = [...entries, ...randomSuggestions.items];

Bonus

We include a helper function to map the data to fit out BlogPost interface

/**
 * Maps the items fetched by contentful
 * @param entries
 */
private mapData(entries): BlogPost[] {
    return entries.map(({sys, fields}: { sys: any; fields: any }) => ({
        id: sys.id,
        title: fields.title,
        description: fields.description,
        heroImage: fields.heroImage.fields.file.url,
        slug: fields.slug,
        tags: fields.tags,
        publishedAt: fields.publishDate
            ? new Date(fields.publishDate)
            : new Date(sys.createdAt),
    }));
}

Displaying the suggestions

Let's modify our pages/post/index.tsx to fetch and display the suggestions.

Let's start first by fetching the data before the view is initialized, i.e: getInitialProps:

PostPage.getInitialProps = async ({ query }) => {
  const contentfulService = new ContentfulService();

  const { post } = query;
  const article = await contentfulService.getPostBySlug(post);
  // map the tags that we have fetched from Contentful
  const tags = article.tags ? article.tags.map(tag => tag.sys.id) : [];
  // pass the tags to the function we have built
  const suggestedArticles = await contentfulService.fetchSuggestions(
    tags,
    article.slug
  );

  return { article, suggestedArticles };
};

Now that the component is receiving the suggestions, we can now display them:

// helper function to display the cards
const renderCards = suggestions =>
  suggestions.map((suggestion, index) => (
    <Card key={index} info={suggestion} />
  ));
const PostPage: NextPage = (props: Props) => {
...
   return (
...
<div className="suggestions">{renderCards(props.suggestedArticles)}</div>
...
   );
};

The final step is to fix how the cards are displayed. Under pages/post/styles.css, add the following:

...
.suggestions {
  display: flex;
  flex-flow: row;
  padding: 1.5rem 0;
  margin: 1rem auto 1rem 4rem;
  justify-content: flex-start;
}

.suggestions .card {
  margin: 0 1rem;
  height: 450px;
  width: 320px;
}

.suggestions .card:first-of-type {
  margin-left: 0;
}

Final words

Congratulations! You have successfully integrated suggestions into your NextJs Blog and powered by Contentful while utilizing the power of static websites!


Ready-made Starter Kit

To make things easier for you, we have created a starter kit that includes a template and can get you bootstrapped in no time. We even created a script to create your Contentful Content Data automatically and includes everything you have learned so far in building a great Blog.

Feel free to submit your PRs, issues and don't forget to star our repo ⭐.