✓ Valoracion guardada

Sistema de logs para tu WordPress

★ ★ ★ ★ ★
117 valoraciones de lectores

Cuando una web falla, lo que vende un freelance no es el código — es saber qué pasó, dónde y por qué. Este post explica cómo montar un sistema de logs a medida en WordPress para detectar dos fallos silenciosos muy comunes: emails que no llegan (wp_mail_failed) y errores de JavaScript que solo ve el usuario, nunca tú. Con ejemplos de código en PHP y JS, y el porqué de que esto ahorre dinero de verdad.

Cuando una empresa te contrata para tocar su web, el escenario real es otro: la tecnología es el vehículo, la empresa compra la necesidad de entender el destino de ese vehículo. No compra un plugin, ni una función, ni una línea de código bonita. Compra la certeza de que, si algo se rompe, alguien va a saber qué pasó, dónde y por qué — antes de que se convierta en un cliente enfadado o un pedido perdido.

El problema es que la mayoría de fallos en WordPress son silenciosos. No hay un cartel rojo que diga "esto ha fallado". Simplemente... no pasa nada. Y "no pasa nada" es lo más caro que existe cuando debería haber pasado algo.

El ejemplo perfecto: el email que nunca llega

WordPress envía correos con wp_mail(), que por debajo usa la función mail() de PHP. Muchísimos hostings la bloquean o la limitan para evitar spam. Resultado: un pedido de WooCommerce se confirma en la base de datos, pero el email de confirmación nunca sale. El cliente no recibe nada, piensa que algo ha ido mal, y te escribe enfadado — o directamente no vuelve.

Nadie se entera. Ni tú, ni el dueño del negocio. Hasta que ya cuesta dinero.

La solución mínima: engancharse al fallo real

WordPress dispara un hook específico cuando el envío falla: wp_mail_failed. Con esto ya tienes medio sistema de logs hecho:

add_action( 'wp_mail_failed', 'i8_log_mail_error' );

function i8_log_mail_error( $wp_error ) {
    $log_line = sprintf(
        "[%s] EMAIL FALLIDO | Destinatario: %s | Error: %s\n",
        current_time( 'mysql' ),
        $wp_error->get_error_data()['to'] ?? 'desconocido',
        $wp_error->get_error_message()
    );

    error_log( $log_line, 3, WP_CONTENT_DIR . '/logs/mail-errors.log' );
}

Con esto, cada fallo queda registrado con fecha, destinatario y motivo real (SMTP rechazado, credenciales mal, servidor caído...). Ya no dependes de que el cliente te avise — tú te enteras primero.

Importante: esa carpeta /logs/ tiene que estar protegida (un .htaccess con deny from all, o fuera de la raíz pública) para que nadie acceda a esos datos desde fuera.

¿Y si el fallo es en JavaScript?

Aquí cambia la naturaleza del problema. El JS corre en el navegador del usuario, no en tu servidor — así que si se rompe un carrito AJAX, un formulario multistep o un slider, tú no ves nada. El error vive y muere en el ordenador de tu cliente, y jamás te enteras.

JavaScript no puede escribir directamente en un archivo del servidor, pero sí puede avisar al servidor de que algo ha fallado. El sistema de log sigue siendo el mismo (PHP escribiendo en el mismo log); lo único que cambia es cómo llega la información hasta ahí.

Paso 1: capturar el error en el navegador

window.addEventListener('error', function (event) {
  reportarError({
    mensaje: event.message,
    archivo: event.filename,
    linea: event.lineno,
    url: window.location.href
  });
});

window.addEventListener('unhandledrejection', function (event) {
  reportarError({
    mensaje: event.reason?.message || 'Promesa rechazada',
    url: window.location.href
  });
});

function reportarError(datos) {
  fetch('/wp-json/i8/v1/log-error', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(datos)
  });
}

Paso 2: recibirlo en PHP y unificarlo con el resto de logs

add_action( 'rest_api_init', function () {
    register_rest_route( 'i8/v1', '/log-error', [
        'methods'  => 'POST',
        'callback' => 'i8_log_js_error',
        'permission_callback' => '__return_true',
    ]);
});

function i8_log_js_error( WP_REST_Request $request ) {
    $data = $request->get_json_params();

    $log_line = sprintf(
        "[%s] JS FALLIDO | URL: %s | Error: %s\n",
        current_time( 'mysql' ),
        $data['url'] ?? 'desconocida',
        $data['mensaje'] ?? 'sin detalle'
    );

    error_log( $log_line, 3, WP_CONTENT_DIR . '/logs/js-errors.log' );

    return new WP_REST_Response( [ 'ok' => true ], 200 );
}

Resultado: un único punto donde caen los fallos, vengan del servidor (email, conexión, pago) o del navegador de un cliente al otro lado del mundo. No importa dónde nace el problema — todo termina en el mismo sitio donde tú vas a mirar primero.

Por qué esto ahorra dinero de verdad

Sin logs, diagnosticar un fallo intermitente puede llevar horas: reproducir el error, preguntar al cliente qué hizo exactamente, probar en distintos navegadores... Con un log bien diseñado, el tiempo de diagnóstico baja de horas a minutos. Y en un negocio, tiempo de resolución = dinero: menos horas facturadas en debugging, menos pedidos perdidos, menos clientes enfadados esperando una respuesta que no llega.

Diseñar el software asumiendo que algo va a salir mal no es pesimismo — es la diferencia entre "no sé qué ha pasado" y "esto pasó a las 14:32, aquí está el motivo, ya está arreglado". Esa frase, dicha en cinco minutos en vez de en tres días, es la que hace que un cliente confíe en seguir trabajando contigo.


Emergencias webMantenimientoWebmasterSoporte

Preguntas frecuentes

¿Necesito un plugin para esto o me lo puedes montar a medida?

No hace falta ningún plugin de terceros para lo básico — como ves en los ejemplos, con unas pocas líneas de PHP enganchadas a los hooks correctos ya tienes un sistema funcional. En gabiirese.es monto estos sistemas a medida, ajustados a qué falla realmente en tu proyecto (emails, pagos, formularios, JS), sin añadir plugins que ralenticen la web ni dependencias que luego haya que mantener.

Tengo una tienda WooCommerce y sospecho que estoy perdiendo pedidos por fallos invisibles, ¿cómo lo reviso?

El primer paso es exactamente el que ves arriba: enganchar wp_mail_failed y revisar el log unos días. Si quieres, puedo hacer una auditoría rápida de tu proyecto — email, checkout y JS del carrito — y decirte con datos reales (no suposiciones) dónde se están perdiendo pedidos o leads.

¿Esto solo sirve para detectar fallos o también ayuda a prevenirlos?

Las dos cosas. Un log bien diseñado no solo te avisa cuando algo se rompe — con el tiempo, los patrones que aparecen (mismo error, misma hora, mismo plugin) te dicen dónde está el punto débil antes de que se convierta en una crisis. Es la base de cualquier mantenimiento serio, y es justo el tipo de trabajo que hago para clientes que quieren dejar de apagar fuegos y empezar a prevenirlos.

¿Necesitas mejorar tu web?