Cache e gclid: query del clic sull'annuncio, chiave di cache della pagina e primo byte misurato

La gestione della cache con gclid consiste nell'ignorare la query gclid aggiunta alla fine dell'URL di un clic sull'annuncio e nel rispondere con il file di cache dell'URL senza query. Le misure del primo byte per query e per stato della cache su un server WordPress con Nginx + Apache hanno mostrato che gclid aggiungeva 0,014–0,015 secondi e che ritardi di diversi secondi si verificavano solo quando la cache non poteva essere usata.
Misurato all'interno dello stesso server, il primo byte arrivava in 0,014–0,015 secondi senza query e in 0,029–0,030 secondi con le query del clic sull'annuncio. Quando WordPress ha ricostruito la stessa pagina senza cache, ci sono voluti 3,639 e 3,260 secondi.
1️⃣ Cache e gclid: URL dei clic sugli annunci e chiave di cache
Con il tagging automatico di Google Ads attivo, alla fine dell'URL dei visitatori che cliccano su un annuncio viene aggiunto [?gclid=valore]. Questo valore è un parametro che identifica il clic sull'annuncio, quindi cambia da visitatore a visitatore, anche se la stessa persona che clicca di nuovo sullo stesso annuncio può ricevere lo stesso valore.
Gli URL reali dei clic sugli annunci raramente hanno solo gclid. Spesso si aggiungono gad_source, gad_campaignid e gbraid, e a volte anche wbraid.
https://example.com/sample-page/?gad_source=1&gad_campaignid=1234567890&gbraid=EXAMPLE&gclid=EXAMPLE
https://example.com/sample-page/?gclid=EXAMPLE&gbraid=EXAMPLE&wbraid=EXAMPLECon una query alla fine dell'URL il browser apre comunque la stessa pagina, ma per una cache è un indirizzo diverso. Lo standard di caching HTTP (RFC 9111) definisce la chiave di cache, il criterio con cui una cache sceglie una risposta salvata, come composta almeno dal metodo della richiesta e dall'URI di destinazione, e l'URI di destinazione comprende anche la query string.
Se la query string entra così com'è nella chiave di cache, ogni clic con un valore di gclid diverso diventa un nuovo indirizzo. La CDN, nginx e WP Rocket, da cui passa la risposta, gestiscono questa query ognuno con un criterio diverso.
Se la CDN non ha una copia o la sua chiave di cache distingue le query, la richiesta prosegue verso il server di origine. Da lì la velocità dipende dal fatto che nginx e WP Rocket trovino un file di cache.
2️⃣ Servizio statico di nginx: le richieste con query passano ad Apache
Anche se il file di cache è su disco, nginx in una configurazione Nginx + Apache non lo serve direttamente a una richiesta con query. Il motivo è che la configurazione qui sotto, che fa leggere a nginx direttamente i file di cache di WP Rocket, costruisce il percorso del file solo quando la query string è vuota.
# nginx.conf — blocco http: condizioni per saltare il file di cache
map $http_cookie $rocket_cookie {
default 0;
'~*wordpress_logged_in' 1;
'~*wp-postpass' 1;
'~*comment_author' 1;
'~*woocommerce_items' 1;
}
map $request_method $rocket_method {
default 1;
GET 0;
HEAD 0;
}
map $query_string $rocket_query {
default 1;
'' 0; # 0 solo quando la query string è vuota
}
# blocco server
set $rocket_bypass '';
if ($rocket_cookie = 1) { set $rocket_bypass '1'; }
if ($rocket_method = 1) { set $rocket_bypass '1'; }
if ($rocket_query = 1) { set $rocket_bypass '1'; }
set $rocket_file '/wp-content/cache/wp-rocket/example.com${request_uri}index-https.html';
if ($rocket_bypass = '1') { set $rocket_file ''; }
location / {
try_files $rocket_file @apache; # ad Apache se il percorso è vuoto o il file manca
add_header X-Rocket-Nginx-Serving-File 'HIT' always; # segna le risposte che nginx ha servito direttamente dal file di cache
}[$rocket_query] controlla solo se l'intera query string è vuota, quindi gclid, che WP Rocket ignora, viene trattato come qualsiasi altra query. Se le copie per mobile sono tenute a parte, c'è un controllo in più che aggiunge [-mobile] al nome del file.
Anche le regole [.htaccess] che WP Rocket scrive per Apache richiedono una query string vuota. Che sia nginx o Apache, il passaggio che serve il file di cache direttamente senza PHP vale solo per le richieste senza query.
Le richieste senza query avevano l'intestazione [X-Rocket-Nginx-Serving-File: HIT], le sei richieste con gclid e query in stile annuncio no. Il primo byte è cresciuto di 0,014–0,015 secondi per le richieste con query perché al percorso si sono aggiunti Apache e PHP che leggono e restituiscono il file di cache.
curl -so /dev/null -H 'Accept-Encoding: gzip' -w '%{time_starttransfer}\n' \
'https://example.com/sample-page/'0.015127curl -so /dev/null -H 'Accept-Encoding: gzip' -w '%{time_starttransfer}\n' \
'https://example.com/sample-page/?gclid=test123'0.029525curl -sI 'https://example.com/sample-page/' | grep -i x-rocket-nginx-serving-filex-rocket-nginx-serving-file: HIT[time_starttransfer] è il tempo dalla richiesta all'arrivo del primo byte. Per misurare all'interno del server senza passare dalla CDN, aggiungi [--resolve example.com:443:127.0.0.1].
3️⃣ Elenco delle query ignorate di WP Rocket: lo stesso file di cache
Non mettere in cache gli URL con query è il comportamento predefinito di WP Rocket, ma le query dei clic sugli annunci sono un'eccezione. WP Rocket toglie i parametri del suo elenco da ignorare prima di decidere e, se non resta nessuna query, risponde con il file di cache dell'URL senza query.
// wp-rocket/inc/classes/Buffer/class-tests.php (3.23.5.1)
public function get_query_params() {
// …
$params = array_diff_key( // prima toglie le query ignorate
self::$get,
$this->config->get_config( 'cache_ignored_parameters' )
);
// …
}
public function can_process_query_string() {
// …
$params = $this->get_query_params();
if ( ! $params ) { // nessuna query rimasta: gestisce con la cache
return self::memoize( __FUNCTION__, [], true );
}
// passano solo lang · s · permalink_name · lp-variation-id e le query inserite in [Cache Query String(s)]
// …
}Se quello che [get_query_params] restituisce dopo aver tolto le query ignorate è vuoto, anche il percorso del file di cache diventa quello dell'URL senza query. La richiesta con gclid è passata da Apache e PHP, ma il commento di cache alla fine dell'HTML era uguale a quello della richiesta senza query, e la dimensione della risposta era di 350.668 byte, la stessa del file di cache (gzip).
L'elenco delle query ignorate è un elenco predefinito che WP Rocket scarica dai propri server una volta a settimana e salva in [wp-content/wp-rocket-config/dynamic-lists.json]. Al 17 ottobre 2026 l'elenco comprende gclid, gbraid, wbraid, gad_source e gad_campaignid.
Se c'è anche una sola query che non è nell'elenco, WP Rocket non usa la cache: la stessa pagina con una query qualsiasi fuori elenco è stata ricostruita da WordPress, senza commento di cache. Se gli URL dei tuoi annunci hanno query di tracciamento create da te, quei clic seguono ogni volta questa strada.
Per modificare l'elenco usa il plugin di supporto indicato da WP Rocket. Il plugin aggiunge o toglie query con il filtro [rocket_cache_ignored_parameters] e rigenera il file di configurazione di WP Rocket quando viene attivato o disattivato.
// da WP Rocket | Ignore Query Strings 1.1.1 (plugin di supporto del team di assistenza di WP Rocket)
function define_ignored_parameters( array $params ) {
$params['new_query_string'] = 1; // aggiunge alle query ignorate
//unset ( $params['utm_source'] ); // toglie dalle query ignorate
return $params;
}
add_filter( 'rocket_cache_ignored_parameters', __NAMESPACE__ . '\define_ignored_parameters', 999 );
register_activation_hook( __FILE__, __NAMESPACE__ . '\flush_wp_rocket' ); // esegue rocket_generate_config_file() all'attivazioneWP Rocket scrive questo elenco nel file di configurazione con il nome del dominio dentro [wp-content/wp-rocket-config/] e legge quel file a ogni richiesta, quindi se aggiungi solo il filtro senza rigenerare il file di configurazione il nuovo elenco non viene applicato. Le query dell'elenco condividono l'unico file di cache dell'URL di base qualunque sia il valore, quindi non aggiungere query il cui valore cambia ciò che la pagina mostra.
Dopo aver aggiunto al plugin di supporto [uk_test], che non era nell'elenco, e averlo attivato, il file di configurazione è stato rigenerato con quella query in fondo all'elenco. Poi sono stati richiesti in sequenza l'URL senza query e due URL con valori diversi di [uk_test].
curl -s -o /dev/null -w '%{size_download} %{time_starttransfer}\n' -H 'Accept-Encoding: gzip' 'https://example.com/sample-page/'
curl -s -o /dev/null -w '%{size_download} %{time_starttransfer}\n' -H 'Accept-Encoding: gzip' 'https://example.com/sample-page/?uk_test=abc'
curl -s -o /dev/null -w '%{size_download} %{time_starttransfer}\n' -H 'Accept-Encoding: gzip' 'https://example.com/sample-page/?uk_test=xyz'21390 0.025720
21390 0.025507
21390 0.027929Tutte e tre le richieste hanno restituito gli stessi 21.390 byte entro 0,03 secondi, e la fine dell'HTML della richiesta con [uk_test] è stata aperta per controllare l'ora della cache.
curl -s --compressed 'https://example.com/sample-page/?uk_test=abc' | tail -c 200ck=lazyLoadYoutubeIframe;}});</script></body>
</html>
<!-- This website is like a Rocket, isn't it? Performance optimized by WP Rocket. Learn more: https://wp-rocket.me - Debug: cached@1792248839 -->L'ora della cache nel commento finale coincideva con il file di cache dell'URL senza query. Prima di attivare il plugin di supporto, la stessa richiesta veniva ricostruita in 0,36–0,38 secondi, senza commento di cache.
Anche dopo l'attivazione, una richiesta che aveva anche [foo], non presente nell'elenco, non ha usato il file di cache ed è stata ricostruita.
Per un minuto subito dopo la rigenerazione del file di configurazione anche le richieste con [uk_test] sono state ricostruite. Con PHP OPcache impostato per ricontrollare i file modificati ogni 60 secondi (revalidate_freq), le risposte sono arrivate dal file di cache solo dopo un minuto.
Anche dopo aver disattivato ed eliminato il plugin di supporto, la riga di [uk_test] è rimasta nel file di configurazione. Il codice di disattivazione prova a togliere il filtro, aggiunto con priorità 999, alla priorità predefinita, quindi il file di configurazione viene rigenerato con il filtro ancora attivo. Solo rigenerando il file di configurazione un'altra volta dopo aver eliminato il plugin la query esce dall'elenco.
4️⃣ Chiave di cache della CDN: escludere le query degli annunci e richieste all'origine
Se la CDN mette la query string così com'è nella chiave di cache, ogni clic con un valore di gclid diverso non trova una copia e la richiesta arriva fino al server di origine. Togliere del tutto le query risolve il problema, ma non va bene per siti con URL il cui contenuto cambia in base alla query, come i risultati di ricerca, quindi è meglio togliere dalla chiave di cache solo le query degli annunci.
Con le query degli annunci tolte in questo modo, la CDN risponde con la stessa copia dell'URL senza query anche quando il valore di gclid cambia, e solo quando non ha una copia invia la richiesta, con la query attaccata, al server di origine.
# stato della cache CDN di due richieste con valori di gclid diversi (i nomi delle intestazioni variano da CDN a CDN)
curl -sI 'https://example.com/sample-page/?gclid=test1' | grep -i -E 'cache|age'curl -sI 'https://example.com/sample-page/?gclid=test2' | grep -i -E 'cache|age'Se entrambe le richieste con valori diversi sono HIT e le loro copie sono state salvate alla stessa ora di quella dell'URL senza query, quella CDN sta lasciando gclid fuori dalla chiave di cache. La prima visita in una località senza copia passa comunque da nginx e WP Rocket sul server di origine, anche se la CDN toglie le query degli annunci dalla chiave.
5️⃣ Cosa rallenta i clic sugli annunci: una cache delle pagine vuota
Quando la prima pagina da un annuncio si carica lentamente, viene facile dare la colpa a gclid per aver aggirato la cache, ma se esiste un file di cache viene servito lo stesso file anche con una query. Ciò che aggiunge secondi al primo byte è un file di cache vuoto, che costringe WordPress a ricostruire la pagina da zero.
I file di cache vengono eliminati allo scadere del tempo impostato in Vita utile della cache; il valore predefinito di WP Rocket è 10 ore. Salvare un articolo o le impostazioni elimina anche la cache collegata, e quando l'elenco che WP Rocket scarica una volta a settimana viene sostituito da una nuova versione e salvato, si svuota anche la cache dell'intero sito.
Con il preload attivo, WP Rocket riapre gli URL svuotati e riempie di nuovo la cache, e i visitatori che arrivano prima aspettano mentre la pagina viene costruita. Anche una richiesta con sole query degli annunci crea il file di cache sotto l'URL senza query, quindi il clic sull'annuncio che trova per primo la cache vuota la riempie per il visitatore successivo.
Subito dopo aver svuotato la cache, la prima richiesta aperta con query in stile annuncio non ha trovato un file di cache ed è stata ricostruita in 0,341–0,369 secondi, e nello stesso secondo è comparso il file di cache dell'URL senza query.
curl -s -o /dev/null -w '%{size_download} %{time_starttransfer}\n' -H 'Accept-Encoding: gzip' 'https://example.com/sample-page/?gclid=EXAMPLE1'
ls -l --time-style='+%F %T' wp-content/cache/wp-rocket/example.com/sample-page/
curl -s -o /dev/null -w '%{size_download} %{time_starttransfer}\n' -H 'Accept-Encoding: gzip' 'https://example.com/sample-page/'21361 0.366881
Totale 116
-rw-r--r-- 1 example nobody 90908 2026-10-17 23:56:38 index-https.html
-rw-r--r-- 1 example nobody 21385 2026-10-17 23:56:38 index-https.html_gzip
21385 0.025379Tutte e tre le volte è andata nello stesso ordine, e la richiesta senza query successiva ha avuto risposta dal nuovo file di cache in 0,023–0,025 secondi. Poiché la richiesta non veniva da un dispositivo mobile, sono stati creati solo i due file per desktop.
Per gli URL a cui puntano i tuoi annunci controlla tu stesso se esiste un file di cache e quando è stato creato; se le copie per mobile vengono create a parte, controlla sia il file desktop sia quello mobile.
ls -l --time-style='+%F %T' wp-content/cache/wp-rocket/example.com/sample-page/Totale 3520
-rw-r--r-- 1 example nobody 1445922 2026-10-17 14:07:44 index-https.html
-rw-r--r-- 1 example nobody 350668 2026-10-17 14:07:44 index-https.html_gzip
-rw-r--r-- 1 example nobody 1446862 2026-10-17 14:07:47 index-mobile-https.html
-rw-r--r-- 1 example nobody 351042 2026-10-17 14:07:47 index-mobile-https.html_gzipcurl -s --compressed 'https://example.com/sample-page/?gclid=test123' | tail -c 200n/1/wp-content/uploads/example-plugin/style.css' media='all' /></noscript></body>
</html>
<!-- Cached for great performance - Debug: cached@1792213663 -->Una risposta servita da un file di cache riporta nel commento alla fine dell'HTML, dopo [Debug: cached@], l'ora in cui il file è stato creato, in tempo Unix. Senza questo segno, quella risposta l'ha ricostruita WordPress.
🔢 FAQ & contenuti consigliati














ℹ️ Informativa sull'affiliazione
I contenuti di questo sito includono link di affiliazione. Se un visitatore acquista un prodotto o un servizio tramite uno di questi link, il sito riceve una commissione dal venditore. In questo processo l'importo pagato dall'acquirente (durante le promozioni l'importo scende↓) non aumenta. Prezzi, sconti e disponibilità indicati si riferiscono al momento della stesura e possono differire da quelli reali: prima di acquistare verifica sempre presso il venditore. I prodotti vengono scelti e valutati secondo criteri propri, e le commissioni non influiscono sull'ordine di presentazione né sul contenuto delle valutazioni.

