I'm trying to show a message on a product if the user is logged in, and the product is in the chains category, but I have assigned children/grandchildren of that term, not chains itself, and I don't know how to test for this.

I have tried two options, get_term_children and has_term. Both don't produce the desired outcome. I'm sure there is a simple adaptation, but can't get it to work.

Simple to add multiple categories to option 1, but due to the number of child categories, don't want to add to code every time a new category is added in admin.

Category structure

  • Chains (slug:chains / ID:22)
    • Al (slug:al-series-chain / ID:167
    • BL (slug:bl-series-chain / ID:168
    • ...

Things I've Tried

Option 1: Displays only on product pages selected with parent category chain.

It doesn't show on product pages of child categories of the parent category (chains) (Product in child category, but not in parent category).

Not all products are in parent and child categories - but I do want to show the message if in parent or child category.

        if ( has_term( 'chains', 'product_cat' ) && is_user_logged_in() ){
echo '<div class="test">' . 'hello' . '</div>' ; 

Option 2 Displays on all product pages regardless of category - all categories in parent and child categories and unrelated categories.

        if ( get_term_children( 22, 'chains' ) && is_user_logged_in() ){
echo '<div class="test">' . 'hello' . '</div>' ; 
  • I've edited the question to fix formatting, noting that WooCommerce is offtopic here so your wording took a general taxonomy problem and turned it into something that could have gotten your question closed! The root problem you have is usually solved by the general programming tactic of recursion, aka a function that checks if a term matches, if not fetch its parent or children and call again. You know how to get a terms children, but you don't know how to get their childrens children, and you haven't checked the terms parent since "chains" might not be an immediate parent or child term
    – Tom J Nowell
    Commented Apr 12, 2023 at 11:30

2 Answers 2


It sounds like you're looking for get_ancestors(). In your case, something like get_ancestors( $term_id, 'product_cat', 'taxonomy' ); should get an array of ancestor (parent, grandparent, etc) IDs for a given $term_id.


Using get_ancestors has displays top-level category also works with product pages at top level not in sub categories.

PARENT - Chains (ID:22)
--> Product Page - shows message

Child Category - Al (ID:167)
-> Product Page - shows message
Child Category - BL (ID:168)
-> Product Page - shows message
PARENT - Pins (ID:171)
--> Product Page - shows message
PARENT - Tools (ID:26)
--> Product Page - shows message

        global $post;
        $prod_terms = get_the_terms( $product->ID, 'product_cat' );
        foreach ($prod_terms as $prod_term); 
        // gets product cat id
        $product_cat_id = $prod_term->term_id;

        $parentcats = get_ancestors($product_cat_id, 'product_cat');
        foreach($parentcats as $parentcat);
        if (($parentcat === 22) || ( has_term( 22, 'product_cat' ) &&  !is_user_logged_in() )){
            echo 'message Chains Category';
        elseif (($parentcat === 171) || ( has_term(171, 'product_cat' ) &&  !is_user_logged_in() )){
            echo 'message Pins Category';
        elseif (($parentcat === 26) || ( has_term( 26, 'product_cat' ) &&  !is_user_logged_in() )){
            echo 'message Tools Category';

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.