I would like to show 4-5 posts by thumbnail and title below each product. For all products I have added a custom taxonomy to group all these products under their own group term. A custom tag so to speak.

Now I want to query 5 posts under each product that share that same term chosen for custom taxonomy group. So far I have created this to query the posts by taxonomy and term:

function shortcode_imwz_custom_taxonomy_by_term() {
  global $wp_query,$post;
  // wp_get_object_terms( $post->ID, 'portfolio-skills', array( 'fields' => 'names' ) );
  // https://stackoverflow.com/a/14798097/460885
  // $product_terms = wp_get_object_terms( $post->ID,  'product' );
  // For performance, functions like get_the_terms() (which the results of has been cached), 
  // should be used.
  // get the terms Retrieve the terms of the taxonomy that are attached to the post.
  // $term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) );
  // https://wordpress.stackexchange.com/a/21425/12260
  $terms = get_the_terms( get_the_ID(), 'group' );

  $loop = new WP_Query( array(
      'posts_per_page'    => 5,
      'post_type'         => 'product',
      'orderby'           => 'menu_order title',
      'order'             => 'ASC',
      'tax_query'         => array( array(
          'taxonomy'  => 'group',
          'field'     => 'slug',
          'terms'     =>  $terms
      ) )
  ) );

  if( ! $loop->have_posts() ) {
      return false;

  while( $loop->have_posts() ) {
      // echo thumbnail
      echo the_title();


I added a shortcode based on this code

function register_grouped_products_shortcode() {
  add_shortcode( 'grouped-products', 'shortcode_imwz_custom_taxonomy_by_term' );
add_action( 'init', 'register_grouped_products_shortcode' );

to a product to use the WP Query and did add a term of choice. But I do not see anything loaded yet. What am I missing here? So many options I found to get the terms to filter posts on taxonomy AND term entered.. Perhaps an issue here?

1 Answer 1


get_the_terms() returns an array of WP_Term objects on success, so you can't simply pass the returned array to WP_Query, and if you want to query the related posts by the term slugs, then you can use wp_list_pluck() to get just the term slugs, although you can also use the function to get any properties of the term object like term_id:

$slugs = [];
if ( $terms && ! is_wp_error( $terms ) ) {
    $slugs = wp_list_pluck( $terms, 'slug' );

Then in your tax_query, use 'terms' => $slugs, in addition to setting the field to slug (see examples below).

See here for more info about the tax_query's parameters.

// Example 1: Query posts by term slugs.
'tax_query' => array( array(
    'taxonomy' => 'group',
    'field'    => 'slug', // if this is 'slug'
    'terms'    =>  $slugs // then this should be term slugs
) )

// Example 2: Query posts by term IDs.
'tax_query' => array( array(
    'taxonomy' => 'group',
    'field'    => 'term_id', // if this is 'term_id'
    'terms'    =>  $ids      // then this should be term IDs
    // assume $ids is wp_list_pluck( $terms, 'term_id' )
) )

Additional Notes

  1. the_title() already echoes the output, so no need to echo the the_title(). If you want to manually echo it, you could use get_the_title()echo get_the_title();.

  2. Secondly, a shortcode callback should always return the output. Otherwise, the output would be displayed at the wrong place — normally, before the post content is rendered. And if you need to echo something in a shortcode (callback), you would want to concatenate the output without any calls to echoing functions or for complex HTML, you can use output buffering — Stack Overflow has lots of info on that, but basically in your case, you could do:

    // At the start of the function:
    // Then just run your loop...
    while( $loop->have_posts() ) {
    // And at the end of the function:
    return ob_get_clean();
  3. If the query is not giving you the expected results after you confirmed all the query arguments are good, then you could debug the query by echoing the SQL command for that query — add echo $loop->request; after your new WP_Query() call, then see if the SQL is good and you can also copy the SQL and run it on phpMyAdmin (or a similar tool) and check if the SQL returns any results.

  4. If you want to exclude the current post, you can use the post__not_in parameter:

    new WP_Query( array(
        'post__not_in' => array( get_the_ID() ), // you need to pass an array
    ) )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.