Changing user role after purchasing

Some months ago I talked about how to add a checkout field only for a specific user role with WooCommerce.

Today I’ll show you how to change the user role after purchasing a specific product.

Open your functions.php file in wp-content/themes/your-child-theme-name/ and add this code at the end of the file:


add_action( 'woocommerce_order_status_completed', 'change_role_on_purchase' );
function change_role_on_purchase( $order_id ) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
$products_to_check = array( '1', '2', '3' );
foreach ( $items as $item ) {
if ( $order->user_id > 0 && in_array( $item['product_id'], $products_to_check ) ) {
$user = new WP_User( $order->user_id );
// Change role
$user->remove_role( 'customer' );
$user->add_role( 'new-role' );
// Exit the loop
break;
}
}
}

view raw

functions.php

hosted with ❤ by GitHub

Note the code on line 6. It is a list of products to check, which means that the custom script will check if one of the products purchased by the customer is in that list. If yes, the user role will change to what you define on line 14.

Line 13 removes the customer’s old role, by default it’s Customer when they buy from you, but it could be different. If you want to remove more than one role, just duplicate the line and change the role slug.

Note: If you defined multiple role switch and the customer purchased more products that will change their role, only the first one found will switch their role.

The original code is by troydean.


More Posts That You Might Like…


53 responses to “Changing user role after purchasing”

  1. Hi,

    Thank you for the post. I tried your code but when the user do checkout, I get a internal server error and a user with the default role “customer” is created. Any ideia what could be causing this problem?

    1. Hi ams,
      No sorry, the Internal Server Error is a generic error. If you check your error log you should have a specific error though which could help in understanding what’s going on.

      Otherwise, you can temporarily enable WP_DEBUG and get the error on the screen directly.

      Please check this document on Debugging in WordPress.

  2. I really like this code, but can you help me?¡, i have 6 products and each product must create a different role , what can i do?

    Thank you

    1. Hi Diego,
      Inside the if on line 9 you should add a switch on the product ID and change the role there.

      Something like this: https://gist.github.com/SiR-DanieL/20372ea13fe4bfa784c2

      1. Ciao Nicola, sto cercando di usare il tuo codice inserendolo nel file functions.php del tema in uso ma continuo a ricevere errore 500 internal server quando lo metto in produzione.

        add_action( ‘woocommerce_order_status_completed’, ‘change_role_on_purchase’ );
        function change_role_on_purchase( $order_id ) {
        $order = wc_get_order( $order_id );
        $items = $order->get_items();

        $products_to_check = array( '9466', '9467', '9468', '9469', '9470' );

        foreach ( $items as $item ) {
        if ( $order->user_id > 0 && in_array( $item['product_id'], $products_to_check ) ) {
        $role = 'new-role';
        switch ( $item['product_id' ] ) {
        case 9466: $role = 'golfista-trial'; break;
        case 9467: $role = 'golfista-premium-1; break;
        case 9468: $role = 'golfista-premium-2; break;
        case 9469: $role = 'golfista-premium-3; break;
        case 9470: $role = 'golfista-premium-4; break;
        }

        $user = new WP_User( $order->user_id );

        // Change role
        $user->remove_role( 'customer' );
        $user->add_role( $role );

        // Exit the loop
        break;
        }
        }

        }

        Vedi qualcosa di sbagliato qua?

        1. Ciao,
          Si. In tutti i case, eccetto il primo, hai dimenticato l’apice di chiusura dopo 'golfista-premium-1, e tutti gli altri.

  3. Nice, but what if i wanted to remove that role after product expiration (like a subscription product) ??

    1. Hi Hugo,
      You don’t need a snippet for that. You can choose the roles used when the customer’s subscription is active/inactive in WooCommerce > Settings > Subscriptions:

      See this screenshot: http://cld.wthms.co/RZ66/48AH6qYp+

  4. Hi, I was excited to find your script but not working – am I missing something? see below

    add_action( 'woocommerce_order_status_completed', 'change_role_on_purchase' );
    function change_role_on_purchase( $order_id ) {
        $order = wc_get_order( $order_id );
        $items = $order->get_items();
    
        $products_to_check = array( '3379', '3376' );
    
    foreach ( $items as $item ) {
        if ( $order->user_id > 0 && in_array( $item['product_id'], $products_to_check ) ) {
            $user = new WP_User( $order->user_id );
    
            // Change role
            $user->remove_role( 'customer' );
            $user->add_role( 'subscriber' );
    
            // Exit the loop
            break;
        }
    }
    
    }
    
    1. Hi Jessica,
      Can you try by using numeric IDs instead of strings?

      Remove the quotes here: array( '3379', '3376' )

  5. Valerie Robinson Avatar
    Valerie Robinson

    Hi-this added the new user role I specified but it did not remove the customer role. Instead it has both roles listed. I see that the code says to remove the customer role. Since they’re both there now, does that mean something didn’t work right with that line?

  6. I wish this worked – am I missing something? (I tried with and without quotation marks):

    add_action( ‘woocommerce_order_status_completed’, ‘change_role_on_purchase’ );
    function change_role_on_purchase( $order_id ) {
    $order = wc_get_order( $order_id );
    $items = $order->get_items();
    $products_to_check = array( ‘944 ‘);
    foreach ( $items as $item ) {
    if ( $order->user_id > 0 && in_array( $item[‘product_id’], $products_to_check ) ) {
    $user = new WP_User( $order->user_id );
    // Change role
    $user->remove_role( ‘subscriber’ );
    $user->add_role( ‘customer’ );
    // Exit the loop
    break;
    }
    }
    }

    1. It worked, I am dim.

  7. Hello ! Thank you for your helpfull code!
    Do you know what kind of hook i can use for yith woocommerce subscriptions plugins ?

    Thank you !
    Marco.

    1. Hi Marco,
      No, I’d suggest to ask them directly.

  8. Hello, Nikola!

    Very good code! And you can make it as a wordpress plugin? It would be very convenient to use, especially to users who do not know programming.

    1. Hello,
      Sorry but I don’t think that I’m gonna make a plugin for this. Feel free to do one with my code though if you want!

  9. I noticed a bug: when a first time successful payment happens, the goods do not disappear from the shopping cart. And if you make the payment again (the same product), being already in the new user role, then the product disappears from the shopping cart.

    What could it be? This is due to the change in roles when purchasing goods?

    1. Hey,
      I’m not sure if this is due to the role change. Can you try without my custom code?

      Does it happen anyway?

  10. Nicola!

    I deleted your code from the file and re-made the payment through Woocommerce. The product no longer appeared, everything went well.

    Then I added your code again and made a payment from the cart. But I have two-factor authentication from the DUO two-factor (https://duo.com) for the role that the old user role changes when making a payment.

    And when the payment system confirms a successful payment, your code assigns a new role (for me it is a “student”), and immediately for this role the DUO requires authentication. When successful authentication passes, I go to the shopping cart, and there again there is a product on which a successful payment has just been made.

    Maybe this is the problem?

  11. I just checked. I deleted the DUO from my user, and everything went as it should. After purchasing the product, the old user role was replaced by a new role. And the product disappeared from the shopping cart.

    I’m at a loss … I just need that for a new user role there was a possibility of two-factor authentication after the purchase of the product.

    I do not know what the problem is, I’m not a programmer …

    But your code works fine, it’s confirmed!

  12. This added a capability rather than a role. Any idea why?

  13. I removed my capital F in Free and it worked on test 2. Cool and thanks!

    1. You’re welcome!

  14. Is there a way to get this to work with a variable product?

    For instance, if I have a product called SUBSCRIPTION with variations: FREE and PAID. I’d like to set people with a PAID subscription to the role Subscriber, and people with the FREE subscription to a role called Free Subscriber.

    It seems if I create these as two separate products, it sort of works, but if I make them variations (which I’d prefer to facilitate upgrading and downgrading), it won’t work.

    Thanks.

    1. Hi David,
      You should add more code to check if the purchased product has specific meta fields.

      You can use wc_get_order_item_meta() to do that.

    2. Did you ever get this to work David or Nicola? I too would love this functionality. Thanks in advance.

      1. Hi Eric,
        I never actually wrote the code to make it work with variations, but as I said before you can use wc_get-order_item_meta() to make it work by checking the item meta data.

  15. Nice snippet! Are there any thoughts on changing the role based on the purchase certain product categories rather than individual id’s?

    1. Hey Jasha,
      You have the product ID, from there you can get their categories with $terms = get_the_terms( $item['product_id'], 'product_cat' ); and then loop through them to get their IDs. Later, instead of checking against an array of product IDs you can check with the category IDs.

      1. Hi Nicola,
        thank you for the great snippet!
        Can you tell me please how i can make it work with a category? I tried now several days, but im not able to make it work. Per product works fine, but i need it for a category.

        Thank you very much,

        Marco

  16. For some reason, this isn’t working for me. This is my code. I am testing it on a free product. Does that make a difference?

    add_action( ‘woocommerce_order_status_completed’, ‘change_role_on_purchase’ );
    function change_role_on_purchase( $order_id ) {
    $order = wc_get_order( $order_id );
    $items = $order->get_items();

    $products_to_check = array( '210', '11858', '11674' );

    foreach ( $items as $item ) {
    if ( $order->user_id > 0 && in_array( $item['product_id'], $products_to_check ) ) {
    $user = new WP_User( $order->user_id );

    // Change role
    $user->remove_role( 'employer' );
    $user->add_role( 'vendor' );

    // Exit the loop
    break;
    }
    }

    }

    1. No Mark,
      it should not make any difference. Make sure that the IDs are correct, and try with a different theme/without other plugins.

  17. thanks dude .
    it’s worked .
    good Job

    1. You’re welcome Farhad!

  18. I tried using your code and it just doesn’t do anything. I have customers that purchase a subscription product which automatically changes their role from customer to a subscriber, but I want the role to change to a newly created one (member) when they purchase one specific subscription and the other two subscription products will keep their subscriber role. Do I have to do some extra step since it is already changing the role when they purchase the product? I feel like there is something I’m missing to bring the pieces together.

    The product ID is 18973.

    add_action( ‘woocommerce_order_status_completed’, ‘change_role_on_purchase’ );
    function change_role_on_purchase( $order_id ) {
    $order = wc_get_order( $order_id );
    $items = $order->get_items();

    $products_to_check = array( '18973' );

    foreach ( $items as $item ) {
    if ( $order->user_id > 0 && in_array( $item['product_id'], $products_to_check ) ) {
    $user = new WP_User( $order->user_id );

    // Change role
    $user->remove_role( 'customer' );
    $user->add_role( 'member' );

    // Exit the loop
    break;
    }
    }

    }

  19. I am so happy I found this, you have greatly helped me solve this issue. This works perfectly!
    Kudos ++++++++

    1. You’re welcome, Angela! And thanks for sharing the info below!

  20. I also just want to add, in my case:

    Until the payment is processed and completed the user did not update. Once the payment is received or the process is manually completed, then the role changes. In my case I have Paypal set to auto complete the order upon the user purchasing, so the role automatically updates. But I also have another payment gateway using E-Transfer. This type of payment has to be approved by the admin once the payment is received, so for this reason I didnt see the role update right away, it was until I completed the action that the above script completed the role change! It does work perfectly but you may need to consider how your payments are processed! hope that might help someone!

    thanks again!

    1. This worked for me as a work around

      add_action( ‘woocommerce_thankyou’, ‘change_role_on_purchase’ );

  21. FYI, There is a relatively new plug-in that accomplishes automatic role changing after purchase. It’s called YITH Automatic Role Changer.

  22. This did exactly what I wanted and now I can be happy again. Not a lot out there to solve this problem. thank you!!

    1. You’re very welcome!

  23. Thanks you! It Worked.
    Can you write a tut if i want to changed role when a customer total spent > some money?

  24. hi i tried looking for the php file in my files, but there is no funtions.php. i went to themes and my theme but functions was not there .where could i find it.

    1. i found in in my child theme (cherry framework)

  25. Hello, thanks for this code! How would I alter it to include any purchase? Basically I’m selling wholesale and want to lower minimum purchases after the first initial order from $300 (newcustomer) to $100 (repeat customer). Once they complete the 1st time purchase set to minimum $300 for user role newcustomer, it will change them to ‘repeat customer’ who has a minimum order level set at $100.

  26. This is exactly what I was looking for. i.e. to change the role depending on the product that was purchased.

  27. So if I understand that this hook will be executed only when the Order transitions to “Completed”?
    Second question, should there be quotes around the product id numbers? Does it make a difference?

  28. Hi there, a comment to your reply here, if you are using Memberships this role change is not an option, so this is much needed, as Memberships does not provide this.

    ‘Nice, but what if i wanted to remove that role after product expiration (like a subscription product) ??
    Reply
    You don’t need a snippet for that. You can choose the roles used when the customer’s subscription is active/inactive in WooCommerce > Settings > Subscriptions:’

    Regards
    Carsten

  29. Thank you for this — very helpful.

    Because I don’t want to edit my functions.php file each time I add a new product that should trigger a change to a new user role, I added a custom field, “new_role,” when creating a product, then edited the function to first check if there’s a value in that custom field.

    See here: https://gist.github.com/wjlevay/d7f898300acdc50cf46a422f51ac2c47

  30. @Bill, that’s a clever way to avoid manual editing function.php file. I was thinking the same solution too. Thanks for the gist 🙂

  31. How do you modify this code so that role is changed if customer makes any kind of order (any product)

    Thank you.

Leave a Reply

Categories

Newsletter

Receive new articles from this blog directly in your inbox!

No spam guaranteed!

Blog at WordPress.com.

%d bloggers like this: