Conditionally remove the 'Add to cart' button in WooCommerce.
Earlier this month Ptunder commented on my Product Enquiry form using WooCommerce and Contact Form 7 post asking how to remove the “Add to cart” button for products above a certain price. With WooCommerce the answer is likely actions (or maybe filters).
I searched through the WooCommerce source code for the add_action() calls that add the “Add to cart” buttons to the single product page and the category archive pages.
For the single product page there are 4 calls, corresponding to the different product types – single, variable, external and grouped. The category archive page had one call.
Then I wrote a small plugin to make matching remove_action() calls. This removed all those buttons. That’s step 1. Then I began on the conditional part, adding a function that would call these remove_action() calls.
Later that evening I read a post in the Advanced WooCommerce Facebook group where the poster was trying to do the very same thing – conditionally remove the “Add to cart” button. His initial plan was similar to mine – remove_action() calls – but ended up using the filter in the is_purchasable() product class member function. Removing actions is easy for a single product page but gets complicated for the category archive page as you have to remove and add the action after examining each product in the page. A filter is simpler to code.
I did a quick experiment on the single product page. My test page uses the Storefront theme and shows 3 Related Products under the product listing. The filter in the is_purchasable() function was called twice for the main product and then 6!! times for each of the related products!
In the category archive showing 12 products, the filter was called 6 times for each simple product, 3 times for each variable product, 2 times for each grouped product and 2 times for each external product.
My filter function will have to cater for this situation and cache information so that it doesn’t slow down the site. A PHP class will be needed.
The code here uses an array to cache whether each product can be purchased so that it can just return that decision when the filter function is called multiple times. It includes two simple examples:
- Use has_term() to check if product in specific categories e.g. has_term( array(‘hoodies’, ‘accessories’ ), ‘product_cat’, $product->get_id() )
- Check if price above or below a certain price using $product->get_price().
This situation does allow the customer to see all possible variations. Removing the ‘Add to cart’ button would require additional add_action() and remove_action() calls and, as mentioned earlier, gets messy for category archives.
When I was looking for ideas on conditionals I found a great one at Business Bloomer – Rename ‘Add to cart’ button if product already in cart. This code would be easily adapted as a conditional to remove the ‘Add to cart’ button.
You could also check whether the product has a specific shipping class or the stock level is below a certain amount. As the filter function receives the product object, you can check anything about the product.