Single Page Applications have always been a bit of an awkward fit for Core Web Vitals. And not because SPAs are inherently slow.
A browser historically only understands the first navigation of a page lifecycle. Everything after that became difficult to measure consistently.
Chromium is trying to change that with an API dedicated to detecting soft navigations. This API is currently experimental and available through an Origin Trial. For RUM providers, it improves attribution and changes how SPA performance can be measured.
Origin trials
Recently, Chrome Developers published the final Soft Navigations Origin Trial announcement, explaining how soft navigations are becoming part of the Core Web Vitals ecosystem.
At RUMvision, we joined Chrome's soft-navigation Origin Trial for a second time. The first one was back in 2023. We joined Chrome's final Soft Navigations origin trial on April 8th and shared one specific React case where their soft-navigations were not picked up yet.

Origin trials allow developers and RUM providers to try…
What soft navigations are not
Soft-navigations API is not yet another library or framework to build websites with. The purpose is to be baked into the browser so that it becomes available as a native API. This API is primarily a measurement and browser visibility improvement.
(not the) first origin trial
Speed Kit, amongst others, also participated in one of the earlier trials and shared feedback based on SPA versus MPA comparisons. Chromium fixed bugs and holes in the heuristics and task attribution model.
This is also why the latest trial is described as the final Origin Trial. This version incorporates feedback from previous trials and reflects the expected final API shape before release.
Why the web needs a native API
SPAs have been difficult for Core Web Vitals. Traditional Core Web Vitals were designed around a hard navigation lifecycle:
- The browser navigates
- The HTML document loads
- Metrics get measured
That still works well for multi-page applications. But modern SPAs behave differently:
- Route changes often happen without a full page reload
- UI updates are driven by JavaScript
- URLs change while the document remains alive
- Multiple “page views” can exist within a single document lifecycle
Browser do not expose these transitions as real navigations. So, RUM vendors tied navigations to History API methods such as history.pushState() and history.replaceState().
The soft-nav challenge
Chances are it still won’t detect every soft navigation out there. Considering the number of frameworks, routers and custom implementations on the web, not every URL and DOM change is something users would actually experience as a navigation.
In other words, knowing when to reset metrics remains a huge challenge.
That is exactly why browser-level heuristics matter. The same edge cases may still exist, but I expect them to become exceptions rather than the default. Because with a browser-native API:
- adoption by RUM providers gets easier, as they no longer have to build and maintain their own logic around History API methods.
- framework vendors get a clearer browser-level target to align with when their navigations are not detected yet
Why SPAs were hard to measure
In short, collected metrics would be logged against the last hard navigation, such as the session landing page (typically homepage) or a browser refresh. But issues could have occurred at the collection or even product page, instead of the homepage.
This could result in:
- LCP often only represented the first page
- INP became aggregated across unrelated screens
- Navigation attribution became blurry
- Route-level performance analysis became unreliable
This diagram visualizes that:

Google Search Console
As Core Web Vitals is an invention by the Google Chrome, you might expect Google tools to report this correctly.
That's not the case though. Even Google Search Console (GSC) can display misattributed data, since it sources this information from Google CrUX.

I covered CrUX misattribution for SPAs in GSC during my SEO Benelux presentation
GCS users might see moderate or even poor Core Web Vitals data for landing pages, while real users might have experienced issues across other pages they navigated to. The introduction of INP made this even more visible.
Because once interaction responsiveness became a Core Web Vital, SPA owners suddenly needed visibility into actual user journeys, not just initial page loads.
How Chromium is fixing this
The Soft Navigations API allows browsers to recognize SPA route transitions as navigations, by looking at a combination of URL and DOM changes.
That means metrics like LCP, INP and CLS can now be associated with individual soft navigations instead of only the initial hard navigation.
And that changes a lot for RUM tooling.
Web Vitals library
Luckily, Chrome also maintains the web-vitals.js library, where they introduced a soft-navs build.
The remaining challenge is attributing metrics to the correct (soft) navigation in their dataset. Because the moment multiple navigations can exist within a single document lifecycle, your entire beaconing and navigation model changes.
So we fully refurbished our tracking architecture for this and the first SPA shops in our dataset have already switched to our new version with soft-navigations enabled.
What changes for RUM tooling
Though self-inflicted because of using the fetchLater API, the implementation of soft-navigations came with challenges.
Multiple navigations inside a single page lifecycle
This was one of the biggest architectural changes. Request IDs are automatically regenerated for non-SPAs, as our tracking agent is executed from the start with every hard navigation.
Within SPAs, we have to look at the navigationId or reported metrics to determine to which request they belong in order to give site owners the correct visibility and filters.
Our new navigation model now supports:
- navigation-specific request IDs
- isolated metric attribution
- independent beacon buffering
- stale navigation eviction
- navigation-aware flushing strategies
The new SPA helper logic manages multiple concurrent navigations while preventing beacon duplication and stale state leakage.
TTFB becomes tricky for soft navs
One interesting side effect: The web-vitals library currently dispatches a 0ms TTFB for soft navigations. And that makes sense, because just like navigations from back-forward-cache, there is no actual network-level HTML navigation request happening during a client-side route transition.
But this also means that you cannot treat back-forward-cache nor soft-navigation TTFB the same way as hard-navigation TTFB. At RUMvision, we therefore exclude soft-navigation-related navigations from TTFB-based health checks.
For example:
- query-string impact analysis
- backend latency investigations
- cache effectiveness checks
- origin response diagnostics
Otherwise, 0ms TTFB values would heavily skew datasets and create misleading recommendations.
Beaconing also had to change
Soft navigations introduced another challenge: When do you actually send the beacon?
SPAs can stay alive for a very long time. So our new architecture separates:
- eager preflight beacons
- lifecycle metric updates
- late interaction metrics
- behavior tracking
- final unload flushing
The new flow:
- Sends an early beacon quickly
- Queues lifecycle metrics separately
- Expands or replaces pending beacons when needed
- Falls back gracefully when
fetchLater()is unavailable - Handles visibility/pagehide edge cases
This became especially important because:
- some browsers terminate tabs aggressively
- some platforms make
fetchLater()unusable (Shopify) - Safari event ordering behaves differently
- bfcache introduces additional lifecycle complexity
A large part of the new architecture focuses on making beacon delivery resilient without creating excessive network overhead.
Early SPA insights from our dataset
After enabling the Origin Trial, we immediately started seeing differences between navigation types inside real-world SPA traffic.
Here is an example of INP p75 segmented by navigation type:
And this is what we see:
- Mobile P75 data across different navigation types
- Of a single SPA, compared with (via the Trend column) collected data when the soft-navigations API was not used yet
- INP across normal navigations became 15.3% better, because higher INP values are now attributed to soft navigations
That might not be an expected result as many SPA frameworks have historically been advocating themselves as blazing-fast framework. On the other hand though, we never really knew about their responsiveness before INP was introduced.
Soft-Navigations API is enabling RUM tools (and their very own Google Chrome browser) to attribute such data against the correct pages.
In short: This is exactly the type of visibility SPA owners were previously missing.
What happens next?
RUM tools implementing the Soft Navigations API today are already able to expose more accurately attributed Core Web Vitals data. Eventually, more RUM tools will follow. But I don't expect changes to stop on RUM-side of things.
Browsers
Chromium describes this as the final Origin Trial phase. That signals two important things:
- The Chromium team received substantial feedback during earlier origin trials and refined the soft-navigation heuristics accordingly;
- The API is likely getting close to a stable browser release.
Browsers like FireFox and Safari already support LCP and INP. And based on how it changes data collected via improved attribution, it would surely get our vote for (maybe already) next year's Web Interopability to hopefully see it adopted beyond Chromium-only browsers.

At RUMvision, our focus is helping site owners make the…
Platforms and tooling
Over time, CrUX may start using these soft-navigation heuristics as well. That could eventually result in more accurately attributed CrUX data and more actionable reporting inside tools like Google Search Console. The exact timeline, however, is still unknown.
Soft navigations are not “just another metric”. They fundamentally change what a navigation means on the modern web.




