Glossario

Cosa fa la bfcache alle navigazioni indietro e ai tuoi conteggi di pageview

Taras Shynkarenko
Taras Shynkarenko
•Aggiornato: •8 min di lettura
Cosa fa la bfcache alle navigazioni indietro e ai tuoi conteggi di pageviewCosa fa la bfcache alle navigazioni indietro e ai tuoi conteggi di pageview

In breve, la risposta rapida

8 min di lettura

La bfcache (back/forward cache) conserva in memoria un'istantanea completa della pagina quando il visitatore se ne va, così un clic su indietro o avanti la ripristina subito, senza ricaricarla. Chrome, Firefox e Safari ne hanno una. Poiché la pagina non viene caricata di nuovo, uno script di analytics che conta le pageview solo al caricamento perde il ripristino. Ascolta l'evento pageshow e controlla event.persisted per contare i ripristini, ed evita i listener unload, Cache-Control: no-store e le connessioni aperte che rendono una pagina non idonea.

Che cos'è la bfcache?

La bfcache, abbreviazione di back/forward cache, è un'ottimizzazione del browser che conserva in memoria un'istantanea completa della pagina quando il visitatore se ne va. Così un clic su indietro o avanti ripristina quella pagina all'istante, invece di ricaricarla da zero. web.dev la definisce come «un'ottimizzazione del browser che permette una navigazione avanti e indietro istantanea» e ne descrive il meccanismo: «invece di distruggere una pagina quando l'utente si sposta altrove, rimandiamo la distruzione e mettiamo in pausa l'esecuzione del JS. Se l'utente torna indietro a breve, rendiamo di nuovo visibile la pagina e riprendiamo l'esecuzione del JS.»

Tutti i principali browser ce l'hanno: Chrome dalla versione 96, Firefox e Safari. I clic su indietro e avanti pesano parecchio sulla navigazione. web.dev riporta che «i dati di utilizzo di Chrome mostrano che 1 navigazione su 10 su desktop e 1 su 5 su mobile è un'azione di indietro o avanti.»

Per le analytics conta soprattutto ciò che non succede durante un ripristino. Non viene richiesto nessun HTML, nessuno script riparte dall'inizio e non scatta alcun evento load. Il tuo tracker si risveglia esattamente dove era stato messo in pausa.

Un libro aperto con un segnalibro che tiene il posto del lettore, come una pagina messa in pausa in memoria e ripresa da dove si era interrotta.

In che cosa la bfcache è diversa dalla cache HTTP?

La bfcache conserva l'intera pagina attiva, mentre la cache HTTP conserva le singole risposte. web.dev lo spiega così: «la bfcache è un'istantanea dell'intera pagina in memoria, compreso l'heap JavaScript, mentre la cache HTTP contiene solo le risposte alle richieste fatte in precedenza.» Una pagina servita dalla cache HTTP viene comunque caricata: il browser analizza l'HTML, esegue ogni script e fa scattare load, quindi il tuo tracker invia una normale pageview. Una pagina ripristinata dalla bfcache salta tutto questo.

Anche timer e promise vanno in pausa. web.dev osserva che «i browser mettono in pausa i timer in sospeso e le promise non risolte per le pagine nella bfcache» e li riprendono al ripristino. Un heartbeat o un timer di engagement riparte dopo l'intervallo, senza contarlo.

Quali pagine sono idonee alla bfcache?

Una pagina è idonea alla bfcache a meno che qualcosa al suo interno renda la memorizzazione poco sicura, e i blocchi più comuni dipendono da te. La tabella elenca quelli che web.dev e la documentazione di Chrome segnalano.

BloccoEffetto sulla bfcacheSoluzione
Listener unloadNon idonea in Chrome e Firefox su desktop; Firefox anche su mobile, tranne iOSUsa pagehide al suo posto
Cache-Control: no-store sulla paginaIn passato escludeva la pagina dalla bfcacheUsa no-cache o max-age=0, a meno che la pagina sia sensibile
Listener beforeunload incondizionatoNei browser moderni non blocca più, ma in passato sì, secondo web.devAggiungilo solo quando ci sono modifiche non salvate
Riferimento window.openerUna pagina con un opener non nullo «non può essere messa in sicurezza nella bfcache»Usa rel="noopener"
Connessione IndexedDB apertaAlcuni browser non memorizzano la paginaChiudila su pagehide, riaprila su pageshow
fetch() o XMLHttpRequest in corsoAlcuni browser non memorizzano la paginaLascia finire le richieste o interrompile su pagehide
Connessione WebSocket o WebRTC apertaBlocca in alcuni browser; Chrome 149 e successivi e Safari non bloccano con WebSocket apertiChiudila su pagehide

Alcuni mancati ripristini non c'entrano nulla con il tuo codice. web.dev elenca le navigazioni avanti o indietro che non usano la bfcache «quando l'utente chiude il browser e lo riavvia», «quando l'utente duplica una scheda» e «quando l'utente chiude una scheda e la riapre», e precisa che i browser scartano le pagine in cache dopo un certo tempo per risparmiare memoria. Un tasso di successo del 100% non è un obiettivo realistico.

Gli iframe seguono la pagina principale. Un iframe non viene memorizzato separatamente, e un iframe che usa un'API bloccante può tenere l'intera pagina fuori dalla bfcache.

Come segnalano la bfcache pageshow e pagehide?

Gli eventi pageshow e pagehide segnalano la bfcache tramite la proprietà persisted. Su pageshow, persisted vale true quando la pagina è tornata dalla bfcache e false in un caricamento normale. Su pagehide, persisted a true significa che il browser intende memorizzare la pagina, anche se web.dev sottolinea che «non garantisce che la pagina verrà messa in cache».

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    console.log('This page was restored from the bfcache.');
  } else {
    console.log('This page was loaded normally.');
  }
});

pageshow «scatta subito dopo l'evento load quando la pagina si carica per la prima volta e ogni volta che la pagina viene ripristinata dalla bfcache.» Per le analytics questo dettaglio conta, come vedrai nella prossima sezione. I browser Chromium fanno scattare anche gli eventi del Page Lifecycle freeze e resume quando una pagina entra ed esce dalla bfcache, ma web.dev fa notare che per misurare il tasso di successo della tua bfcache serve pageshow.

Pendolari che passano attraverso un tornello, dove chi torna indietro senza essere notato non viene contato, come una navigazione all'indietro che le analytics non vedono.

Perché le analytics perdono o contano due volte le navigazioni all'indietro?

Le analytics perdono le navigazioni all'indietro perché un ripristino dalla bfcache non riesegue gli script della pagina, quindi un tracker che invia la pageview al caricamento resta in silenzio. web.dev avverte i proprietari dei siti che potrebbero notare «un calo del numero totale di pageview riportate, man mano che Chrome abilita la bfcache per più utenti», e aggiunge che molti siti stanno «già sottostimando le pageview provenienti da altri browser che implementano la bfcache, perché molte librerie di analytics diffuse non misurano i ripristini dalla bfcache come nuove pageview.»

Il doppio conteggio nasce dalla correzione opposta, fatta con poca attenzione. Poiché pageshow scatta anche a ogni caricamento normale, un listener che invia una pageview a ogni pageshow senza controllare persisted ne manda due per caricamento: una dall'avvio normale del tracker, una dal listener.

Lo stesso meccanismo produce altre distorsioni:

Flowsery
Flowsery

Inizia la prova gratuita di 14 giorni

Dashboard in tempo reale

Monitoraggio degli obiettivi

Tracciamento senza cookie

  • Vuoti nell'engagement. I timer in pausa riprendono al ripristino, quindi timer di engagement e heartbeat saltano il tempo in cui la pagina è rimasta in memoria.
  • Eventi di uscita che non partono mai. Una pagina che entra nella bfcache non fa mai scattare unload. La guida beforeunload vs pagehide spiega perché i beacon di uscita vanno agganciati a pagehide e visibilitychange.
  • Pagine più veloci che sembrano più lente. web.dev spiega che i ripristini prendono il posto delle visite ripetute, che sono tra i caricamenti più rapidi di un dataset, quindi i dati sui tempi di caricamento peggiorano anche se i visitatori hanno avuto un'esperienza più veloce.
  • Conteggi misti. Una navigazione all'indietro che non trova la bfcache ricarica tutta la pagina e viene contata, mentre una che la trova no. Lo stesso schema di clic produce numeri diversi a seconda dell'idoneità.

La guida pageview, sessioni e utenti mostra come queste lacune si ripercuotono sulle metriche per sessione.

Tre modi di gestire un clic su indietro
Nessun listener pageshow
  • Il tracker invia la pageview al caricamento
  • Un ripristino dalla bfcache non fa scattare nessun evento load
  • Il clic su indietro non viene mai contato
pageshow senza controllo
  • pageshow scatta anche a ogni caricamento normale
  • Ogni caricamento invia due pageview
  • I ripristini vengono contati, ma i caricamenti sono raddoppiati
pageshow con controllo di persisted
  • Il listener invia solo quando event.persisted è true
  • Un caricamento normale resta a una pageview
  • Ogni ripristino ne aggiunge esattamente una
Solo il controllo di persisted conta ogni clic su indietro esattamente una volta.

Come si contano correttamente i ripristini dalla bfcache?

I ripristini dalla bfcache si contano aggiungendo un listener pageshow che invia una visualizzazione di pagina solo quando event.persisted è true, poi verificando che ogni clic su indietro produca esattamente un solo hit.

  1. Aggiungi il listener. L'esempio di Google Analytics di web.dev invia gtag('event', 'page_view') dentro if (event.persisted), lasciando il caricamento normale alla visualizzazione di pagina predefinita.
  2. Etichetta il tipo di navigazione. Per misurare il tuo hit ratio, web.dev disattiva la visualizzazione di pagina predefinita con send_page_view: false, ne invia una con navigation_type preso da performance.getEntriesByType('navigation')[0].type e usa navigation_type: 'back_forward_cache' per i ripristini. Confronta poi i conteggi di back_forward e back_forward_cache.
  3. Esegui il test di DevTools. In Chrome DevTools apri Application, poi Back-forward Cache, e clicca su Run Test. Se il test passa, leggi "Restored from back-forward cache". Se fallisce, vedi l'elenco dei motivi, con quelli risolvibili segnati come Actionable.
  4. Raccogli i motivi dalle visite reali. La proprietà notRestoredReasons della voce di navigation timing indica perché una pagina non è stata ripristinata. La documentazione di Chrome dice che "has shipped from Chrome 123", con motivi come unload-listener e response-cache-control-no-store.
  5. Risolvi i blocchi. Sostituisci unload con pagehide, togli no-store dalle pagine che non contengono dati sensibili e chiudi le connessioni IndexedDB o WebSocket su pagehide.

Anche le metriche di performance richiedono la stessa attenzione. web.dev spiega che strumenti come il Chrome User Experience Report trattano i ripristini come visite separate, e che la libreria web-vitals li supporta. Dopo un ripristino, il Largest Contentful Paint si misura dal timestamp di pageshow fino al frame successivo disegnato, mentre Cumulative Layout Shift e INP ripartono da 0.

Come influisce la bfcache sui dati di Flowsery?

La documentazione di Flowsery non descrive come il suo tracker tratti un ripristino dalla bfcache, quindi prova sul tuo sito prima di aggiungere qualsiasi codice. La vista analisi in tempo reale di Flowsery mostra ogni visualizzazione di pagina sulla tua dashboard nel momento in cui avviene, e rende il controllo rapido: apri una pagina, clicca su un link, premi indietro e guarda se la pagina ripristinata compare come nuova visualizzazione. Esegui prima il test bfcache di DevTools, così sai che la pagina è stata ripristinata e non ricaricata. Se i ripristini non compaiono e vuoi contarli, l'SDK npm di Flowsery espone un metodo trackPageview() che puoi chiamare da un listener pageshow che controlla event.persisted, evitando il doppio conteggio che causerebbe un listener privo di quel controllo.

Domande frequenti

Tutti i browser hanno una bfcache?

Sì, tutti i principali browser ne hanno una. web.dev elenca Chrome dalla versione 96, Firefox e Safari. Ogni browser ha regole di idoneità proprie, ed è per questo che la stessa pagina può finire nella cache in un browser e venire ricaricata in un altro.

Un ripristino dalla bfcache attiva l'evento load?

No. Un ripristino rende di nuovo visibile la pagina in pausa e riprende il suo JavaScript, quindi load e DOMContentLoaded non vengono attivati. Viene invece attivato l'evento pageshow, con persisted impostato su true.

Perché le mie visualizzazioni di pagina sono calate dopo che Chrome ha esteso la bfcache?

Più clic su indietro e avanti sono diventati ripristini invece di ricaricamenti, e molti script di analytics contano le visualizzazioni di pagina solo al caricamento. web.dev descrive proprio questo calo. Se vuoi contare i ripristini, aggiungi un listener pageshow che invii una visualizzazione di pagina quando event.persisted è true.

Cache-Control: no-store disattiva la bfcache?

Sulla pagina stessa, storicamente ha escluso le pagine dalla bfcache. web.dev consiglia di usarlo solo per le pagine con informazioni sensibili, e di usare no-cache o max-age=0 per quelle che hanno solo bisogno di contenuti aggiornati. Nessuno dei due influisce sull'idoneità.

Come verifico se una pagina è idonea alla bfcache?

In Chrome DevTools vai su Application, poi Back-forward Cache, e clicca su Run Test. Il pannello indica se la pagina è stata ripristinata e, in caso contrario, elenca i motivi del blocco. Per le visite reali, leggi notRestoredReasons dalla voce di navigation timing.

La bfcache funziona dentro una single-page app?

No. web.dev afferma che la bfcache "doesn't work for 'soft navigations' within a single-page app." Si applica quando un visitatore esce dall'app e ci torna con il pulsante indietro: se la pagina è idonea, può essere ripristinata l'intera app invece di ripartire da zero.

Cosa succede a timer e heartbeat mentre una pagina è nella bfcache?

I browser mettono in pausa i timer in sospeso e le promise non risolte, poi li riprendono al ripristino. Un heartbeat o un timer di coinvolgimento riparte dopo la pausa, quindi il tempo che la pagina ha passato in memoria non viene contato come coinvolgimento.

Un listener unload tiene una pagina fuori dalla bfcache?

Sì, in Chrome e Firefox su desktop, e in Firefox su mobile tranne iOS. Sostituisci unload con pagehide e la pagina resta idonea.

Come evito di contare due volte le visualizzazioni di pagina con un listener pageshow?

pageshow si attiva a ogni caricamento normale oltre che a ogni ripristino, quindi invia la visualizzazione di pagina solo quando event.persisted è true. L'avvio normale del tracker copre già il caricamento regolare. Poi premi indietro su una pagina di prova e controlla che ogni clic produca esattamente un hit.

Flowsery conta automaticamente i ripristini dalla bfcache?

La documentazione di Flowsery non lo descrive, quindi prova sul tuo sito. Apri una pagina, clicca su un link, premi indietro e guarda nella vista di analisi in tempo reale se compare una nuova visualizzazione di pagina. Se non compare, chiama trackPageview() dall'SDK npm dentro un listener pageshow che controlla event.persisted.

Questo articolo ti è stato utile?

Facci sapere cosa ne pensi!

Vedici più spesso su Google

Con un clic imposti Flowsery come fonte preferita e i nostri articoli salgono in Notizie principali, Modalità AI e AI Overview.

Prima di andare...

Flowsery

Flowsery

Analytics per il tuo sito che parte dalle entrate

Monitora ogni visitatore, sorgente e conversione in tempo reale. Semplice, potente e senza cookie.

Dashboard in tempo reale

Monitoraggio degli obiettivi

Tracciamento senza cookie

Termini del glossario correlati

Come il tracking delle SPA conta le visualizzazioni di pagina quando la pagina non si ricarica maiCome il tracking delle SPA conta le visualizzazioni di pagina quando la pagina non si ricarica mai
Glossario

Come il tracking delle SPA conta le visualizzazioni di pagina quando la pagina non si ricarica mai

Un tracking SPA accurato significa una pageview per schermata con il referrer giusto. Come lavorano insieme History API, pageview virtuali ed eventi di cronologia di GA4.

•8 min di lettura
Perché il bounce rate di GA4 è solo l'engagement rate al contrarioPerché il bounce rate di GA4 è solo l'engagement rate al contrario
Glossario

Perché il bounce rate di GA4 è solo l'engagement rate al contrario

Il bounce rate di GA4 è la quota di sessioni senza interazione. Come lo definisce Google, in cosa differisce da Universal Analytics e dove aggiungerlo.

•8 min di lettura
Cosa conta il report Pagine di destinazione di GA4 e dove resta vuotoCosa conta il report Pagine di destinazione di GA4 e dove resta vuoto
Glossario

Cosa conta il report Pagine di destinazione di GA4 e dove resta vuoto

Il report Pagine di destinazione di GA4 elenca la prima pagina di ogni sessione. Dove trovarlo, le metriche predefinite, perché compaiono righe (not set) e come aggiungere la fonte.

•9 min di lettura
Come il tracciamento della ricerca interna di GA4 registra ciò che digitano i visitatoriCome il tracciamento della ricerca interna di GA4 registra ciò che digitano i visitatori
Glossario

Come il tracciamento della ricerca interna di GA4 registra ciò che digitano i visitatori

Configura la ricerca interna di GA4 con la misurazione avanzata, aggiungi i tuoi parametri di query, trova la dimensione Termine di ricerca e traccia le ricerche senza URL.

•8 min di lettura
Impostare le proprietà utente di GA4 e analizzarle nei reportImpostare le proprietà utente di GA4 e analizzarle nei report
Glossario

Impostare le proprietà utente di GA4 e analizzarle nei report

Imposta le proprietà utente di GA4 con gtag o Tag Manager, registrale come dimensioni personalizzate a livello utente e resta entro il limite di 25 proprietà.

•9 min di lettura
Come collegare Search Console a GA4 e pubblicarne i reportCome collegare Search Console a GA4 e pubblicarne i report
Glossario

Come collegare Search Console a GA4 e pubblicarne i report

Scopri come collegare Search Console a GA4 da Amministrazione, quali ruoli ti servono, come pubblicare i due report nella Raccolta e quali dati non si possono unire.

•8 min di lettura

Articoli correlati