I was curious if was possible to display related posts by multiple tags.
The site I am working on has about 5 tags per post. Most posts have 1 or 2 tags in common. The related posts I’d like to show have 3-5 tags in common.
So, I’d like the related posts to function by looking for posts with the most number of tags in common and display them in descending order.
Let’s say I display 3 related posts: relatedpost1 would have 4 tags in common, relatedpost2 would have 3 in common and relatedpost3 would have 1 in common.
Is it even possible to do this?
Right now I am messing around with two ways of displaying the posts but they arent functioning as I’d like:
The first method (code) just shows posts with ANY tags in common.
<?php $orig_post = $post;
global $post;
$tags = wp_get_post_tags($post->ID);
if ($tags) {
$tag_ids = array();
foreach($tags as $individual_tag) $tag_ids[] = $individual_tag->term_id;
$args=array(
'tag__in' => $tag_ids,
'post__not_in' => array($post->ID),
'posts_per_page'=>3, // Number of related posts that will be shown.
'caller_get_posts'=>1
);
$my_query = new wp_query( $args );
if( $my_query->have_posts() ) {
echo '<div id="relatedposts"><h3>Related Posts</h3><div class="relatedbreak"></div><ul id="relatedul">';
while( $my_query->have_posts() ) {
$my_query->the_post(); ?>
<li><div class="relatedthumb"><a href="<? the_permalink()?>" rel="bookmark" title="<?php the_title(); ?>"><?php the_post_thumbnail(array(185, 185)); ?></a></div>
<div class="relatedcontent">
<center><a href="<? the_permalink()?>" rel="bookmark" title="<?php the_title(); ?>"><div class="comments_text"><?php the_title(); ?></div></center></a>
</div>
</li>
<? }
echo '</ul></div>';
}
}
$post = $orig_post;
wp_reset_query(); ?>`
The second method (code) just shows posts with the first tag in common.
<?php
//for use in the loop, list 5 post titles related to first tag on current post
$tags = wp_get_post_tags($post->ID);
if ($tags) {
echo '<div id="relatedposts"><h3>Related Posts</h3></div><div class="relatedbreak"></div>';
$first_tag = $tags[0]->term_id;
$args=array(
'tag__in' => array($first_tag),
'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() ) {
while ($my_query->have_posts()) : $my_query->the_post(); ?>
<ul id="relatedul">
<li><div class="relatedthumb"><a href="<? the_permalink()?>" rel="bookmark" title="<?php the_title(); ?>"><?php the_post_thumbnail(array(185, 185)); ?></a></div>
<a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><div class="comments_text"><?php the_title(); ?></div></a></li>
</ul>
<?php
endwhile;
}
wp_reset_query();
}
?>
Both ways kind of suck; I’m either getting pretty random posts displaying (since most of my posts have at least 1 tag in common) or (for some posts) getting no related posts (since their common tags are tag 4 or 5).
Any help would be greatly appreciated.
I had the same idea and wrote a small little plugin to help me do this.
It looks for posts that have common terms and the terms are sorted by frequency so the least used terms come first then the more popular terms. The first function fetches the data and stores it in a transient so the results aren’t run over and over and over again unnecessarily. The second function just renders the output. This is what powers our related posts on one of our sites at work http://www.pewresearch.org/fact-tank/2013/08/02/both-parties-underwater-heading-into-2014-elections/
The algorithm works like this:
(least popular to more popular)
AND Term2 AND Term3
broadening our results until we get the desired number of posts or
we only have one term left to check.
posts that contain Term1 OR Term2 OR Term3
again for a while.
Hope this helps you out.
I don’t think
query_posts()
ornew WP_Query()
will do any good here. You need to query the database directly. Here goes the method I’ve written to achieve what you seem to need:The mehtod is designed to fetch related posts based on a single taxonomy, by default on ‘post_tag’ taxonomy. Posts are sorted by the number of common terms from highest to lowest. To fetch related posts for multiple common taxonomies at once, you would need to tweak
AND tt.taxonomy = %s
to something likeAND ( tt.taxonomy = 'post_tag' OR tt.taxonomy = 'category' )
. The same applies if you wanted to fetch posts of different post types.Thanks @Dero. Please remember to set the database prefix correctly:
So it works great on all systems.