En este artículo aprenderás cómo construir un formulario contacto en WordPress sin usar plugins, para lograrlo usaremos plantillas de página y código adicional en el archivo functions.php
Resultado Final
Al mostrar un ítem de menú con la página de contacto veremos un formulario como se muestra en la siguiente imagen:

Plantilla de página
En el artículo de Plantillas de Página en WordPress, habías visto cómo crear una plantilla de página. Para nuestro formulario de contacto necesitamos construir la vista HTML a través de una plantilla de página, usaremos como base el siguiente código de formulario.
<?php
if ( isset($_GET['sent']) ){
if ( $_GET['sent'] == '1'){
echo "<p> ✔ Formulario enviado correctamente</p><br>";
}
else {
echo "<p> Hubo un error al enviar</p><br>";
}
}
?>
<form method="post" action="<?php echo admin_url( 'admin-post.php' ) ?>" >
<label for="name">Nombre:</label>
<input type="text" name="name" id="name" required>
<br>
<label for="email">Correo:</label>
<input type="email" name="email" id="email" required>
<br>
<label for="message">Mensaje:</label>
<textarea name="message" id="message" cols="30" rows="10" required></textarea>
<br>
<p><input type="checkbox" id="terms" name="terms" required> Acepto los <a href="#">Términos y Condiciones</a></p>
<br>
<input type="hidden" name="action" value="process_form">
<input type="submit" name="submit" value="Enviar">
</form>
En el código anterior:
- Hay una comprobación si se enviaron los datos correctamente, esto a través de $_GET, ya que cuando confirmamos el envío del correo redireccionaremos a la misma url con un parámetro
- Luego viene el código del formulario, aquí lo importante es que estamos haciendo referencia al archivo : admin-post.php
- Creamos los controles de nombre, correo y mensaje y lo más importante un campo oculto llamado action, que en conjunto con admin-post.php permitirán procesar el formulario
Luego que tengas el archivo, crea una página en WordPress, la puedes llamar “contacto”, y asigna la plantilla de página, tal como se muestra en la siguiente imagen.

Código en functions.php
Debido a que en el código anterior hemos usado la llamada a admin-post.php para que procese el formulario, será necesario construir los hooks y funciones callbacks en el archivo functions.php.
Como te comenté anteriormente, hemos usado un campo oculto llamado action con el valor process_form, por lo tanto la lógica para construir los hooks es similar a la que vimos en el artículo de Ajax en WordPress.
Los hooks que usaremos serán:
admin_post_XXX
admin_post_nopriv_XXX
Reemplazando XXX por el valor del campo action que es process_form
Por lo tanto nuestro código quedaría:
// Hooks admin-post
add_action( 'admin_post_nopriv_process_form', 'send_mail_data' );
add_action( 'admin_post_process_form', 'send_mail_data' );
// Funcion callback
function send_mail_data() {
$name = sanitize_text_field($_POST['name']);
$email = sanitize_email($_POST['email']);
$message = sanitize_textarea_field($_POST['message']);
$adminmail = "destino@dominio.com"; //email destino
$subject = 'Formulario de contacto'; //asunto
$headers = "Reply-to: " . $name . " <" . $email . ">";
//Cuerpo del mensaje
$msg = "Nombre: " . $name . "\n";
$msg .= "E-mail: " . $email . "\n\n";
$msg .= "Mensaje: \n\n" . $message . "\n";
$sendmail = wp_mail( $adminmail, $subject, $msg, $headers);
wp_redirect( home_url("/contacto/")."?sent=".$sendmail ); //asumiendo que existe esta url
}
En el código anterior
- Los hooks hacen referencia a la función send_mail_data
- En la función obtenemos los datos de los diferentes campos y los validamos
- Definimos el email destino, asunto y cabeceras
- Construimos el cuerpo del mensaje en la variable $msg
- Finalmente usamos wp_mail para enviar el correo
- Esta variable devuelve un booleano, por lo tanto al hacer la redirección pasamos la variable
Conclusión
Hemos visto que podemos crear un formulario con plantillas de página y usar el poder de WordPress para procesarlo, esto puede extendenderse no sólo a la creación de un formulario de contacto sino a cualquier tipo de formulario y construir algo personalizado.
¿Aún con dudas?, en el siguiente video se detalla como implementar los puntos anteriores.
Hola, felicidades por tu sitio. Hice el procedimiento correcto, según creo, y el formulario se envió correctamente, pero no recibí el correo en cuenta. Algunada recomendación que puedas darme.
Muchas gracias,
Eduardo
Hola, prueba configurando para recibir en un correo de de tu propio domino y no un correo público como gmail o hotmail.
Brother, eres el mejor. ¡Muchas Gracias!
Hola, me gustaría saber como integrar en “atributos de página” la opción “plantilla”, solo me aparece superior y orden.
Muchas gracias,
Saludos.
No le veo relación a tu consulta con este artículo artículo, te sugiero revisar: https://decodecms.com/plantillas-pagina-wordpress/
Artículo genial, bien explicado y el código funciona correctamente.
Tengo una duda que seguro que se resuelve fácilmente por alguien con experiencia como tú, pero que probablemente habrá más personas que al leer este artículo se topen con la misma cuestión que yo:
¿Qué debería hacer si quiero crear distintos formularios de contacto? Por ejemplo, uno para la página “Contacto” y otro para la página “Colaboraciones” (en este ejemplo, me interesa tener dos páginas bien diferenciadas en vez de aglomerarlo todo en el mismo formulario).
Las consultas hechas en el formulario de la página “Contacto” serían enviadas a una dirección de correo, mientras que las realizadas en el formulario de la página “Colaboraciones” se enviarían a otra dirección de correo diferente.
Hola, mejor envíame información adicional a través del formulario de contacto, tu código y el error que te aparece.
Un post interesante, aunque no me ha funcionado. Al realizar el envio lleva a una pagina que no encuentra o simplemente la muestra en blanco (“dominio”/wp-admin/admin-post.php). No me interesa la parte del mail puesto que mi idea es usar esos datos para una consulta a una base de datos externa(La consulta me funciona correctamente) ¿A que puede deberse el error?¿Sera por no usar la plantilla predeterminada? Espero su respuesta, gracias.
Hola te lleva al admin-post.php porque así esta programado, prueba primero con el código original sin modificaciones, enviando mail y verifica si te funciona, es posible que si obtienes una página en blanco se este generando errores 500 que debes revisar en tu error_log.
Muy bueno me has ayudado mucho, tengo un problemita, el diseño de mi página tiene el formulario de contacto en el footer, agregué las funciones y el código php a mi theme pero al enviar los datos, no los envía, me redirige a una página que no tengo en el theme y tampoco me lanza errores, Por favor necesito tu ayuda, soy nuevo en esto y de eso depende mi trabajo
Hola, a qué página te redirige?, si sigues con problemas mejor envíame tu consulta a través del formulario de contacto. https://decodecms.com/contacto/
¡Hola!
Primero, felicidades por la claridad del post.
Tengo la duda de cómo hacer para:
1. Ya se enviaron los datos del formulario
2. Ya los recibí en variables en functions.php y se procesaron, quedando el resultado almacenado en $resultado
Mi duda es: ¿cómo puedo mostrar en otra página “../resultado/ el valor de $resultado?
Espero mi duda aplique bien con el tema, muchas gracias
Hola, en el código php final hay una redirección, podrías pasar la variable $resultado en la url
Hola mucho gusto, disculpa pero solo me redirecciona al admin-post.php y no hace mas nada, que puedo hacer? gracias
Hola buen dia, si yo no quisiera enviarlo a un correo sino directamente a mi whatsapp, ¿Còmo serìa?
Hola, dependes de una aplicación para esto, ya sea tu aplicación de movil o el navegador, si no quieres una aplicación tendrías que usar la API de whatsapp, veo que hay algunos servicios externos que la usan podrías revisar: http://wassame.com
Hola, buena explicación, me gustaría saber como transformar esa misma plantilla en un plugin, intente realizar esa conversión pero no resulta como esperaba, y no se si pudieras ayudarme con ese problema, de antemano muchas gracias y felicitaciones por tu post.
Hola, no sigue la estructura de un plugin, podrías rescatar algo de la lógica pero para aplicarla podrías crear un shortcode, para la estructura de un plugin revisa: https://decodecms.com/generador-de-plugins-base-para-wordpress/ , para hacer un shortcode: https://decodecms.com/que-son-los-shortcodes-en-wordpress-y-como-usarlos/
Muchas Gracias, no sabes la cantidad de códigos y nada. Con el tuyo súper fácil y de una.
Gracias Ruth. Saludos.
Hola:
Excelente articulo. Me pongo ahora mismo con ello, pero me surge un problema me gustaría cumplir con la ley de protección de datos y que incluyera un checkbox seria posible que incluyeras el código que habría que poner.
Muchísimas gracias
Hola Nekane, gracias por la sugerencia, he agregado el checkbox en el código del formulario, sólo tendrías que cambiar el # por la url de tu página de términos y condiciones.
Agradecer lo rápido que me has contestado dando una solución y felicitarte por la excelente web que nos ofreces. Me ha funciona perfecto, visualmente se me montan un poco las casillas y no sé muy bien como modificarlo, pero estoy encantada de haberlo hecho sin usar un plugin.
Sigo dando una vuelta a todos tus contenidos, que te explicas genial y tengo mucho por aprender.
Mil gracias
Hola Jhon !
Gracias por el aporte, intenté usar dos formularios y cambiar algunos nombres en el hooks de functions pero sólo envía el primer formulario creado y vació, del segundo creado ni sus luces, como es la correcta definición de los valores? o si este segundo hook queda fuera de functions.php?
Hola, ambos formularios aparecen en la misma página?, mejor asegúrate primero que funcione un solo formulario y que te llegue el contenido, sino actualmente sólo te llega el asunto del mensaje sin contenido, revisa la variable $msg.
Hola Jhon- muchas gracias por tu post. Quiero saber como hacer para que al final de ejecutar mi código de la función php, el cual genera un pdf con la información del formulario e implementando la libreria mpdf, no me quede en la url …/wp-admin/admin-post.php
Muchas gracias
Hola, en tu caso en lugar de enviar el mensaje final de enviado correctamente, tendrías que colocar en ese lugar tu código o la referencia a un archivo en donde esta tu código o una redirección. Es decir tendrías que remplazar este código:
Hola!
me va saliendo todo, pero cuando pongo el código del formulario tal cual aparece en este tutorial y refresco el sitio, en lugar de salirme el formulario como tal me sigue apareciendo “codigo de formulario”, le he dado mil vueltas pero no se donde está el error.
Estoy usando un tema propio de underscore.
Hola, en donde agregaste el código?, si lo agregas en el functions.php no debería mostrarse el código, sino ejecutarse. Saludos.
Lo he agregado en t_page_contacto.php tal y como se indica en el video.
Un saludo!
Hola agregaste al inicio del archivo:
Hola, Quisiera agregar el formulario de contacto en un widget seria lo mismo, es decir de ves de colocar el codigo en una plantilla de página lo puedo colocar en un widget que voy a crear, seguiria funcionando igual??
Un saludo!
Hola
Si vas a usar un Widget lo ideal sería que no te recargue la página, creo que tendrías que manejarlo con Ajax, el código de este artículo es con recarga de página, no lo veo muy aplicable a un Widget.
Hola,
He seguido tus explicaciones y genial, me ha salido a la primera. Quisiera preguntarle para dejarlo acabado como añadir el capcha y un enlace a la pagina con los terminos y condiciones.
Salidos
Hola, tendrías que agregar como parte del código HTML en el archivo de contacto.php código adicional, revisa la documentación oficial: https://blog.argentinareseller.com/2019/06/22/como-incluir-captcha-en-tus-formularios-web/ , sólo la parte del body, el script tendrías que insertarlo tal como se comenta en el punto 3 de este artículo: https://decodecms.com/insertar-javascript-en-wordpress-de-forma-correcta/
Hola,
Gracias por su ayuda. Añadir el captcha me ha costado un poco pero creo que lo he conseguido, solo faltaria añadir al formulario que solicite que el campo sea requerido. ¿Como añadir al fichero el campo requerido?
Saludos
Excelente aporte amigo. Solo tengo una duda, como puedo obtener la información de los formularios en MySQL o en alguna otra base de datos. Me gusto como se recibe la información en gmail, pero también la quisiera poder visualizar y extraer desde una base de datos. Espero haya sido claro y me puedas resolver esta duda.
Saludos.
Hola, supongo que te refieres a guardarlos en alguna tabla de la base de datos, en al funcionalidad de envío sería agregar esto, tomo nota para actualizar o hacer un nuevo artículo sobre esto.
Hola, he realizado un artículo para guardar la información enviada por el formulario en la base de datos de WordPress
Hola amigo, gracias por tu aporte, realmente bueno, una consulta, tiene alguna limitacion usar esto con un shortcode, ya que al hacerlo solo me funciona para usuarios registrados, mil gracias
Hola, no debería haber problema, asegúrate de usar ambos hooks: admin_post_nopriv_process_form y admin_post_process_form
Cómo puedo crear un formulario que me sirva para que el que se registra pueda recibir un pdf a su correo?
Hola, la función de WordPress wp_mail() que sirve para enviar correo, tiene un parámetro opcional de adjuntos (attachments), revisa esta discusión: https://wordpress.stackexchange.com/questions/50264/using-wp-mail-with-attachments-but-no-attachments-received/50382
Hola, amigo ya inplemetento el proyecto ami sito y todo bien, pero tengo una duda. ¿Como puedo modificar los textos?, “✔ Formulario enviado correctamente” & “Hubo un error al enviar” con css para darle un poco de color y estilos, intete modificrlo pero mi web se cae y tengo que modificar el archivo desde el cpanel si me puedes ayudar gracias.
Hola amigo ya pude resolver el problema era super simple, pero aun no me adapto a php estoy recien comensando en esto asi que ya supe como hacerlo para borres mi comentario gracias.
Buenas! Muy buena la guía! Muchas gracias!
Seguí todo al pie de la letra, pero al intentar enviar el mail desde local, me tira error.
En sí al no tener hosting para probar, necesito resolverlo de esta forma.
Probé con un plugin (Contact Form 7) y funciona, pero no de esta manera.
Alguna sugerencia? Estoy utilizando para el envío de correos local a Mercury.
Gracias!
Hola, desde local no podrás enviar correo al menos tengas salida SMTP o algún software interceptor de correos para probar.
Saludos.
Excelente fue de mucha ayuda para mi sitio que estoy empezando y no tenía espacio para instalar plugins.
Hola consulta el formulario no debería variar si lo hago desde un custom post type? para mostrarlo en mi landing? porque no me esta resultando 🙁 me envía el mensaje de error
Hola, no debería variar, sin embargo prueba primero tal como lo hago y verifica, ya que igual es un problema con el envío del correo.
Hola amigo una pregunta ¿Como puedo hacer que los datos no sean persistentes sin plugins? es decir, si refresco la pagina o si omito el formulario y accedo a la url donde estan los datos pues que no se los muestre si no hacer el proceso del formulario.
Hola, tienes que capturar el valor, por ejemplo con $_GET, revisa este artículo en donde el valor de la búsqueda es persistente: https://decodecms.com/shortcode-para-busqueda-en-tabla-personalizada-en-wordpress/
hola, he probado el código y me salta el mensaje de que no se ha podido enviar el mensaje y no entiendo por qué. El código es igual al tuyo
Revisa si desde otras partes de tu sitio puedes enviar mensajes correctamente.
Hola, me pasa lo mismo que Dania, he copiado y pegado tu código adaptándolo y me aparece que hubo un error al enviar, estoy añadiendo una dirección de gmail, no se si será eso, también lo estoy haciendo en localhost. Llevo ya dos días intentando esto, por favor si me puedes ayudar D:
Hola, si estas en localhost es probable que no tengas configurado un servidor de correos de manera local.
Podrías probar configurar algún plugin de SMTP y configurar un servidor externo.
Saludos.
Hola John conocía tu página desde hace ya tiempo pero alguna vez e intentado hacer un tutorial pero sin éxito ahora con algún poco de conocimiento sobre desarrollo he probado este ya que siempre me fallaban los plugins de contacto y chapeu lo hecho y perfecto lo único hacer recapcha o algo para que no llege spam?? Tienes algo?? Sin plugins??
Hola Marcos
Tengo pendiente hacer un artículo para agregar recaptcha a este formulario, espero tenerlo listo próximamente por lo que permanece atento.
Hola Marcos, he creado un artículo recientemente sobre cómo implementar recaptcha, revisa: https://decodecms.com/agregar-recaptcha-v3-en-formulario-de-contacto/
Excelente, facil y liviana solución sin plugins. Y me llega el mensaje al correo sin problema 🙂
Yo dejé el código del form en page.php (anidado dentro de un IF) y a través de un campo personalizado decido si aparecerá el formulario en la página o no.
¡Muchas gracias! 👏
Hola Joan, si, es una buena forma también de mostrarlo sólo en las páginas que lo necesites. Saludos.
Hola, gracias por compartir, una duda como puedo agregar datos adjuntos al formulario, la parte de html la tengo clara, pero en el código que va en el en functions.php no, gracias
Hola, si deseas adjuntos de correos lo haces en la función wp_mail(), revisa la documentación de la función, espero hacer un artículo sobre cómo agregar adjuntos próximamente.
Hola, Jhon, gracias por el tutorial lo he seguido hoy con éxito para desprenderme por fin de otro plugin. Ahora voy a meterle mano a lo del captcha 😛
Hola, revisa este artículo de guia: https://decodecms.com/agregar-recaptcha-v3-en-formulario-de-contacto/
Hola se haría el mismo procedimiento si tengo en 2 páginas diferentes un formulario?
Hola, en ese caso seria mejor encapsular el código en un shortcode, de esa forma puedes utilizarlo en varias páginas de tu sitio