Posted on Leave a comment

How to hide products by user role in WooCommerce

Sometimes you need to hide a product or make it non-purchasable depending on the visitor’s user role, for example, make all products non-purchasable for not logged users, i.e. “guests”. You can use a plugin for that or add a PHP snippet to your (child) theme’s functions.php file.

There is a number of ways we can make product non-purchasable or hide it from the shop:

In addition we can also:

First of all, we will need functions to determine if we need to hide a product for the current user’s role.

if ( ! function_exists( 'wpf_is_current_user_role' ) ) {
    /**
     * Checks current user's role. Handles multiple roles per user.
     */
    function wpf_is_current_user_role( $roles_to_check ) {
        $current_user       = wp_get_current_user();
        $current_user_roles = ( empty( $current_user->roles ) ? array( '' ) : $current_user->roles );
        $roles_intersect    = array_intersect( $current_user_roles, $roles_to_check );
        return ( ! empty( $roles_intersect ) );
    }
}
if ( ! function_exists( 'wpf_do_hide_product' ) ) {
    /**
     * Checks if the product needs to be hidden.
     */
    function wpf_do_hide_product( $product_id_to_check ) {

        // TODO: You need to replace product IDs & user roles with your own here.
        $products_to_hide  = array( 100, 150 );       // product IDs
        $roles_to_hide_for = array( '', 'customer' ); // empty string is for the "guest" user role

        // Check if the product must be hidden.
        return (
            in_array( $product_id_to_check, $products_to_hide ) && // product ID match
            wpf_is_current_user_role( $roles_to_hide_for )         // user role match
        );
    }
}

Hiding products from the catalog

To hide products from the catalog we can use woocommerce_product_is_visible filter. This will hide selected products in shop and search results. However, the products still will be accessible via direct link.

Before After
How to hide products by user role in WooCommerce - Catalog - Before How to hide products by user role in WooCommerce - Catalog - After
add_filter( 'woocommerce_product_is_visible', 'wpf_product_visible_by_user_role', PHP_INT_MAX, 2 );
if ( ! function_exists( 'wpf_product_visible_by_user_role' ) ) {
    /**
     * Hides product from shop and search results by user role.
     */
    function wpf_product_visible_by_user_role( $visible, $product_id ) {
        return ( wpf_do_hide_product( $product_id ) ? false : $visible );
    }
}

Making products non-purchasable

To make products non-purchasable we can use woocommerce_is_purchasable filter. This will make selected products non-purchasable, i.e. products can’t be added to the cart.

Before After
How to hide products by user role in WooCommerce - Purchasable - Before How to hide products by user role in WooCommerce - Purchasable - After

The algorithm is similar to hiding product in catalog, however, instead of $product_id we are passing $product->get_id().

add_filter( 'woocommerce_is_purchasable', 'wpf_product_purchasable_by_user_role', PHP_INT_MAX, 2 );
if ( ! function_exists( 'wpf_product_purchasable_by_user_role' ) ) {
    /**
     * Makes product non-purchasable by user role.
     */
    function wpf_product_purchasable_by_user_role( $purchasable, $product ) {
        return ( wpf_do_hide_product( $product->get_id() ) ? false : $purchasable );
    }
}

Removing products price

We can remove product price by user role and in addition, as there is no price, WooCommerce will make the product non-purchasable automatically.

Before After
How to hide products by user role in WooCommerce - Purchasable - Before How to hide products by user role in WooCommerce - Price - After

Again, the algorithm is similar to hiding product in catalog or making non-purchasable, however, instead of false we are returning empty string ''.

add_filter( 'woocommerce_product_get_price', 'wpf_remove_product_price_by_user_role', PHP_INT_MAX, 2 );
if ( ! function_exists( 'wpf_remove_product_price_by_user_role' ) ) {
    /**
     * Hides product price by user role.
     */
    function wpf_remove_product_price_by_user_role( $price, $product ) {
        return ( wpf_do_hide_product( $product->get_id() ) ? '' : $price );
    }
}

Hiding products by user ID instead of user role

If we need to check the exact user (instead of user role), we can use user’s ID. “Guest” will have ID at 0.

if ( ! function_exists( 'wpf_is_current_user_id' ) ) {
    /**
     * Checks current user's ID.
     */
    function wpf_is_current_user_id( $user_ids_to_check ) {
        $current_user = wp_get_current_user();
        return ( in_array( $current_user->ID, $user_ids_to_check ) );
    }
}

We’ll need to replace wpf_is_current_user_role() with wpf_is_current_user_id() in wpf_do_hide_product() function.

if ( ! function_exists( 'wpf_do_hide_product' ) ) {
    /**
     * Checks if the product needs to be hidden.
     */
    function wpf_do_hide_product( $product_id_to_check ) {

        // TODO: You need to replace product & user IDs with your own here.
        $products_to_hide  = array( 100, 150 ); // product IDs
        $users_to_hide_for = array( 10, 20 );   // user IDs

        // Check if the product must be hidden.
        return (
            in_array( $product_id_to_check, $products_to_hide ) && // product ID match
            wpf_is_current_user_id( $users_to_hide_for )           // user ID match
        );
    }
}

Hiding products by product category instead of product ID

If we need to hide product by category:

if ( ! function_exists( 'wpf_is_product_cat' ) ) {
    /**
     * Checks product's category.
     */
    function wpf_is_product_cat( $product_id, $product_cats ) {
        $current_cats = get_the_terms( $product_id, 'product_cat' );
        if ( $current_cats && ! is_wp_error( $current_cats ) ) {
            $current_cats   = wp_list_pluck( $current_cats, 'slug' );
            $cats_intersect = array_intersect( $current_cats, $product_cats );
            return ( ! empty( $cats_intersect ) );
        }
        return false;
    }
}

And in wpf_do_hide_product() function:

if ( ! function_exists( 'wpf_do_hide_product' ) ) {
    /**
     * Checks if the product needs to be hidden.
     */
    function wpf_do_hide_product( $product_id_to_check ) {

        // TODO: You need to replace product categories & user roles with your own here.
        $product_cats_to_hide = array( 'hoodies', 'hats' ); // product categories (slugs)
        $roles_to_hide_for    = array( '', 'customer' );    // empty string is for the "guest" user role

        // Check if the product must be hidden.
        return (
            wpf_is_product_cat( $product_id_to_check, $product_cats_to_hide ) && // product category
            wpf_is_current_user_role( $roles_to_hide_for )                       // user role match
        );
    }
}
Leave a Reply

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