Borrar todos los clientes sin pedidos en WooCommerce

En muchas tiendas online que encuentro existe un problema originado por haber tenido el registro abierto sin mecanismos anti bots durante un tiempo: la existencia de miles (en ocasiones cientos de miles) clientes “fake”. Es decir, clientes que se han dado de alta en el sitio, aparecen como clientes, pero realmente son usuarios creados por bots.

Problemas de tener tantos usuarios falsos en WooCommerce

Tener por decir algo 100.000 clientes “fake”en tu base de datos de WooCommerce hará que tengas un tamaño de base de datos inútil enorme:

  • Por cada entrada en la tabla de usuarios se crean varias entradas en la tabla usermeta así que multiplicad por N los M usuarios falsos que tenéis y veréis qué peso más absurdo
  • Esto hará que las consultas que impliquen a usuarios o a clientes, como las realizadas por WooCommerce en la parte de análisis, tengan una carga extra importante
  • Las copias de seguridad de la base de datos pesarán más y por lo tanto serán más lentas de hacer y más lentas de recuperar
  • Y en general todas las operaciones que involucren tratar con las tabla de los usuarios: inicio de sesión, registro, buscar el nombre de un usuario que se está mostrando (en el loop del blog), finalizar una compra, etc. muchas operaciones más operaciones de las que te imaginas, tendrán un retraso enorme respecto a una base de datos limpia

Solución: borrar los usuarios sin pedido

La solución más básica es buscar todos los clientes, iterar por ellos, y borrar los que no tienen pedidos asociados. Puede que algún cliente se te haya dado de alta y no haya comprado, pero será un caso raro y es la única forma rápida de hacerlo.

Se podría hacer todo con un solo SQL usando el _customer_id que guardan en la tabla postmeta los pedidos, pero eso tiene un riesgo. La base de datos de clientes y pedidos de WooCommerce está cambiando así que mejor usar la API de WooCommerce, las funciones que ofrece de forma nativa, para asegurarnos que todo se hace bien. El proceso se hará más lento pero dará seguridad.

Haced una copia de seguridad antes por si acaso

Os dejo un código que hace justo esto que os comento:

$args = array(
        'role'    => 'customer',
        'number'  => -1,
        'fields'  => 'ID',
    );
$users = get_users( $args );

echo "<ul>";

foreach( $users as $user_id ) {
  $order_count = wc_get_customer_order_count( $user_id );
  if ( $order_count === 0 ){
     echo "<li>Borrando " . $user_id . "</li>";
     wp_delete_user( $user_id, $id_usuario_contenido_destino ); // $id_usuario_contenido_destino guardará el user_id del usuario al que se le copiará todo el contenido del usuario que se está borrando, solo por si acaso alguno tiene contenido de valor
  }
  else{
     echo "<li>No borro " . $user_id . "</li>";
}

echo "</ul>";

Como todo en todo proceso largo de PHP si lo ejecutáis tal cual, probablemente os dará problemas: el proxy os desconectará por falta de respuesta en PHP (errores 502 de nginx por ejemplo), un error 500 de PHP por exceso en el tiempo de ejecución… así que para resolverlo podéis paginar la consulta:

$args = array(
        'role'    => 'customer',
        'number'  => -1,
        'fields'  => 'ID',
        'orderby' => 'user_nicename', // parámetros de ordenación para que siempre se ejecute en el mismo orden
        'order'   => 'ASC',
        'number'  => 1000, // tamaño del paso
        'offset'  => 1000 * $paso, // empezando con $paso = 0, irá paso a paso borrando
    );
$users = get_users( $args );

El resto sigue igual pero si implementáis esto con un formulario, con parámetros o con JS que vaya llamando al proceso dando paso tened en cuenta una cosa:

  • cada paso que se da, como borra usuarios, afecta a la consulta, de forma que de alguna forma tenéis que controlar esto (aumentando el tamaño del paso o haciendo un loop final con ‘number’ => -1 para que coja todos) para quedaros tranquilos

Cómo ejecuto este código

Pues tienes diferentes formas pero yo así de forma sencilla en un plugin de funciones o en el functions.php de vuestro tema hijo metería el código en una página que créeis o si queréis con una llamada GET que es algo más sucio pero más rápido. Total, esto es una operación de mantenimiento, la hacéis y borráis luego.

NUNCA uséis plugins de snippets de código para estas cosas, tener código en base de datos, es nada eficiente y nada seguro,

El método ese que os digo de un parámetro GET podría ser algo así por ejemplo:

add_action( 'admin_head', function(){
    if( !isset( $_GET['borrar_customers_sin_pedido'] ) || empty( $_GET['borrar_customers_sin_pedido'] ) )
        return;

   // aquí el código

Si hacéis una llamada https://misitio.com/wp-admin/?borrar_customers_sin_pedido=si ejecutará este código lo primero.

1 estrella2 estrellas3 estrellas4 estrellas5 estrellas (Ninguna valoración todavía)
Cargando…

Almacenamos las IPs desde la que se envían las valoraciones para evitar fraudes

Carrito