Blog

Disable Repeat WooCommerce Purchases for a Product Category

We previously wrote up a tutorial on preventing repeat purchases for a particular WooCommerce product, or for any product in your store. However, based on the comments there, some merchants wanted to disable repeat WooCommerce purchases for a set of products, but not all products.

In order to do so, you could use a product category to check whether repeat purchases should be allowed or not. This would let you group all products that shouldn’t allow multiple purchases into your own category (i.e., a “Single Purchase” category), and check for this to see if customers should be able to purchase.

Obviously this will only work for logged-in customers, as without having the customer logged in, we have no way of knowing their email to see if they’ve bought a product.

Let’s take a look at checking for a product category, then disabling purchase if a product is in the desired category. We’ve discussed checking the cart for a particular category, so we’ll do something similar with the has_term() check here.

This tutorial requires intermediate WooCommerce and PHP development skills.

A Helper: Check if the Customer Has Purchased Before

First, we’ll set up a helper method that does one thing given a product: checks if the customer has bought it before. Typically the wc_customer_bought_product() function would do just fine, but we want to see if the product is in a given category before making this check.

Let’s write a helper function whose only purpose is to run this check if the product is in our target category (the one for which repeat purchases are not allowed). Note that to our helper requires WooCommerce 2.5 or newer since it uses the $product->get_id() method.

/**
 * Helper function to see if a customer has purchased a product 
 * in a given category
 *
 * @param \WC_Product $product the WooCommerce product instance
 * @return bool - true if product is in category and has been purchased
 */
function sv_wc_customer_purchased_product_in_cat( $product ) {

    // enter the category for which a single purchase is allowed
    $non_repeatable = 'clothing';
    
    // bail if this product is in not in our target category
    if ( ! has_term( $non_repeatable, 'product_cat', $product->get_id() ) ) {
        return false;
    }
    
    // the product has our target category, so return whether the customer purchased
    return wc_customer_bought_product( wp_get_current_user()->user_email, get_current_user_id(), $product->get_id() );
}

Alright, this is a nice small function: give it a product, return whether it’s been purchased and is in our no-repeats category.

Disable Product Purchasing

Next, we’ll use this function to check if the product meets our criteria, and if so, we’ll disable purchase. We did this in more detail in the previous tutorial, but the gist of it is we’ll use the woocommerce_is_purchasable filter and the woocommerce_variation_is_purchasable filter.

We probably don’t need the latter one, but in case direct add to cart links are used somewhere for the variation, it’s a good safety net.

/**
 * Disables repeat purchase for a product category; checks if a product is in the category
 * and if it's already been purchased, then disables purchasing if so
 * 
 * @param bool $purchasable true if product can be purchased
 * @param \WC_Product $product the WooCommerce product
 * @return bool - the updated is_purchasable check
 */
function sv_wc_disable_repeat_purchase( $purchasable, $product ) {

    if ( sv_wc_customer_purchased_product_in_cat( $product ) ) {
        $purchasable = false;
    }
    
    // double-check for variations: if parent is not purchasable, then variation is not
    if ( $purchasable && $product->is_type( 'variation' ) ) {
        $purchasable = $product->parent->is_purchasable();
    }
    
    return $purchasable;
}
add_filter( 'woocommerce_variation_is_purchasable', 'sv_wc_disable_repeat_purchase', 10, 2 );
add_filter( 'woocommerce_is_purchasable', 'sv_wc_disable_repeat_purchase', 10, 2 );

Now we’ve disabled repeat purchasing, so the “add to cart” section will be removed from product pages, and the shop loop will say, “Read More” for the product instead of “Add to cart” or “Select Options”.

Let’s add a nicer notice to the product page instead explaining why it can’t be purchased.

Add a “Purchase Disabled” Message

This one is a pretty straight-forward function: use a product page action to check if the product meets our criteria, add a notice on the product page if so.

/**
 * Shows a "purchase disabled" message to the customer
 */
function sv_wc_purchase_disabled_message() {

    // get the current product to check if purchasing should be disabled
    global $product;
    
    // now we know we're in the category, check if we've purchased already
    if ( sv_wc_customer_purchased_product_in_cat( $product ) ) {
        // Create your message for the customer here
        echo '<div class="woocommerce"><div class="woocommerce-info wc-nonpurchasable-message">
        You\'ve already purchased this product! It can only be purchased once.
        </div></div>';
    }
}
add_action( 'woocommerce_single_product_summary', 'sv_wc_purchase_disabled_message', 31 );

Now for products in our target category that have not been purchased before, they’ll look pretty standard:

WooCommerce standard purchase

However, once a product in this category has been purchased, it will have the purchasing disabled and will show our custom message:

WooCommerce Disable category repeat purchase

Summary

This gives you a way to disable repeat purchases for multiple products by grouping them together into a category. You can view the full code in this gist to see it all put together.

This will not disable purchasing for the entire category if one product is purchased (just the one the customer already bought), as this kind of set up would be more complex — we don’t have a simple way to check, “has the customer bought anything in this category?” so set ups that require disabling purchase for a different product when another is purchased would require a fair bit of customization, for which this can be a starting point.

Need some help taking this further? We recommend the folks at Codeable, who do a great job with customization requests like this.

9 Comments

  • […] for developers: you can disable repeat purchases for a WooCommerce product category using this tutorial from […]

  • Josh Rogers 10 months ago Reply

    YES! Thanks Beka – my client has been waiting on this for a while now, and I’m so grateful you took the time to write it out for other developers.

    Thank you,
    Josh

  • Raman 8 months ago Reply

    Thank you.
    This was useful.
    Only issue is that if the product has been added to the cart before the user logs in, then after logging in, the item gets removed from the cart with a message: “The item has been removed from the cart because it can no longer be purchased”. This message is little confusing for the user. It will be good to customize it saying that it is a repeat purchase and hence removed from the cart.

    Thank you,
    Raman

    • Beka Rice 8 months ago Reply

      Hey Raman, to target the message to this specific situation would be a little involved to do, but if you wanted to always change that message, you could translate it with a plugin like Say What?.

      • Raman 7 months ago Reply

        Thank you very much for the suggestion. I will try.

  • Szilard 4 months ago Reply

    Thanks Beka,

    I have some issue with this solution. After purchase sometimes I got an error msg on the thank you page telling me that the item was removed from my cart because it can’t be purchased. I think it happens because woocommerce leaves the item in the cart after purchase and removes it only as the last step of the checkout. So there is a moment when the item is already purchased but the cart still contains the item. Is there any way to fix this?

    Best,
    Szilard

  • Danny 2 months ago Reply

    Can this script include guest checkout as well?

    • Beka Rice 2 months ago Reply

      This would need to be done differently for guest users given that you don’t have access to an email address for them on product pages, so there’s nothing to check against to disable purchasing. Instead, the only place you could do this check is when “Place Order” is clicked and add warnings / empty the cart as needed, so it’s not really something this would assist with directly.

      • Danny 2 months ago Reply

        Hey Beka, thank you for the swift response and I can understand where you’re coming from. Looks like more thinking is going to have to go into this.

Submit a Comment