WooCommerce Link Guest Orders to Customer Accounts(Existing & New Orders)

Faizan Shaikh, May 9, 2023

WooCommerce does not automatically link past guest orders to new user accounts. That should have been the default behavior, but unfortunately that’s not the case.

Anyways, here’s the solution

<?php

require_once $_SERVER["DOCUMENT_ROOT"] . "/wp-load.php";

// Get all orders with 'guest' status
$args = [
    "status" => "completed", // Completed orders
    "return" => "ids", // Just the ids
];

$order_ids = wc_get_orders($args);
foreach ($order_ids as $order_id) {
    // Get the order
    $order = wc_get_order($order_id);

    // Check if the order was made by a guest
    if (0 == $order->get_user_id()) {
        // This order was made by a guest
        // Now we get the order's billing email
        $order_email = $order->get_billing_email();

        // Search for a user with this email
        $user = get_user_by("email", $order_email);

        if ($user) {
            // We found a user with this email
            // Now we link the order to this user
            $order->set_customer_id($user->ID);
            $order->save();
        }
    }
}

Put this code in a .php file and upload the file to the root of your server. Example, if you used quvor.php then go to yourwebsite.com/quvor.php

Executing this script can take a good amount of time, depending on the number of orders you have, and your server speed. You may need to increase your max_execution_time in PHP settings.

If it times out, you can refresh the page again. Make sure to back up your website before running the script.

If you want to link guest orders by emails(which is what I needed), you can use the below script

<?php

require_once $_SERVER["DOCUMENT_ROOT"] . "/wp-load.php";

$emails = ["[email protected]", "[email protected]"]; // put the emails here

// Loop through each email
foreach ($emails as $email) {
    // Use WP_Query to get all guest orders for the current email
    $args = [
        "post_type" => "shop_order",
        "post_status" => "any",
        "meta_query" => [
            [
                "key" => "_billing_email",
                "value" => $email,
                "compare" => "=",
            ],
            [
                "key" => "_customer_user",
                "value" => 0,
                "compare" => "=",
            ],
        ],
    ];

    $orders = get_posts($args);

    // If there are any orders
    if ($orders) {
        // Get the WP_User object for the current email
        $user = get_user_by("email", $email);

        // If a user exists for the email
        if ($user) {
            // Loop through each order
            foreach ($orders as $order) {
                // Update the _customer_user meta field with the user's ID
                update_post_meta($order->ID, "_customer_user", $user->ID);
            }
        }
    }
}

That’s it. Once the script is successfully executed, all your store orders will be linked to users who have an account.

Once that’s done, make sure to delete the file.

The previous script won’t do anything for future orders.

Somethings the guest users when placing a new order decide to register. In this case, their previous orders are not linked to their new accounts.

To fix that, add the below code to your child theme’s functions.php or a code snippets plugin.

<?php

/* Credits: https://stackoverflow.com/questions/71112271/how-to-link-woocommerce-guest-orders-to-customer-account-after-registration */

function action_woocommerce_created_customer( $customer_id, $new_customer_data, $password_generated ) {
    // Link past orders to this newly created customer
    wc_update_new_customer_past_orders( $customer_id );
}
add_action( 'woocommerce_created_customer', 'action_woocommerce_created_customer', 10, 3 ); 

That is it. You don’t need to remove this snippet.

Oh hi there 👋 It’s nice to meet you.

Sign up to receive awesome WordPress content in your inbox

We don’t spam! Unsubscribe anytime.

Leave the first comment