Batch Deleting WooCommerce Customers with No Orders or Money Spent with WP-CLI

Working on WooCommerce is always a fun challenge. I had a client who had a ton of spam customers because where was missing security on the site. This meant he had several thousand users who were clogging up the database and mailing list!

This tutorial will show you how to delete WooCommerce customers who have no orders with WP-CLI. If you are looking for how to process all of the pages of data that the WooCommerce wp wc commands return then this post is for you too since I show you how to programmatically loop through the pages of results with the bash script below.

Batch Deleting WooCommerce Customers with No Orders with WP-CLI

Let’s list all of the users who are customers and count them first

wp user list --role=customer | wc -l

That is a lot of customers, over 4000 🙂

4351

Extract user ids who have 0 orders, this awk command will check to see if the orders_count (here column 2) column is 0 and only then will it show the user id (here column 1)

wp wc customer list --fields=id,orders_count --user=1 | awk '$2 == "0" {print $1}'

For privacy reasons I cannot show the output of the above command but we can count them instead.

wp wc customer list --fields=id,orders_count --user=1 | awk '$2 == "0" {print $1}' | wc -l

Looks like there are 78 customers with 0 orders.

78

So why are there only 78 shown when we know there are over 4000 users and we know there are over 1000 spam users. I will explain this after we check how many customers have an order count that is not 0.

Let’s find out how many customers there are with an orders_ count that is not 0.

wp wc customer list --fields=id,orders_count --user=1 | awk '$2 != "0" {print $1}' | wc -l

Now there are 22, what is going on?

22

Notice how this is also a very low number but now we can understand why. Using basic arithmetic we can find out that 78+22 is 100. This is not a coincidence.

According to the WP-CLI WooCommerce command documentation we can only get 100 items at at time for each page of the REST API results. This means we have to navigate through the pages of the results to process them all!

Using division we can find out how many pages of results there will be by combining the wp user list command with some awk division.

wp user list --role=customer | wc -l | awk '{print $1/100}' | awk '{print int($1+0.99)}'

This gives the output of 42 meaning there are 42 pages to wade through and process.

This bash script should get you started with processing the results of REST API pages from WP-CLI WooCommerce commands.

The script below will create a list of all of the user IDs which have 0 orders into the /tmp/user-ids.txt file.

# define ADMIN user to use the REST API for WooCommerce via WP-CLI
ADMINUSER=1

# calculate number of pages and round up https://stackoverflow.com/questions/13182070/best-way-to-divide-in-bash-using-pipes
PAGES=$(wp user list --role=customer | wc -l | awk '{print $1/100}' | awk '{print int($1+0.99)}')
#41.19

# create the list of users and loop through each page
for i in $(seq 1 $PAGES); do
    # redirect stdout to stderr so the text doesn't show up in our text file
    echo "Processing page ${i} of ${PAGES}" 1>&2
    # get the user ID and the number of orders per user, only show IDs that have 0 as order count with awk https://stackoverflow.com/questions/14739057/awk-print-column-3-if-2-a-specific-value
    wp wc customer list --fields=id,orders_count --user=${ADMINUSER} --page=${i} | awk '$2 == "0" {print $1}'
done > /tmp/user-ids.txt

We can delete these now by looping through the text file of all of the user IDs and deleting them with the wp wc customer delete command.

# delete found users
ADMINUSER=1
USERCOUNT=$(cat /tmp/user-ids.txt | wc -l)
COUNT=1

while read -r USER
do
    echo "Deleting ${USER} ${COUNT} of ${USERCOUNT}"
    # delete customer
    wp wc customer delete ${USER} --user=${ADMINUSER} --force=true
    # increment the COUNT
    ((COUNT++))
done < /tmp/user-ids.txt

Let’s use a similar technique for removing users who have spent no money but are still called customers 🙂

Batch Deleting WooCommerce Customers with No Money Spent with WP-CLI

Deleting users who have spent no money we can use the amount_spent field instead of the orders_count field.

Notice that we need to check if the total_spent field is equal to 0.00 instead of 0 like we did with orders_count.

wp wc customer list --fields=id,total_spent --user=1 | awk '$2 == "0.00" {print $1}' | wc -l

Here is a modified version of the above script for no orders that will find customers who have spent 0.00 money at the store.

# define ADMIN user to use the REST API for WooCommerce via WP-CLI
ADMINUSER=1

# calculate number of pages and round up https://stackoverflow.com/questions/13182070/best-way-to-divide-in-bash-using-pipes
PAGES=$(wp user list --role=customer | wc -l | awk '{print $1/100}' | awk '{print int($1+0.99)}')
#41.19

# create the list of users and loop through each page
for i in $(seq 1 $PAGES); do
    # redirect stdout to stderr so the text doesn't show up in our text file, total_spent used to be amount_spent
    echo "Processing page ${i} of ${PAGES}" 1>&2
    # get the user ID and the amount spent per user, only show IDs that have 0.00 as amount_spent with awk https://stackoverflow.com/questions/14739057/awk-print-column-3-if-2-a-specific-value
    wp wc customer list --fields=id,total_spent --user=${ADMINUSER} --page=${i} | awk '$2 == "0.00" {print $1}'
done > /tmp/user-ids-total-spent.txt

Sources

How to Divide Using pipes with bash
awk Processing with Conditional Logic
WooCommerce WP-CLI Wiki Customer Command
MySQL Get all Users for WordPress
Get all WooCommerce Customers with Paid Orders