
⚡ Contact Form 7 - caricamento differito di script e stili per velocizzare WordPress
Come CF7 rallenta il tuo sito e perché puoi risolverlo in 5 minuti
Contact Form 7 è installato su oltre 5 milioni di siti WordPress. Il plugin è affidabile, flessibile e gratuito, e i moduli di contatto creati con esso funzionano praticamente su ogni sito. Ma questa comodità ha un rovescio della medaglia: per impostazione predefinita, CF7 carica i suoi CSS e JavaScript su ogni pagina del sito, anche quando non c'è alcun modulo nelle vicinanze.
Per la homepage, il blog, le landing page e decine di altre pagine, questo è peso morto: richieste extra, DOM Content Loaded aumentato, dimensioni della pagina gonfiate. In numeri, circa 10-30 KB di traffico compresso e 1-2 richieste bloccanti senza motivo. PageSpeed Insights non perdona queste cose.
Questo si può risolvere in tre modi, da un semplice defer di due righe a un attento caricamento condizionale "da manuale" secondo lo sviluppatore del plugin. Li vedremo tutti, con codice e senza giri di parole.
💡 Panoramica rapida:
- Disabilitare il caricamento globale di CF7 tramite le costanti
WPCF7_LOAD_JSeWPCF7_LOAD_CSSinwp-config.php, il metodo ufficiale più pulito. - Riabilitare script e stili, ma solo sulle pagine con un modulo, tramite
wpcf7_enqueue_scripts()nel template della pagina. - Per bundle personalizzati, il pacchetto
lazy-cf7-assets, che trova automaticamente il modulo sulla pagina e carica il JS dinamicamente.
Metodo 1: caricamento differito dello script CF7 via functions.php
L'opzione più rapida e semplice è aggiungere l'attributo defer allo script di Contact Form 7. Dice al browser: "carica il file in background, ma eseguilo quando il DOM è pronto". Il modulo continua a funzionare, ma lo script non blocca più il rendering della pagina.
Aggiungi questo codice al functions.php del tuo tema attivo (o tramite il plugin Code Snippets, più sicuro durante gli aggiornamenti):
1 if ( ! 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 funzione controlla l'URL di ogni script accodato tramite l'hook clean_url. Se l'indirizzo contiene contact-form-7 e l'estensione .js, aggiunge defer='defer'. Tutti gli altri script restano invariati.
Vantaggio: una soluzione in 10 righe che non richiede modifiche ai template o alla configurazione del plugin. Adatta per temi dove non esiste un template separato per la pagina contatti.
Svantaggio: lo script viene comunque caricato su ogni pagina, si sta solo rimuovendo il comportamento bloccante per il rendering. Il traffico e le richieste al server non si riducono. Questo metodo non influisce affatto sui CSS del plugin, il foglio di stile si carica come al solito.
Metodo 2: metodo ufficiale, caricamento condizionale tramite costanti
Questo approccio è descritto nella documentazione di Contact Form 7 dallo stesso sviluppatore del plugin, Takayuki Miyoshi. L'idea si articola in due passaggi: prima disabilitare globalmente gli script e gli stili di CF7, poi riabilitarli, ma solo sulle pagine dove il modulo è effettivamente utilizzato.
Passaggio 1: disabilitare il caricamento su tutte le pagine
Aggiungi due costanti a wp-config.php:
1 define( 'WPCF7_LOAD_JS', false ); 2 define( 'WPCF7_LOAD_CSS', false );
In alternativa, tramite il functions.php del tuo tema:
1 add_filter( 'wpcf7_load_js', '__return_false' ); 2 add_filter( 'wpcf7_load_css', '__return_false' );
Fatto questo, CF7 non caricherà una sola riga del suo codice su nessuna pagina del sito, incluse quelle dove il form è presente. Senza script, il form perde l'invio AJAX e la validazione, quindi serve il passo 2.
Step 2: ripristinare gli script sulle pagine con un form
Supponiamo che la tua pagina contatti usi il template page-contact.php nella cartella del tema. Aggiungi questo al template prima di chiamare wp_head():
1 if ( function_exists( 'wpcf7_enqueue_scripts' ) ) { 2 wpcf7_enqueue_scripts(); 3 } 4 5 if ( function_exists( 'wpcf7_enqueue_styles' ) ) { 6 wpcf7_enqueue_styles(); 7 }
Le funzioni wpcf7_enqueue_scripts() e wpcf7_enqueue_styles() caricano manualmente script e stili di CF7 solo su questo template. Tutte le altre pagine del sito restano pulite.
Vantaggio: il metodo è «ufficiale», garantito per non rompersi con gli aggiornamenti del plugin. Funziona con le versioni CF7 5.x e 6.x, versione corrente 6.1.6 a giugno 2026 (elenco release). Nessun caricamento inutile sulle pagine senza form.
Svantaggio: richiede di modificare i template del tema. Se hai più pagine con form, devi ricordarti di aggiungere le chiamate a ogni template. Se il form è inserito tramite shortcode nel contenuto (anziché in un template), il metodo non funziona senza condizioni aggiuntive.
Metodo 3: il pacchetto lazy-cf7-assets per bundle JavaScript
Se costruisci il frontend con un bundler (Webpack, Vite, esbuild) e usi un tema moderno con un bundle JavaScript personalizzato, esiste un pacchetto npm chiamato lazy-cf7-assets. Risolve lo stesso problema, ma lato client: scansiona il DOM, individua il form CF7 e solo a quel punto carica dinamicamente gli script del plugin.
Installazione:
1 npm install lazy-cf7-assets
Prima di usarlo, devi disabilitare il caricamento automatico dei JS da parte del plugin (come nel metodo 2, tramite wpcf7_load_js):
1 add_filter( 'wpcf7_load_js', '__return_false' );
Poi nel tuo bundle JS:
1 import lazyform from 'lazy-cf7-assets'; 2 3 // Initialize after DOM ready 4 lazyform.init();
Se gli script vengono caricati nel <head> anziché in fondo al <body>, specifica un percorso assoluto all'immagine GIF di caricamento, così il form non «lampeggia» in uno stato vuoto:
1 lazyform.init({ 2 gifPath: '/wp-content/themes/my-theme/images/ajax-loader.gif' 3 });

Vantaggio: nessun intervento lato PHP, non serve modificare i template per ogni pagina con un form. Il pacchetto rileva automaticamente se nella pagina esiste uno shortcode CF7 e carica gli script solo in quel caso. Adatto ai siti dove il form è inserito via shortcode nel contenuto (anziché essere scritto direttamente nel template).
Svantaggio: funziona solo con JavaScript (i CSS del plugin vanno comunque disabilitati a parte). Richiede un bundler nel progetto. Il pacchetto è minimale (1 stella su GitHub), mantenuto da un singolo sviluppatore: per produzione conviene farne un fork e verificare la compatibilità con gli aggiornamenti di CF7.
Cosa scegliere: confronto tra i tre approcci
Criterio | defer via hook | Costanti + template | lazy-cf7-assets |
|---|---|---|---|
Risparmio di traffico | ❌ no | ✅ pieno | ✅ pieno (JS) |
Protezione da aggiornamenti CF7 | ✅ sì | ✅ sì | richiede verifica |
Nessuna modifica ai template | ✅ sì | ❌ no | ✅ sì |
Disabilita i CSS | ❌ no | ✅ sì | ❌ no |
Complessità di implementazione | bassa | media | media |
Shortcode form nel contenuto | ✅ funziona | ❌ difficoltà | ✅ funziona |
Se il tuo form risiede su una singola pagina in un template dedicato, usa il metodo 2 (metodo ufficiale). Se il sito usa un bundler moderno e puoi avere più form in punti diversi, scegli il metodo 3 (lazy-cf7-assets). Se ti serve una soluzione «subito» senza modificare template, va bene il metodo 1 (defer), ma tieni presenti i limiti.
Una precisazione importante: dopo qualsiasi di queste modifiche, verifica sempre che il form invii correttamente, la validazione funzioni, reCAPTCHA non sia bloccato e gli stili non si siano spostati. Apri la pagina con il form in modalità incognito, compila e invia un messaggio di prova prima e dopo l'intervento.
⁉️🤔 Domande frequenti
Perché CF7 carica gli script su tutte le pagine?
Il plugin non può sapere, nella fase di caricamento di WordPress, se una pagina specifica contiene uno shortcode del form. WordPress assembla la pagina più tardi, quando la coda degli script è già stata formata. Lo sviluppatore Takayuki Miyoshi lo spiega nella documentazione ufficiale: è tecnicamente impossibile rilevare la presenza di uno shortcode prima dell'hook
wp_head. È stata quindi scelta una strategia conservativa, quella di caricare sempre. Non è un bug, ma una decisione architetturale deliberata: il plugin sacrifica le performance in favore della funzionalità garantita. L'onere dell'ottimizzazione è trasferito allo sviluppatore del sito.
Il form si rompe dopo aver disabilitato il caricamento globale?
No, se riabiliti con attenzione gli script sulle pagine necessarie. Il form perderà l'invio AJAX e la validazione lato client solo sulle pagine dove gli script non sono inclusi. Ecco perché il passo 2 (ripristinare gli script) è obbligatorio: non fermarti solo a
WPCF7_LOAD_JS = false. Verifica l'ordine delle chiamate:wpcf7_enqueue_scripts()deve essere eseguita prima diwp_head(), non dopo. E assicurati che reCAPTCHA non entri in conflitto con il caricamento differito.
Il metodo delle costanti funziona con CF7 6.x?
Sì, le costanti
WPCF7_LOAD_JSeWPCF7_LOAD_CSSsono pienamente supportate nella versione corrente 6.1.6 (vedi il log ufficiale delle versioni). In tutta la storia del plugin, dalla versione 3.9 fino all'attuale 6.x, queste costanti non sono mai state dichiarate deprecate. Questo è il metodo più stabile e documentato per gestire il caricamento.
E se ho più form in punti diversi?
Se i form sono sparsi su pagine diverse tramite shortcode nel contenuto (anziché nei template), il metodo ufficiale con i template è scomodo. Usa
lazy-cf7-assets(metodo 3), oppure il plugin Conditionally Load CF7: aggiunge un'impostazione nel pannello di amministrazione per definire su quali pagine o tipi di contenuto caricare gli script, e funziona senza modificare codice.
Tre righe di codice contro decine di richieste
Il problema "CF7 carica gli script ovunque" esiste da tanto quanto il plugin stesso, e in oltre 10 anni lo sviluppatore non ha modificato il comportamento predefinito, perché si tratta di un compromesso tra semplicità e performance. Un compromesso, però, non una condanna.
La strada più sicura è il metodo ufficiale con costanti e template. Rimuove gli script e gli stili del plugin da tutte le pagine tranne quelle dove servono, e non si rompe con gli aggiornamenti. Se il tuo sito usa uno stack moderno con un bundler, dai un'occhiata a lazy-cf7-assets. Se ti serve qualcosa di rapido e senza modificare i template, il defer tramite l'hook clean_url ti darà miglioramenti misurabili già da oggi.
Verifica il tuo sito con PageSpeed Insights prima e dopo: ridurre il numero di richieste bloccanti di 1-2 unità e risparmiare 10-30 KB per pagina può aumentare il punteggio Performance di 2-5 punti, specialmente su dispositivi mobili.



