How to add related posts links to your WordPress site (without a plugin)

If you scroll down to the bottom of this post, you’ll see above the comments section an aside displaying three other posts on my blog related to the topic we’re discussing here. This can be an affective way to keep people on your site as well as automatically adding some internal linking, both of which are great for SEO.

First, let’s look at the plain markup before adding in our code. You’ll see it’s a simple aside element, a header, and three title headers. How you markup your section is up to you. I’m using H3’s but you may want to use an unordered list, both of which are semantically acceptable options.


<aside class="more-posts"><h2>You might also like...</h2>
  <h3><a href="#">Post tile #1</a></h3>
  <h3><a href="#">Post tile #2</a></h3>
  <h3><a href="#">Post tile #3</a></h3>
</aside>

Next, we need to add our code. If you’re not familiar with the wp_query function, consult the WordPress Codex.

Let’s start with a basic loop to get started:


<aside class="more-posts">

  <h2>You might also like...</h2>

  <?php
  $args = array(
    'posts_per_page' => '3'
  );
  $query = new WP_Query( $args );
  ?>

  <?php if ( $query->have_posts() ) : ?>
  <?php while ( $query->have_posts() ) : $query->the_post(); ?>

  <h3><a href="<?php the_permalink(); ?>" ?>"><?php the_title(); ?></a></h3>
 
  <?php endwhile; ?>
  <?php endif; ?>

  <?php wp_reset_postdata(); ?>

</aside>

Lookin’ good, but this will display the three most recently published posts regardless of category. We need to display the three most recent posts based on similar category while omitting the post you’re actually reading.


<?php $orig_post = $post;
  global $post;
  
  $categories = get_the_category($post->ID);
  
  if ($categories) {
    $category_ids = array();
    foreach($categories as $individual_category) $category_ids[] = $individual_category->term_id;
    
  $args=array(
    'category__in' => $category_ids,
    'post__not_in' => array($post->ID),
    'posts_per_page'=> 3,
    'caller_get_posts'=>1
  );
  
  $my_query = new wp_query( $args );
  
  if( $my_query->have_posts() ) {
    echo '<aside class="more-posts"><h2>You might also like...</h2>';
      while( $my_query->have_posts() ) {
        $my_query->the_post();?>
        <h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
	<? }
          echo '</aside>';
      }
    }
  
  $post = $orig_post;

  wp_reset_query(); ?>

Voila.

Now, when using it in your theme, you can add this where you want it to appear in your single.php template file, but I recommend saving it in an include file and calling it with the get_template_part function in case you wish to use it elsewhere in your theme, which is more efficient for future maintenance.

Save your file as moreposts.php in your theme folder and add the following to your theme files where you wish it to appear:


<?php get_template_part( 'moreposts' ); ?>

Plugin alternatives

I’m always a fan of not using a plugin whenever possible because plugins can unnecessarily weight down your site, which isn’t ideal for performance. But you may not be comfortable with working directly with code so a plugin is your only practical option. Here are some suggestions. I’ve used each of these with varying degrees of satisfaction, so be thorough when selecting your solution!

Have fun!

Discussion

Please note that while I am available to respond to requests for assistance, my work schedule doesn't always permit me to respond immediately.