
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).
Some actions
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.
Caching
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
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().
The user experience for a variable product isn’t ideal. The ‘Add to cart’ button is still shown but no variations can be added to the cart – the button is disabled and a JavaScript alert is shown with the message: “Sorry, this product is unavailable. Please choose a different combination.“
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 adding this to a client site I felt that the JavaScript alert wasn’t a good user experience so I added the code to hide the variations dropdown and the ‘Add to cart‘ button. The category archives says ‘Read more‘ and that is okay.
Enhancements
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.
This is great but I have one question, would it be possible to still show the variations on a variable product and just hide the price and add to cart buttons?
I’m trying to use it to allow customers to get a quote on items that are not directly purchasable from the site
@Joss – If you comment out line 80 you will still see the variations dropdown(s).
remove_action( 'woocommerce_variable_add_to_cart', 'woocommerce_variable_add_to_cart', 30 );
It does show the price when a variation is selected. You could use CSS to hide that e.g.
.woocommerce-variation-price { display: none; }
You could then use CF7 for a quote form or Ninja Forms.
Hi, Thanks for the code! How can I use this to remove the ‘add to cart’ if a value of “hide me” has been selected from a drop down box/select element with a name of “drop down1” Thanks!
@Greg: If you have a variable product then it is quite difficult as you would need JavaScript code to watch the attribute dropdowns and hide and unhide the button.
It would probably be much easier to change either not have the variation in question as an option or set the variation to be out of stock and use CSS to hide the button (I think that the button gets a new class or gets set to disabled and you could make use of that feature in your CSS).
It’s not a variable product. It’s a simple product actually and we have overlaid a plugin that allows people to customise the options on the product. It is literally just metadata so that we know how to produce the base product they select.
Anyways, seems like the code they provided here works. What do you think Damien? :) https://stackoverflow.com/questions/64780548/hide-add-to-cart-when-certain-value-in-dropdown-is-selected
Hi! Thanks for the sharing this awesome feature! How can the code be modified so you can actually still allow the purchase of simple products in the backend while still keeping the add-to-cart button disabled on single product pages? I see that variations of variable products can actually still be bought via https://example.com/add-to-cart=25 (variation product ID) while for simple products it is not possible.
Thanks!
@Florian – I fixed the issue with variable products – I added code to check the categories of the parent product when determining whether to include or exclude it.
Hi, can you add dp code to be able to change the texts on the buttons? Instead of “Read More” and “Add to cart” for any? It would be great :)
Thnx
@Greg – I suggest using the ‘woocommerce_product_add_to_cart_text’ filter to change ‘Select options’/’Read more’/’View products’ (it depends on whether it is a simple, variable or grouped product) and ‘woocommerce_product_single_add_to_cart_text’ for ‘Add to cart’/’Read more’ (it depends on whether the product is purchasable).
Your filter function will have to check the product type and $product->is_purchasable(). The $product object is passed to the filter function.
Hello, Thanks for this valuable code. I guess, I am in the right place to ask about a similar issue. Please click the link below to see the screenshot: https://ibb.co/RjLCNBK My idea is to have a regular page where the customer can add the minimum item to the cart and then once that minimum item/ quantity is added, the section marked in the green outline then drops down from behind the add to cart option to allow the customer to now order more units to add to their minimum purchase. So for example, the minimum order is a 6 pack of cookies but then after ordering that, the customer can just add another 1 or 2 extra to make the order 7 or 8 of those cookies to their total order. I need your help in this regard. is there any free or paid plugin for this purpose? If not, can you provide me with any code or guide to it? Many thanks
@Abdul – Your idea to reveal a new section to order above the minimum sounds like a confusing user experience.
I did find a free plugin but it might only set a minimum quantity for all products: https://wordpress.org/plugins/min-and-max-quantity-for-woocommerce/
There is a plugin from WooCommerce for $39 per year. https://woocommerce.com/document/minmax-quantities/ I think that it sets the minimum amount but does not have an “extra” section like you said. I think that not having the extra section is easier for customers.