The Speculation Rules API: making the click on a landing page's CTA truly instant
Published on 31 August 2026 · 8 min read
A visitor clicks a landing page's call-to-action button — "Book a demo," "Join the waitlist," "See pricing" — and the browser briefly holds on the previous page while the next one loads. A few hundred milliseconds, rarely more than a second: nothing that would drive off a determined visitor, but enough to introduce a micro-hesitation at exactly the moment it costs the most, right after the decision to click. Cutting that delay to zero hasn't just been a bandwidth question for a few years now — it's a browser API question, and Chrome's Speculation Rules API is currently the most complete tool for it.
What Next.js already preloads, and what it doesn't
Next.js's <Link> component automatically preloads, as soon as a link enters the viewport, the data for the target route (the React Server Components payload, or the cached static segment). That's already a real gain: at click time, the browser no longer needs to fetch that data over the network. But the preloading stops there — it doesn't build the page in an invisible tab, doesn't execute client-side JavaScript, doesn't paint anything on screen. At click time, hydration, script execution, and final render still have to happen in the time between the click and the display. For a standard internal navigation between two pages of the same Next.js app, the gap is already small. It becomes noticeable once the target page is heavier to hydrate, or falls outside what Next.js can prepare ahead of time — a payment page hosted on a different domain, for instance.
What the Speculation Rules API adds
The Speculation Rules API lets you declare, inside a <script type="speculationrules"> block, a list of URLs Chrome should prerender in the background: the target page is loaded, its JavaScript executes, it gets painted — exactly as if it were open in an invisible tab. On click, the browser simply "reveals" that already-ready tab in place of the old one, producing a navigation that feels instant, without the usual loading delay. It's the direct successor to the old (and now deprecated) <link rel="prerender">, with much finer control over when and what triggers the prerender.
Why that delay matters especially on a landing page
A study by Fiona Fui-Hoon Nah, published in 2004 in the journal Behaviour & Information Technology (available on Google Scholar), measured how long web users tolerate waiting before a page feels slow: roughly two seconds when no loading feedback is shown, a threshold that stretches when a progress indicator is present. That result matters especially here because a landing page is, by design, a single click away from its conversion — the demo booking page, the waitlist confirmation, the payment screen. That's precisely the navigation where this tolerance threshold is at stake, and the one a targeted prerender can push below the perception threshold rather than merely shorten.
Two trigger levels, two levels of risk
- "moderate" (on hover or
pointerdown): the prerender only fires once the visitor shows a real intent to click — the mouse hovers the link, or a finger touches the screen before release. This is the safest setting for a landing page: the number of pages prerendered for nothing stays low, and the time saved already covers most of the perceived delay. - "eager" (as soon as the link appears on screen): the prerender starts as soon as the call-to-action button enters the viewport, without waiting for an intent signal. The time saved is maximal if the visitor does click, but the cost in wasted bandwidth and server requests climbs quickly if many visitors never click — best reserved for pages where the click-through rate on that specific link is already known to be high.
Speculative prerendering isn't free
The idea of guessing ahead of time what a visitor will ask for, to serve it faster, isn't new: as early as 1995, a study by Azer Bestavros, presented at the ACM CIKM conference and focused on using speculation to reduce server load and service time on the Web (available on Google Scholar), already laid out the central trade-off of any predictive preloading strategy: anticipating a request the visitor never actually makes consumes bandwidth and server resources for nothing, and that cost grows with the number of speculated pages. On a landing page, that trade-off plays out concretely: every URL added to the speculation rules is a page potentially loaded, executed, and rendered for nothing if the visitor doesn't click — which is why it pays to keep the list limited to the exact conversion path rather than speculating on every link on the page.
Implementing it on a Next.js landing page
In practice, a speculation rules block gets added directly to the <head> generated by app/layout.tsx, targeting only the URL of the next conversion step:
<script type="speculationrules">
{
"prerender": [{
"urls": ["/checkout", "/thank-you"],
"eagerness": "moderate"
}]
}
</script>
Browser support currently remains limited to Chrome, Edge, and Opera (Chromium-based browsers) — Safari and Firefox silently ignore this block, with no error or regression. This is progressive enhancement in the strict sense: visitors on a browser that doesn't understand it simply fall back to normal behavior, Next.js prefetch included. It makes the most sense once the page targeted by the CTA falls outside what Next.js can already preload itself — a payment page hosted on a third-party domain, or a static page served outside the application.
Pitfalls to know before turning it on
- A prerendered page can run tracking scripts before it's ever actually seen. A Meta pixel or a GA4 event placed on page load fires as soon as the prerender happens, not on the real click — which can artificially inflate stats if many prerenders never get activated. Best practice is to listen for the
prerenderingchangeevent and only fire tracking once the page actually becomes visible. - A page with a side effect on load (generating a unique token, an API call that changes data) should never be added to the speculation rules without revisiting that behavior first: the prerender can run that code multiple times, or for visitors who never actually make the navigation.
- Chrome already respects data-saving mode (Data Saver, the
Save-Dataheader) and disables speculative prerendering on its own for affected visitors — a built-in safeguard that limits the risk of wasting a visitor's mobile data on a 3G connection, but that doesn't excuse leaving the list of targeted URLs anything but short and deliberate.
Across the ten LanderKit React/Next.js templates, this setting matters most on the single URL that actually counts: wherever the main call-to-action button points — the demo page for the SaaS Waitlist template, a signup confirmation, or a payment page. The gain stacks with the network optimizations already in place: our article on preconnect and preload covers preparing connections to third-party domains, while TTFB and LCP remain the metrics to watch to confirm the effect actually shows up in production, not just in theory. Deployment itself is covered in our guide on Next.js and Vercel.
FAQ
Frequently asked questions
What's the difference between Next.js's prefetch and the Speculation Rules API?
Next.js's prefetch downloads the route's data ahead of time (the React Server Components payload or static segment), but doesn't execute or paint the page. The Speculation Rules API goes further: it loads, executes the JavaScript, and renders the target page in an invisible tab before the click, making the navigation feel near-instant on activation.
Does the Speculation Rules API work in every browser?
No, only in Chromium-based browsers (Chrome, Edge, Opera) as of now. Safari and Firefox silently ignore the rules block, with no error: it's progressive enhancement, with no negative effect on browsers that don't yet support it.
Can speculative prerendering skew Google Analytics data?
It can, if a tracking event fires as soon as the page loads, before the visitor has actually seen it. The fix is to listen for the prerenderingchange event and only fire tracking once the page becomes visible, not at prerender time.
Should you enable speculation across the whole landing page, or just on the call-to-action button?
Just on the precise conversion path — the URL or URLs the main CTA points to. Speculating on every link on a page burns bandwidth and server resources on navigations many visitors will never make, a trade-off already documented in predictive preloading research going back to the 1990s.
Read next
Related articles
- Content-Security-Policy on a landing page: allowing GTM, Meta Pixel and Stripe without blocking everythingA landing page loads five to ten third-party scripts on average — GTM, Meta Pixel, a Google Ads conversion tag, a reviews widget, Stripe — and the browser runs every one of them with exactly the same trust it gives the site's own code. A Content-Security-Policy header changes that rule: it explicitly lists what is allowed to execute and blocks everything else by default. How to write one without breaking anything, and why the most common configuration protects against nothing at all.
- The View Transitions API on a Next.js landing page: useful fade or gimmick?Click a template card and the next page snaps into place with no visual thread connecting the image you just saw to the one that replaces it. The browser's View Transitions API, now controllable from Next.js without a third-party library, lets one visual element persist from one page to the next. Two studies on perceived waiting time and animation help explain where that fade actually helps, and where it's just a gimmick that slows the page down for nothing.
- Preconnect, preload, dns-prefetch: preparing connections before the browser needs themBefore a browser can download a single file, it has to resolve the domain name, open a TCP connection, and negotiate TLS encryption — three invisible network round trips, repeated for every third-party domain the page calls (a font, a chat widget, a video, a payment script). The dns-prefetch, preconnect, and preload resource hints let you get that work done before the browser even discovers it needs it. Used well, they shave hundreds of milliseconds off LCP; used carelessly, they slow down the very page they were meant to speed up.