skip to Main Content

I have a woocommerce store with the two standard taxonomies – "categories" and "tags" – and a custom taxonomy "sport." I have used the following code to focus Related Products on the "primary" category. ( Taken from this post: WooCommerce Related Products by children category as fallback to Rank Math Primary Category )

Now what I would like to do is to pick products that share the "custom taxonomy" "sport" rather than a "category."

Is there a simple way to adapt this code to "sport" rather than "category" to select Related Products?

Thanks.

// Rank Math SEO - Use Primary Category for Related Products
add_filter( 'woocommerce_related_products', 'related_products_from_rank_math_primary_category', 10, 3 );
function related_products_from_rank_math_primary_category( $related_posts, $product_id, $args  ) {
    $taxonomy     = 'product_cat';
    $category_ids = wp_get_post_terms($product_id, $taxonomy, array('fields' => 'ids') ); 
    $term_slugs   = array(); // Initializing   

    if( count($category_ids) == 1 ) {
        // Get children categories
        $children_ids = get_term_children( reset($category_ids), $taxonomy );
        // Loop through children terms Ids
        foreach ( $children_ids as $tem_id ) {
            $term_slugs[] = get_term_by( 'id', $tem_id, $taxonomy )->slug; // get the slug from each term Id
        }
    } 
    elseif( count( $category_ids ) > 1 ) {
        // Get the primary category/term as saved by Rank Math SEO
        $primary_cat_id = get_post_meta( $product_id, 'rank_math_primary_product_cat', true );
        $term_slugs[]   = get_term_by( 'id', $primary_cat_id, $taxonomy )->slug; // get the slug from the term Id
    }

    if ( count($term_slugs) > 0 ) {
        // Product query: Get product Ids
        $related_posts = wc_get_products( array(
            'status'        => 'publish',
            'category'      => $term_slugs,
            'return'        => 'ids',
            'exclude'       => array( $product_id ),
            'visibility'    => 'catalog',
            'limit'         => -1,
        ) );
    }
    return $related_posts;
}

I tried replacing taxonomy=’product_cat’ with taxonomy=’sport’

That led the function to fail.

2

Answers


  1. Chosen as BEST ANSWER

    Thank you for the answer, it worked well. I would like to extend it to use the RankMath "primary" taxonomy. So I combined the answer provided with the original code that used the "primary category" and changed it to "primary taxonomy." That doesn't quite work. The Taxonomy "sport" has three levels: Parent, child, sub-child (grandchild). (For example: Indoor Sport > Arena Sport > Basketball.) The revised code seems to look only to match the Child level (e.g. Arena). The primary taxonomy may be at any of the three levels, though most often it will be a sub-child (e.g. Basketball). I would like the Related Products to look first for the "primary" taxonomy and choose products that share the same "primary" taxonomy, which will require also considering the sub-child level.

    How do I prioritize products that share the same primary taxonomy startimg at the sub-child level?

    Here is how I revised the code to combine the original and the answer:

        add_filter( 'woocommerce_related_products', 'related_products_from_rankmath_primary_esporte_taxonomy', 10, 3 );
        function related_products_from_rankmath_primary_esporte_taxonomy( $related_posts, $product_id, $args ) {
            $taxonomy     = 'sport'; 
            $term_ids     = wp_get_post_terms( $product_id, $taxonomy, array( 'fields' => 'ids' ) ); 
            $term_slugs   = array(); 
      
     if( count($term_ids) == 1 ) {
            // Get children categories
            $children_ids = get_term_children( reset($category_ids), $taxonomy );
            // Loop through children terms Ids
            foreach ( $children_ids as $tem_id ) {
                $term_slugs[] = get_term_by( 'id', $tem_id, $taxonomy )->slug; // get the slug from each term Id
            }
        } 
        elseif( count( $term_ids ) > 1 ) {
            // Get the primary taxonomy/term as saved by Rank Math SEO
            $primary_tax_id = get_post_meta( $product_id, 'rank_math_primary_taxonomy', true );
            $term_slugs[]   = get_term_by( 'id', $primary_tax_id, $taxonomy )->slug; // get the slug from the term Id
        }
            
            
            if ( count( $term_ids ) > 0 ) {
                foreach ( $term_ids as $term_id ) {
                    $term_slugs[] = get_term_by( 'id', $term_id, $taxonomy )->slug; 
        
                    // Gets the IDs of child terms
                    $children_ids = get_term_children( $term_id, $taxonomy );
        
                    foreach ( $children_ids as $child_id ) {
                        $term_slugs[] = get_term_by( 'id', $child_id, $taxonomy )->slug; // Gets the slug of each child term
                    }
                }
       
       
                $related_posts = wc_get_products( array(
                    'status'        => 'publish',
                    'tax_query'     => array(
                        array(
                            'taxonomy' => $taxonomy,
                            'field'    => 'slug',
                            'terms'    => $term_slugs,
                        ),
                    ),
                    'return'        => 'ids',
                    'exclude'       => array( $product_id ),
                    'visibility'    => 'catalog',
                    'limit'         => -1,
                ) );
            }
    
        
        
            return $related_posts;
        }
    

  2. Try adding the filter with the following changes, replacing the use of the ‘product_cat’ taxonomy with the custom ‘sport’ taxonomy and adjusting the logic for obtaining the term information.

    Sample:

        add_filter( 'woocommerce_related_products', 'related_products_from_esporte_taxonomy', 10, 3 );
        function related_products_from_esporte_taxonomy( $related_posts, $product_id, $args ) {
            $taxonomy     = 'sport'; 
            $term_ids     = wp_get_post_terms( $product_id, $taxonomy, array( 'fields' => 'ids' ) ); 
            $term_slugs   = array(); 
        
            if ( count( $term_ids ) > 0 ) {
                foreach ( $term_ids as $term_id ) {
                    $term_slugs[] = get_term_by( 'id', $term_id, $taxonomy )->slug; 
        
                    // Gets the IDs of child terms
                    $children_ids = get_term_children( $term_id, $taxonomy );
        
                    foreach ( $children_ids as $child_id ) {
                        $term_slugs[] = get_term_by( 'id', $child_id, $taxonomy )->slug; // Gets the slug of each child term
                    }
                }
        
                $related_posts = wc_get_products( array(
                    'status'        => 'publish',
                    'tax_query'     => array(
                        array(
                            'taxonomy' => $taxonomy,
                            'field'    => 'slug',
                            'terms'    => $term_slugs,
                        ),
                    ),
                    'return'        => 'ids',
                    'exclude'       => array( $product_id ),
                    'visibility'    => 'catalog',
                    'limit'         => -1,
                ) );
            }
        
            return $related_posts;
        }
    

    Instead of checking categories and their subcategories, you can directly retrieve the terms from the custom taxonomy "sport". The method get_term_children fetches the child terms of the taxonomy for each parent term found in the products. Also, adjust the product query to include a tax_query that searches for products having the selected terms in the custom taxonomy "esporte".

    You can also debug the code to analyze the responses more effectively in WordPress.

    Open the wp-config.php file.
    And insert the following code into the file:

        // Enable debug mode
        define('WP_DEBUG', true);
        // Store logs in /wp-content/debug.log
        define('WP_DEBUG_LOG', true);
    

    In the above code, in addition to enabling debugging, all encountered errors are also stored in a log file. The file is located at wp-content/debug.log.

    If you are working on a live installation, or your code is reporting a lot of bugs, you should also set the following to false in your wp-config.php file,

    define( 'WP_DEBUG_DISPLAY', false );
    

    this will switch off the error logging on the front-end and only log them in the debug.log file.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search