Posted on

WooCommerce Visual Hook Guide: Archive / Shop / Cat Pages

I’ve created a visual HTML hook guide for the WooCommerce Archive Page (which is the same page for the Shop, Category, Tag pages). This visual guide belongs to my “Visual Hook Guide Series“, that I’ve put together so that you can find WooCommerce hooks quickly and easily by seeing their actual locations (and you can also copy/paste). If you like this guide and it is helpful to you, let me know in the comments!

Thanks to this WooCommerce Archive Visual Hooks Guide, you can now go to your template’s functions.php file and use “add_action(‘place-hook-here’,’your-PHP-function-here’);” – you can then place your custom functions exactly where you like them to be. Enjoy!

NEW! You can now “expand” each hook by clicking on the “+”. You will immediately see the relevant default WooCommerce functions, so that you can remove them, move them or add content in that exact position. Enjoy 🙂

WooCommerce Archive Page [Visual Hook Guide]

woocommerce_before_main_content +

Default Actions:

add_action( 'woocommerce_before_main_content', 'woocommerce_output_content_wrapper', 10 );
add_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20 );

Remove Default Actions:

remove_action( 'woocommerce_before_main_content', 'woocommerce_output_content_wrapper', 10 );
remove_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20 );

Add Custom Action:

add_action( 'woocommerce_before_main_content', 'bbloomer_custom_action', 15 );

function bbloomer_custom_action() {
echo 'TEST';
}

Shop

woocommerce_archive_description +

Default Actions:

add_action( 'woocommerce_archive_description', 'woocommerce_taxonomy_archive_description', 10 );
add_action( 'woocommerce_archive_description', 'woocommerce_product_archive_description', 10 );

Remove Default Actions:

remove_action( 'woocommerce_archive_description', 'woocommerce_taxonomy_archive_description', 10 );
remove_action( 'woocommerce_archive_description', 'woocommerce_product_archive_description', 10 );

Add Custom Action:

add_action( 'woocommerce_archive_description', 'bbloomer_custom_action', 15 );

function bbloomer_custom_action() {
echo 'TEST';
}
woocommerce_before_shop_loop +

Default Actions:

add_action( 'woocommerce_before_shop_loop', 'wc_print_notices', 10 );
add_action( 'woocommerce_before_shop_loop', 'woocommerce_result_count', 20 );
add_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 );

Remove Default Actions:

remove_action( 'woocommerce_before_shop_loop', 'wc_print_notices', 10 );
remove_action( 'woocommerce_before_shop_loop', 'woocommerce_result_count', 20 );
remove_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 );

Add Custom Action:

add_action( 'woocommerce_before_shop_loop', 'bbloomer_custom_action', 15 );

function bbloomer_custom_action() {
echo 'TEST';
}

Showing all 4 results

  • woocommerce_before_shop_loop_item +

    Default Actions:

    add_action( 'woocommerce_before_shop_loop_item', 'woocommerce_template_loop_product_link_open', 10 ); 
    

    Remove Default Actions:

    remove_action( 'woocommerce_before_shop_loop_item', 'woocommerce_template_loop_product_link_open', 10 ); 
    

    Add Custom Action:

    add_action( 'woocommerce_before_shop_loop_item', 'bbloomer_custom_action', 15 );
    
    function bbloomer_custom_action() {
    echo 'TEST';
    }
    
    woocommerce_before_shop_loop_item_title +

    Default Actions:

    add_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_show_product_loop_sale_flash', 10 
    add_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
    

    Remove Default Actions:

    remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_show_product_loop_sale_flash', 10 );
    remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
    

    Add Custom Action:

    add_action( 'woocommerce_before_shop_loop_item_title', 'bbloomer_custom_action', 15 );
    
    function bbloomer_custom_action() {
    echo 'TEST';
    }
    

    woocommerce_shop_loop_item_title +

    Default Actions:

    add_action( 'woocommerce_shop_loop_item_title', 'woocommerce_template_loop_product_title', 10 );
    

    Remove Default Actions:

    remove_action( 'woocommerce_shop_loop_item_title', 'woocommerce_template_loop_product_title', 10 );
    

    Add Custom Action:

    add_action( 'woocommerce_shop_loop_item_title', 'bbloomer_custom_action', 15 );
    
    function bbloomer_custom_action() {
    echo 'TEST';
    }
    

    Product Title

    woocommerce_after_shop_loop_item_title +

    Default Actions:

    add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10 );
    add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_rating', 5 );
    

    Remove Default Actions:

    remove_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10 );
    remove_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_rating', 5 );
    

    Add Custom Action:

    add_action( 'woocommerce_after_shop_loop_item_title', 'bbloomer_custom_action', 15 );
    
    function bbloomer_custom_action() {
    echo 'TEST';
    }
    

    €5,00

    woocommerce_after_shop_loop_item +

    Default Actions:

    add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_product_link_close', 5 );
    add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
    

    Remove Default Actions:

    remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_product_link_close', 5 );
    remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
    

    Add Custom Action:

    add_action( 'woocommerce_after_shop_loop_item', 'bbloomer_custom_action', 15 );
    
    function bbloomer_custom_action() {
    echo 'TEST';
    }
    

    Add to cart

  • woocommerce_before_shop_loop_itemwoocommerce_before_shop_loop_item_titlewoocommerce_shop_loop_item_title

    Test 6

    woocommerce_after_shop_loop_item_title

    €5,00

    woocommerce_after_shop_loop_item

    Select options

woocommerce_after_shop_loop +

Default Actions:

add_action( 'woocommerce_after_shop_loop', 'woocommerce_pagination', 10 );

Remove Default Actions:

remove_action( 'woocommerce_after_shop_loop', 'woocommerce_pagination', 10 );

Add Custom Action:

add_action( 'woocommerce_after_shop_loop', 'bbloomer_custom_action', 15 );

function bbloomer_custom_action() {
echo 'TEST';
}
woocommerce_after_main_content +

Default Actions:

add_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end', 10 );

Remove Default Actions:

remove_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end', 10 );

Add Custom Action:

add_action( 'woocommerce_after_main_content', 'bbloomer_custom_action', 15 );

function bbloomer_custom_action() {
echo 'TEST';
}

WooCommerce Archive Page Default add_actions


// These are actions you can unhook/remove!

add_action( 'woocommerce_before_main_content', 'woocommerce_output_content_wrapper', 10 );
add_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20 );

add_action( 'woocommerce_archive_description', 'woocommerce_taxonomy_archive_description', 10 );
add_action( 'woocommerce_archive_description', 'woocommerce_product_archive_description', 10 );

add_action( 'woocommerce_before_shop_loop', 'wc_print_notices', 10 );
add_action( 'woocommerce_before_shop_loop', 'woocommerce_result_count', 20 );
add_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 );

add_action( 'woocommerce_before_shop_loop_item', 'woocommerce_template_loop_product_link_open', 10 ); 

add_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_show_product_loop_sale_flash', 10 ); 
add_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );

add_action( 'woocommerce_shop_loop_item_title', 'woocommerce_template_loop_product_title', 10 );

add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10 );
add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_rating', 5 );

add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_product_link_close', 5 );
add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );

add_action( 'woocommerce_after_shop_loop', 'woocommerce_pagination', 10 );

add_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end', 10 );

Where to add this code?

You can place PHP snippets at the bottom of your child theme functions.php file (before "?>" if you have it). CSS, on the other hand, goes in your child theme style.css file. Make sure you know what you are doing when editing such delicate files - if you need more guidance, please take a look at my free WooCommerce Customization video tutorial.

Does this snippet still work?

Please let me know in the comments if everything worked as expected. I would be happy to revise the snippet if you report otherwise (please provide screenshots). I have tested this code with Storefront theme, the WooCommerce version listed above and a WordPress-friendly hosting on PHP 7.

If you think this code saved you time & money, please join other Business Bloomer supporters and avail of 365 days of WooCommerce benefits. Thank you in advance :)

Need Help with WooCommerce?

Check out these free videos, tutorials and tips!

  • how-to-edit-woocommerce-with-php-snippets
  • woocommerce-hooks-add_action-list-visual
  • woocommerce-customize-single-product-page-PHP
  • woocommerce-customize-shop-page-PHP
  • woocommerce-advanced-customization
  • how-to-edit-woocommerce-cart
  • woocommerce-customize-checkout-page-PHP
  • woocommerce-email-customization
  • woocommerce-conditional-logic

Rodolfo Melogli

Author, WooCommerce expert, WordCamp speaker and Internet marketer, Rodolfo Melogli has worked as a WooCommerce freelancer since 2011. He helps entrepreneurs and developers overcome their WooCommerce nightmares :) Rodolfo is the organiser of WordCamp Dublin, the Dublin WooCommerce Meetup, the Dublin Ecommerce Meetup and the Dublin WordPress Meetup. He enjoys interacting with people, travelling and chasing tennis & soccer balls. Of course, he loves pizza too.

124 thoughts on “WooCommerce Visual Hook Guide: Archive / Shop / Cat Pages

  1. Thank you so much for creating such a complete guide. Easily the most complete Woocommerce knowledge out there.

    1. Excellent 🙂

  2. Rodolfo.
    I just want to say thank you very much for creating these guides. They are great.

    1. Thank you 🙂

  3. I have some attributions called od, ln, r and I want to sort it in asc, but it brings me in order of text and not numeric. 1,11,13,2,3,4 instead of 1,2,3,4,11,13. what I do?

    1. Hey Antonio, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. Thanks a lot for your understanding! ~R

  4. Hello Rodolfo,

    Thank you for the resource and tutorials! They have been very helpful in the ever continuing expansion of our Woocommerce store. I do have an issue I cannot find a solution for, however.

    We have multiple products, some of which we have in stock at our warehouse, others we have factory availability. What I have now is displaying a generic message “Call for Availability” although I do not want this displayed on items I actually have in stock. The in-stock items I have set to manage stock, with quantities. The items that we have factory availability for are simply set to in-stock. Is there a way I can differentiate between the two so that on my category pages in-stock items will display “Call for Availability” while any items I have managed will display # in stock.

    This is what I have loaded currently:

    is_in_stock() ) {
    $availability[‘availability’] = __(‘Need it Quick? Call for Availability (1-800-277-4466)’, ‘woocommerce’);
    }
    if ( $_product->is_in_stock() && $product->get_stock_quantity() == 1 ) {
    $availability[‘availability’] = sprintf( __(‘Availability: %s in stock’, ‘woocommerce’), $product->get_stock_quantity());
    }
    if ( $_product->is_in_stock() && $product->get_stock_quantity() > 1 ) {
    $availability[‘availability’] = sprintf( __(‘Availability: %s in stock’, ‘woocommerce’), $product->get_stock_quantity());
    }
    
    return $availability;
    }
    
    function ahe_stock_catalog() {
    global $product;
    if ( $product->is_in_stock() ) {
    echo ” . $product->get_stock_quantity() . __( ‘ Need it Quick? Call for Availability’, ‘ahe’ ) . ”;
    } else {
    echo ” . __( ‘out of stock’, ‘ahe’ ) . ”;
    }
    }
    add_action( ‘woocommerce_after_shop_loop_item_title’, ‘ahe_stock_catalog’ ); 
    1. Hello there – thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding! ~R

  5. Hi Rodolfo,

    thanks for this resource – it’s so helpful. I am trying to remove the buy product button for my external products (i’m an affiliate store) from my shop pages (category, brand etc.) . Unfortunately this code is not working & I cannot find the alternative for external products.

     remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10); 

    Any idea what I am doing wrong?

    Thanks a million in advance!

    1. Hello Assunta – thanks so much for your comment! Not sure, it could be theme/plugin overrides… if you use the code on 2017 theme, does it work?

  6. Hi Rodolfo, I am a novice web app programmer. I just chanced upon your site today, and I amazed at the quality and detail you have made available to everyone. I learned a lot just by spending a few hours trying out the functions and hooks you have listed. Many thanks for the efforts you have put into this! 🙂

    I am using WooCommerce + Storefront, and want to customize the Shop page by adding some interactive content. I did this by creating a page template containing my HTML and JavaScript, and it works just like it does in the non-WordPress version. Now I want to add the Shop page (as it is, without the header and footer) as a section to this template. What is the function or hook that I should call to do that?

    1. Hey Shrik, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. Thanks a lot for your understanding! ~R

  7. Can anyone confirm that hook: woocommerce_before_main_content is still working?

    Appearantly, no matter what i do, i can’t seem to hook into it. When ever i change the hook name, my function seems to work. This hook doesn’t work for me. I see alot of people had issues with it on the internet, but no one really found a useful solution.

    What’s wiered too, is that the title markup in “archive-product.php” isnt the one getting rendered on front end either. And no matter how many changes i made to archive-product.php (for testing purposes) no change really appears on the frontend.

    This hook is driving me nuts..

    1. It could be your theme… can you switch to another for a second and see if the hook works?

    2. I’m having the exact same problem with a client website. Googled, googled and googled with no luck.

      This visual guide blog is fantastic though! Wish I could get woocommerce_after_main_content to work though.

    3. Hey Ritch, thanks for your comment! It could be your theme has “unhooked” it 🙂

  8. nice

  9. Rodolfo, thanks for your blog posts. One question, I tried editing Infinte Child Theme usuing your instructions but it doesnt work. Any reference onto why is not working?
    Thank you in advance!

    1. Hola Nicolas, thanks for your comment 🙂 Sorry but this is custom troubleshooting and cannot help here via the blog comments. Thank you!

  10. Hi,
    great materials!

    I have one question for which I’ve been looking for answer for 3-4 days in the net.

    How can I add the following info under my products on shop page:
    • Name of the product
    (done by default)
    • SKU
    (managed to do it with woocommerce Booster in the Product Info tab with the following shortcodes: [wcj_product_sku] and Item No: [wcj_product_sku])
    • Price
    (done by default)
    • Subcategory name
    !This one is the main problem!
    The Booster managed to show me all the categories and subcategories with these shortcodes: [wcj_product_categories] and [wcj_product_categories before=”Category: “]. But I want to show only one particular subcategory which is the name of the brand of a particular product. I tried your php solution for this but it didn’t work.

    Please help!
    Thank you.

    1. Hey Ivo, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. Thanks a lot for your understanding! ~R

    2. Hi, i have the same “issues”. It works fine to remove and add, but when i want to remove meta and only add SKU, it doesn’t seems like there an easy way to only add the SKU from the meta?

  11. hi, please do reply soon as soon as possible

    1. Frank, thanks so much for your comment! Unfortunately this looks like custom troubleshooting work and I cannot help here via the blog comments. Thanks a lot for your understanding! ~R

  12. hi, I want to override archieve.php file. and i followed all the steps that are mentioned to override like make a folder named woocomerce in theme directory and in this directory copy the archieve.php file. but nothing works. please guide me what to do to resolve that issue?

  13. Thank you so much nice explanation…
    I have one question
    How can i add Add to wishlist button on shop page?

  14. Great support! Thank you for sharing this with us! Really helpful!

  15. Hey! This is a great visual helper. One question, though – in which hook is the “Showing all 4 results”.
    Also, how can I remove the result_count from there?

    1. Hey Atanas, thanks so much for your comment! I think this should help: https://businessbloomer.com/woocommerce-remove-showing-single-result/

  16. Thanks a lot Rodolfo for this amazing tutorial, really impressive
    I have question for you.
    I “sell” articles on my website. So, the basic template of the shop page is not relevante for me.
    What I would like to do is, more or less, the same presentation of a Search Engine (Google, Bing, …) with
    – the product name for the link
    – the short description product just under the title
    – the price on the same row of the title
    – the add to cart on same row of the title.
    How do you change the template of the loop ?

  17. Thanks for the help with removing the “best sellers” on my woocommerce storefront.
    Best, Linda

    1. Thanks for your feedback Linda!

  18. Thanks Rodolfo and the rest of the commenters.

    This thread quickly refreshed my memory a lot and helped me solve a nice little SEO boost on the archive pages. Adding an h1 of the current product category or tag archive term title to the top of the archive pages and an h3 of it at the bottom of the page.

    Here it is chopped up from the comments

    add_action( 'woocommerce_before_main_content','show_title_intro_TEST');
        
    function show_title_intro_TEST() {
       echo '<h1 class="archivepagehs">';
    			woocommerce_page_title();
    			echo '</h1>';
    		}
    
    add_action( 'woocommerce_after_shop_loop','show_category_intro_TEST');
        
    function show_category_intro_TEST() {
      echo '<h3 class="archivepagehs">';
    			woocommerce_page_title();
    			echo '</h3>';
    		}
    
    1. Nice, thanks for that 🙂

  19. What is the difference between Taxonomy description and product achieve description?

    1. Hey there, thanks for your comment! Taxonomy is strictly related to a specific category, while “product archive” applies to all categories/tags/loops 🙂

  20. You are amazing !! It’s great feeling to control your own website. So I understand everything you are teaching. But what if my theme has already overridden all these hooks?
    Such as I add the line

    remove_action( 'woocommerce_archive_description', 'woocommerce_product_archive_description', 10 );

    in my functions.php of the child theme, but description stays at it is. I suspect it because my theme shopkeeper has altered the hook or function names.

    What do you think in these kinds of cases? Should I make my own hook guide for my theme or just ditch the theme?

    Thanks 🙂

    1. Hey Kiran, thanks for your comment! Yes, you will need to see what your theme is doing with the default WooCommerce calls, and in case remove the functions that your theme adds 🙂

  21. Hey Rodolfo,
    thanks for great articles!
    I’m struggling with simple thing. On my shop page which displays categories, there is category image, and category name below following by number of items inside the category.
    How can I remove the category name/number of items? I just want to have category image, nothing else.
    Thanks in advance

  22. Hey Rodolfo

    Thanks for these!

    Is there a way to use the remove codes to stop all of the shop loop items appearing on woo category pages please?

    So for e.g., if i just wanted to have images that link to sub categories and NO products appearing in category pages can i use one of these codes to achieve that please?

    Thanks
    Matt

    1. Hey Matt, thanks for your comment! Check the WooCommerce settings, you can define this there 🙂

  23. I have a strange issue and wondering if you could give me some advice. The 1st post on the shop page is displaying the long product description at the bottom of the page. The individual product posts are fine. It does not matter the filter I select it always displays the associated posts text at the bottom of the page. I hope I am explaining this in a way that it is understood. I am just baffled by this issue.

    The site was already built when I was hired so I am having to try to salvage this disaster.

    1. Heather, thanks so much for your comment! Yes, there seems to be some problem with your website there – but unfortunately this is custom troubleshooting work and I cannot provide a complementary solution here on the blog. Thanks a lot for your understanding! ~R

  24. Hi Gregory
    I wonder how do I reposition the archive description? (it has a banner shortcode so I’d want it to be full with i.e. before main content)
    I tried this:
    remove_action( ‘woocommerce_archive_description’, ‘woocommerce_taxonomy_archive_description’, 10 );
    add_action( ‘woocommerce_before_main_content’, ‘woocommerce_taxonomy_archive_description’, 5 );
    Daniel

    1. Hi Daniel, Did you figure this out? I tried exactly the same. In the end I had to use a display:none styling (which is a rubbish solution) to hide the existing, because nothing I do seems to be able to remove existing Woo actions. I’m suspicious this is because the theme I’m using (Avada) is at fault thinking that it controls everything.
      Thanks,
      Gerald

  25. […] Personalización de plantillas mediante Hooks. (single, archive) […]

  26. Here is what worked for me when I wanted to separate out a couple of product with their own header on the site. Some of the divs might be a bit overkill but wanted to leave room for styling those parts separately later:

    add_action( 'woocommerce_after_shop_loop','show_below_shop');
        
    function show_below_shop() {
    	if(is_shop()){
       		echo 'Other products and services';
    		echo '';
    		echo do_shortcode('[products ids="1674, 3348" columns="3"]'); 
       		echo '';
    		echo '';
    		echo 'At this time we welcome customers from Europe and the US and Canada. ';
    		echo '&nbsp;';
    	}
    }
    
    1. Thank you Hakan 🙂

  27. I love your guide. But one problem I have. I can’t use the get field of acf in the shoppage above.

    1. Thanks Melanie! Why can’t you use it?

  28. SO helpful! thank you

  29. Hello Rodolfo Melogli,
    I want to add No of Quantity and other some details in Thumbnail product page . please help me .

    1. Pintu, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution here on the blog. Thanks a lot for your understanding! ~R

  30. Hi, thanks for your amazing videos and website. You explain things in a way that is so easy to understand!

    My question, do you know where I should look if I want to customize the small “archive loops” that Woocommerce puts out when you use a shortcode like [related_products] or [sale_products]? Where do the functions for these short codes live? Can you customize them in a similar way as you do in this article?

    1. Thanks for your comment Benjamin! Those shortcodes still generate loops, so all you need is to “target” the name of the loop e.g. “related”. At some stage on this page there is an example for that: https://businessbloomer.com/woocommerce-conditional-logic-ultimate-php-guide/

  31. how to add description in single product-category

  32. Hello Sir,
    Your tutorials are really helpful, Thanks.
    My questions is how should I remove Sidebars of Shop page and show products in full width on screen. I tried from basic page settings but it didn’t worked for me.
    Please help.

    1. Paras, thanks for your comment! Yes, this is possible – but unfortunately this is custom to your specific theme and I cannot provide a complementary solution here on the blog. Thanks a lot for your understanding! ~R

  33. Hi Rodolfo,
    first I like to thank you for the tutorial, and I also have a question for you.
    I am tring to use the following code to print some content right before the title of products (an categories).

    add_action('woocommerce_shop_loop_item_title', 'custom_pre_title');
    function custom_pre_title(){
    	if(is_product_category()){
    		echo '<h3 class="product-title">I am a cat</h3>';	
    	}else{
    		echo '<h3 class="product-title">I am a prod</h3>';
    	}
    }

    It works like charm for products, but it does not show nothing on the categories.
    Just to be clear my website have to show both categories and products in the shop.

    Any suggestion in welcome.
    Thank you in advance.

    1. Hello again,
      I found myself a solution.
      While messing with categories you need to use different hooks like

      add_action('woocommerce_shop_loop_subcategory_title', 'custom_pre_cat_title');

      I found the needed hook while looking at the file:
      content-product_cat.php

      I did not check all your website, but if you missed it I think it will be nice to add also the hooks for the category.

      Thank you again for your really useful tips, and have a nice day.

    2. This is awesome Andrea, thank you very much!

  34. Hello Rodolfo,

    Thanks for sharing your knowledge!
    I juts get in touch to see if there is any way to can hook the shop page thumbnail. I am trying to greyed-out out of stock products but with no results…

    Any suggestions?

    Have a nice day!

    1. Thanks for your comment Diego! What have you tried so far?

  35. Thank you so much! This post is definitely very useful. Cheers!

    1. Awesome, thank you so much David!

  36. Hello Rodolfo

    wooCommerse catalog 4 column per row page product element adds a horizontal scroll bar for about 9 pixels of oversize that looks horible. Is there a Snippet to just remove the scroll bar.

    Thank You
    Jeff

    1. Hey Jeff, thanks for your comment! I’m afraid this is not a PHP thing, there is some customization required on the CSS end, as this is probably something that your theme is causing 🙂 Hope this helps!

  37. hi,
    i m new to woocommerce.
    i want to show the product list in the right side of the sidebar but its showing below
    and i added the below code in the theme’s functions.php –

     add_action(‘woocommerce_before_shop_loop’,’woocommerce_get_sidebar’,10); 

    pls help.

    1. Hey Manjil, thanks for your comment! I guess you also need some CSS work to reduce the width of the products, so you can make room for a sidebar on its left 🙂 Hope this helps!

  38. Hi Rudolfo,

    I love your articles and videos. It is all not so scary anymore!!

    I am trying to add a row of content on the shop page – before the main content.
    Using the Beaver Builder theme.

    I tried this code, and it gave me the blank screen:

    add_action( 'woocommerce_before_main_content', 'my_function_name' ); 
    function my_function_name() { 
    if(is_shop() || is_single()){ 
    echo do_shortcode('[fl_builder_insert_layout slug="product-display"]'); 
    } 
    } 
    

    Do you have any ideas on how to get a beaver builder on the shop page?

    Jean

    1. Hey Jean, thanks for your comment! What error do you get on the white screen?

  39. Rodolfo, first of all: GREAT tutorials! Indeed, I was also working a lot with plugins to get things done. Now, after watching several video’s you published, I removed a few plugins already.

    Okay, down to business 🙂 I have this strange thing going on, on my category pages. As expected, the thumbnails of products and other things like price, etc. are displayed correctly. But, down the category page, these products are once again displayed, but now with the full description. Any idea, what this might be?

    Thanks in advance.

    Gregory

    1. Hey Gregory, thanks for your comment and nice words 🙂

      I actually have no idea about your issue, it could be absolutely anything… did you add another [products] shortcode to your shop page? Not sure 🙂

    2. Problem solved!
      ‘Infinite scrolling’ in the Jetpack plugin was active.

  40. Thanks for sharing this! It’s very helpful. I was recommended this site to help me skip the product page on my Woocommerce shop. But unfortunately I can’t figure it out.

    Do you know how I can make the shop page thumbnails link directly to the external product? Instead of the users having to go to the product page first, and then click the external link?

    I can’t find anything about it anywhere.

    Current:
    Archive page > product page > external page.

    What I’m trying to do:
    Archive page > external page (in a new tab)

    I would really appreciate any help!

    1. Hey Nikolaj, thanks very much for your comment and feedback, much appreciated 🙂 I don’t offer free support/dev here on the blog, however I recommend you take a look at 2 things:

      1) This is how you can disable the link to the product page: https://businessbloomer.com/woocommerce-disable-link-to-product-loop/#woocommerce-snippet-2-hack-free-even-better-disable-link-to-products-loop

      2) Then, you can replace that link you removed above with the link to the external product, which you can get from a PHP function called get_product_url()

      Hope this helps 🙂

  41. I made a ajax product filter widget for best selling product . And its working fine but its changing shop page products layout means its displays 6 products per row . Before filter it was 3 products per row . Can you help me ?

    1. Hey Tushar, thanks for your comment! I’m afraid I can’t help you for custom work – hope you find a fix soon 🙂

  42. […] can find all the shop/archive WooCommerce hooks here. Let’s see how to use conditional logic on these “loop” […]

  43. Very helpful video indeed Rodolfo – thank you.

    Following the video I wanted to try and move the titles of the 2 categories (displayed on the shop page) from below the thumbnail to above it. On doing a bit of googling I found the following snippet – which made sense, and worked after a fashion.

    remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
    add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
    

    The problem was that this applied not only to categories, but also products too, which I didn’t want. So following your suggestions about conditional logic I tried changing it to:

    if ( is_shop() ) {
        remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
        add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
    }
    

    But that didn’t work either. On further googling I then found out that the conditional “is” checks do not work in the body of functions.php. They only work if they are within a function tied to an action. So, I was wondering if you know how I can run the remove_action and add_action conditionally?

    In advance, many thanks.

    1. Excellent 🙂

      You should put all your snippet in a function, and then call the function from somewhere else. I haven’t tested it, but the following should work:

      
      add_action( 'init', 'bbloomer_move_cat_titles');
      
      function bbloomer_move_cat_titles() {
      if ( is_shop() ) {
          remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
          add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
      }
      }
      
      

      Let me know 🙂

    2. Thanks Rodolfo.

      I had actually tried that. I was looking for a hook I could use that might allow me to do that and init was one I tried. And no change I’m afraid.

      I looked up what “woocommerce_template_loop_product_thumbnail” does, and it basically just issues :

      echo woocommerce_get_product_thumbnail();

      So the other thought I had was to maybe override that woo function:

      add_action( 'woocommerce_after_shop_loop_item_title', 'adz_template_loop_product_thumbnail', 10 );
      
      function adz_template_loop_product_thumbnail() {
      	if ( is_shop() ) {
      		remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
      		echo woocommerce_get_product_thumbnail();
      	}
      }
      

      Still no good – it’s almost like the category thumbnail and titile are not treated the same as products?

      You can see at the URL appended to this comment.

      🙁

    3. Andy, the remove_action cannot be called by the “woocommerce_after_shop_loop_item_title” hook as long as I know. It should either be on it’s own line, outside the function, or be called by the “init” hook (default WordPress). Other than that, the rest should work. Keep testing and let me know 🙂

    4. Hi Rodolfo

      Well, in case I had a typo I tried the init approach again..

      /* Woo - Move category titles to above thumbnail */
      add_action( 'init', 'adz_move_cat_titles');
      
      function adz_move_cat_titles() {
      	if ( is_shop() ) {
      		remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
      		add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
      	}
      }
      

      Still no joy I am afraid – no difference at all. Maybe the remove and add actions generally cannot be called within a function? Or maybe those 2 specific ones are called too late to have an effect. Perhaps the answer is to change the template?

    5. Hey Adam, I just tested this on 2016 theme and if you remove the is_shop() check it works. Give it a go and let me know. R

    6. Hi Rodolfo

      Thanks for helping again!

      Sorry – the same as before – removing the is_shop check means it works on on the products page. So the list of products (e.g range of business cards) have the title’s above the thumbnails (which I don’t want – for the listed products I want the title underneath), but the parent page that just lists the 2 categories of “Business Cards” and “Stationery” have the titles stuck under the thumbnails.

      See the site URL for the catalogue for this post – you’ll see categories have the titles underneath, but if you click on a category, the resultant products listed have their titles above. I’m trying to get it the other way around

      🙁

    7. I found the solution 🙂 Instead of using “init” please use “wp_head” (and keep the is_shop() check as you said). Init is too soon for conditional logic!

    8. Hi Rodolfo

      Think I had tried wp_head before too – but tried it again:

      add_action( 'wp_head', 'adz_move_cat_titles');
      function adz_move_cat_titles() {
      	if ( is_shop() ) {
      		remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
      		add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
      	}
      }
      

      Sorry – no change. Catalogue page listing the categories; title is still below thumbnail, but products page titles are now back to under thumbnail as required. In my opinion there’s definitely something different about listing the categories as opposed to listing normal products (i.e. Categories are not treated like products)?

    9. Hey Adam 🙂 Well, there must be something in your theme and/or plugins that is already overriding/removing WooCommerce default hooks. I placed this snippet in the functions.php file of 2016 theme and it worked, so maybe disable everything temporarily and see if anything happens 🙂

  44. Hi Rodolfo, there wasn’t a reply button on your last comment so I had to create a new comment – sorry.

    Anyway, I’ve restored the archive-products.php to it’s oroiginal state as you advised, and I also added the code you sent to my functions.php (the one in the child theme). but nothing is showing at the bottom of my shop page or category page. It’s as you said, I think the theme author has removed it. Is there anyway to restore it into the archive-products.php file?

    Also does it matter that the archive-products.php file is not in a fiolder called templates. It is in wp-content>themes>themefolder>woocommerce>archive-products.php

    1. No problem – thanks for spotting the “max 5 comments bug” 🙂 So, yes, you’re right, they removed that part. No idea why!

      Anyway, copy that file into your child theme’s /woocommerce folder (if it’s not there already, and yes – you don’t need to create a /templates folder), and just before the last closing add:

      
      <?php do_action( 'woocommerce_after_shop_loop' ); ?>
      
      

      Then, go to your functions.php and do what I said in the last comment.

      Let me know 🙂

    2. Still no luck Rodulfo 🙁

      I added the archive-products.php file into my child theme and added the

      <?php do_action( 'woocommerce_after_shop_loop' ); ?>

      at the end, but still no joy. Just in case I put it in the wrong place, i also tried placing it near the top and towards the middle. but still nothing.

      Its strange because when I change the functions.php file to

      add_action( 'woocommerce_before_shop_loop','show_category_intro_TEST');

      , it works just fine, the text appears at the top – just like in your tutorial video.

      At this point I’m really baffled.
      Since I have the archive-products.php in my child theme now, I guess I could just go ahead and make changes to it directly without worrying about an update that might break things, right? Although, it would be really good to get this working the correct way.

    3. Have you tried calling it differently e.g.

      
      <?php do_action( 'woocommerce_after_shop_loop_CUSTOM' ); ?>
      
      

      Then of course, you will need to use that hook in your add_action.

    4. Renaming it doesnt seem to work either. I added

      <?php do_action( 'woocommerce_after_shop_loop_CUSTOM' ); ?>

      to the very end of the archive-products.php file. is that the correct place for it? or should it be somewhere else?

    5. Lol, I should have said this 6 comments ago… can you email me your WP & FTP details and I’ll take a quick look for a minute?

  45. Excellent video Rodolpho. just one question. The ‘woocommerce_after_shop_loop’ and the ‘woocommerce_after_main_content’ dont do anything to add content to the bottom of my theme’s shop page. I’ve checked the archive-products.php in my theme and there is no mention of either ‘woocommerce_after_shop_loop’ or ‘woocommerce_after_main_content’. COuld it be that I need to add them manually? If so, could you kindly explain how please.

    1. Thanks Ewan! It seems your theme is overriding the WooCommerce template, which is actually not recommended. Not sure if they are overriding an old version which did not contain those actions (weird), or they removed them (even more strange). Is your theme up to date i.e. they released an update in the last 3-4 weeks and you’re running that version?

    2. Yes, its a very up to date version a theme called The Retailer. I’m tempted to email in to their support desk to ask for help, but from past experience I know they will just tell me it’s beyond the scope of their support 🙁

      This is what the archive-products.php looks like:

       
      <?php
      /**
       * The Template for displaying product archives, including the main shop page which is a post type archive.
       *
       * Override this template by copying it to yourtheme/woocommerce/archive-product.php
       *
       * @author 		WooThemes
       * @package 	WooCommerce/Templates
       * @version     2.0.0
       */
       
      global $theretailer_theme_options;
      
      global $wp_query;
      
      //woocommerce_before_main_content
      remove_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20, 0 );
      remove_action( 'woocommerce_before_main_content', 'woocommerce_output_content_wrapper', 10 );
      
      add_action( 'woocommerce_before_main_content_breadcrumb', 'woocommerce_breadcrumb', 20 );
      
      //woocommerce_before_shop_loop
      remove_action( 'woocommerce_before_shop_loop', 'woocommerce_result_count', 20 );
      remove_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 );
      
      add_action( 'woocommerce_before_shop_loop_result_count', 'woocommerce_result_count', 20 );
      add_action( 'woocommerce_before_shop_loop_catalog_ordering', 'woocommerce_catalog_ordering', 30 );
      
      
      //woocommerce_after_shop_loop
      add_action( 'woocommerce_after_shop_loop', 'woocommerce_pagination', 10 );
      add_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end', 10 );
      
      
      
      ....
      
      ....
      
      

      Near the bottom you can see some echo lines where I’ve attempted to add the content manually. That seems the only way to do it for now.

      This works fine, but I’m worried about when the theme gets updated. Do you have any suggestions?

    3. See at the top where they use remove_action? There they’re removing some WooCommerce default actions and substituting them with their own ones.

      However, “woocommerce_after_shop_loop” is still there, so it must work.

      Can you post the snippet you’re using, as there must be an error there 🙂

    4. Apologies, I added those lines, because they were not in there:

       
      //woocommerce_after_shop_loop
      add_action( 'woocommerce_after_shop_loop', 'woocommerce_pagination', 10 );
      add_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end', 10 );
      

      I should have made that clear, sorry. (I just copied them from your visual guide page thinking that i could manually add them)

      The lines above + the echo bits are my own additions.

      Either way, this is the snippet I’m using:

       
      <?php
      add_action( 'woocommerce_after_shop_loop','show_category_intro');
         function show_category_intro() {
      	if ( is_product_category('silk-fabrics') ) {
      		echo 'This should only appear on the silk fabric category  pages';
      		}
         }
      

      I really appreciate you taking the time to reply to my question 🙂

    5. Alright Ewan, a bit of a mess here – let’s see if I can help a little more:

      1) Please restore the original archive-products.php. From that moment on, all your PHP customization will exclusively be placed in functions.php instead

      2) Try this in your functions.php:

      
      add_action( 'woocommerce_after_shop_loop','show_category_intro_TEST');
         
      function show_category_intro_TEST() {
         echo 'This is a test. This should show under ALL loop pages such as shop, cats and tags';
      }
      
      

      Let me know if this first test works!

  46. Just wanted to thank you for taking the time to make these visual guides, they are extremely helpful and come in handy all the time. Actually saved me from purchasing some plugin that builds Woo templates, No need when Rodolfo taught me how to do it myself! ha!

    Thanks again Rodolfo you are awesome.

    1. Kyle, thank you SO MUCH! You made my day & weekend already 🙂

  47. Hi,

    I have a design for my shop page. how can I customize shop page to look like my design ? can you please give suggestion ?

    Thank in advance

    1. Hey Ferdaus, thanks for your comment! I’m afraid without looking at your design I find it difficult to give you suggestions 🙂 Upload them to Google Docs or DropBox and I’ll take a look!

    2. Here is the design link please check it and help me .

      http://prntscr.com/bayk2h

      Thank you

    3. Ferdaus, thanks for the link. I’m afraid that’s way too custom and I can’t help you in this occasion 🙂 Hope you can find a skilled freelancer that can help you with that complicated layout! Thanks 🙂

  48. Hey! Loving your guides! Thank you! One thing I have trouble with is product attribute archives. They look like category pages but are not as I realize when trying to modify them. I´d like to put the attribute archive description below the products but cannot find how to do it! do you have a solution for that perhaps? 😀

    1. Thank you Asa! Much appreciated 🙂 In relation to the product attribute archives, they use the same template file of Product Tags: taxonomy-product_tag.php, and have the same exact hooks of the Archive/Shop/Cat/Tag pages. What are you trying to display? Thank you!

    2. hmm, well then it is something else I don´t understand 🙂 Thought Woo changed the attribute set up to not act as a taxonomy anymore! I am trying to make the attribute archive page to look like a tag or a category page. I am using the genesis framework. This is a category on my site: https://asamaria.se/produkt-kategori/orhangen/ I have descriptions above and below the products. the genesis category description above and then I have moved the “usual” description to display below. Now look at an attribute page https://asamaria.se/pa_adelsten/ametist/ that description you see is the description output by genesis. There is no display of the “ususal” description. The field is present in the editor so I have text there but it is not visible.

      This is what I used to move the usual description to below the products

      remove_action( ‘woocommerce_archive_description’, ‘woocommerce_taxonomy_archive_description’, 10 );

      add_action( ‘woocommerce_after_shop_loop’, ‘woocommerce_taxonomy_archive_description’, 100 );

      works perfectly on categories and tags. Ideally I would like to show the attributes on the single products page and have that link to the attribute. Now I have blocked the attribute form search engines and added them as tags as well. I guess it works but I would love to have the attributes there. You know like: Metal: Silver, Gemstone: Amethyst, Model: Effie

      What am I missing? 🙂

    3. Hey Asa 🙂 The woocommerce_taxonomy_archive_description() only works for tags and categories. This is why it does not show for attributes.

      You will need to code this from scratch and do something along the line of “if is product attribute page, show attribute description”.

      Hope this helps!

  49. hello Rodolfo. You know what!!?? Thank you very much!! i like it!!

    1. Thank you Olivier 🙂 Much appreciated!

  50. Excellent resource! Thank you so much!!!

    1. Thank you Patty! Any particular request for the next Visual Guide?

Questions? Feedback? Support? Leave your Comment Now!
If you're writing code, please wrap it between: [php] code_here [/php]

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.