Hide prices and add-to-cart buttons by category

I recently decided to hash a problem out for someone on a reddit post, because A: I was intrigued by the problem and B: the solution ended up not being as simple as I thought.

What this redditor wanted was a way to hide prices for users who weren’t logged in. This is normally quite easy and can be done the way Rodolfo Melogli has done over here: https://www.businessbloomer.com/woocommerce-hide-price-add-cart-logged-users/. Nice and clean, and it works well. The only problem is that in addition to applying this to logged-out users, our redditor wanted this to work only for a certain category of items. The rest of the websites price’s can be visible to users who aren’t logged in.

That makes things a little more complicated. While it’s easy to filter for a certain category, you can’t simply remove the actions and drop in new ones as described on Rodolfo’s website. If you try, as soon as you filter the category in the loop and remove the action, you actually end up removing the action for everything after that even if it didn’t fall into the filter. Not ideal.

I had to deal with this problem basically on 2 fronts: filtering out the categories in the product loop, and then also filtering them out for single products (i.e. when you click on a product and view it). Both of them require different code to handle the add-to-cart buttons and whether the price is shown or not. I found a much better way to deal with this and all it required was finding the right hook and filtering it in the correct place.

First, let’s see how to remove the add-to-cart button and replace it for the single product view. The code below actually also does work outside of the single product pages, it changes the add-to-cart links to “Read More”, but I went a step further and changed the text and links as required. First for the single products and then for the shop loop in the next step.

add_action('woocommerce_before_main_content', 'semper_modify_purchasable');

function semper_modify_purchasable( $is_purchasable ) {
  if ((has_term('hoodies', 'product_cat') && !is_user_logged_in())) {
      add_filter('woocommerce_is_purchasable', '__return_false');

      if (is_singular()) {
          add_action( 'woocommerce_single_product_summary', 'semper_login_for_price_button', 31);
      }
    
  } 
  return $is_purchasable;

}

function semper_login_for_price_button() {
  echo sprintf('<a class="single_add_to_cart_button button alt" href="%s">%s</a>', esc_url(get_permalink(wc_get_page_id('myaccount'))), __('Login to see prices', 'text-domain'));
}

In my initial attempts at this I made use of the 'wp' action hook to remove and add the 'woocommerce_single_product_summary' but I prefer to hook into actions only right when they’re needed, not right in the beginning or the end after everything has run. I also don’t like to remove or add actions unnecessarily, which is why I’ve checked that we’re on a singular product page before removing and adding the actions required. The removing and adding of the single summary template is also only technically required for variable products, because if you make something “non-purchasable” it removes the add to cart button for single products, but it still allows product selection and only disables the add-to-cart button, rather than completely removes it, for variable products. The 'woocommerce_is_purchasable' filter also prevents someone from being sneaky and calling the add-to-cart URL with the correct product ID and adding the item to the cart. Unlikely, but why not close that door while we’re here?

The next step is to modify the add-to-cart buttons in the shop loop. This changes the text and URL for the shop and category archive pages.

add_filter('woocommerce_loop_add_to_cart_link', 'semper_modify_add_to_cart_link');

function semper_modify_add_to_cart_link($add_to_cart_html) {
  if ( has_term('hoodies', 'product_cat') && !is_user_logged_in() ) {
    $add_to_cart_html = sprintf('<a href="%s" class="button">%s</a>', esc_url(get_permalink(wc_get_page_id('myaccount'))), __('Login to see prices', 'text-domain'));
  }

  return $add_to_cart_html;
}

The last step is to hide the prices. This one is simple and you can either remove the prices completely or change it to something else.

add_filter( 'woocommerce_get_price_html', 'semper_hide_prices' );

function semper_hide_prices( $price) {
  if (!is_admin() && has_term('hoodies', 'product_cat') && !is_user_logged_in()) {
    $price = '##.##'; // You can set this to '' to remove the price altogether. 
  }
  return $price;
}

That wraps it up. It’s a bit more complicated than simply removing all the prices and add-to-cart buttons for logged-out users but anything can be done and customized exactly the way you want it. As always, drop the code into your functions.php file. Here’s the full Gist:

Leave a Reply

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

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.