13 Settembre 2026

LiteSpeed e cloaking di Google PageSpeed Insights: come ti trucco i test facendoti credere che il sito sia veloce.

LiteSpeed Cache riconosce PageSpeed Insights, ritarda il JavaScript e altera il benchmark: un meccanismo truffaldino che può maschera problemi reali e bloccare ulteriori ottimizzazioni.

Prendete un sito WordPress ospitato su LiteSpeed Web Server, installate LiteSpeed Cache (LSCache) e poi eseguite due test apparentemente equivalenti sulla versione Mobile di Lighthouse, quella normalmente più severa.

Il profilo mobile simula infatti un ambiente molto meno favorevole rispetto alla classica fibra dell’ufficio: connessione 4G lenta, latenza più alta e un Motorola Moto G Power (2022) emulato, smartphone di fascia medio-bassa pensato proprio per rappresentare hardware non particolarmente potente.

La scelta ha senso perché le performance dipendono anche dalla capacità del dispositivo di elaborare HTML, CSS e soprattutto JavaScript. Un sito che sembra istantaneo su desktop può diventare molto più lento su uno smartphone economico.

È quindi un banco prova volutamente difficile.

Il primo con Google PageSpeed Insights.

Risultato:

  • Performance: 100;
  • First Contentful Paint: 1,1 secondi;
  • Largest Contentful Paint: 1,1 secondi;
  • Total Blocking Time: 0 millisecondi;
  • Speed Index: 1,1 secondi;
  • CLS: 0.

Un sito apparentemente perfetto.

Test sito WordPress mobile Google PageSpeed Insight
Test sito WordPress mobile Google PageSpeed Insight

Poi aprite la stessa pagina con Chrome, lanciate Lighthouse direttamente dal browser e ottenete:

  • Performance: 77;
  • First Contentful Paint: 3 secondi;
  • Largest Contentful Paint: 4,5 secondi;
  • Total Blocking Time: 170 millisecondi;
  • Speed Index: 3 secondi;
  • CLS: 0.
Test Litespeed Chrome Lightouse
Test Litespeed Chrome Lightouse

Naturalmente due esecuzioni Lighthouse possono differire leggermente. Hardware, CPU, versione di Chrome, throttling e condizioni della macchina possono modificare il risultato.

Ma quando passiamo da 77 a 100, da un LCP di 4,5 secondi a 1,1 secondi e soprattutto da 170 millisecondi di Total Blocking Time a zero, vale la pena smettere di guardare il cerchio verde e iniziare a guardare il codice.

Lo abbiamo fatto.

Abbiamo clonato il repository ufficiale litespeedtech/lscache_wp su GitHub e letto il sorgente della versione corrente al momento in cui scriviamo, la 7.9.1. Tutti i file, i metodi e le righe citate in questo articolo sono riferite a quella versione e chiunque può verificarle.

E nel codice di LiteSpeed Cache il meccanismo è molto più chiaro di quanto ci aspettassimo.

LiteSpeed Cache è in grado di riconoscere determinate richieste di test e di lasciarle su una variante della pagina nella quale il JavaScript viene ritardato aggressivamente, mentre un browser reale viene fatto transitare, dopo la prima visita, sulla versione normale.

Se vogliamo utilizzare una parola semplice, questa per noi è una forma di cloaking del benchmark.

Non stiamo parlando del normale Delay JavaScript

Facciamo subito una distinzione importante.

Ritardare il JavaScript non è di per sé qualcosa di scorretto.

Lo fanno WP Rocket, FlyingPress, Perfmatters e molti altri strumenti di performance.

Defer, delay, minificazione, Critical CSS, lazy loading e riduzione del CSS inutilizzato sono tecniche perfettamente valide e, quando applicate correttamente agli utenti reali, possono produrre miglioramenti concreti.

Il problema qui è differente.

Il problema nasce quando il software è in grado di capire chi lo sta misurando e mantenere il tester in una condizione differente da quella nella quale finirà normalmente il browser dell’utente.

È la differenza tra:

“ottimizzo il mio sito”

e:

“quando arriva il banco prova, attivo la configurazione che fa ottenere il voto migliore”.

E il codice di LiteSpeed Cache ci permette di seguire questo percorso passo dopo passo.

Primo passaggio: LiteSpeed mantiene una lista dei tester

Nel repository ufficiale di LiteSpeed Cache esiste un file chiamato data/gm_uas.txt.

È la lista di User-Agent utilizzata dal sistema Guest Mode.

Nel file troviamo esplicitamente:

Lighthouse
GTmetrix
Google
Pingdom
bot
spider
PTST
HeadlessChrome

Non stiamo inferendo il comportamento da un nome di variabile oscuro.

Lighthouse è scritto letteralmente nella lista.

Così come Google, GTmetrix, Pingdom e HeadlessChrome. La corrispondenza è una regular expression case-insensitive costruita concatenando le voci con |: basta che una di queste stringhe compaia da qualche parte nello User-Agent. La voce Google, ad esempio, intercetta sia PageSpeed Insights sia Googlebot.

Ma accanto a quel file ce n’è un secondo, che nella discussione pubblica viene quasi sempre ignorato: data/gm_ips.txt.

È la lista degli indirizzi IP da trattare sempre come Guest. Le prime righe sono queste:

66.102.0.0/20
66.249.64.0/19
74.125.0.0/16
142.250.0.0/15
172.255.48.128/27
172.255.61.32/28
208.70.247.157

seguite da una quarantina di IP singoli appartenenti a datacenter cloud.

I primi quattro blocchi sono range di Google: 66.249.64.0/19 è il range storico di Googlebot, gli altri sono infrastruttura Google generica, cioè anche quella da cui partono i test di PageSpeed Insights. I due blocchi 172.255.x sono GTmetrix.

Questo significa una cosa precisa: anche se un tester cambiasse User-Agent, verrebbe comunque riconosciuto dall’indirizzo di provenienza. Il riconoscimento è doppio.

Dalla 7.7 la lista dei tester si aggiorna da sola, e l’amministratore non può più modificarla

Fino alla versione 7.6 le due liste erano configurabili dal pannello, nella scheda General → Tuning, con le opzioni “Guest Mode User Agents” e “Guest Mode IPs”.

Con la versione 7.7 è cambiato tutto, e il changelog ufficiale lo dice in una riga:

* **Cloud** Guest Mode IP/UA lists now sync automatically from the QUIC.cloud API.

Nel sorgente il meccanismo è in src/guest.cls.php: un cron giornaliero (litespeed_task_guest_sync) scarica da https://wpapi.quic.cloud/gm_ips e https://wpapi.quic.cloud/gm_uas le liste aggiornate e le salva in wp-content/litespeed/cloud/gm_ips.txt e gm_uas.txt.

Il metodo che carica le liste, _load_gm_list(), ha una priorità esplicita:

// Try cloud synced file first, then fallback to plugin data file
$files = [
    LSCWP_CONTENT_FOLDER . '/litespeed/cloud/' . $filename,
    dirname( __DIR__ ) . '/data/' . $filename,
];

Il file sincronizzato dal cloud vince sul file del plugin.

E la routine di aggiornamento in src/data.upgrade.func.php fa il resto:

Debug2::debug( '[Data] v7.7 upgrade: dropping guest_ips/guest_uas options' );
Conf::delete_option( 'conf.guest_ips' );
Conf::delete_option( 'conf.guest_uas' );

Le due opzioni vengono cancellate dal database al momento dell’aggiornamento e nel codice sono marcate come deprecated, da rimuovere dopo la versione 9.

Il risultato pratico è che oggi l’elenco di chi viene tenuto in Guest Mode non lo decide più chi amministra il sito: lo decide QUIC.cloud, l’azienda che sviluppa il plugin, e lo può aggiornare in qualsiasi momento su tutte le installazioni senza rilasciare una nuova versione. Se domani nasce un nuovo servizio di test, basta aggiungere una riga lato server.

Secondo passaggio: il codice confronta User-Agent e IP

Nel file lib/guest.cls.php troviamo il metodo always_guest().

Il file è volutamente leggero e viene caricato da guest.vary.php senza avviare WordPress: lo dice il commento in testa al file stesso.

Il funzionamento è semplice.

Carica la lista degli User-Agent, costruisce una regular expression e la confronta con:

$_SERVER['HTTP_USER_AGENT']

Se trova una corrispondenza restituisce true.

Subito dopo viene effettuato anche il controllo sull’indirizzo IP, che dalla 7.7 supporta anche la notazione CIDR (ed è per questo che nella lista compaiono interi range Google).

In termini semplificati il codice fa questo:

if (user_agent_presente_nella_lista()) {
    return true;
}

if (ip_presente_nella_lista()) {
    return true;
}

return false;

Questa è una rappresentazione semplificata, ma la logica del sorgente originale è esattamente questa.

Quindi LiteSpeed dispone esplicitamente di una funzione che risponde alla domanda:

“Questa richiesta appartiene a uno dei client che voglio mantenere sempre in Guest Mode?”

Terzo passaggio: chi entra in Guest Mode, e chi non ne esce

Ed è qui che la questione diventa molto più interessante, perché il meccanismo ha due cancelli distinti.

Il primo cancello è nel plugin, dentro WordPress, nel metodo _maybe_guest_mode() di src/vary.cls.php. E qui la sorpresa: questo metodo non guarda affatto User-Agent o IP. Guarda solo una cosa:

// If vary is set, then not a guest.
if ( self::has_vary() ) {
    return;
}

Se la richiesta non porta il cookie _lscache_vary, è Guest. Punto. Chiunque arrivi senza quel cookie, uomo o macchina, riceve la variante Guest, e se Guest Optimization è attiva viene definita la costante LITESPEED_GUEST_OPTM che vedremo tra poco.

Il secondo cancello è in guest.vary.php, ed è quello che decide chi riceve il cookie e quindi chi esce dalla Guest Mode.

LiteSpeed inserisce infatti in fondo alla pagina Guest un piccolo script (assets/js/guest.js) che, se il cookie non c’è, fa una richiesta POST verso guest.vary.php. Nel metodo update_guest_vary() troviamo il passaggio decisivo:

if ( $this->always_guest() ) {
    echo '[]';
    exit;
}

Tradotto in italiano:

se sei uno dei client che LiteSpeed riconosce come “always guest”, non ti do il cookie e non ti dico di ricaricare la pagina normale.

Il processo termina.

Per gli altri visitatori, invece, LiteSpeed imposta il vary cookie (valido due giorni) e restituisce una risposta che ordina il reload:

setcookie( self::$_vary_name, $vary, $expire, '/', false, $is_ssl, true );
echo json_encode( [ 'reload' => 'yes' ] );

E lo script lato browser esegue letteralmente:

if (data.hasOwnProperty('reload') && data.reload == 'yes') {
    sessionStorage.setItem('litespeed_docref', document.referrer);
    sessionStorage.setItem('litespeed_reloaded', '1');
    window.location.reload(true);
}

Il browser reale ricarica quindi la pagina e prosegue con la variante corretta.

Il tester riconosciuto attraverso User-Agent o IP, invece, resta sulla variante Guest altamente ottimizzata.

Questa differenza è fondamentale.

Il prezzo nascosto per l’utente reale: la pagina si carica due volte

Fermiamoci un attimo su quel window.location.reload(true), perché la narrazione ufficiale della Guest Mode è “rendere velocissima la prima visita”.

Quello che succede davvero al primo visitatore reale è questo:

  1. riceve la pagina Guest dalla cache;
  2. la renderizza;
  3. lo script contatta guest.vary.php, che avvia PHP (senza WordPress) e imposta il cookie;
  4. il browser ricarica l’intera pagina;
  5. riceve la variante normale, quella con il JavaScript configurato dall’amministratore.

La “prima visita velocissima” è quindi una pagina che l’utente vede per una frazione di secondo prima che venga sostituita da un secondo caricamento completo. Il costo reale della prima visita è la somma dei due.

Che il reload sia un problema noto lo dimostra un dettaglio nel codice: LiteSpeed inserisce nell’<head> un secondo script, guest.docref.js, che dopo il reload sovrascrive document.referrer con il valore salvato prima del reload:

Object.defineProperty(document, 'referrer', {
    get: function () {
        return litespeed_docref;
    },
});

Serve perché altrimenti Google Analytics e simili vedrebbero il sito stesso come referrer di tutte le visite e il traffico organico sparirebbe dai report. Hanno dovuto scrivere una patch per riparare un effetto collaterale del proprio meccanismo. Il tester, che non ricarica mai, di tutto questo non vede nulla.

Ed è qui che PageSpeed Insights e Chrome prendono due strade differenti

Immaginiamo PageSpeed Insights.

La richiesta arriva dall’infrastruttura di Google, quindi da un IP nei range di gm_ips.txt, con uno User-Agent che contiene Chrome-Lighthouse. Non ha cookie, perché ogni test parte da un profilo pulito.

Primo cancello: niente cookie, quindi variante Guest.

Secondo cancello: lo script chiama guest.vary.php, always_guest() risponde true, nessun cookie, nessun reload.

Il test viene condotto interamente sulla variante Guest.

Ora prendiamo Chrome sul nostro computer.

È il browser con cui abbiamo già aperto il sito almeno una volta. Ha quindi già il cookie _lscache_vary, oppure lo riceve al primo caricamento e ricarica. Da quel momento, per il primo cancello, Chrome non è più un Guest, indipendentemente da cosa dichiari lo User-Agent: il cookie è la sola cosa che il plugin controlla lato WordPress.

Lighthouse lanciato da DevTools misura quindi la variante normale, quella che vede chiunque abbia già visitato il sito. Cioè quasi tutti i vostri utenti.

Abbiamo così due percorsi:

Litespeed test Google Pagespeed Insights

e il test fatto direttamente da Lighthouse su Chrome:

Litespeed LSCache Cloacking

A questo punto manca soltanto l’ultimo pezzo ed una domanda che sorge spontanea: che cosa fa Guest Optimization al JavaScript?

Quarto passaggio: Guest Optimization forza il JavaScript in modalità Delay

Apriamo src/optimize.cls.php.

Il plugin prima legge la normale configurazione JavaScript impostata dall’amministratore.

Poi incontra questo controllo:

$this-&gt;cfg_js_defer = $this-&gt;conf(self::O_OPTM_JS_DEFER);
if (defined('LITESPEED_GUEST_OPTM')) {
    $this-&gt;cfg_js_defer = 2;
}

Questa riga è particolarmente importante.

Quando Guest Optimization è attiva, LiteSpeed forza internamente il valore JavaScript a 2.

Nel codice del plugin il valore 2 rappresenta la modalità delayed.

Non è quindi soltanto un normale defer.

È la modalità nella quale gli script vengono neutralizzati e caricati successivamente.

E questo override avviene anche se la configurazione ordinaria del sito prevede un comportamento differente.

Non è un’ipotesi accademica: è esattamente ciò che fanno i preset ufficiali del plugin. Nei file data/preset/advanced.data e data/preset/aggressive.data, i due profili “consigliati” per la maggior parte dei siti, troviamo:

["guest",true]
["guest_optm",true]
["optm-js_defer",1]

Guest Mode attiva, Guest Optimization attiva, e JavaScript a 1, cioè semplice defer, per tutti gli altri.

Il preset stesso configura la divergenza: il tester ottiene il delay (2), l’utente reale ottiene il defer (1). Un amministratore che applica il preset “Advanced” con un click ha, senza saperlo, due siti diversi.

Solo il preset “Extreme” imposta 2 per tutti, e lì, almeno, il tester e l’utente vedono la stessa cosa.

Non solo JavaScript: cosa forza davvero Guest Optimization

Cercando LITESPEED_GUEST_OPTM nel sorgente si scopre che il JavaScript è solo la voce più vistosa. Quando quella costante è definita, il plugin forza indipendentemente dalle impostazioni dell’amministratore:

  • minificazione e combinazione di CSS e JS (optimize.cls.php);
  • caricamento asincrono del CSS e UCSS, se il sito è collegato a QUIC.cloud;
  • rimozione dei Google Fonts (cfg_ggfonts_rm forzato a true): il tester vede una pagina senza web font esterni;
  • minificazione HTML e controllo del DNS prefetch;
  • lazy load di immagini e iframe, Viewport Images, sostituzione WebP, aggiunta delle dimensioni mancanti alle immagini (media.cls.php);
  • rimozione dei tag <noscript> (cfg_trim_noscript), cioè dei fallback che normalmente accompagnano il lazy load;
  • placeholder responsive per le immagini (placeholder.cls.php).

E soprattutto salta i controlli di sicurezza che l’amministratore avrebbe a disposizione. In optimize.cls.php:

if (!defined('LITESPEED_GUEST_OPTM')) {
    if (!Control::is_cacheable()) {
        return $content;
    }
    // Check if hit URI excludes
    ...
}

Le “URI Excludes” dell’ottimizzazione vengono applicate solo quando non si è in Guest Optimization. Lo stesso vale per i “Role Excludes” in core.cls.php. E per il JavaScript viene ignorata la normale lista “JS Deferred Excludes” a favore di una lista separata, “Guest Mode JS Excludes”, che di default è vuota.

In altre parole: tutto ciò che l’amministratore ha escluso perché sa che si rompe, per il tester viene ottimizzato lo stesso. Il tester non naviga, non compila form, non apre menu: non si accorgerà mai che qualcosa è rotto.

Quinto passaggio: il tag script smette di essere uno script

Vediamo ora cosa accade concretamente al markup.

Un normale file JavaScript sarebbe dichiarato così:

&lt;script src="/wp-content/themes/theme/app.js"&gt;&lt;/script&gt;

Un browser che incontra questo elemento riconosce src e può richiedere il file JavaScript.

Quando LiteSpeed utilizza la modalità delayed, il tag viene trasformato in questo (la riga è in optimize.cls.php):

&lt;script data-optimized="1" type="litespeed/javascript" data-src="/wp-content/themes/theme/app.js"&gt;&lt;/script&gt;

Ed ecco il punto fondamentale.

type="litespeed/javascript" non è un normale tipo JavaScript riconosciuto dal browser.

E soprattutto l’URL non è più nell’attributo src.

È stato spostato in:

data-src="..."

Per Chrome quel file non è quindi, in quel momento, una risorsa JavaScript da scaricare ed eseguire.

Il riferimento esiste nell’HTML, ma la richiesta di rete verso quel file non parte come partirebbe con un normale tag script.

Lo stesso trattamento viene riservato agli script inline, il cui contenuto resta nel tag con type="litespeed/javascript", e agli iframe: src diventa data-litespeed-src, quindi embed YouTube, mappe e advertising non vengono caricati finché non c’è interazione.

C’è anche un dettaglio meno noto. In optimize.cls.php, quando il delay è attivo, il plugin modifica il contenuto stesso dei file JavaScript che serve:

$con = str_replace('DOMContentLoaded', 'DOMContentLiteSpeedLoaded', $con);

Ogni script che aspetta DOMContentLoaded viene riscritto per aspettare un evento inventato da LiteSpeed, che il loader emetterà solo dopo aver caricato tutti gli script ritardati. Non è più il vostro JavaScript: è il vostro JavaScript con le stringhe sostituite.

Questa distinzione è importante anche terminologicamente.

Non diciamo che LiteSpeed cancella necessariamente ogni riferimento al JavaScript.

Diciamo una cosa tecnicamente più precisa e ancora più significativa: il file JavaScript viene sottratto al normale caricamento del browser, o meglio alla sua esecuzione.

Sesto passaggio: quando partono davvero quei JavaScript?

Serve naturalmente un loader che successivamente trasformi quegli elementi nuovamente in normali script.

Il file di LiteSpeed si chiama js_delay.min.js, e la versione non minificata assets/js/js_delay.js si legge in un minuto.

E qui troviamo l’ultimo tassello.

Il loader registra eventi dell’utente:

window.litespeed_ui_events = window.litespeed_ui_events || ['mouseover', 'click', 'keydown', 'wheel', 'touchmove', 'touchstart', 'pointerup', 'pointerdown'];

Quando avviene una di queste interazioni, parte la funzione di caricamento ritardato.

Il loader cerca gli elementi:

script[type="litespeed/javascript"]

e soltanto in quel momento crea normali elementi <script>, trasformando data-src nuovamente in src, caricandoli uno alla volta, in sequenza.

A quel punto il browser scarica il JavaScript.

Prima dell’interazione, no.

E poi c’è questa riga, che nel sorgente è commentata:

// const litespeed_js_delay_timer = setTimeout( litespeed_load_delayed_js, 70 );

Un fallback temporale esisteva, o era stato quantomeno previsto: dopo 70 millisecondi gli script sarebbero partiti comunque, interazione o no. È stato disattivato. Senza interazione, il JavaScript ritardato non parte mai. Né dopo 70 millisecondi, né dopo 70 secondi. Un utente che apre la pagina e legge senza toccare nulla ha una pagina il cui JavaScript non è mai stato eseguito.

Con un timer, un test Lighthouse che dura diversi secondi avrebbe visto partire gli script e ne avrebbe misurato il costo. Senza timer, non li vede.

E Lighthouse non è un utente che muove il mouse

Ora rimettiamo insieme tutti i pezzi.

PageSpeed Insights avvia Lighthouse.

LiteSpeed riconosce la richiesta attraverso le proprie liste UA/IP, che oggi vengono aggiornate direttamente da QUIC.cloud.

La mantiene nella variante Guest, non consegnandole mai il cookie.

Guest Optimization forza il JavaScript in modalità Delay, anche se il preset del sito dice defer.

I normali src diventano data-src.

I tag diventano type="litespeed/javascript".

Il caricamento reale avviene quando si verifica un’interazione utente, e solo allora.

Ma un test Lighthouse non utilizza la pagina come una persona che muove il mouse, gira la rotella, tocca lo schermo o apre il menu.

Il risultato pratico è evidente.

Durante la finestra nella quale vengono misurate le performance, il codice JavaScript non viene eseguito.

Ed ecco come si arriva a:

Total Blocking Time: 0 ms.

Non perché il JavaScript del sito sia diventato magicamente gratuito, ma perché quel lavoro non sta avvenendo durante il test.

Come verificarlo sul vostro sito in due minuti

Non serve fidarsi di noi. Bastano due richieste curl dalla shell di un server qualunque.

La prima simula il tester: nessun cookie, User-Agent che contiene Lighthouse.

curl -s -A "Mozilla/5.0 (Linux; Android 11; moto g power (2022)) Chrome-Lighthouse" https://www.esempio.it/ \
  | grep -c 'type="litespeed/javascript"'

La seconda simula un utente di ritorno: stesso URL, ma con il cookie di vary presente (il valore non è importante, il plugin controlla solo che esista).

curl -s -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/128.0.0.0" \
  -b "_lscache_vary=1" https://www.esempio.it/ \
  | grep -c 'type="litespeed/javascript"'

Se il primo comando restituisce decine di occorrenze e il secondo zero, avete appena osservato le due varianti con i vostri occhi. Per confronto, il plugin stesso espone un parametro documentato per forzare la variante non-Guest: ?litespeed_guest_off=1.

Se invece volete un numero PageSpeed onesto senza toccare il sito, l’unico modo è disattivare Guest Optimization, oppure impostare per tutti lo stesso livello che ricevono i tester. In entrambi i casi il punteggio scenderà. Quello è il numero vero.

Il test vede una pagina che l’utente non utilizzerà nello stesso modo

Questa, per noi, è la definizione pratica del problema.

PageSpeed Insights dovrebbe rispondere alla domanda:

“Come si comporta questa pagina?”

Ma se la pagina è in grado di riconoscere PageSpeed Insights e cambiare il proprio comportamento, il test finisce per rispondere a una domanda differente:

“Come si comporta questa pagina quando sa di essere sotto PageSpeed Insights?”

Sono due cose completamente diverse.

E c’è un corollario che riguarda la SEO in senso stretto. La voce Google nella lista UA e il range 66.249.64.0/19 nella lista IP intercettano Googlebot. Anche il crawler che indicizza il sito, quindi, riceve la variante Guest, con il JavaScript neutralizzato e i <noscript> rimossi. Che cosa veda esattamente il rendering di Googlebot su un sito il cui JavaScript parte solo al mouseover è una domanda che ogni proprietario di un sito con contenuti generati lato client dovrebbe porsi.

Il parallelismo Volkswagen diventa quasi imbarazzante

Torniamo per un momento al Dieselgate. Ve lo ricordate?

La centralina Volkswagen non rendeva l’automobile inesistente durante il test.

Il motore era sempre lì.

Le componenti erano sempre quelle.

Quello che cambiava era il comportamento quando la vettura riconosceva le condizioni del banco prova.

Durante l’omologazione attivava una modalità particolarmente favorevole, motore pulito, basse emissioni, un motore apparentemente non inquinante e rispettoso dell’ambiente.

Fuori dal banco prova tornava a comportarsi diversamente e scoppiò lo scandalo dei test truccati.

DieselGate

Con LiteSpeed Cache il parallelismo tecnologico non è ovviamente letterale, ma quello logico è difficile da ignorare.

Qui abbiamo:

  • un software che deve essere misurato;
  • un sistema che identifica caratteristiche del misuratore, per User-Agent e per indirizzo IP;
  • una lista dei misuratori aggiornata centralmente dal produttore;
  • una modalità speciale associata alle richieste qualificate;
  • un comportamento differente nel caricamento delle risorse;
  • un risultato del benchmark enormemente migliore.

Il tester arriva e il motore cambia mappatura.

Solo che qui la mappatura è fatta di PHP, cookie, User-Agent, range IP, data-src e JavaScript ritardato.

La stessa LiteSpeed ammette che il risultato può mascherare i problemi

A rendere questa vicenda ancora più sorprendente è la documentazione ufficiale.

LiteSpeed spiega esplicitamente che Guest Optimization applica il massimo livello di ottimizzazione alla pagina Guest anche quando alcune funzionalità sarebbero normalmente disattivate.

Dice inoltre che le richieste qualificanti comprendono bot, determinati User-Agent e prime visite.

E cita espressamente PageSpeed Insights e GTmetrix spiegando che Guest Optimization può migliorare molto i page speed score perché questi servizi ricevono una pagina cached e altamente ottimizzata.

Poi arriva la parte più significativa.

La documentazione avverte che Guest Optimization può mascherare i problemi reali e suggerisce di disabilitarla se si desidera ottenere una valutazione accurata dai siti di performance testing.

È una frase straordinaria.

Perché equivale sostanzialmente a dire: se volete sapere davvero quali problemi ha il sito, spegnete la funzione che gli fa ottenere il voto migliore.

Le comunicazioni sono ovviamente con toni molto pacati e politically correct, non scrivono mica “Stiamo barando i test PageSpeed per vendere di più”, ma di fatto è quello che fanno.

Va detto, per completezza, che nell’installazione da zero Guest Mode e Guest Optimization sono disattivate. Vengono attivate dai preset “Advanced”, “Aggressive” ed “Extreme”, cioè esattamente i profili che vengono consigliati a chi vuole “più velocità” con un click, e da buona parte delle guide di configurazione pubblicate dai provider che vendono hosting LiteSpeed.

Il danno vero è psicologico: il 100 interrompe l’ottimizzazione e la cazzimma !

Ed è questo il motivo per cui riteniamo questa scelta particolarmente dannosa.

Il problema non è soltanto tecnico.

È cognitivo.

Un sito che ottiene 77 genera domande.

Perché il Largest Contentful Paint impiega 4,5 secondi?

Perché abbiamo 170 millisecondi di Total Blocking Time?

Quanto JavaScript stiamo caricando?

Quale plugin sta bloccando il main thread?

Possiamo eliminare qualche libreria?

Il tema è troppo pesante?

Gli advertising script partono troppo presto?

Le immagini sono correttamente dimensionate?

Il CSS è eccessivo?

Un 77 spinge uno sviluppatore serio ad aprire DevTools e lavorare.

Un 100 dice invece che il lavoro è finito.

Ed è qui che un benchmark eccessivamente favorevole produce il danno maggiore.

Il cliente vede 100.

L’agenzia vede 100.

Il responsabile marketing vede 100.

Chi dovrebbe autorizzare ulteriori ore di ottimizzazione si domanda perché spendere soldi su un sito che Google apparentemente valuta perfetto.

Il problema reale rimane.

Ma nessuno lo cerca più.

E c’è un dato che nessun preset può truccare: i Core Web Vitals che Google usa per il ranking non arrivano da Lighthouse, ma dal Chrome User Experience Report, cioè dai browser degli utenti reali. Quelli con il cookie. Quelli sulla variante normale. È esattamente per questo che il 100 di PageSpeed Insights e il rosso nella sezione “Scopri cosa provano i tuoi utenti reali” della stessa pagina convivono così spesso sui siti LiteSpeed.

Non è LiteSpeed Web Server il problema

Va fatta anche un’altra distinzione.

LiteSpeed Web Server è un prodotto differente dal plugin LiteSpeed Cache.

Il caching server-side di LiteSpeed può essere estremamente efficace esattamente come lo è FastCGI Cache o Proxy Cache su NGINX o Varnish Cache se parliamo di Full Page Cache pure.

Servire HTML già pronto evitando l’avvio completo di WordPress, PHP e database è una tecnica eccellente.

Non è questo ciò che stiamo criticando.

Allo stesso modo non stiamo sostenendo che minificazione, UCSS, Critical CSS, lazy load, defer o delay JavaScript siano tecniche scorrette.

Sono strumenti perfettamente legittimi quando il miglioramento viene applicato all’esperienza che vogliamo realmente fornire agli utenti.

Quello che contestiamo è l’utilizzo di una variante riconoscibile dal tester che permette al benchmark di osservare condizioni significativamente differenti.

C’è tuttavia un dettaglio non indifferente da tenere in considerazione, nel momento in cui si vuole sfruttare appieno il webserver LiteSpeed, si necessita di “comunicare” con il webserver per il purge della cache lato server ed a quel punto il plugin LSCache non è più un’opzione facoltativa, una scelta discrezionale dell’utente, ma un obbligo e l’unica scelta possibile, ed ecco qua che anche a voler sforzarsi di assolvere le intenzioni di LiteSpeed (webserver) separandolo dal plugin LSCache, ricordiamoci sempre che la “combo” è voluta dalla stessa azienda commerciale che sviluppa e VENDE entrambi con sistemi in grado di barare i test facendoli percepire come migliori rispetto ad altre tecnologie, e l’utente non esperto purtroppo ci crede.

La prova è nel sorgente, non nelle nostre opinioni

La cosa che rende questa analisi particolarmente difficile da liquidare come semplice polemica è che tutti i passaggi fondamentali sono visibili nel repository ufficiale, versione 7.9.1.

Abbiamo:

  • una lista UA con Lighthouse, Google, GTmetrix e HeadlessChrome (data/gm_uas.txt);
  • una lista IP con i range di Google e GTmetrix (data/gm_ips.txt);
  • dalla 7.7, un cron che scarica entrambe le liste da wpapi.quic.cloud con priorità sul file locale, e la cancellazione delle opzioni corrispondenti dal pannello;
  • un metodo always_guest() che confronta User-Agent e indirizzi IP;
  • una decisione lato WordPress basata solo sull’assenza del cookie _lscache_vary;
  • un ramo in guest.vary.php che ai tester non consegna il cookie e non ordina il reload;
  • un reload forzato per tutti gli altri, con una patch a document.referrer per non rompere Analytics;
  • Guest Optimization che forza cfg_js_defer = 2, rimuove Google Fonts e noscript, e ignora URI Excludes e Role Excludes;
  • preset ufficiali che attivano Guest Optimization lasciando il JavaScript a 1 per gli utenti;
  • script riscritti come type="litespeed/javascript", URL spostati da src a data-src, iframe in data-litespeed-src;
  • la stringa DOMContentLoaded sostituita dentro i file JavaScript;
  • un loader che aspetta eventi come click, mouseover, wheel o touch prima di caricarli, con il timer di fallback commentato.

Non serve immaginare cosa faccia il software.

Il software ce lo dice.

Conclusioni: PageSpeed vede il banco prova, l’utente vede la strada

Il problema di Guest Optimization non è che LiteSpeed sappia ottimizzare una pagina.

Anzi.

Il fatto che riesca a minificare, combinare, ritardare JavaScript, produrre Critical CSS e ridurre il lavoro iniziale dimostra che possiede strumenti tecnicamente interessanti.

Il problema è un altro.

Il sistema è progettato per riconoscere determinate richieste di test e mantenerle in una condizione particolarmente favorevole.

In quella condizione Guest Optimization forza il delay JavaScript.

I normali script esterni vengono trasformati in elementi che il browser non carica immediatamente.

I loro URL vengono parcheggiati in data-src.

La successiva esecuzione dipende da un loader attivato dall’interazione, senza alcun fallback temporale.

E durante un audit automatico quella interazione semplicemente non avviene.

Il risultato è che PageSpeed Insights giudica una pagina sulla quale il costo reale di una parte consistente del JavaScript non è ancora entrato in gioco.

Il browser dell’utente, invece, deve prima o poi pagarne il conto. Anzi, alla prima visita lo paga due volte.

Ecco perché possiamo trovarci con 100 su PageSpeed Insights e 77 su Lighthouse eseguito in Chrome.

Ed ecco perché quel 100 non dovrebbe rassicurarci.

Dovrebbe insospettirci.

Nel Dieselgate la centralina riconosceva il banco prova e cambiava mappatura.

Qui un plugin riconosce caratteristiche del tester e cambia la modalità con la quale viene caricata una parte fondamentale della pagina.

Le conseguenze non sono naturalmente comparabili sul piano legale, ambientale o economico.

Ma il principio del benchmark alterato perché il software sa di essere osservato è sorprendentemente simile.

E il danno, nel nostro settore, è subdolo.

Non è soltanto ricevere un numero discutibile.

È convincersi che non esista più nulla da ottimizzare.

È smettere di cercare quel JavaScript pesante.

È lasciare quell’LCP a quattro secondi.

È non intervenire sul tema, sui plugin e sulle terze parti.

È mostrare al cliente un 100 e chiamarlo performance.

Per noi la regola dovrebbe essere molto più semplice.

Un sito veloce non dovrebbe avere bisogno di riconoscere chi lo sta testando.

Dovrebbe essere veloce per Google PageSpeed Insights.

Dovrebbe essere veloce per Lighthouse.

Ma soprattutto dovrebbe essere veloce per una persona vera che apre Chrome dal proprio telefono.

Se il banco prova e la strada raccontano due storie differenti, noi preferiamo credere alla strada.

E tutti i venditori di Hosting che pur sapendo tacciono, sono correi di un comportamento che in qualsiasi altro settore sarebbe finito in prima pagina per truffa.

Hai dei dubbi? Non sai da dove iniziare? Contattaci !

Abbiamo tutte le risposte alle tue domande per aiutarti nella giusta scelta.

Chatta con noi

Chatta direttamente con il nostro supporto prevendita.

0256569681

Contattaci telefonicamente negli orari d’ufficio 9:30 – 19:30

Contattaci online

Apri una richiesta direttamente nell’area dei contatti.

DISCLAIMER, Note Legali e Copyright. Red Hat, Inc. detiene i diritti su Red Hat®, RHEL®, RedHat Linux®, e CentOS®; AlmaLinux™ è un marchio di AlmaLinux OS Foundation; Rocky Linux® è un marchio registrato di Rocky Linux Foundation; SUSE® è un marchio registrato di SUSE LLC; Canonical Ltd. detiene i diritti su Ubuntu®; Software in the Public Interest, Inc. detiene i diritti su Debian®; Linus Torvalds detiene i diritti su Linux®; FreeBSD® è un marchio registrato di The FreeBSD Foundation; NetBSD® è un marchio registrato di The NetBSD Foundation; OpenBSD® è un marchio registrato di Theo de Raadt; Oracle Corporation detiene i diritti su Oracle®, MySQL®, MyRocks®, VirtualBox® e ZFS®; Percona® è un marchio registrato di Percona LLC; MariaDB® è un marchio registrato di MariaDB Corporation Ab; PostgreSQL® è un marchio registrato di PostgreSQL Global Development Group; SQLite® è un marchio registrato di Hipp, Wyrick & Company, Inc.; KeyDB® è un marchio registrato di EQ Alpha Technology Ltd.; Typesense® è un marchio registrato di Typesense Inc.; REDIS® è un marchio registrato di Redis Labs Ltd; F5 Networks, Inc. detiene i diritti su NGINX® e NGINX Plus®; Varnish® è un marchio registrato di Varnish Software AB; HAProxy® è un marchio registrato di HAProxy Technologies LLC; Traefik® è un marchio registrato di Traefik Labs; Envoy® è un marchio registrato di CNCF; Adobe Inc. detiene i diritti su Magento®; PrestaShop® è un marchio registrato di PrestaShop SA; OpenCart® è un marchio registrato di OpenCart Limited; Automattic Inc. detiene i diritti su WordPress®, WooCommerce®, e JetPack®; Open Source Matters, Inc. detiene i diritti su Joomla®; Dries Buytaert detiene i diritti su Drupal®; Shopify® è un marchio registrato di Shopify Inc.; BigCommerce® è un marchio registrato di BigCommerce Pty. Ltd.; TYPO3® è un marchio registrato di TYPO3 Association; Ghost® è un marchio registrato di Ghost Foundation; Amazon Web Services, Inc. detiene i diritti su AWS® e Amazon SES®; Google LLC detiene i diritti su Google Cloud™, Chrome™, e Google Kubernetes Engine™; Alibaba Cloud® è un marchio registrato di Alibaba Group Holding Limited; DigitalOcean® è un marchio registrato di DigitalOcean, LLC; Linode® è un marchio registrato di Linode, LLC; Vultr® è un marchio registrato di The Constant Company, LLC; Akamai® è un marchio registrato di Akamai Technologies, Inc.; Fastly® è un marchio registrato di Fastly, Inc.; Let’s Encrypt® è un marchio registrato di Internet Security Research Group; Microsoft Corporation detiene i diritti su Microsoft®, Azure®, Windows®, Office®, e Internet Explorer®; Mozilla Foundation detiene i diritti su Firefox®; Apache® è un marchio registrato di The Apache Software Foundation; Apache Tomcat® è un marchio registrato di The Apache Software Foundation; PHP® è un marchio registrato del PHP Group; Docker® è un marchio registrato di Docker, Inc.; Kubernetes® è un marchio registrato di The Linux Foundation; OpenShift® è un marchio registrato di Red Hat, Inc.; Podman® è un marchio registrato di Red Hat, Inc.; Proxmox® è un marchio registrato di Proxmox Server Solutions GmbH; VMware® è un marchio registrato di Broadcom Inc.; CloudFlare® è un marchio registrato di Cloudflare, Inc.; NETSCOUT® è un marchio registrato di NETSCOUT Systems Inc.; ElasticSearch®, LogStash®, e Kibana® sono marchi registrati di Elastic N.V.; Grafana® è un marchio registrato di Grafana Labs; Prometheus® è un marchio registrato di The Linux Foundation; Zabbix® è un marchio registrato di Zabbix LLC; Datadog® è un marchio registrato di Datadog, Inc.; Ceph® è un marchio registrato di Red Hat, Inc.; MinIO® è un marchio registrato di MinIO, Inc.; Mailgun® è un marchio registrato di Mailgun Technologies, Inc.; SendGrid® è un marchio registrato di Twilio Inc.; Postmark® è un marchio registrato di ActiveCampaign, LLC; cPanel®, L.L.C. detiene i diritti su cPanel®; Plesk® è un marchio registrato di Plesk International GmbH; Hetzner® è un marchio registrato di Hetzner Online GmbH; OVHcloud® è un marchio registrato di OVH Groupe SAS; Terraform® è un marchio registrato di HashiCorp, Inc.; Ansible® è un marchio registrato di Red Hat, Inc.; cURL® è un marchio registrato di Daniel Stenberg; Facebook®, Inc. detiene i diritti su Facebook®, Messenger® e Instagram®. Questo sito non è affiliato, sponsorizzato o altrimenti associato a nessuna delle entità sopra menzionate e non rappresenta nessuna di queste entità in alcun modo. Tutti i diritti sui marchi e sui nomi di prodotto menzionati sono di proprietà dei rispettivi detentori di copyright. Ogni altro marchio citato appartiene ai propri registranti. MANAGED SERVER® è un marchio registrato a livello europeo da MANAGED SERVER SRL, con sede legale in Via Flavio Gioia, 6, 62012 Civitanova Marche (MC), Italia e sede operativa in Via Enzo Ferrari, 9, 62012 Civitanova Marche (MC), Italia.

SOLO UN ATTIMO !

Ti sei mai chiesto se il tuo Hosting faccia schifo ?

Scopri subito se il tuo hosting provider ti sta danneggiando con un sito lento degno del 1990 ! Risultato immediato.

Close the CTA
Torna in alto