Show related posts by tag with W4 Post List

You add a “related posts” list under each article. On the first post you check, the top item is the post you are already reading. On the next, the list is empty. Both are the same root cause: the list does not know which post it is sitting on, and you have to tell it.

W4 Post List has no related-posts starter template, and its Tax Query section only takes fixed terms. What it does have is an “exclude the current post” switch and a hook that runs right before the query. That is enough.

Why tags, not a similarity engine

Most related-posts plugins score every candidate against the current post, by title words, content or shared terms, and then rank the results. Either that scoring runs on every page load or the plugin keeps its own cache table that you rebuild when content changes.

A tag match is one indexed query on the term relationships table, the same query your tag archive already runs. Page caching takes care of the rest. The trade is that you get “shares a tag”, not “most similar”, and the order is by date or random, not by overlap. For a blog where you tag with care, that is usually the better deal.

Build the list

Go to W4 Post List > Add New. Set List Type to Posts. In the Posts section:

  • Post type: post
  • Items per page: 5
  • Orderby: date, Order: DESC
  • Exclude self: Yes

That last one is the fix for the first failure. It only applies on single post pages, which is where the list belongs.

Pick Start from a template and choose Simple list, or Thumbnail cards if you want images. The starter templates guide shows each one. Leave Posts: Tax Query empty. Publish, and note the list ID from the Shortcode column.

Tell the list which tags to use

Add this to a small plugin or your theme’s functions.php, with your list ID in place of 123:

add_action( 'w4pl/parse_query_args', function ( $list ) {
    if ( 123 !== (int) $list->id || ! is_singular( 'post' ) ) {
        return;
    }
    $tag_ids = wp_get_post_tags( get_the_ID(), [ 'fields' => 'ids' ] );
    if ( empty( $tag_ids ) ) {
        return;
    }
    $list->posts_args['tax_query'] = [
        [ 'taxonomy' => 'post_tag', 'field' => 'term_id', 'terms' => $tag_ids ],
    ];
}, 30 );

Priority 30 matters. The plugin applies its own Tax Query settings at 20, so yours has to run after that.

The empty check is the fix for the second failure. A tag query with no terms returns no posts at all, and the plugin renders nothing when the query is empty. With the early return, an untagged post falls back to your latest posts instead of a blank space. If you would rather show a message, set No items text in the list and return no posts.

Place it under the post

On a block theme, open the Single Posts template in the Site Editor and add the W4 Post List block below the post content, then pick your list. On a classic theme, drop the shortcode into single.php:

<?php echo do_shortcode( '[postlist id="123"]' ); ?>

Everything else is template markup. Add [post_terms tax="post_tag" sep=", "] inside the loop if you want each related post to show why it is there.

W4 Post List is free on WordPress.org. If this is your first list, start with the getting started guide and come back for the filter.