Related Posts Plugins are very popular as a method for WordPress users to display related content at the end of their posts, providing the reader with additional relevant content. Typically, related posts plugins use Post Tags to compare posts and find those that are related to the currently displayed post. The problem with this method is that it doesn’t work for any post type that doesn’t use Post Tags or that has custom taxonomies.

[box style=”notice”]You may download the plugin version of this tutorial for free here[/box]

So what we are going to do here is write a simple plugin that will greatly improve the relevancy of our related posts. We are also going to make it possible to utilize custom taxonomies as a comparison tool.

Because we are going to be using custom taxonomies as our comparison base, we will use the tax_query parameter of query_posts. This parameter is rather complex, so I’m not going to go into detail about it, but you can read my tutorial at WP Mods for a more detailed explanation.

1 – Setup The Plugin File

Our plugin is going to consist of just a single file with just one function inside of it. First, we need to define the plugin header:

1
2
3
4
5
6
7
8
/*
Plugin Name: Related Posts by Taxonomy
Plugin URI: http://pippinspages.com/related-posts-by-taxonomy
Description: Adds a related posts section to your posts that displays those related by custom taxonomies
Version: 1.0
Author: Pippin Williamson
Author URI: http://pippinspages.com
*/

This simply tells WordPress about our plugin.

2 – Begin Our Related Posts Function

Defining our function is simple, just the function name and one parameter.

1
2
3
function pippin_related_posts($taxonomy = '') {
    // our function code will be here
}

3 – The Body of Our Function

The rest of the code for our function will replace

// our function code will be here

We will begin by defining a global variable for the $post object, a default taxonomy of Post Tags, and we will also retrieve a list of all of the terms set to our current post.

1
2
3
4
5
global $post;
 
if($taxonomy == '') { $taxonomy = 'post_tag'; }
 
$tags = wp_get_post_terms($post->ID, $taxonomy);

A very important next step is to include a condition check that will cause the next couple of steps to only run if the wp_get_post_terms() function does not return empty.

1
2
3
if ($tags) {
   // the next couple of steps go in here
}

We now have a variable called $tags that is holding all of the terms applied to the current post. The next step is to setup the arguments that we will pass to our get_posts() function, which will query the posts that are considered related.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$first_tag 	= $tags[0]->term_id;
$second_tag = $tags[1]->term_id;
$third_tag 	= $tags[2]->term_id;
$args = array(
	'post_type' => get_post_type($post->ID),
	'posts_per_page' => 4,
	'tax_query' => array(
		'relation' => 'OR',
		array(
			'taxonomy' => $taxonomy,
			'terms' => $second_tag,
			'field' => 'id',
			'operator' => 'IN',
		),
		array(
			'taxonomy' => $taxonomy,
			'terms' => $first_tag,
			'field' => 'id',
			'operator' => 'IN',
		),
		array(
			'taxonomy' => $taxonomy,
			'terms' => $third_tag,
			'field' => 'id',
			'operator' => 'IN',
		)
	)
);

Notice that I have setup three variables, one for each of the first three tags (or terms) applied to the post. These three tags are how we will consider a post to be related. In order to find the related posts, or others that have the same tags applied to them, I have setup a rather complex tax_query that makes the get_posts() function only look for posts that have these tags. As I mentioned above, the tax_query parameter is rather complicated, so please read the articles linked at the top for more info.

The next step is to setup the actual get_posts() call, which will display our related posts.

1
2
3
4
5
6
7
8
9
10
11
12
 
$related = get_posts($args);
if( $related ) {
	$temp_post = $post;
		foreach($related as $post) : setup_postdata($post);
			$content .= '<ul class="related-posts-box">';
				$content .= '<li><a href="' . get_permalink() . '" title="' . get_the_title() . '">' . get_the_title() . '</a></li>';
			$content .= '</ul>';
 
		endforeach;
	$post = $temp_post;
}

Notice how I have setup a temporary variable called $temp_post and set it equal to $post, and at the end of the foreach loop I have reset the $post variable back to its original state by setting it equal to $temp_post. This is very important because it ensures that we don’t cause any conflicts with the currently displayed post’s content.

Now, there is just one more step in the function writing process. Put this next line after the closing } of the if ($tags conditional check.

1
return $content;

That’s it!

3 – Our Final Plugin Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/*
Plugin Name: Related Posts by Taxonomy
Plugin URI: http://pippinspages.com/related-posts-by-taxonomy
Description: Adds a related posts section to your posts that displays those related by custom taxonomies
Version: 1.0
Author: Pippin Williamson
Author URI: http://pippinspages.com
*/
 
function pippin_related_posts($taxonomy = '') {
 
global $post;
 
if($taxonomy == '') { $taxonomy = 'post_tag'; }
 
$tags = wp_get_post_terms($post->ID, $taxonomy);
 
	if ($tags) {
		$first_tag 	= $tags[0]->term_id;
		$second_tag = $tags[1]->term_id;
		$third_tag 	= $tags[2]->term_id;
		$args = array(
			'post_type' => get_post_type($post->ID),
			'posts_per_page' => 4,
			'tax_query' => array(
				'relation' => 'OR',
				array(
					'taxonomy' => $taxonomy,
					'terms' => $second_tag,
					'field' => 'id',
					'operator' => 'IN',
				),
				array(
					'taxonomy' => $taxonomy,
					'terms' => $first_tag,
					'field' => 'id',
					'operator' => 'IN',
				),
				array(
					'taxonomy' => $taxonomy,
					'terms' => $third_tag,
					'field' => 'id',
					'operator' => 'IN',
				)
			)
		);
		$related = get_posts($args);
		if( $related ) {
			$temp_post = $post;
				foreach($related as $post) : setup_postdata($post);
					$content .= '<ul class="related-posts-box">';
						$content .= '<li><a href="' . get_permalink() . '" title="' . get_the_title() . '">' . get_the_title() . '</a></li>';
					$content .= '</ul>';
 
				endforeach;
			$post = $temp_post;
		}
	}
	return $content;
}

4 – Displaying Our Related Posts

To display the related posts, place this inside your single.php loop:

1
echo pippin_related_posts();

This will display an unordered list of four related posts.

If you want to display posts related by a custom taxonomy, such as “Genres”, then you can do this:

1
echo pippin_related_posts('genres');

If coding isn’t quite your thing, you can download the complete plugin for free here.

  1. Emile Jobity

    awesome very helpful indeed. thanks.

    • Pippin

      @Emile – Excellent. Glad it was helpful.

  2. Sophia Kaylee

    This post really help to me to create custom tags in WordPress thanks

  3. Miha

    Hi,
    Great plugin!

    i would like to modify it in a way to use more than one taxonomy as related post filter…

    Also as a suggestion, I would give a visitor an option to “checkbox” select which taxonomies want to be included in the related posts…

    Lets say user is viewing the post with taxonomies (car type, brand,condition etc)
    1. By default (show all or, all checked checkboxes) it should show all related posts to all taxonomies of current post (even better would be if this could also be specified in options, so we could select which taxonomies to use as related)

    2. Visitor should be able to “uncheck” the taxonomy that they don’t want to use in related posts, so when the Post from taxonomies “Car – Ford – new” is viewed, user should be able to “uncheck” – condition taxonomy and get also used cars related to this post…

    – Also using post type with custom taxonomies as filter for related posts would be great feature!

    Hope you see it useful and it will be done.. if not, could you please point me where to start to achieve this?

    Thanks!
    cheers!

    • Pippin

      The tax_query parameter for WP_Query allows you to query on multiple taxonomies, so you will want to use that. Note: querying by multiple taxonomies has a significant impact on performance.

  4. George Stephanis

    Instead of hardcoding and expecting at least three array indices in the tags, maybe iterate through and use all of them like — (I also added post__not_in to omit the original from being related to itself)


    if ( $tags = wp_get_post_terms( get_the_ID(), $taxonomy ) ) {
    $args = array(
    'post_type' => get_post_type( get_the_ID() ),
    'post__not_in' => array( get_the_ID() ),
    'posts_per_page' => 5,
    'tax_query' => array( 'relation' => 'OR' ),
    'orderby' => 'rand',
    );
    foreach ( $tags as $tag ) {
    $args['tax_query'][] = array(
    'taxonomy' => $taxonomy,
    'terms' => $tag->term_id,
    'field' => 'id',
    'operator' => 'IN',
    );
    }
    }

    • Pippin

      Nice enhancement, thanks ๐Ÿ™‚

    • Miguel

      Hello,

      I’m trying to implement this because it seems to be a cleaner version, but without luck… Can you provide the full code? Thanks

  5. hiphopinenglish

    Hi Pippin.
    Great work here, thanks. One question: How can I split up line 14 to include my taxonomy (which is the only form of tagging posts I use on a custom post type) and ‘post_tag’, used on normal post types, to which my custom taxonomy also applies.
    Complicated?
    To be clear:
    I have a custom taxonomy ‘hhie_artists’ which is used on ‘posts’ and CPT ‘hhie_artists’. ‘hhie_lyrics’ only uses ‘hhie_artists’ (no tags), but normal posts in category “Releases” use ‘hhie_artists’ AND tags. I would like to incorporate `$taxonomy = ‘post_tag’ && ‘hhie_artistsยด if this is possible.
    Thanks. Joe

    • Pippin

      Joe, I”m sorry but I don’t understand your question ๐Ÿ˜€

  6. hiphopinenglish

    I knew I’d worded that badly! What I would like is to incorporate a Custom Taxonomy and regular Post Tags as our related terms. This is because one of our CPTs only uses a custom taxonomy (no post tags), and our “normal Posts” use the custom taxonomy AND post tags. Does this make more sense?

    • Pippin

      Yes, that makes sense ๐Ÿ™‚ All you need to do is set the relation to “AND”:

      'relation' => 'AND'
      
  7. Tom

    Hi Pippin,

    I attempted to use this without the plugin. With the plugin and I am receiving this error: “Fatal error: Cannot use object of type WP_Error as array in”.

    My goal is to show related tags from my custom taxonomy “intags” and for my custom post type “insights”. I added “intags” to the first line of your code and when I echoed out the function I added “insights” as per you example. Any thoughts?

  8. Miha

    I tried to create a widget with options to select “category or tag” as first taxonomy AND “custom taxonomy” for second one (if empty only first should be used for relation)…

    It could then show posts from same category AND with same custom taxonomy, in my case I would like to display posts from same category on the same location * custom taxonomy.

    It doesn’t seem to be so complicated to achieve this, but I still had no luck.

    Any help?

    Thank you!

    • Pippin

      Can you show me some of the code you have?

  9. Bibiana

    Hi Pippin! Thanks for your help with this plugin!

    But is there some way that I can get the terms from more than one taxonomy?
    I have multiple taxonomies incorporated with posts, and I would like to show related custom post types (multiples). Its working fine with one taxonomy, but I need it with more than one.

    Let me made an example:
    My taxonomies are: t-web, t-world, t-brand, etc…
    And my custom post types are: p-books, p-movies, p-games, etc…
    I would like to show related products (p-books, p-movies…), from post terms (t-web,t-world), but I just can make it works with ONE taxonomie (t-web) search.

    I tried: function pippin_related_post ($taxonomy = array (‘t-web’,’t-world’))
    but didnt work (and I’m not very good with php). Can it be done??

    Thanks anyway!

    • Pippin

      No, sorry, that’s not possible with this plugin / tutorial.

  10. Renee

    Hey Pippin, nice plugin. Working perfectly! I want to add the term name above the related items, e.g. See more $first_tag_name items. I can get the id # by adding $first_tag there but have tried everything to get the name and am stumped. Any ideas?

    Thanks, R

    • Pippin

      Can you show me the complete code you have?

  11. papuapost

    Hi Pippin,

    I got this plugin and used in my theme, and it works perfectly well. I just want to say thank you in this email. I have been looking for this for a long time.

    Thank you.

  12. Miguel

    This plugin throws a lot of errors with WP_DEBUG on. Should I be concerned?

    • Pippin

      What is the error?

  13. JD

    Wow. This worked for me. Thanks a lot for sharing this.

  14. hot girl

    i like the post you review it ,but it will more faster if u can use plugin for the site, this is my opinion i hope u can accept my info palls….thanks for sharing the info friends, best regards from susugede.net

  15. Roshan Singh

    Instead of hardcoding and expecting at least three array indices in the tags, maybe iterate through and use all of them like โ€” (I also added post__not_in to omit the original from being related to itself). Great

  16. Mike

    Hi Pippin,

    I got this plugin and used in my theme, and it works perfectly well. I just want to say thank you in this email. I have been looking for this for a long time.

    Thank you.

Comments are closed.