Algo que no entiendo es que WordPress no incluya aún por defecto un formulario de contacto simple, pero completo.
Como habitualmente hago tareas de optimización de WordPress , tanto aquí como en sitios ajenos, en muchas ocasiones sustituyo plugins engordados innecesariamente con opciones, bloques y adornos que nunca se usan o no se necesitan por código para aligerar la carga.
Este formulario de contacto es una solución completa y personalizable para WordPress, diseñado para ser seguro, fácil de usar y respetuoso con la privacidad del usuario. Además, puedes añadir o quitar opciones a tu interés. Es el formulario que uso aquí .
Estas son sus principales funciones y características y las instrucciones para añadirlo a cualquier página o post de tu blog con un shortcode.
Estructura y opciones Nombre : Campo obligatorio para que el usuario ingrese su nombre.Email : Campo obligatorio para que el usuario ingrese su dirección de correo electrónico.Mensaje : Campo obligatorio para que el usuario escriba su mensaje. Debe tener al menos 15 caracteres y un máximo de 1000. No se permiten enlaces ni direcciones de correo en el cuerpo del mensaje.Captcha de suma : Un captcha simple que pide al usuario resolver una suma de dos números aleatorios entre 1 y 9.Aceptación de política de privacidad : Casilla de verificación obligatoria para aceptar la política de privacidad antes de enviar el formulario.2. Validaciones y seguridad Validación de campos obligatorios : Todos los campos son obligatorios. Si falta alguno, se muestra un mensaje de error.Validación de enlaces : No se permiten enlaces (URLs) en los campos de nombre o mensaje.Captcha de suma : Evita el spam automatizado al requerir que el usuario resuelva una operación matemática simple.Google reCAPTCHA (opcional) : Si se configuran las claves de reCAPTCHA de Google, se añade un segundo nivel de seguridad para evitar bots. Si no se añaden las claves de reCAPTCHA al código, este no se añadirá al formulario.Validación de palabras prohibidas : Opcionalmente, se pueden bloquear palabras específicas en el mensaje, por ejemplo: piña,pizza,bitcoin (separadas con coma y sin espacios)Nonce de seguridad : Protege contra ataques CSRF (Cross-Site Request Forgery).3. Privacidad Sin almacenamiento de datos : No se almacena ningún dato del usuario (ni correos, ni IPs, ni URLs de referencia, nada). Este enfoque cumple con las normativas de privacidad como el RGPD, ya que no se recopila ni almacena información personal alguna.Política de privacidad : Incluye un enlace a la política de privacidad que el usuario debe leer aceptar antes de enviar el formulario.4. Mensajes de retroalimentación Mensajes de error : Se muestran en un bloque al principio del formulario si hay errores en la validación.Mensaje de éxito : Tras enviar el formulario correctamente, se muestra un mensaje de éxito en verde, con un tamaño de 14px y en negrita: "¡Gracias! Tu mensaje ha sido enviado .". Puedes cambiar este texto y su formato en el código. El resto de los estilos como el fondo amarillo, el borde y sombra de la caja que contiene el formulario que puedes ver aquí , así como otros elementos exteriores no se incluyen en el código ya que están añadidos con un contenedor de GenerateBlocks .5. Personalización Texto del captcha : Personalizable (por defecto: "¿Eres humano? Resuelve esta suma:").Palabras prohibidas : Se puede añadir una lista de palabras prohibidas separadas por comas.Google reCAPTCHA : Opcional, solo se añade si se configuran y añaden las claves del sitio y secreta de tu captcha al código.6. Rendimiento En el código se verifica si el shortcode está presente y si no está el shortcode, no mostrará nada, por lo que sólo se ejecutará en la página o post donde se haya añadido shortcode.
El rendimiento allá donde se muestra es óptimo.
Instrucciones de instalación y configuración 1. Copiar y añadir el código Abre el archivo functions.php de tu tema WordPress (o crea un plugin personalizado si prefieres no modificar el tema o usa Code Snippets ). Copia y pega el código completo del formulario en el archivo functions.php 2. Configurar Google reCAPTCHA (Opcional) Dirígete a Google reCAPTCHA . Selecciona reCAPTCHA v2 y elige la opción "I'm not a robot" Checkbox . Registra tu sitio web y obtén las claves:Clave del sitio (Site Key) Clave secreta (Secret Key) En el código del formulario, reemplaza 'TU_CLAVE_DEL_SITIO'
y 'TU_CLAVE_SECRETA'
con las claves que obtuviste.Si no deseas usar reCAPTCHA , deja las claves como están. Es decir, así: ('TU_CLAVE_DEL_SITIO'
y 'TU_CLAVE_SECRETA'
). 3. Configurar palabras prohibidas (Opcional) 1 - En el código del formulario, busca la línea:
$palabras_prohibidas = ' ';
2 - Añade las palabras que deseas bloquear, separadas por comas. Por ejemplo:
$palabras_prohibidas = 'caca,culo,pedo,pis';
Si no quieres bloquear ninguna palabra, deja la variable vacía.
4. Personaliza el texto del captcha de la suma (Opcional) En el código del formulario, busca esta línea:
<label for="captcha">¿Eres humano? Resuelve esta suma: <strong><?php echo $num1; ?> + <?php echo $num2; ?> = </strong></label>
Cambia el texto "¿Eres humano? Resuelve esta suma:" por el que quieras mostrar.
5. Añade la URL de tu política de privacidad Sustituye la url de ejemplo por la URL de la política de privacidad de tu página en esta línea:
$politica_privacidad_url = 'https://tuweb.com/declaracion-de-privacidad/';
6. Shortcode Añade el shortcode en la página o post donde quieras que se muestre el formulario.
[formulario_contacto]
Por último, solo tendrás que probarlo para verificar que los correos se envían y llegan y observar el uso para prevenir que los incansables spammers consigan colar sus mierdas complicando el captcha matemático y´/o activando ambos captchas al tiempo. El código siempre es mejorable y se puede depurar y optimizar. También puedes traducirlo si necesitas usarlo en otro idioma.
Si hago cambios o mejoras en el código en función del resultado iré añadiendo las notas aquí mismo.
Código //Crea un shortcode que genera un formulario de contacto para añadir en cualquier página o post de tu blog. Código actualizado en https://jrmora.com/formulario-contacto-wordpress-sin-plugin/
// Shortcode para mostrar el formulario de contacto
function contacto_form_shortcode() {
// Verificar si el shortcode está presente en el contenido actual
if (!has_shortcode(get_the_content(), 'formulario_contacto')) {
return ''; // Si no está el shortcode, no mostrar nada
}
ob_start(); // Iniciar el buffer de salida
// Claves de Google reCAPTCHA (cambia estas por las tuyas)
$site_key = 'TU_CLAVE_DEL_SITIO'; // Clave del sitio de reCAPTCHA
$secret_key = 'TU_CLAVE_SECRETA'; // Clave secreta de reCAPTCHA
// Verificar si las claves son las predeterminadas
$recaptcha_enabled = ($site_key !== 'TU_CLAVE_DEL_SITIO' && $secret_key !== 'TU_CLAVE_SECRETA');
// Lista de palabras prohibidas (separadas por comas)
// Ejemplo: $palabras_prohibidas = 'spam,publicidad,oferta';
$palabras_prohibidas = 'copywriter'; // No hay palabras prohibidas por defecto si está vacío
// Convertir la lista de palabras prohibidas en un array
$palabras_prohibidas_array = !empty($palabras_prohibidas) ? explode(',', $palabras_prohibidas) : [];
// Variables para almacenar errores
$errors = [];
// Verificar si el formulario ha sido enviado
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['contacto_nonce'])) {
// Verificar el nonce para seguridad
if (!wp_verify_nonce($_POST['contacto_nonce'], 'contacto_form_nonce')) {
$errors[] = 'Error de seguridad. Inténtalo de nuevo.';
} else {
// Validar el captcha de suma
$captcha = sanitize_text_field($_POST['captcha']);
$captcha_correct = sanitize_text_field($_POST['captcha_correct']);
if ($captcha !== $captcha_correct) {
$errors[] = 'El resultado de la operación es incorrecto. Inténtalo de nuevo.';
} else {
// Validar la aceptación de la política de privacidad
if (!isset($_POST['aceptar_privacidad'])) {
$errors[] = 'Debes aceptar la política de privacidad para enviar el formulario.';
} else {
// Validar Google reCAPTCHA (solo si está habilitado)
if ($recaptcha_enabled) {
if (isset($_POST['g-recaptcha-response'])) {
$recaptcha_response = sanitize_text_field($_POST['g-recaptcha-response']);
$recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify';
$recaptcha_data = [
'secret' => $secret_key,
'response' => $recaptcha_response,
];
$recaptcha_options = [
'http' => [
'method' => 'POST',
'header' => 'Content-Type: application/x-www-form-urlencoded',
'content' => http_build_query($recaptcha_data),
],
];
$recaptcha_context = stream_context_create($recaptcha_options);
$recaptcha_result = file_get_contents($recaptcha_url, false, $recaptcha_context);
$recaptcha_json = json_decode($recaptcha_result);
if (!$recaptcha_json->success) {
$errors[] = 'Por favor, verifica que no eres un robot.';
}
} else {
$errors[] = 'Por favor, completa el reCAPTCHA.';
}
}
// Si no hay errores, procesar el formulario
if (empty($errors)) {
$nombre = sanitize_text_field($_POST['nombre']);
$email = sanitize_email($_POST['email']);
$mensaje = sanitize_textarea_field($_POST['mensaje']);
// Validar campos obligatorios
if (empty($nombre)) {
$errors[] = 'El campo nombre es obligatorio.';
}
if (empty($email)) {
$errors[] = 'El campo email es obligatorio.';
}
if (empty($mensaje)) {
$errors[] = 'El campo mensaje es obligatorio.';
}
// Validar que no se hayan añadido enlaces en los campos
if (preg_match('/http|www|\[url|\[link|href=/i', $nombre . $mensaje)) {
$errors[] = 'No se permiten enlaces en los campos del formulario.';
}
// Validar que no se hayan añadido direcciones de correo en el mensaje
if (preg_match('/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/', $mensaje)) {
$errors[] = 'No se permiten direcciones de correo en el mensaje.';
}
// Validar que el mensaje tenga al menos 15 caracteres
if (strlen($mensaje) < 15) {
$errors[] = 'El mensaje debe tener al menos 15 caracteres.';
}
// Validar que el mensaje no supere los 1000 caracteres
if (strlen($mensaje) > 1000) {
$errors[] = 'El mensaje no puede superar los 1000 caracteres.';
}
// Validar palabras prohibidas (solo si hay palabras en la lista)
if (!empty($palabras_prohibidas_array)) {
foreach ($palabras_prohibidas_array as $palabra) {
if (stripos($mensaje, $palabra) !== false) {
$errors[] = 'El mensaje contiene palabras no permitidas.';
break; // Detener la validación al encontrar una palabra prohibida
}
}
}
// Si no hay errores, enviar el correo
if (empty($errors)) {
$to = get_option('admin_email'); // Correo del administrador
$subject = 'Nuevo mensaje de contacto desde el sitio web';
$headers = array('Content-Type: text/html; charset=UTF-8', 'From: ' . $nombre . ' <' . $email . '>');
$body = "<p><strong>Nombre:</strong> $nombre</p>";
$body .= "<p><strong>Email:</strong> $email</p>";
$body .= "<p><strong>Mensaje:</strong> $mensaje</p>";
if (wp_mail($to, $subject, $body, $headers)) {
// Redirigir para evitar reenvío al refrescar la página
wp_redirect(add_query_arg('contacto', 'success', wp_get_referer()));
exit;
} else {
$errors[] = 'Hubo un error al enviar el mensaje. Inténtalo de nuevo.';
}
}
}
}
}
}
}
// Mostrar mensaje de éxito después de la redirección
if (isset($_GET['contacto']) && $_GET['contacto'] === 'success') {
echo '<p style="font-size: 14px; font-weight: bold; color: green;">¡Gracias! Tu mensaje ha sido enviado.</p>';
}
// Generar un captcha de suma de dos números aleatorios entre 1 y 9
$num1 = rand(1, 9); // Primer número aleatorio entre 1 y 9
$num2 = rand(1, 9); // Segundo número aleatorio entre 1 y 9
$captcha_result = $num1 + $num2; // Resultado de la suma
// URL de la política de privacidad
$politica_privacidad_url = 'https://jrmora.com/declaracion-de-privacidad-ue/';
// Mostrar el formulario
?>
<?php if (!empty($errors)) : ?>
<div style="color: red; margin-bottom: 20px;">
<?php foreach ($errors as $error) : ?>
<p><?php echo esc_html($error); ?></p>
<?php endforeach; ?>
</div>
<?php endif; ?>
<form action="" method="post">
<p>
<label for="nombre">Nombre:</label><br>
<input type="text" name="nombre" id="nombre" value="<?php echo isset($nombre) ? esc_attr($nombre) : ''; ?>" required>
</p>
<p>
<label for="email">Email:</label><br>
<input type="email" name="email" id="email" value="<?php echo isset($email) ? esc_attr($email) : ''; ?>" required>
</p>
<p>
<label for="mensaje">Mensaje:</label><br>
<textarea name="mensaje" id="mensaje" rows="5" maxlength="1000" required><?php echo isset($mensaje) ? esc_textarea($mensaje) : ''; ?></textarea>
</p>
<p>
<label for="captcha">¿Eres humano? Resuelve esta suma: <strong><?php echo $num1; ?> + <?php echo $num2; ?> = </strong></label><br>
<input type="text" name="captcha" id="captcha" required>
<input type="hidden" name="captcha_correct" value="<?php echo $captcha_result; ?>">
</p>
<?php if ($recaptcha_enabled) : ?>
<p>
<div class="g-recaptcha" data-sitekey="<?php echo esc_attr($site_key); ?>"></div>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
</p>
<?php endif; ?>
<p>
<input type="checkbox" name="aceptar_privacidad" id="aceptar_privacidad" required>
<label for="aceptar_privacidad">He leído y acepto la <a href="<?php echo esc_url($politica_privacidad_url); ?>" target="_blank">política de privacidad</a>.</label>
</p>
<p>
<?php wp_nonce_field('contacto_form_nonce', 'contacto_nonce'); ?>
<input type="submit" value="Enviar">
</p>
</form>
<?php
return ob_get_clean(); // Devolver el contenido del buffer
}
add_shortcode('formulario_contacto', 'contacto_form_shortcode');
¡Buenas!
Muy buen aporte para quienes buscan un formulario de contacto sin depender de plugins en WordPress. Me ha gustado que incluya validaciones de seguridad como el nonce y la opción de Google reCAPTCHA. Además, el captcha de suma es un buen filtro anti-spam ligero. Es importante medir bien el uso de plugins, porque si los usas para todo, puedes acabar con un sitio pesado e impracticable. Este tipo de soluciones en código ayudan a mantener WordPress optimizado. Un código bien estructurado, funcional y con margen para personalizarlo según las necesidades de cada sitio. ¡Gracias, compañero!