Skip to content
Advertisement

Display content on WooCommerce single products based on product categories when they have child categories

I am trying to display the test div below on any product page that is in the category cat1title or cat2title. Using the hook below, which I thought was correct, I should be seeing this div on the page but I am not seeing it at all. The page displays just fine but no div. No errors in the console either. According to docs, this should still be valid with the latest version of Woo. What am I missing?

    add_action( 'woocommerce_single_product_summary', 'custom_button_by_categories', 32 ,0 );
function custom_button_by_categories(){
    
    global $product;

    // Define your categories in this array (can be Ids, slugs or names)
    $product_cats = array('cat1title', 'cat2title');

    if( has_term( $product_cats, 'product_cat', $product->get_id() ) ){
         //$demo_url = get_post_meta( $product->get_id(), 'demo_url', true );
         echo '<div style="background: lightblue; height 1000px; width:1000px; z-index:999; position:absolute; top:0; left:0">test</div>';
    }
}

Advertisement

Answer

The defined product categories need to be set on the products to work with has_term() conditional function…

So this will not work for parent product categories which child subcategories are set for a product…

To check for parent product categories too you could use this custom conditional function:

// Custom conditional function that handle parent product categories too
function has_product_categories( $categories, $product_id = 0 ) {
    $parent_term_ids = $categories_ids = array(); // Initializing
    $taxonomy        = 'product_cat';
    $product_id      = $product_id == 0 ? get_the_id() : $product_id;

    if( is_string( $categories ) ) {
        $categories = (array) $categories;
    }

    // Convert categories term names and slugs to categories term ids
    foreach ( $categories as $category ){
        $result = (array) term_exists( $category, $taxonomy );
        if ( ! empty( $result ) ) {
            $categories_ids[] = reset($result);
        }
    }

    // Loop through the current product category terms to get only parent main category term
    foreach( get_the_terms( $product_id, $taxonomy ) as $term ){
        if( $term->parent > 0 ){
            $parent_term_ids[] = $term->parent; // Set the parent product category
            $parent_term_ids[] = $term->term_id; // (and the child)
        } else {
            $parent_term_ids[] = $term->term_id; // It is the Main category term and we set it.
        }
    }
    return array_intersect( $categories_ids, array_unique($parent_term_ids) ) ? true : false;
}

So in your code:

add_action( 'woocommerce_single_product_summary', 'custom_button_by_categories', 32 ,0 );
function custom_button_by_categories(){
    global $product;

    // Define your categories in this array (can be Ids, slugs or names)
    $categories = array('cat1title', 'cat2title');

    if( has_product_categories( $categories, $product->get_id() ) ){
         //$demo_url = get_post_meta( $product->get_id(), 'demo_url', true );
         echo '<div style="background: lightblue; height 1000px; width:1000px; z-index:999; position:absolute; top:0; left:0">test</div>';
    }
}

Code goes in functions.php file of the active child theme (or active theme).

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement