Glosario

Qué hace la bfcache con la navegación hacia atrás y tus páginas vistas

Taras Shynkarenko
Taras Shynkarenko
•Actualizado: •9 min de lectura
Qué hace la bfcache con la navegación hacia atrás y tus páginas vistasQué hace la bfcache con la navegación hacia atrás y tus páginas vistas

TL;DR, Respuesta rápida

9 min de lectura

La bfcache (caché de avance y retroceso) guarda en memoria una instantánea completa de una página cuando el visitante sale de ella, así que un clic en atrás o adelante la restaura al instante sin recargarla. Chrome, Firefox y Safari tienen una. Como la página no vuelve a cargarse, un script de analítica que solo cuenta páginas vistas al cargar no registra la restauración. Escucha pageshow y comprueba event.persisted para contar las restauraciones, y evita los listeners de unload, Cache-Control: no-store y las conexiones abiertas que hacen que una página no sea apta.

¿Qué es la bfcache?

La bfcache, abreviatura de back/forward cache o caché de avance y retroceso, es una optimización del navegador que guarda en memoria una instantánea completa de una página cuando el visitante sale de ella, de modo que un clic en atrás o adelante restaura esa página al instante en lugar de cargarla de nuevo. web.dev la define como "a browser optimization that enables instant back and forward navigation," y describe el mecanismo: "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."

Todos los navegadores principales tienen una: Chrome desde la versión 96, Firefox y Safari. Los clics en atrás y adelante son una parte grande de la navegación. web.dev informa de que "Chrome usage data shows that 1 in 10 navigations on desktop and 1 in 5 on mobile are either back or forward."

Para la analítica, lo importante es lo que no ocurre en una restauración. No se pide HTML, ningún script se ejecuta desde el principio y no se dispara ningún evento load. Tu tracker se despierta exactamente donde se quedó pausado.

Un libro abierto con un marcapáginas que guarda el lugar, como una página en pausa en memoria que se retoma donde se dejó.

¿En qué se diferencia la bfcache de la caché HTTP?

La bfcache guarda la página viva entera, mientras que la caché HTTP guarda respuestas individuales. web.dev lo explica así: "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." Una página servida desde la caché HTTP sigue cargándose: el navegador analiza el HTML, ejecuta todos los scripts y dispara load, así que tu tracker envía una página vista normal. Una página restaurada desde la bfcache se salta todo eso.

Los temporizadores y las promesas también se pausan. web.dev señala que "browsers pause any pending timers or unresolved promises for pages in bfcache" y los reanudan al restaurar, así que un heartbeat o un temporizador de interacción continúa después del hueco en lugar de contarlo.

¿Qué páginas son aptas para la bfcache?

Una página es apta para la bfcache salvo que algo en ella haga inseguro guardarla, y los bloqueos más comunes dependen de ti. La tabla recoge los que señalan web.dev y la documentación de Chrome.

BloqueoEfecto en la bfcacheSolución
Listener de unloadNo apta en Chrome y Firefox de escritorio; en Firefox también en móvil salvo iOSUsa pagehide en su lugar
Cache-Control: no-store en la páginaHistóricamente deja la página fuera de la bfcacheUsa no-cache o max-age=0 salvo que la página sea sensible
Listener de beforeunload incondicionalYa no bloquea en los navegadores modernos, pero antes sí, según web.devAñádelo solo mientras haya cambios sin guardar
Referencia a window.openerUna página con un opener no nulo "can't safely be put into bfcache"Usa rel="noopener"
Conexión IndexedDB abiertaAlgunos navegadores no guardan la páginaCiérrala en pagehide y vuelve a abrirla en pageshow
fetch() o XMLHttpRequest en cursoAlgunos navegadores no guardan la páginaDeja que las peticiones terminen o cancélalas en pagehide
Conexión WebSocket o WebRTC abiertaBloquea en algunos navegadores; Chrome 149 y posteriores y Safari no bloquean con WebSockets abiertosCiérrala en pagehide

Algunos fallos no tienen nada que ver con tu código. web.dev enumera navegaciones hacia atrás o adelante que no usan la bfcache "when the user quits the browser and starts it again," "when the user duplicates a tab," y "when the user closes a tab and reopens it," y señala que los navegadores descartan las páginas guardadas pasado un tiempo para ahorrar memoria. Una tasa de aciertos del 100% no es un objetivo realista.

Los iframes siguen a la página principal. Un iframe no se guarda por separado, y un iframe que usa una API bloqueante puede dejar la página entera fuera de la bfcache.

¿Cómo informan pageshow y pagehide sobre la bfcache?

Los eventos pageshow y pagehide informan sobre la bfcache mediante su propiedad persisted. En pageshow, persisted vale true cuando la página vuelve de la bfcache y false en una carga normal. En pagehide, que persisted valga true significa que el navegador tiene intención de guardar la página, aunque web.dev insiste en que eso "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." Ese detalle importa para la analítica, como muestra la siguiente sección. Los navegadores basados en Chromium también disparan los eventos de Page Lifecycle freeze y resume cuando una página entra en la bfcache y sale de ella, pero web.dev señala que medir tu tasa de aciertos de la bfcache requiere pageshow.

Viajeros cruzando un torniquete, donde quien vuelve sin ser detectado no se cuenta, como una navegación hacia atrás que la analítica pasa por alto.

¿Por qué la analítica pierde o cuenta dos veces las navegaciones hacia atrás?

La analítica pierde las navegaciones hacia atrás porque una restauración desde la bfcache no vuelve a ejecutar los scripts de la página, así que un tracker que envía su página vista al cargar no dice nada. web.dev avisa a los propietarios de sitios de que pueden notar "a decrease in the total number of pageviews reported as Chrome enables bfcache for more users," y añade que muchos sitios ya están "already underreporting pageviews from other browsers that implement bfcache, because many popular analytics libraries don't measure bfcache restores as new pageviews."

El doble conteo viene de aplicar sin cuidado el arreglo contrario. Como pageshow también se dispara en cada carga normal, un listener que envía una página vista en cada pageshow sin comprobar persisted envía dos páginas vistas por carga: una del arranque normal del tracker y otra del listener.

Del mismo mecanismo salen otras distorsiones:

Flowsery
Flowsery

Empieza tu prueba gratis de 14 días

Panel en tiempo real

Seguimiento de objetivos

Rastreo sin cookies

  • Huecos en la interacción. Los temporizadores pausados se reanudan al restaurar, así que los temporizadores de interacción y los heartbeats se saltan el tiempo que la página pasó en memoria.
  • Eventos de salida que nunca se envían. Una página que entra en la bfcache nunca dispara unload. La guía de beforeunload frente a pagehide explica por qué los beacons de salida deben ir en pagehide y visibilitychange.
  • Páginas más rápidas que parecen más lentas. web.dev explica que las restauraciones sustituyen a las visitas repetidas, que están entre las cargas de página más rápidas de un conjunto de datos, así que los datos de tiempo de carga se inclinan hacia lo lento aunque los visitantes hayan tenido una experiencia más rápida.
  • Recuentos mezclados. Una navegación hacia atrás que no usa la bfcache hace una recarga completa y se cuenta, mientras que una que sí la usa no se cuenta. El mismo patrón de clics produce cifras distintas según la aptitud de la página.

La guía de páginas vistas frente a sesiones frente a usuarios muestra cómo estos huecos se trasladan a las métricas por sesión.

Tres formas de tratar un clic hacia atrás
Sin listener de pageshow
  • El tracker envía la página vista al cargar
  • Una restauración desde la bfcache no dispara load
  • El clic hacia atrás nunca se cuenta
pageshow sin comprobación
  • pageshow también se dispara en cada carga normal
  • Cada carga envía dos páginas vistas
  • Las restauraciones se cuentan, pero las cargas se duplican
pageshow con comprobación de persisted
  • El listener envía solo cuando event.persisted es true
  • Una carga normal se queda en una página vista
  • Cada restauración suma exactamente una
Solo la comprobación de persisted cuenta cada clic hacia atrás exactamente una vez.

¿Cómo cuentas correctamente las restauraciones desde la bfcache?

Las restauraciones desde la bfcache se cuentan añadiendo un listener de pageshow que envía una página vista solo cuando event.persisted vale true, y comprobando después que cada clic en atrás produce exactamente un hit.

  1. Añade el listener. El ejemplo de Google Analytics de web.dev envía gtag('event', 'page_view') dentro de if (event.persisted) y deja la carga normal a la página vista predeterminada.
  2. Etiqueta el tipo de navegación. Para medir tu tasa de aciertos, web.dev desactiva la página vista predeterminada con send_page_view: false, envía una con navigation_type a partir de performance.getEntriesByType('navigation')[0].type y envía navigation_type: 'back_forward_cache' en las restauraciones. Compara los recuentos de back_forward con los de back_forward_cache.
  3. Ejecuta la prueba de DevTools. En Chrome DevTools, abre Application, después Back-forward Cache, y haz clic en Run Test. Si pasa, verás "Restored from back-forward cache"; si falla, se listan los motivos y se marcan como Actionable los que puedes corregir.
  4. Recoge los motivos de visitas reales. La propiedad notRestoredReasons de la entrada de navigation timing indica por qué no se restauró una página. La documentación de Chrome dice que "has shipped from Chrome 123," con motivos como unload-listener y response-cache-control-no-store.
  5. Corrige los bloqueos. Sustituye unload por pagehide, quita no-store de las páginas que no son sensibles y cierra las conexiones IndexedDB o WebSocket en pagehide.

Las métricas de rendimiento necesitan el mismo cuidado. web.dev explica que herramientas como el Chrome User Experience Report tratan las restauraciones como visitas de página separadas, y que la librería web-vitals admite las restauraciones. En una restauración, el Largest Contentful Paint se mide desde la marca de tiempo de pageshow hasta el siguiente fotograma pintado, mientras que el Cumulative Layout Shift y el INP vuelven a 0.

¿Cómo afecta la bfcache a los datos de Flowsery?

La documentación de Flowsery no describe cómo trata su tracker una restauración desde la bfcache, así que pruébalo en tu propio sitio antes de añadir código. La vista de analítica en tiempo real de Flowsery muestra cada página vista en tu panel en el momento en que ocurre, lo que hace la comprobación rápida: abre una página, haz clic en un enlace, pulsa atrás y mira si la página restaurada aparece como una página vista nueva. Ejecuta antes la prueba de bfcache de DevTools para saber que la página se restauró y no se recargó. Si las restauraciones no aparecen y quieres contarlas, el SDK de npm de Flowsery expone un método trackPageview() que puedes llamar desde un listener de pageshow que compruebe event.persisted, lo que evita el doble conteo que provocaría un listener sin esa comprobación.

Preguntas frecuentes

¿Todos los navegadores tienen bfcache?

Sí, todos los navegadores principales incluyen una. web.dev cita Chrome desde la versión 96, Firefox y Safari. Cada navegador tiene sus propias reglas de aptitud, y por eso la misma página puede guardarse en un navegador y recargarse en otro.

¿Una restauración desde la bfcache dispara el evento load?

No. Una restauración vuelve a hacer visible la página pausada y reanuda su JavaScript, así que load y DOMContentLoaded no se disparan. Se dispara el evento pageshow, con persisted a true.

¿Por qué bajaron mis páginas vistas cuando Chrome amplió la bfcache?

Más clics en atrás y adelante pasaron a ser restauraciones en lugar de recargas, y muchos scripts de analítica solo cuentan páginas vistas al cargar. web.dev describe exactamente esta caída. Añade un listener de pageshow que envíe una página vista cuando event.persisted valga true si quieres contar las restauraciones.

¿Cache-Control: no-store desactiva la bfcache?

En la propia página, históricamente ha dejado las páginas fuera de la bfcache. web.dev recomienda usarlo solo en páginas con información sensible, y usar no-cache o max-age=0 en las páginas que solo necesitan contenido actualizado. Ninguna de esas dos opciones afecta a la aptitud.

¿Cómo compruebo si una página es apta para la bfcache?

En Chrome DevTools, ve a Application, después a Back-forward Cache, y haz clic en Run Test. El panel indica si la página se restauró y, si no, lista los motivos del bloqueo. Para visitas reales, lee notRestoredReasons de la entrada de navigation timing.

¿La bfcache funciona dentro de una aplicación de una sola página?

No. web.dev afirma que la bfcache "doesn't work for 'soft navigations' within a single-page app." Se aplica cuando un visitante sale de la app y vuelve con el botón atrás, lo que puede restaurar la app entera en lugar de arrancarla desde cero si la página cumple los requisitos.

¿Qué pasa con los temporizadores y los heartbeats mientras una página está en la bfcache?

Los navegadores pausan los temporizadores pendientes y las promesas sin resolver, y los reanudan al restaurar. Un heartbeat o un temporizador de interacción continúa después del hueco, así que el tiempo que la página pasó en memoria no cuenta como interacción.

¿Un listener de unload deja una página fuera de la bfcache?

Sí, en Chrome y Firefox de escritorio, y en Firefox móvil salvo en iOS. Sustituye unload por pagehide y la página sigue siendo apta.

¿Cómo evito contar páginas vistas dos veces con un listener de pageshow?

pageshow se dispara en cada carga normal y en cada restauración, así que envía la página vista solo cuando event.persisted sea true. El arranque normal del tracker ya cubre la carga habitual. Después pulsa atrás en una página de prueba y comprueba que cada clic genera exactamente un registro.

¿Flowsery cuenta automáticamente las restauraciones desde la bfcache?

La documentación de Flowsery no lo describe, así que pruébalo en tu propio sitio. Abre una página, haz clic en un enlace, pulsa atrás y mira en la vista de analítica en tiempo real si aparece una página vista nueva. Si no aparece, llama a trackPageview() del SDK de npm dentro de un listener de pageshow que compruebe event.persisted.

¿Te resultó útil este artículo?

¡Cuéntanos qué opinas!

Vernos más en Google

Un clic marca Flowsery como fuente preferida y nuestros artículos aparecen más arriba en tus Noticias destacadas, el modo IA y los resúmenes con IA.

Antes de irte...

Flowsery

Flowsery

Analítica orientada a ingresos para tu sitio web

Rastrea cada visitante, fuente y conversión en tiempo real. Simple, potente y sin cookies.

Panel en tiempo real

Seguimiento de objetivos

Rastreo sin cookies

Términos relacionados del glosario

Cómo el tracking de SPA cuenta páginas vistas si la página nunca se recargaCómo el tracking de SPA cuenta páginas vistas si la página nunca se recarga
Glosario

Cómo el tracking de SPA cuenta páginas vistas si la página nunca se recarga

Un buen tracking de SPA registra una página vista por pantalla con el referrer correcto. Cómo encajan la History API, las vistas virtuales y GA4.

•9 min de lectura
Por qué tu tasa de rebote de GA4 es la tasa de interacción al revésPor qué tu tasa de rebote de GA4 es la tasa de interacción al revés
Glosario

Por qué tu tasa de rebote de GA4 es la tasa de interacción al revés

Google mide la tasa de rebote de GA4 como la proporción de sesiones sin interacción. Cómo la define, en qué difiere de Universal Analytics y dónde añadirla.

•9 min de lectura
Qué cuenta el informe de páginas de destino de GA4 y dónde se queda en blancoQué cuenta el informe de páginas de destino de GA4 y dónde se queda en blanco
Glosario

Qué cuenta el informe de páginas de destino de GA4 y dónde se queda en blanco

En Reports, el informe de páginas de destino de GA4 lista la primera página de cada sesión. Dónde está, sus métricas, por qué sale (not set) y la fuente.

•10 min de lectura
Cómo registra la búsqueda en el sitio de GA4 lo que escriben los visitantesCómo registra la búsqueda en el sitio de GA4 lo que escriben los visitantes
Glosario

Cómo registra la búsqueda en el sitio de GA4 lo que escriben los visitantes

Configura la búsqueda en el sitio de GA4 con la medición mejorada, añade tus parámetros de consulta, halla la dimensión Search term y mide sin URL.

•10 min de lectura
Cómo definir propiedades de usuario de GA4 y usarlas en informesCómo definir propiedades de usuario de GA4 y usarlas en informes
Glosario

Cómo definir propiedades de usuario de GA4 y usarlas en informes

Define propiedades de usuario de GA4 con gtag o Tag Manager, regístralas como dimensiones personalizadas de usuario y no pases del límite de 25.

•10 min de lectura
Cómo vincular Search Console con GA4 y publicar sus informesCómo vincular Search Console con GA4 y publicar sus informes
Glosario

Cómo vincular Search Console con GA4 y publicar sus informes

Aprende a vincular Search Console con GA4 en Admin, qué roles necesitas, cómo publicar los dos informes en Library y qué datos no se pueden cruzar.

•9 min de lectura

Artículos relacionados