With WooCommerce, if an email is already associated with an account and the "create account" checkbox is ticked on the checkout page, WooCommerce will require the customer to login to his account before processing the payment.

It makes sense but it clearly hinders transformation rate. I'd rather have the customer complete the transaction and transparently associate the order with the email's matching account.

However, I have no clue how I could alter the default behaviour to make this possible.

Any idea?


Thanks to @Gabriel's answer, if finally found a way. Gabriel pointed me to process_customer function.

It turns out there's a hook before process_customer is called. This hook is woocommerce_checkout_process.

Knowing this, it's just a couple of lines:

  • check if user isn't already logged in & createaccount is checked
    • if yes, check if a user account matches the provided email
      • if not, do nothing, default behaviour is good
      • if yes, then use wp_set_current_user to set the email matching account as the current user (won't make the user logged in!). That will have the effect of linking the order to the already existing acount (and updating shipping/billing info).
add_action('woocommerce_checkout_process', function () {
    if (!is_user_logged_in() && $_POST['billing_email'] && $_POST['createaccount'] == 1) {
        $user = get_user_by('email', $_POST['billing_email']);
        if ($user) wp_set_current_user($user->ID);
  • 1
    So clearly this isn't a generic PHP/MySQL question. It's about WooCommerce, one of the most popular plugins in the ecosystem. It even has a tag with almost 4k questions on this very site. Therefore I really don't get why this question was marked as off-topic. If we're just allowed to talk about WP core, then the very nature of WordPress – extensibility – is negated.
    – Buzut
    Apr 29, 2020 at 21:02

1 Answer 1


You would allow the user to fill the email, use it to find the user id at the database and then use the id for the order.

One possible solution is to replace function wc_create_new_customer( $email, $username = '', $password = '', $args = array() ) with a custom function.

This is where the function is called, all your custom function needs to do is find the correct user_id.

    protected function process_customer( $data ) {
        $customer_id = apply_filters( 'woocommerce_checkout_customer_id', get_current_user_id() );

        if ( ! is_user_logged_in() && ( $this->is_registration_required() || ! empty( $data['createaccount'] ) ) ) {
            $username    = ! empty( $data['account_username'] ) ? $data['account_username'] : '';
            $password    = ! empty( $data['account_password'] ) ? $data['account_password'] : '';
            $customer_id = wc_create_new_customer(
                    'first_name' => ! empty( $data['billing_first_name'] ) ? $data['billing_first_name'] : '',
                    'last_name'  => ! empty( $data['billing_last_name'] ) ? $data['billing_last_name'] : '',

            if ( is_wp_error( $customer_id ) ) {
                throw new Exception( $customer_id->get_error_message() );

            wc_set_customer_auth_cookie( $customer_id );

            // As we are now logged in, checkout will need to refresh to show logged in data.
            WC()->session->set( 'reload_checkout', true );

            // Also, recalculate cart totals to reveal any role-based discounts that were unavailable before registering.

Hope this helps to point you in the right direction.

Cheers, Gabriel

  • 1
    Hey Gabriel, I don't know why you were downvoted. Your answer is actually very helpful at pointing me to the right direction, thanks a lot!
    – Buzut
    Apr 29, 2020 at 19:08
  • 1
    I'm going to check if there are some hooks I could use to bypass this function (while keeping the whole thing secure).
    – Buzut
    Apr 29, 2020 at 19:09
  • 1
    Glad to know you found a solution :-) Apr 30, 2020 at 3:40

Not the answer you're looking for? Browse other questions tagged or ask your own question.