El sistema de comentarios predeterminado de WordPress tiene un gran problema de SPAM, no es un secreto. Sin embargo, hay técnicas que reducen drásticamente el SPAM realizado por robots y que podemos implementar de forma muy sencilla. Una de estas técnicas es conocida como honeypot, que se puede traducir al español como tarro de miel o mielero.

La gran mayoría de robots que se dedican a spamear lo hacen rellenando formularios de forma automatizada y enviándolos sin discriminación. La técnica honeypot aprovecha este punto débil y añade un campo de texto genérico al formulario para que el robot lo complete. Al procesar el formulario, si este campo contiene algún valor, será por que el formulario lo envió un robot.

Para que no interfiera con el usuario normal, el campo del formulario se esconde con CSS. Se puede hacer de varias formas, para este tutorial utilizaré como ejemplo display: none. Es recomendable añadir una etiqueta label apropiada para que el usuario que necesite del uso de lectores de pantalla y asistentes de navegación puedan reconocer el honeypot y omitirlo.

Para añadir el honeypot al formulario de comentarios de WordPress podemos utilizar el filtro comment_form_defaults:

add_filter( 'comment_form_defaults', 'honeypot_field_comment_form' );
function honeypot_field_comment_form( $args ) {
 
  if( ! is_user_logged_in() ) {
    // Agregar el input escondido al formulario
    // sólo para usuarios que no han iniciado sesión
    $args['comment_field'] .= '<div style="display: none;">';
    $args['comment_field'] .= '<label for="cyb-msg">' . __( 'If you are human, please, do not fill this field', 'textdomain' ) . '</label>';
    $args['comment_field'] .= '<input type="text" id="cyb-msg" name="cyb-msg" value="">';
    $args['comment_field'] .= '</div>';
  }
 
  return $args;

}

Fíjate en que he utilizado cyb-msg como atributo name para el input que hace de honeypot; siéntete libre de cambiarlo por el que más te convenga, eso sí, no vayas a utilizar cosas como honeypot, la idea es que el robot confunda este input con un campo del formulario que debería completar, nombres genéricos como description, message, etc son los más apropiados.

Ahora, en el filtro preprocess_comment podemos comprobar el valor del campo honeypot y si no está vacío parar la ejecución:

add_filter( 'preprocess_comment', 'cyb_anti_spam' );
function cyb_anti_spam( $commentdata ) {

  if ( isset( $_POST['cyb-msg'] ) && $_POST['cyb-msg'] != "" ) {
    wp_die( __( 'Thank you for being a silly bot.', 'textdomain' ) );
  }
 
  return $commentdata;

}

Para interrumpir la ejecución he utilizado la función wp_die(). Esta función genera un código de estado HTTP 500, que significa “Error del servidor”. Hay quien opina que debería devolverse un código de estado igual a 200, que significa “Ok” y así engañar al robot hasta el final. Si quieres hacerlo, puedes especificar el código de estado en el tercer parámetro de wp_die(), por ejemplo:

wp_die( __( 'Thank you for being a silly bot.', 'textdomain' ), '', array( "response" => 200 ) );

Con esta sencilla técnica verás como el SPAM en tu blog se reducirá de forma espectacular, no me atrevo a decir que a cero, pero casi.