Skip to content

Todo para WordPress, el desarrollo web — y mucho más

⚡ Contact Form 7 - carga diferida de scripts y estilos para acelerar WordPress

⚡ Contact Form 7 - carga diferida de scripts y estilos para acelerar WordPress

Cómo CF7 ralentiza su sitio y por qué puede solucionarlo en 5 minutos

Contact Form 7 está instalado en más de 5 millones de sitios WordPress. El plugin es fiable, flexible y gratuito, y los formularios de contacto creados con él funcionan en prácticamente cualquier sitio. Pero esta comodidad tiene una contrapartida: por defecto, CF7 carga su CSS y JavaScript en todas las páginas de su sitio, incluso cuando no hay ningún formulario cerca.

Para la página de inicio, el blog, las landing pages y decenas de páginas más, esto es peso muerto: peticiones extra, mayor DOM Content Loaded, tamaño de página inflado. En cifras, aproximadamente entre 10 y 30 KB de tráfico comprimido y 1 o 2 peticiones bloqueantes sin motivo. PageSpeed Insights no perdona estas cosas.

Esto puede solucionarse de tres maneras, desde un diferimiento primitivo de dos líneas hasta una carga condicional cuidadosa «según las reglas» del desarrollador del plugin. Cubriremos cada una, con código y sin rodeos.

💡 Resumen rápido:

  • Desactive la carga global de CF7 mediante las constantes WPCF7_LOAD_JS y WPCF7_LOAD_CSS en wp-config.php, el método oficial más limpio.
  • Reactive los scripts y estilos, pero solo en las páginas con un formulario, mediante wpcf7_enqueue_scripts() en la plantilla de página.
  • Para paquetes personalizados, el paquete lazy-cf7-assets, que encuentra automáticamente el formulario en la página y carga el JS de forma dinámica.

Método 1: carga diferida del script de CF7 mediante functions.php

La opción más rápida y sencilla es añadir el atributo defer al script de Contact Form 7. Este indica al navegador: «cargue el archivo en segundo plano, pero ejecútelo cuando el DOM esté listo». El formulario sigue funcionando, pero el script ya no bloquea la renderización de la página.

Añada este código a functions.php en su tema activo (o mediante el plugin Code Snippets, más seguro durante las actualizaciones):

1if ( ! function_exists( 'add_defer_to_cf7' ) ) {
2 function add_defer_to_cf7( $url ) {
3 if (
4 false === strpos( $url, 'contact-form-7' ) ||
5 false === strpos( $url, '.js' )
6 ) {
7 return $url;
8 }
9 return "$url' defer='defer";
10 }
11 add_filter( 'clean_url', 'add_defer_to_cf7', 11, 1 );
12}

La función verifica la URL de cada script encolado mediante el hook clean_url. Si la dirección contiene contact-form-7 y la extensión .js, añade defer='defer'. Todos los demás scripts se dejan intactos.

Ventaja: una solución en 10 líneas que no requiere editar plantillas ni la configuración del plugin. Adecuada para temas donde no existe una plantilla separada para la página de contacto.

Desventaja: el script se sigue cargando en cada página, solo está eliminando el comportamiento bloqueante de la renderización. El tráfico y las peticiones al servidor no se reducen. Este método no afecta en absoluto al CSS del plugin, la hoja de estilos se carga como de costumbre.

Método 2: método oficial, carga condicional mediante constantes

Este enfoque está descrito en la documentación de Contact Form 7 por el propio desarrollador del plugin, Takayuki Miyoshi. La idea tiene dos pasos: primero desactive globalmente los scripts y estilos de CF7, luego actívelos de nuevo, pero solo en las páginas donde se utiliza realmente el formulario.

Paso 1: desactive la carga en todas las páginas

Añada dos constantes a wp-config.php:

1define( 'WPCF7_LOAD_JS', false );
2define( 'WPCF7_LOAD_CSS', false );

Alternativamente, mediante el functions.php de su tema:

1add_filter( 'wpcf7_load_js', '__return_false' );
2add_filter( 'wpcf7_load_css', '__return_false' );

Después de esto, CF7 no cargará ni una sola línea de su código en ninguna página de su sitio, incluidas aquellas donde exista un formulario. Sin scripts, el formulario pierde el envío por AJAX y la validación, por lo que se necesita el paso 2.

Paso 2: restaurar los scripts en las páginas con formulario

Supongamos que su página de contacto usa la plantilla page-contact.php en la carpeta de su tema. Agregue esto a esa plantilla antes de llamar a wp_head():

1if ( function_exists( 'wpcf7_enqueue_scripts' ) ) {
2 wpcf7_enqueue_scripts();
3}
4
5if ( function_exists( 'wpcf7_enqueue_styles' ) ) {
6 wpcf7_enqueue_styles();
7}

Las funciones wpcf7_enqueue_scripts() y wpcf7_enqueue_styles() encolan manualmente los scripts y estilos de CF7 solo en esta plantilla. Todas las demás páginas de su sitio permanecen limpias.

Ventaja: el método es «del fabricante», con garantía de no romperse durante las actualizaciones del plugin. Funciona con las versiones 5.x y 6.x de CF7, versión actual 6.1.6 a junio de 2026 (lista de versiones). Cero carga innecesaria en páginas sin formulario.

Desventaja: requiere editar las plantillas del tema. Si tiene varias páginas con formularios, debe recordar agregar las llamadas a cada plantilla. Si el formulario se inserta mediante shortcode en el contenido (en lugar de en una plantilla), el método no funcionará sin condiciones adicionales.

Método 3: el paquete lazy-cf7-assets para bundles de JavaScript

Si construye su frontend con un empaquetador (Webpack, Vite, esbuild) y usa un tema moderno con un bundle de JavaScript personalizado, existe un paquete npm llamado lazy-cf7-assets. Resuelve el mismo problema, pero del lado del cliente: escanea el DOM, encuentra el formulario de CF7 y solo entonces carga dinámicamente los scripts del plugin.

Instalación:

1npm install lazy-cf7-assets

Antes de usarlo, necesita desactivar la carga automática de JS por parte del plugin (como en el método 2, mediante wpcf7_load_js):

1add_filter( 'wpcf7_load_js', '__return_false' );

Luego en su bundle de JS:

1import lazyform from 'lazy-cf7-assets';
2
3// Initialize after DOM ready
4lazyform.init();

Si los scripts se cargan en el <head> en lugar de al final del <body>, especifique una ruta absoluta a la imagen GIF de carga para que el formulario no «parpadee» en un estado vacío:

1lazyform.init({
2 gifPath: '/wp-content/themes/my-theme/images/ajax-loader.gif'
3});
Captura de pantalla del repositorio lazy-cf7-assets en GitHub

Ventaja: cero intervención del lado PHP, no necesita editar plantillas para cada página con formulario. El paquete detecta automáticamente si existe un shortcode de CF7 en la página y carga los scripts solo entonces. Adecuado para sitios donde el formulario se muestra mediante shortcode en el contenido (en lugar de estar incrustado en una plantilla).

Desventaja: solo funciona con JavaScript (el CSS del plugin aún debe desactivarse por separado). Requiere un empaquetador en el proyecto. El paquete es mínimo (1 estrella en GitHub), mantenido por un único desarrollador; para producción debería bifurcarlo y verificar la compatibilidad con las actualizaciones de CF7.

Qué elegir: comparación de los tres enfoques

Criterio

Diferir mediante hook

Constantes + plantilla

lazy-cf7-assets

Ahorro de tráfico

❌ no

✅ total

✅ total (JS)

Protección ante actualizaciones de CF7

✅ sí

✅ sí

requiere verificación

No requiere editar plantillas

✅ sí

❌ no

✅ sí

Desactiva CSS

❌ no

✅ sí

❌ no

Complejidad de implementación

baja

media

media

Shortcode de formulario en contenido

✅ funciona

❌ dificultades

✅ funciona

Si su formulario reside en una sola página con una plantilla separada, use el método 2 (método oficial). Si el sitio usa un empaquetador moderno y podría tener varios formularios en distintos lugares, el método 3 (lazy-cf7-assets). Si necesita una solución «ahora mismo» sin editar plantillas, el método 1 (diferir), pero recuerde las limitaciones.

Una advertencia importante: después de cualquiera de estos cambios, asegúrese de verificar que el formulario se envía, la validación funciona, reCAPTCHA no está roto y los estilos no se han desplazado. Abra la página con el formulario en modo incógnito, complete y envíe un mensaje de prueba antes y después.

⁉️🤔 Preguntas frecuentes

¿Por qué CF7 carga scripts en todas las páginas de todas formas?

El plugin no sabe en la etapa de carga de WordPress si una página específica contiene un shortcode de formulario. WordPress ensambla la página más tarde, cuando la cola de scripts ya se ha formado. El desarrollador Takayuki Miyoshi lo explica en la documentación oficial: es técnicamente imposible detectar la presencia de un shortcode antes del hook wp_head. Así que se optó por un enfoque conservador, cargar siempre. Esta es una decisión arquitectónica deliberada, no un error: el plugin sacrifica rendimiento por funcionalidad garantizada. La carga de la optimización se transfiere al desarrollador del sitio.

¿Se romperá el formulario después de desactivar la carga global?

No, si vuelve a habilitar cuidadosamente los scripts en las páginas necesarias. El formulario perderá el envío AJAX y la validación del lado del cliente solo en las páginas donde los scripts no estén incluidos. Por eso el paso 2 (restaurar scripts) es obligatorio, no se detenga solo en WPCF7_LOAD_JS = false. Verifique el orden de las llamadas: wpcf7_enqueue_scripts() debe ir antes de wp_head(), no después. Y asegúrese de que reCAPTCHA no entre en conflicto con la carga diferida.

¿Funciona el método de las constantes con CF7 6.x?

Sí, las constantes WPCF7_LOAD_JS y WPCF7_LOAD_CSS son totalmente compatibles en la versión actual 6.1.6 (consulte el registro oficial de versiones). A lo largo de toda la historia del plugin, desde la versión 3.9 hasta la actual 6.x, estas constantes nunca han sido declaradas obsoletas. Este es el método más estable y documentado para gestionar la carga.

¿Qué pasa si tengo varios formularios en diferentes lugares?

Si los formularios están dispersos en diferentes páginas mediante shortcodes en el contenido (en lugar de en plantillas), el método oficial con plantillas es inconveniente. Utilice lazy-cf7-assets (método 3), o el plugin Conditionally Load CF7: añade una configuración en el panel de administración para qué páginas o tipos de contenido deben cargar scripts, y funciona sin editar código.

Tres líneas de código frente a docenas de solicitudes

El problema de «CF7 carga scripts en todas partes» ha existido exactamente desde que existe el plugin, y durante más de 10 años el desarrollador no ha cambiado el comportamiento predeterminado, porque es un compromiso entre simplicidad y rendimiento. Pero un compromiso, no una sentencia.

El camino más seguro es el método oficial con constantes y plantillas. Elimina los scripts y estilos del plugin de todas las páginas excepto aquellas donde se necesitan, y no se rompe durante las actualizaciones. Si su sitio utiliza un stack moderno con un empaquetador, eche un vistazo a lazy-cf7-assets. Si necesita algo rápido y sin editar plantillas, la carga diferida mediante el hook clean_url le dará mejoras en las métricas hoy mismo.

Revise su sitio con PageSpeed Insights antes y después: reducir el número de solicitudes bloqueantes en 1 o 2 unidades y ahorrar de 10 a 30 KB por página puede aumentar la puntuación de Rendimiento de 2 a 5 puntos, especialmente en dispositivos móviles.