I originally wrote this guide to work with the WP Approve User plugin, however that plugin appears to not be well maintained any longer, so this is a similar guide for the “New User Approve” plugin instead.

When building an ecommerce website with wholesale functions, there were two key modifications that needed to be completed to WooCommerce in order to make it work for the customer’s business:

  1. New users (distributors) must be able to be moderated by an admin so the site owner can choose to approve or reject them as distributors of their product
  2. Visitors must be blocked from seeing pricing and adding items to their cart until they have been registered and approved

Catalog Visibility

In order to hide pricing and block adding items to the cart for users that are not logged in, WooCommerce already has a fantastic (albeit paid) plugin called Catalog Visibility Options. This plugin worked perfectly for what we needed using just a couple drop downs. What it doesn’t do (nor does it claim to do) is manage user registrations – the other half of the puzzle.


User Moderation

Although the New User Approve plugin is a well devised addition to WordPress, the custom registration and login capabilities of WooCommerce do not play nicely with plugins that use registration and login hooks. Additionally, WooCommerce has some great email notifications built in, whereas New User Approve has its own designed notifications.

Upon installing New User Approve, the user registration process goes like this:

  1. User registers
  2. WooCommerce automatically logs them in [PROBLEM]
  3. If the user logs out, they can’t get in again since they have yet to be approved

Removing / working around auto login

At this point, the registration is not obeying the New User Approve plugin when it automatically logs the user in, but the login form *is* obeying the hooks provided by New User Approve. In order to fix this automatic login during registration, I wrote the following hooks to be placed in your theme’s functions.php file:

function ws_new_user_approve_autologout(){
       if ( is_user_logged_in() ) {
                $current_user = wp_get_current_user();
                $user_id = $current_user->ID;
                if ( get_user_meta($user_id, 'pw_user_status', true )  === 'approved' ){ $approved = true; }
        else{ $approved = false; }
        if ( $approved ){ 
            return $redirect_url;
                else{ //when user not approved yet, log them out
                        return add_query_arg( 'approved', 'false', get_permalink( get_option('woocommerce_myaccount_page_id') ) );
add_action('woocommerce_registration_redirect', 'ws_new_user_approve_autologout', 2);
function ws_new_user_approve_registration_message(){
        $not_approved_message = '<p class="registration">Send in your registration application today!<br /> NOTE: Your account will be held for moderation and you will be unable to login until it is approved.</p>';
        if( isset($_REQUEST['approved']) ){
                $approved = $_REQUEST['approved'];
                if ($approved == 'false')  echo '<p class="registration successful">Registration successful! You will be notified upon approval of your account.</p>';
                else echo $not_approved_message;
        else echo $not_approved_message;
add_action('woocommerce_before_customer_login_form', 'ws_new_user_approve_registration_message', 2);

This accomplishes two things. It takes care of making sure the user is logged out immediately after WooCommerce logs them in, and second it notifies the user that their registration completed successfully, but they cannot login until they have been approved. The successful registration notification was never needed by WooCommerce because it normally just logs them right into their account – something we can’t do in this case.

Notification Emails

New User Approve has a couple of Action Hooks we can plug in to for sending out notification emails. Although I didn’t make use of the unapprove hook, you can easily duplicate my existing work to make that happen if you wish.

You will want to first do as WooCommerce suggests: “For more advanced control copy woocommerce/templates/emails/ to yourtheme/woocommerce/emails/.”

Once you’ve’ copied the templates for adjustment, head to yourtheme/woocommerce/emails and edit the customer-new-account.php file.

Note that with WooCommerce 3.0 and newer you can now do this from the UI by going to WooCommerce > Settings > Emails and clicking the cog icon to the far right of the “New account” email template in the list. Click the “Copy file to theme” button. Once done, you can then click “View Template” to edit the file and make your changes.

You will want to add to this template something that indicates that the account has been held for moderation. This way, the email template is sent out to indicate to them that they cannot login immediately.

We also need an email template that is sent when the user is approved by an admin. In yourtheme/woocommerce/emails, create a file called customer-account-approved.php and paste the following in:

<?php if (!defined('ABSPATH')) exit; ?>
<?php do_action('woocommerce_email_header', $email_heading); ?>
<p><?php echo sprintf(__("Good news! Your account has been approved. You can now login here: %s.", 'woocommerce'), make_clickable(esc_url( wc_get_page_permalink('myaccount')))); ?></p>
        <li><?php echo sprintf(__('Username: %s', 'woocommerce'), $user_login); ?></li>
        <li><?php echo sprintf(__('Password: %s', 'woocommerce'), $user_pass); ?></li>
<p><?php echo sprintf(__("Thanks for registering with %s!", 'woocommerce'), $blogname); ?></p>
<div style="clear:both;"></div>
<?php do_action('woocommerce_email_footer'); ?>    

Now that we’ve got our email templates ready to roll, we need an action hook to send off the approval email when the admin clicks “approve” for any user. Again, enter the following in your theme’s functions.php file:

//Email Notifications
//Content parsing borrowed from: woocommerce/classes/class-wc-email.php
function ws_new_user_approve_send_approved_email($user_id){
    global $woocommerce;
    //Instantiate mailer
    $mailer = $woocommerce->mailer();
        if (!$user_id) return;
        $user = new WP_User($user_id);
        $user_login = stripslashes($user->user_login);
        $user_email = stripslashes($user->user_email);
        $user_pass  = "As specified during registration";
        $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
        $subject  = apply_filters( 'woocommerce_email_subject_customer_new_account', sprintf( __( 'Your account on %s has been approved!', 'woocommerce'), $blogname ), $user );
        $email_heading  = "User $user_login has been approved";
        // Buffer
        // Get mail template
        woocommerce_get_template('emails/customer-account-approved.php', array(
                'user_login'    => $user_login,
                'user_pass'             => $user_pass,
                'blogname'              => $blogname,
                'email_heading' => $email_heading
        // Get contents
        $message = ob_get_clean();
        // Send the mail
        woocommerce_mail( $user_email, $subject, $message, $headers = "Content-Type: text/htmlrn", $attachments = "" );

// Do not send built in approve user message
add_filter( 'new_user_approve_approve_user_message', '__return_false' );
// Add new approve user action
add_action( 'new_user_approve_approve_user', 'ws_new_user_approve_send_approved_email', 10, 1 );

function ws_new_user_approve_send_denied_email($user_id){
// Remove existing deny action
remove_action( 'new_user_approve_deny_user', array( pw_new_user_approve(), 'deny_user' ) );
// Add new deny action
add_action('new_user_approve_deny_user', 'ws_new_user_approve_send_denied_email', 10, 1);

As I mentioned above, you can do the very same with denied users. If you wish to do this, use the same code from the approve function and copy/paste it to the denied function that currently returns nothing, then create another email template like above.

One reader of this post, Maya, had a need to lock down registration by preventing auto-login when an order is placed. Typically in wholesale account environments, orders can’t be placed until an account is registered and approved, however Maya’s scenario was a bit different. If you also require that functionality, Maya was kind enough to share the code. Note that I haven’t used this code myself, so I won’t be of much help if you have trouble with it.

function wc_custom_redirect_after_purchase() {
  global $woocommerce;
  if ( is_checkout() &amp;&amp; ! empty( $wp->query_vars['order-received']) &amp;&amp; ws_new_user_approve_autologout() ) {
    return apply_filters( 'woocommerce_get_return_url', $return_url, $order );
add_action( 'woocommerce_thankyou', 'wc_custom_redirect_after_purchase' );

I hope this helps anyone else trying to use the New User Approve plugin! Please leave your comments and suggestions along with any problems you may have encountered.

If you need a hand integrating this code on your site, send us a message: we’d love to help make that happen.

About Jordan Schelew

Jordan has been working with computers, security, and network systems since the 90s and is a managing partner at Websavers Inc. As a founder of the company, he's been in the web tech space for over 15 years.


  1. Hamza Marzoug on October 14, 2020 at 1:55 pm

    Thank you. Can I integrate a list of pending approve user in my account page?, if yes then how?

  2. netzih on July 7, 2020 at 7:02 pm

    I found a way to avoid 2 emails (and only have the one you set with woocommerce to be sent) and not change the plugin files.
    I got this from their FAQ https://newuserapprove.com/support/faq/do-not-send-email-to-denied-users/
    Add the following to the functions.php (or create a snippet using a snippet plugin) the first snippet is for approval emails and the second is for denials..
    remove_action( ‘new_user_approve_approve_user’, array( pw_new_user_approve(), ‘approve_user’ ) );
    remove_action( ‘new_user_approve_deny_user’, array( pw_new_user_approve(), ‘deny_user’ ) );

    Like this it’s a snippet and not editing the actual plugin (which will be deleted once updated)

    • Jordan Schelew on July 7, 2020 at 8:02 pm

      Thanks so much for this Netzih!

      • netzih on July 7, 2020 at 8:08 pm

        I actually made a mistake.
        If you use the approve user it does not allow user approvals to go through and they just stay pending (even though the woocommerce email goes through).
        Can you edit my comment to change the approve user snippet to
        “add_filter( ‘new_user_approve_approve_user_message’, ‘__return_false’ );” (without quotations)
        The deny user snippet can stay the same
        Snippets plugin I use is https://wordpress.org/plugins/code-snippets/ I also use it to create snippets with all the things you recommend putting into functions.php

        • Jordan Schelew on July 7, 2020 at 8:12 pm

          Hey Netzih,

          I’ve added your code to the guide directly and replaced the approve user code with the updated version. For those that wish to use the deny user email override, do you know if there’s also a filter for `new_user_approve_deny_user_message` ?

  3. Fernando on June 22, 2020 at 12:08 am

    Hi Jordan Grean Post, everything went well for me but I have a problem. When I approve a userr. the url that generates me is the following

    • Jordan Schelew on June 24, 2020 at 10:51 am

      Hey Fernando, What’s the trouble with the URL? If it’s that it’s a staging URL, that would be something to bring up with your host 🙂

  4. Stefano on May 25, 2020 at 10:21 am

    Fantastic thanks! but I show the white mail the user with an attachment … what am I wrong? then you can completely write the code to send the message to the blocked?

    • Jordan Schelew on May 25, 2020 at 10:28 am

      You’re welcome! I’m not quite sure of your question. Es possible yo entiendo mejor si tu escribes en Español. Es eso mejor?

  5. Nathan on October 7, 2019 at 12:06 am

    Not sure if this thread is still active, but here goes!
    Am having issues where once registration has been sent, the site returns a blank page “The site is experiencing technical difficulties” and defaults to the URL “www.mydomain.com/my-account/”
    After some testing I found that if I manually type the url “www.mydomain.com/my-account/?approved=false”

    This completes the redirect fine.
    I have updated the auto logout function to read this:
    return add_query_arg( ‘approved’, ‘false’, get_permalink( get_option(‘woocommerce_myaccount_page_id’ ) ) ) . “?approved=false”;

    Thinking this might work, but still does not re-direct.

    Any ideas?

    • Jordan Schelew on October 7, 2019 at 12:25 pm

      Hey Nathan,

      Check your web server error logs when you get that error as described in our matching guide. If you can provide the actual error from the logs, we can surely get that fixed up!


      • Nathan on October 7, 2019 at 5:47 pm

        Thanks very much, this is the log that is generated when I run the task. Not sure if this is relevant?
        Any help that you can give would be much appreciated, otherwise I will try the WP Approve plugin as this has now been updated recently.

        [Mon Oct 07 13:42:53.469780 2019] [autoindex:error] [pid 2821135:tid 47358828152576] [client] AH01276: Cannot serve directory /public_html/whitelabelstock.com/: No matching DirectoryIndex (index.html.var,index.htm,index.html,index.xhtml,index.wml,index.perl,index.pl,index.plx,index.ppl,index.cgi,index.jsp,index.js,index.jp,index.php4,index.php3,index.php,index.phtml,index.shtml,default.htm,default.html,home.htm,index.php5,Default.html,Default.htm,home.html,welcome.html) found, and server-generated directory index forbidden by Options directive

  6. Paulo on September 10, 2019 at 9:52 am

    In my scenario a weird thing was happening. When registering new users for testing, after approving them, I couldn’t login with their credentials until I logged in as admin and logged back out again. SO after some searching I stumbled upon a piece of code that solved my problem.
    After line 15 of your first bit of code, responsible for the autologout feature, I added one small line that made it:
    Bear in mind that placement of that line is crucial. I first put it after `wp_logout();` and got a 502 upon registration.
    Hope this helps in a similar situation.

  7. Paulo on August 24, 2019 at 10:57 pm

    Hello Jordan!
    Thank you for this greatly useful code and tutorial.

    I’ve come across a weird problem when testing this.
    The problem is with logging in after account approval. Login attempts do not work at all, even after a full (Ctrl+R) refresh of the login (My Account) page. But only for this particular newly approved user. If I login with another username, logout, and then login again with the newly approved user, then I can login with no problems. Do you have any ideas what might be causing this and how to make sure this doesn’t happen?

    • Jordan Schelew on August 26, 2019 at 10:10 am

      Hey Paulo,

      My pleasure! That is indeed super odd; can you confirm this still occurs even when using a different browser with no cache/cookie history on the site? It definitely *sounds* like something cookie or cache related to me.


      • Paulo on September 10, 2019 at 9:54 am

        Hi Jordan, thanks for the hint. I was able to find a line of code that I put on line 16 of your autologout snippet.
        I made a separate comment on this as well.

        • Jordan Schelew on September 10, 2019 at 12:13 pm

          Thanks for the feedback! I’ll add it to the code above in case others run into the same issue 🙂

          • Paulo on September 11, 2019 at 4:06 pm

            Thank you!
            I see you put it on line 14, but it might break things from there.
            For me it only works with no errors on line 16, after the `return add_query_arg` line.

          • Jordan Schelew on October 7, 2019 at 12:28 pm

            Hey Paulo,

            Well that’s confusing — you say it needs to go *after* the return statement? That means the code won’t actually ever run – code after a return statement (unless within a conditional) does not do a thing… are you sure you didn’t mean that `wp_clear_auth_cookie();` should go after `wp_logout();` ? (I’ve changed it to this, as that seems to make the most sense).


  8. Adnan on May 24, 2019 at 5:21 am

    Hi Jordan Schelew,
    This supposed to be a life-saving post. But unfortunately not working.
    Have you checked it recently?

    • Jordan Schelew on May 26, 2019 at 1:13 pm

      Hi Adnan, We do not use this integration any longer, but many people have successfully set this up, as you will see in the comments. The comments also contain fixes for common issues, like when notification emails are not sending.

  9. Jerry Peres on May 22, 2019 at 3:18 am

    You have shared a great stuff for wp plugin woocommerce. Thanks.

  10. ohmicha on May 10, 2019 at 1:56 pm

    That’s too good information. I’ve done what you told me.
    I get one error.
    In general, there is no error in use. but

    My Private Site plugin
    When you use it, you will not get a message about the success of membership.
    Please check the site and you will know.

Leave a Comment