Avoiding Analytics Double Counting on Prerender

This guide is part of Speculative Loading & Prefetching, within Network & Server Response Optimization. When a browser prerenders a page, it runs the page's JavaScript in the background — including analytics. If the analytics script sends a page view immediately, every prerender counts as a visit, even when the user never navigates there. Page views inflate, bounce rates and session counts distort, ad impressions are recorded for ads nobody saw, and A/B tests log exposures for users who never saw the variant.

The browser exposes everything needed to fix this: document.prerendering is true while a page is being prerendered, the prerenderingchange event fires when it is activated, and the navigation timing entry's activationStart records when activation happened. Analytics, ads and experiments should wait for activation; performance metrics should be measured relative to it.

Prerender lifecycle and analytics Sequence showing a prerendered page deferring its page view until activation. Prerender lifecycle and analytics Browser Prerendered page Analytics prerender (hidden) document.prerendering = true user clicks → activate page view on prerenderingchange

Rapid Diagnosis

  • Compare page views with server-side navigation logs after enabling prerendering; a jump in page views without matching engagement suggests double counting.
  • Check analytics libraries' prerender support (many major ones already defer).
  • Test in DevTools: trigger a prerender (Speculative loads panel), and watch network requests from the hidden page for analytics hits before activation.
  • Check ad and experimentation scripts separately; they may not handle prerendering.

Root Cause Analysis

1. Scripts fire on load. Analytics send hits as soon as they execute.

2. Custom tracking. Hand-written beacons ignore prerender state.

3. Ads and experiments. Impression and exposure logging on load.

4. Performance metrics. Measuring from navigation start instead of activation produces misleading values.

Step-by-Step Resolution

1. Defer side effects until activation

javascript
export function onActivation(fn) {
  if (document.prerendering) {
    document.addEventListener('prerenderingchange', () => fn(), { once: true });
  } else {
    fn();
  }
}
onActivation(() => {
  analytics.pageView();
  experiments.logExposure();
});
// trade-off: work deferred to activation runs right after the page becomes visible;
// keep it light so it does not delay the first interactions.

2. Configure tag managers

Use triggers that wait for activation. Some tag managers provide prerender-aware triggers; otherwise, push a custom event from onActivation and fire page view tags on that event.

3. Measure performance from activation

The web-vitals library reports metrics relative to activationStart for prerendered pages and sets navigationType: 'prerender'. If you measure manually, subtract activationStart.

javascript
const nav = performance.getEntriesByType('navigation')[0];
const activation = nav.activationStart || 0;
new PerformanceObserver((list) => {
  const lcp = list.getEntries().at(-1);
  report({ lcp: Math.max(lcp.startTime - activation, 0), prerendered: activation > 0 });
}).observe({ type: 'largest-contentful-paint', buffered: true });

4. Segment reports

Report prerendered navigations separately in performance dashboards, so improvements from speculation are visible and do not hide regressions in normal loads.

What to defer until activation Script categories and whether they should run during prerender or wait for activation. What to defer until activation Script During prerender After activation Rendering and hydration run - Analytics page view defer send Ad requests and impressions defer load A/B exposure logging defer log Chat widgets, autoplay media defer start

Verification

Prerender a page in DevTools and confirm no analytics, ad or experiment requests leave the hidden page until you activate it. After activation, exactly one page view should be sent. In analytics, compare page view volume with server-side navigation logs before and after enabling speculation rules: the ratio should stay stable.

Worked Example: A Media Publisher

A publisher enabled moderate-eagerness prerendering for article links. Within a day, page views rose 23% while ad revenue per page view dropped and time-on-page fell — a signature of counting prerenders that were never activated. Their main analytics library already handled prerendering, but a custom engagement script and the ad stack fired on load. The team wrapped both in an activation helper and configured the ad library's prerender support. Page views returned to the pre-change trend (with a modest real increase from faster navigations), ad viewability metrics recovered, and LCP dashboards gained a "prerendered" segment showing 0.2-second LCP for those navigations.

Experiments and Personalisation

A/B testing during prerender has two concerns: exposure logging (defer until activation) and assignment stability (the variant chosen during prerender must match what the user sees, which it does since it is the same page instance). Server-side experiments that assign variants via cookies work naturally. Client-side experiments that modify the page should run during prerender — so the activated page already shows the variant — but log the exposure only on activation. Personalisation that depends on time-sensitive state (cart counts, notifications) may need a refresh on activation.

Page views vs server navigations after enabling prerender Bar chart comparing reported page views with server-side navigations before and after fixing prerender counting. Page views vs server navigations after enabling prerender Page views (scripts fire on load) 123% Server navigations (activated) 104% Page views (deferred to activation) 104%

Auditing Third-Party Scripts for Prerender Safety

List every script that runs on prerenderable pages and classify it: rendering (safe to run), measurement (defer until activation), monetisation (defer), engagement (defer), and anything with user-visible side effects (defer). For each third-party script, check the vendor's documentation for prerender support, then verify in DevTools by triggering a prerender and inspecting requests from the hidden page. Scripts that cannot be made prerender-aware can be loaded inside the activation helper instead of directly in the page, which defers their execution entirely until the user sees the page.

Reporting Metrics for Prerendered Navigations

Performance dashboards should treat prerendered navigations as a separate category. Their LCP values are often under 100ms, which is correct from the user's point of view but very different from normal loads. Mixing them in a single distribution makes the overall p75 improve as speculation coverage grows, which can mask regressions in non-speculated loads. Report the share of prerendered navigations, the metrics for each navigation type, and the overall distribution together, so trends in each remain visible and a regression in one is never hidden by gains in another.

Common Mistakes

  • Assuming all scripts handle prerendering. Check each analytics, ad and experiment script.
  • Deferring rendering work. Only side effects should wait; rendering should complete in the prerender.
  • Measuring LCP from navigation start. Produces large, meaningless values for prerendered pages.
  • Not segmenting. Mixed data hides both the benefit and regressions.

Edge Cases

Pages never activated. They are discarded without sending anything — the intended outcome.

Back/forward cache. Restores from bfcache are separate; page views on bfcache restore use the pageshow event with persisted.

Server-side analytics. Server logs see prerender requests (with Sec-Purpose); exclude or tag them.

Consent management. Consent prompts should not appear in a prerendered page before activation; defer them too.

FAQ

Do prerendered pages run JavaScript?

Yes. They load and execute scripts in the background, which is why side effects must wait for activation.

Does Google Analytics handle prerendering?

Major analytics libraries, including Google's, defer page views until activation. Verify your configuration and any custom tags.

How do I detect a prerendered page?

Check document.prerendering during load, listen for prerenderingchange, or check activationStart > 0 in the navigation entry after activation.

How should LCP be measured for prerendered pages?

Relative to activationStart. The web-vitals library does this automatically.

Do prefetches cause double counting?

No. Prefetch only downloads the document without running scripts.

Should ads load during prerender?

No. Ad requests and impressions should wait for activation, both for accuracy and to avoid wasting ad inventory.

What about server-side tracking pixels in HTML?

Image pixels in the HTML load during prerender. Move them behind the activation helper or identify prerender requests server-side.

Can I test this without real traffic?

Yes. Use DevTools to trigger prerenders and inspect network activity from the hidden page before activation.

Do session replay tools handle prerendering?

Check each vendor. Session recording should start on activation; otherwise it may record a session for a page nobody saw.

Will unused prerenders appear in server logs?

Yes. The HTML request is made, carrying a Sec-Purpose header. Filter or tag those requests in log-based analytics.