Programación

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.

Nota: Hay una valoración incrustada en esta entrada, por favor, visita esta entrada para valorarla.

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

Francisco Javier Carazo Gil

Ver comentarios

Entradas recientes

¿Por qué falla Bizum en WooCommerce? 9 causas

Por qué falla Bizum WooCommerce: detecta errores de credenciales, firma, entorno y pedidos para recuperar…

hace % días

Plugin gratuito Redsys WordPress: qué revisar

Elige un plugin gratuito Redsys WordPress con criterio: compatibilidad, seguridad, configuración bancaria y límites para…

hace % días

Qué necesito para activar CECA Online en mi web

¿Qué necesito para activar CECA Online? Revisa contrato bancario, datos del terminal, seguridad, pruebas y…

hace % días

Cómo elegir una pasarela para suscripciones

Aprende a elegir una pasarela para suscripciones en WordPress: revisa recurrencia, compatibilidad, seguridad y soporte…

hace % días

Plugin Bizum WordPress para cobrar con control

Elige un plugin Bizum WordPress compatible con tu flujo de venta, configura la pasarela bancaria…

hace % días

Cómo aceptar CECA en reservas de WordPress

Aprende cómo aceptar CECA en reservas WordPress, configurar pagos seguros y confirmar cada reserva sin…

hace % días