Skip to content

Instantly share code, notes, and snippets.

@dhilowitz
Created January 26, 2026 21:49
Show Gist options
  • Select an option

  • Save dhilowitz/8b4ff657bfc166771950c72de588d050 to your computer and use it in GitHub Desktop.

Select an option

Save dhilowitz/8b4ff657bfc166771950c72de588d050 to your computer and use it in GitHub Desktop.
WordPress/WooCommerce CLI script to associate guest orders with user accounts. Automatically creates users if they don't exist and links all past orders by billing email.
#!/usr/bin/env php
<?php
/**
* Associate Guest Orders with User Accounts
*
* This script goes through all WooCommerce orders and:
* 1. Finds orders with guest customers (no user ID)
* 2. Checks if a user exists with the billing email
* 3. Creates a new user if one doesn't exist
* 4. Associates the order with the user account
*
* Put this script in the root of your Wordpress installation and run it from the command-line.
* This script comes with no WARRANTY. USE AT YOUR OWN RISK. ALWAYS BACK UP YOUR DATA FIRST.
*
* Usage: php associate-guest-orders.php [--dry-run]
*/
// Check if running from command line
if (php_sapi_name() !== 'cli') {
die("This script can only be run from the command line.\n");
}
// Parse command line arguments
$dry_run = in_array('--dry-run', $argv);
// Determine the WordPress root directory
$wp_root = dirname(__FILE__);
if (!file_exists($wp_root . '/wp-load.php')) {
die("Error: Cannot find wp-load.php. Please run this script from the WordPress root directory.\n");
}
// Load WordPress
require_once($wp_root . '/wp-load.php');
// Check if WooCommerce is active
if (!class_exists('WooCommerce')) {
die("Error: WooCommerce is not active.\n");
}
// Initialize counters
$total_orders = 0;
$guest_orders = 0;
$orders_associated = 0;
$users_created = 0;
$errors = 0;
echo "================================================================================\n";
echo "Associate Guest Orders with User Accounts\n";
echo "================================================================================\n";
if ($dry_run) {
echo "MODE: DRY RUN (no changes will be made)\n";
echo "================================================================================\n";
}
echo "\n";
// Process orders in batches to avoid memory issues
$batch_size = 500;
$offset = 0;
$has_more = true;
echo "Processing orders in batches of {$batch_size}...\n\n";
while ($has_more) {
// Get batch of orders
$args = array(
'limit' => $batch_size,
'offset' => $offset,
'orderby' => 'date',
'order' => 'ASC',
'return' => 'ids',
'type' => 'shop_order',
);
$order_ids = wc_get_orders($args);
if (empty($order_ids)) {
$has_more = false;
break;
}
echo "Processing batch: orders " . ($offset + 1) . " to " . ($offset + count($order_ids)) . "\n";
// Process each order
foreach ($order_ids as $order_id) {
$total_orders++;
try {
$order = wc_get_order($order_id);
if (!$order) {
echo "⚠️ Order #{$order_id}: Could not load order\n";
$errors++;
continue;
}
// Get order details
$order_user_id = $order->get_user_id();
$billing_email = $order->get_billing_email();
// Skip if order already has a user associated
if ($order_user_id > 0) {
continue;
}
$guest_orders++;
// Skip if no billing email
if (empty($billing_email)) {
echo "⚠️ Order #{$order_id}: No billing email found\n";
$errors++;
continue;
}
// Check if user exists with this email
$user = get_user_by('email', $billing_email);
if (!$user) {
// Create new user
$billing_first_name = $order->get_billing_first_name();
$billing_last_name = $order->get_billing_last_name();
// Generate username from email or first name
$username = !empty($billing_first_name) ? sanitize_user($billing_first_name) : sanitize_user(current(explode('@', $billing_email)));
// Ensure unique username
$base_username = $username;
$counter = 1;
while (username_exists($username)) {
$username = $base_username . $counter;
$counter++;
}
if ($dry_run) {
echo "🔍 Order #{$order_id}: Would create user '{$username}' for {$billing_email}\n";
$users_created++;
} else {
// Generate random password
$random_password = wp_generate_password(12, true, true);
// Create the user
$user_id = wp_create_user($username, $random_password, $billing_email);
if (is_wp_error($user_id)) {
echo "❌ Order #{$order_id}: Failed to create user for {$billing_email} - " . $user_id->get_error_message() . "\n";
$errors++;
continue;
}
echo "✅ Order #{$order_id}: Created user '{$username}' (ID: {$user_id}) for {$billing_email}\n";
$users_created++;
// Mark as guest customer
update_user_meta($user_id, 'guest', 'yes');
// Update user's billing data
update_user_meta($user_id, 'billing_first_name', $order->get_billing_first_name());
update_user_meta($user_id, 'billing_last_name', $order->get_billing_last_name());
update_user_meta($user_id, 'billing_company', $order->get_billing_company());
update_user_meta($user_id, 'billing_address_1', $order->get_billing_address_1());
update_user_meta($user_id, 'billing_address_2', $order->get_billing_address_2());
update_user_meta($user_id, 'billing_city', $order->get_billing_city());
update_user_meta($user_id, 'billing_state', $order->get_billing_state());
update_user_meta($user_id, 'billing_postcode', $order->get_billing_postcode());
update_user_meta($user_id, 'billing_country', $order->get_billing_country());
update_user_meta($user_id, 'billing_email', $billing_email);
update_user_meta($user_id, 'billing_phone', $order->get_billing_phone());
// Update user's shipping data
update_user_meta($user_id, 'shipping_first_name', $order->get_shipping_first_name());
update_user_meta($user_id, 'shipping_last_name', $order->get_shipping_last_name());
update_user_meta($user_id, 'shipping_company', $order->get_shipping_company());
update_user_meta($user_id, 'shipping_address_1', $order->get_shipping_address_1());
update_user_meta($user_id, 'shipping_address_2', $order->get_shipping_address_2());
update_user_meta($user_id, 'shipping_city', $order->get_shipping_city());
update_user_meta($user_id, 'shipping_state', $order->get_shipping_state());
update_user_meta($user_id, 'shipping_postcode', $order->get_shipping_postcode());
update_user_meta($user_id, 'shipping_country', $order->get_shipping_country());
// Update first and last name
wp_update_user(array(
'ID' => $user_id,
'first_name' => $billing_first_name,
'last_name' => $billing_last_name,
));
// Associate the order with the new user
$order->set_customer_id($user_id);
$order->save();
$orders_associated++;
}
} else {
// User exists - associate order
$user_id = $user->ID;
if ($dry_run) {
echo "🔍 Order #{$order_id}: Would associate with existing user '{$user->user_login}' (ID: {$user_id}) - {$billing_email}\n";
} else {
$order->set_customer_id($user_id);
$order->save();
echo "✅ Order #{$order_id}: Associated with user '{$user->user_login}' (ID: {$user_id}) - {$billing_email}\n";
}
$orders_associated++;
}
} catch (Exception $e) {
echo "❌ Order #{$order_id}: Exception - " . $e->getMessage() . "\n";
$errors++;
}
}
// Move to next batch
$offset += $batch_size;
// Clear object cache to free memory
wp_cache_flush();
if (count($order_ids) < $batch_size) {
$has_more = false;
}
}
// Print summary
echo "\n";
echo "================================================================================\n";
echo "Summary\n";
echo "================================================================================\n";
echo "Total orders processed: {$total_orders}\n";
echo "Guest orders found: {$guest_orders}\n";
echo "Orders associated: {$orders_associated}\n";
echo "New users created: {$users_created}\n";
echo "Errors: {$errors}\n";
echo "================================================================================\n";
if ($dry_run) {
echo "\nThis was a DRY RUN. No changes were made.\n";
echo "Run without --dry-run to actually process the orders.\n";
}
echo "\nDone!\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment