TL;DR, Réponse rapide
9 min de lectureLe bfcache (back/forward cache) garde en mémoire un instantané complet d'une page quand le visiteur la quitte, si bien qu'un clic sur Précédent ou Suivant la restaure instantanément sans rechargement. Chrome, Firefox et Safari en ont tous un. Comme la page ne se recharge pas, un script d'analytics qui ne compte les pages vues qu'au chargement rate la restauration. Écoutez pageshow et vérifiez event.persisted pour compter les restaurations, et évitez les écouteurs unload, Cache-Control: no-store et les connexions ouvertes qui rendent une page inéligible.
Qu'est-ce que le bfcache ?
Dans un navigateur, le bfcache, abréviation de back/forward cache, est une optimisation qui garde en mémoire un instantané complet d'une page quand le visiteur la quitte, si bien qu'un clic sur Précédent ou Suivant restaure cette page instantanément au lieu de la recharger. web.dev le définit comme "a browser optimization that enables instant back and forward navigation," et décrit le mécanisme : "instead of destroying a page when the user navigates away, we postpone destruction and pause JS execution. If the user navigates back soon, we make the page visible again and unpause JS execution."
Tous les grands navigateurs en ont un : Chrome depuis la version 96, Firefox et Safari. Les clics sur Précédent et Suivant représentent une grande part de la navigation. web.dev rapporte que "Chrome usage data shows that 1 in 10 navigations on desktop and 1 in 5 on mobile are either back or forward."
Pour l'analytics, l'important est ce qui ne se produit pas lors d'une restauration. Aucun HTML n'est demandé, aucun script ne repart du début et aucun événement load ne se déclenche. Votre tracker se réveille exactement là où il avait été mis en pause.

En quoi le bfcache diffère-t-il du cache HTTP ?
Le bfcache stocke toute la page vivante, alors que le cache HTTP stocke des réponses individuelles. web.dev le formule ainsi : "bfcache is a snapshot of the entire page in memory, including the JavaScript heap, whereas the HTTP cache contains only the responses for previously made requests." Une page servie depuis le cache HTTP se charge quand même : le navigateur analyse le HTML, exécute chaque script et déclenche load, donc votre tracker envoie une page vue normale. Une page restaurée depuis le bfcache saute toutes ces étapes.
Les minuteurs et les promesses sont eux aussi mis en pause. web.dev note que "browsers pause any pending timers or unresolved promises for pages in bfcache" et les reprennent à la restauration, donc un heartbeat ou un minuteur d'engagement reprend après l'interruption au lieu de compter pendant celle-ci.
Quelles pages sont éligibles au bfcache ?
Une page est éligible au bfcache sauf si un élément rend sa mise en cache risquée, et les blocages les plus courants dépendent de vous. Le tableau reprend ceux que signalent web.dev et la documentation de Chrome.
| Blocage | Effet sur le bfcache | Correction |
|---|---|---|
Écouteur unload | Inéligible dans Chrome et Firefox sur ordinateur ; dans Firefox aussi sur mobile, sauf iOS | Utilisez pagehide à la place |
Cache-Control: no-store sur la page | Exclut historiquement la page du bfcache | Utilisez no-cache ou max-age=0, sauf si la page est sensible |
Écouteur beforeunload inconditionnel | Ne bloque plus dans les navigateurs modernes mais bloquait auparavant, selon web.dev | Ajoutez-le seulement tant qu'il existe des modifications non enregistrées |
Référence window.opener | Une page dont l'opener n'est pas null "can't safely be put into bfcache" | Utilisez rel="noopener" |
| Connexion IndexedDB ouverte | Certains navigateurs ne mettent pas la page en cache | Fermez-la sur pagehide, rouvrez-la sur pageshow |
fetch() ou XMLHttpRequest en cours | Certains navigateurs ne mettent pas la page en cache | Laissez les requêtes se terminer ou annulez-les sur pagehide |
| Connexion WebSocket ou WebRTC ouverte | Bloque dans certains navigateurs ; Chrome 149 et suivants et Safari ne bloquent pas sur les WebSockets ouverts | Fermez-la sur pagehide |
Certains échecs n'ont rien à voir avec votre code. web.dev liste des navigations arrière ou avant qui n'utilisent pas le bfcache "when the user quits the browser and starts it again," "when the user duplicates a tab," et "when the user closes a tab and reopens it," et note que les navigateurs suppriment les pages en cache au bout d'un certain temps pour économiser de la mémoire. Un taux de réussite de 100% n'est pas un objectif réaliste.
Les iframes suivent la page principale. Une iframe n'est pas mise en cache séparément, et une iframe qui utilise une API bloquante peut exclure toute la page du bfcache.
Comment pageshow et pagehide signalent-ils le bfcache ?
Les événements pageshow et pagehide signalent le bfcache via leur propriété persisted. Sur pageshow, persisted vaut true quand la page revient du bfcache et false lors d'un chargement normal. Sur pagehide, persisted à true signifie que le navigateur a l'intention de mettre la page en cache, même si web.dev souligne que cela "doesn't guarantee that a page will be cached."
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 "fires right after the load event when the page is initially loading and any time the page is restored from bfcache." Ce détail compte pour l'analytics, comme le montre la section suivante. Les navigateurs Chromium déclenchent aussi les événements Page Lifecycle freeze et resume quand une page entre dans le bfcache et en sort, mais web.dev souligne que mesurer votre taux de réussite du bfcache nécessite pageshow.

Pourquoi l'analytics rate-t-il ou compte-t-il deux fois les navigations arrière ?
L'analytics rate les navigations arrière parce qu'une restauration depuis le bfcache ne réexécute pas les scripts de la page, donc un tracker qui envoie sa page vue au chargement reste muet. web.dev prévient les propriétaires de sites qu'ils peuvent constater "a decrease in the total number of pageviews reported as Chrome enables bfcache for more users," et ajoute que beaucoup de sites sont "already underreporting pageviews from other browsers that implement bfcache, because many popular analytics libraries don't measure bfcache restores as new pageviews."
Le double comptage vient de la correction inverse, faite sans précaution. Comme pageshow se déclenche aussi à chaque chargement normal, un écouteur qui envoie une page vue à chaque pageshow sans vérifier persisted envoie deux pages vues par chargement : une au démarrage normal du tracker, une depuis l'écouteur.
D'autres distorsions découlent du même mécanisme :
Tableau de bord en temps réel
Suivi des objectifs
Suivi sans cookies
- Des trous dans l'engagement. Les minuteurs en pause reprennent à la restauration, donc les minuteurs d'engagement et les heartbeats sautent le temps que la page a passé en mémoire.
- Des événements de sortie jamais envoyés. Une page qui entre dans le bfcache ne déclenche jamais
unload. Le guide beforeunload vs pagehide explique pourquoi les beacons de sortie doivent plutôt se placer surpagehideetvisibilitychange. - Des pages plus rapides qui paraissent plus lentes. web.dev explique que les restaurations remplacent les visites répétées, qui comptent parmi les chargements de page les plus rapides d'un jeu de données, donc les données de temps de chargement penchent vers le lent alors même que les visiteurs ont eu une expérience plus rapide.
- Des comptes mélangés. Une navigation arrière qui rate le bfcache provoque un rechargement complet et est comptée, alors qu'une navigation qui l'atteint ne l'est pas. Le même enchaînement de clics produit des chiffres différents selon l'éligibilité.
Le guide pages vues, sessions et utilisateurs montre comment ces écarts se répercutent sur les métriques par session.
- Le tracker envoie la page vue au chargement
- Une restauration depuis le bfcache ne déclenche pas load
- Le clic retour n'est jamais compté
- pageshow se déclenche aussi à chaque chargement normal
- Chaque chargement envoie deux pages vues
- Les restaurations sont comptées, mais les chargements sont doublés
- L'écouteur n'envoie que si event.persisted vaut true
- Un chargement normal reste à une page vue
- Chaque restauration en ajoute exactement une
Comment compter correctement les restaurations depuis le bfcache ?
Vous comptez les restaurations depuis le bfcache en ajoutant un écouteur pageshow qui n'envoie une page vue que lorsque event.persisted vaut true, puis en vérifiant que chaque clic sur Précédent produit exactement un hit.
- Ajouter l'écouteur. L'exemple Google Analytics de web.dev envoie
gtag('event', 'page_view')dansif (event.persisted)et laisse le chargement normal à la page vue par défaut. - Marquer le type de navigation. Pour mesurer votre taux de réussite, web.dev désactive la page vue par défaut avec
send_page_view: false, en envoie une avecnavigation_typetiré deperformance.getEntriesByType('navigation')[0].type, et envoienavigation_type: 'back_forward_cache'lors des restaurations. Comparez les comptesback_forwardetback_forward_cache. - Lancer le test DevTools. Dans Chrome DevTools, ouvrez Application, puis Back-forward Cache, et cliquez sur Run Test. Un succès affiche "Restored from back-forward cache" ; un échec liste les raisons et marque celles qui sont corrigeables comme Actionable.
- Collecter les raisons sur les vraies visites. La propriété
notRestoredReasonsde l'entrée de navigation timing indique pourquoi une page n'a pas été restaurée. La documentation de Chrome précise qu'elle "has shipped from Chrome 123," avec des raisons commeunload-listeneretresponse-cache-control-no-store. - Corriger les blocages. Remplacez
unloadparpagehide, retirezno-storedes pages qui ne sont pas sensibles, et fermez les connexions IndexedDB ou WebSocket surpagehide.
Les métriques de performance demandent le même soin. web.dev explique que des outils comme le Chrome User Experience Report traitent les restaurations comme des visites de page distinctes, et que la bibliothèque web-vitals prend en charge les restaurations. Lors d'une restauration, le Largest Contentful Paint est mesuré de l'horodatage de pageshow à l'image suivante affichée, tandis que le Cumulative Layout Shift et l'INP repartent à 0.
Comment le bfcache affecte-t-il les données de Flowsery ?
La documentation de Flowsery ne décrit pas la façon dont son tracker traite une restauration depuis le bfcache, alors testez-le sur votre propre site avant d'ajouter du code. La vue analytics en temps réel de Flowsery affiche chaque page vue sur votre tableau de bord au moment où elle se produit, ce qui rend le test rapide : ouvrez une page, cliquez sur un lien, revenez en arrière et regardez si la page restaurée apparaît comme une nouvelle page vue. Lancez d'abord le test bfcache de DevTools pour savoir que la page a été restaurée et non rechargée. Si les restaurations n'apparaissent pas et que vous voulez les compter, le SDK npm de Flowsery expose une méthode trackPageview() que vous pouvez appeler depuis un écouteur pageshow qui vérifie event.persisted, ce qui évite le double comptage qu'entraînerait un écouteur sans cette vérification.
Questions fréquentes
Tous les navigateurs ont-ils un bfcache ?
Oui, tous les grands navigateurs en intègrent un. web.dev cite Chrome depuis la version 96, Firefox et Safari. Chaque navigateur a ses propres règles d'éligibilité, ce qui explique qu'une même page puisse être mise en cache dans un navigateur et rechargée dans un autre.
Une restauration depuis le bfcache déclenche-t-elle l'événement load ?
Non. Une restauration rend la page en pause de nouveau visible et reprend son JavaScript, donc load et DOMContentLoaded ne se déclenchent pas. L'événement pageshow se déclenche, avec persisted à true.
Pourquoi mes pages vues ont-elles baissé quand Chrome a étendu le bfcache ?
Davantage de clics sur Précédent et Suivant sont devenus des restaurations au lieu de rechargements, et beaucoup de scripts d'analytics ne comptent les pages vues qu'au chargement. web.dev décrit exactement cette baisse. Ajoutez un écouteur pageshow qui envoie une page vue quand event.persisted vaut true si vous voulez compter les restaurations.
Cache-Control: no-store désactive-t-il le bfcache ?
Placé sur la page elle-même, il a historiquement exclu les pages du bfcache. web.dev recommande de ne l'utiliser que pour les pages contenant des informations sensibles, et d'utiliser no-cache ou max-age=0 pour les pages qui ont seulement besoin d'un contenu frais. Aucune de ces deux options n'affecte l'éligibilité.
Comment vérifier si une page est éligible au bfcache ?
Dans Chrome DevTools, allez dans Application, puis Back-forward Cache, et cliquez sur Run Test. Le panneau indique si la page a été restaurée et liste les raisons du blocage si ce n'est pas le cas. Pour les vraies visites, lisez notRestoredReasons dans l'entrée de navigation timing.
Le bfcache fonctionne-t-il à l'intérieur d'une application monopage ?
Non. web.dev indique que le bfcache "doesn't work for 'soft navigations' within a single-page app." Il s'applique quand un visiteur quitte l'application et y revient avec le bouton Précédent, ce qui peut restaurer toute l'application au lieu de la relancer de zéro si la page y est éligible.
Que deviennent les minuteurs et les heartbeats pendant qu'une page est dans le bfcache ?
Les navigateurs mettent en pause les minuteurs en attente et les promesses non résolues, puis les relancent à la restauration. Un heartbeat ou un minuteur d'engagement reprend après la pause, donc le temps passé en mémoire n'est pas compté comme de l'engagement.
Un écouteur unload empêche-t-il une page d'entrer dans le bfcache ?
Oui, dans Chrome et Firefox sur ordinateur, et dans Firefox sur mobile sauf sous iOS. Remplacez unload par pagehide et la page reste éligible.
Comment éviter de compter les pages vues en double avec un écouteur pageshow ?
pageshow se déclenche à chaque chargement normal comme à chaque restauration, donc n'envoyez la page vue que lorsque event.persisted vaut true. Le démarrage normal du tracker couvre déjà le chargement ordinaire. Appuyez ensuite sur retour depuis une page de test et vérifiez que chaque clic produit exactement un hit.
Flowsery compte-t-il automatiquement les restaurations depuis le bfcache ?
La documentation de Flowsery ne le décrit pas, testez-le donc sur votre propre site. Ouvrez une page, cliquez sur un lien, appuyez sur retour et regardez dans la vue d'analytics en temps réel si une nouvelle page vue apparaît. Si rien n'apparaît, appelez trackPageview() du SDK npm dans un écouteur pageshow qui vérifie event.persisted.
Cet article vous a-t-il été utile ?
Dites-nous ce que vous en pensez !
Nous voir plus souvent sur Google
Un clic définit Flowsery comme source préférée. Nos articles remontent alors dans vos À la une, en mode IA et dans les aperçus IA.
Avant de partir...
Flowsery
Des analyses orientées revenus pour votre site web
Suivez chaque visiteur, source et conversion en temps réel. Simple, puissant et sans cookies.
Tableau de bord en temps réel
Suivi des objectifs
Suivi sans cookies
Termes connexes du glossaire
Comment le suivi des SPA compte les pages vues quand la page ne se recharge jamais
Un bon suivi des SPA, c'est une page vue par écran avec le bon référent. Comment s'articulent l'API History, les pages vues virtuelles et GA4.


Pourquoi votre taux de rebond GA4 n'est que le taux d'engagement inversé
Votre taux de rebond GA4 est la part des sessions non engagées. Sa définition par Google, l'écart avec Universal Analytics et où l'ajouter aux rapports.


Ce que compte le rapport des pages de destination GA4 et où il reste vide
Dans Google, le rapport des pages de destination GA4 liste la première page de chaque session. Où le trouver, ses métriques, les lignes (not set) et la source.


Comment le suivi de la recherche sur le site GA4 enregistre ce que tapent les visiteurs
Activez la recherche sur le site GA4 via la mesure améliorée, ajoutez vos paramètres, lisez la dimension Search term et suivez les recherches sans URL.


Définir des propriétés utilisateur GA4 et en tirer des rapports
Définissez les propriétés utilisateur GA4 avec gtag ou Tag Manager, déclarez-les en dimensions personnalisées et restez sous la limite des 25 propriétés.


Comment associer Search Console à GA4 et publier ses rapports
Apprenez à associer Search Console à GA4 dans Admin, les rôles requis, comment publier les deux rapports dans Library et ce que les données ne croisent pas.
Articles connexes


Ce qu'est devenu l'abandon des cookies tiers dans Chrome
Dans Chrome, l'abandon des cookies tiers est passé d'un plan en 2020 à un revirement en 2025. Chaque annonce de Google, ce que fait Chrome aujourd'hui.


Pourquoi le CNAME cloaking ne cache plus les traqueurs à Safari ni à Brave
Le CNAME cloaking déguise un traqueur en sous-domaine de votre site. L'astuce DNS, le plafond de 7 jours de Safari, et comment Brave et uBlock le démasquent.


Comment le cookie syncing associe les ID publicitaires d'un site à l'autre
L'ad tech utilise le cookie syncing pour échanger des ID via redirections et pixels. Safari, Firefox et Chrome face à lui, et pourquoi l'analytics s'en passe.

