Page Title

[show_related_posts] – Dynamic Related Posts Shortcode for WordPress

This shortcode displays related posts based on the current post's taxonomy (category, tag, or custom taxonomy) dynamically. It works on any post type and excludes the current post automatically.

✨ Features:

  • Works with any post type: post, product, portfolio, etc.
  • Automatically detects the taxonomy (category, tag, or custom taxonomy)
  • Excludes the current post from the related list
  • Customizable post count
  • Fallback taxonomy supported

🧩 How to Use:

Just place this shortcode anywhere inside a single post, page, or template:

[show_related_posts count="4"]

Optional usage with fallback taxonomy:

[show_related_posts count="4" taxonomy="portfolio_category"]

📦 Add This PHP Code to Your Theme or Custom Plugin:

function related_posts_shortcode($atts) {
    global $post;

    if (!isset($post) || !is_singular()) return ''; // Ensure we are on a single post view

    $atts = shortcode_atts(array(
        'count'     => 3,
        'exclude'   => '',
        'taxonomy'  => '', // Optional: fallback if no taxonomy found
    ), $atts);

    $post_type = get_post_type($post->ID);
    $exclude_ids = array($post->ID);

    if (!empty($atts['exclude'])) {
        $exclude_ids = array_merge($exclude_ids, explode(',', $atts['exclude']));
    }

    // Dynamically detect taxonomy (category, tag, or custom taxonomy)
    $taxonomies = get_object_taxonomies($post_type);
    $terms_query = array();
    $found_terms = false;

    foreach ($taxonomies as $taxonomy) {
        $terms = wp_get_post_terms($post->ID, $taxonomy, array('fields' => 'ids'));

        if (!is_wp_error($terms) && !empty($terms)) {
            $terms_query[] = array(
                'taxonomy' => $taxonomy,
                'field'    => 'term_id',
                'terms'    => $terms,
            );
            $found_terms = true;
            break; // Only use first found taxonomy to keep query light
        }
    }

    // If no terms found, fallback to user-defined taxonomy (optional)
    if (!$found_terms && !empty($atts['taxonomy'])) {
        $terms = wp_get_post_terms($post->ID, $atts['taxonomy'], array('fields' => 'ids'));
        if (!empty($terms)) {
            $terms_query[] = array(
                'taxonomy' => $atts['taxonomy'],
                'field'    => 'term_id',
                'terms'    => $terms,
            );
        }
    }

    // WP_Query args
    $args = array(
        'post_type'           => $post_type,
        'posts_per_page'      => (int) $atts['count'],
        'post__not_in'        => array_map('intval', $exclude_ids),
        'orderby'             => 'date',
        'order'               => 'DESC',
        'ignore_sticky_posts' => true,
    );

    if (!empty($terms_query)) {
        $args['tax_query'] = $terms_query;
    }

    $related_posts = new WP_Query($args);

    ob_start();

    if ($related_posts->have_posts()) :
        ?>
        <style>
        .related-posts.post-style {
            display: flex;
            flex-wrap: wrap;
            gap: 30px;
        }
        </style>
        <div class="related-posts post-style">
            <?php while ($related_posts->have_posts()) : $related_posts->the_post(); ?>
                <article class="related-post" style="flex:1; min-width:280px;">
                    <?php 
                        if (has_post_thumbnail()) {
                            the_post_thumbnail('large', ['style' => 'max-width:100%;height:auto;']);
                        } else {
                            echo "<img src='https://developers.elementor.com/docs/assets/img/elementor-placeholder-image.png' alt='Placeholder'>";
                        }
                    ?>
                    <h4><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h4>
                    <div class="post-date"><?php echo get_the_date('j F Y'); ?></div>
                    <div class="post-excerpt"><?php echo wp_trim_words(get_the_excerpt(), 20, '...'); ?></div>
                </article>
            <?php endwhile; ?>
        </div>
        <?php
    endif;

    wp_reset_postdata();
    return ob_get_clean();
}
add_shortcode('show_related_posts', 'related_posts_shortcode');

📝 Notes:

  • Add this PHP code in your child theme's functions.php file or create a small custom plugin.
  • Make sure to use the shortcode only on single post or single custom post type templates.