Web Analytics
Nikhil Patel

October 19, 2026

How to Optimize Core Web Vitals in JavaScript-Heavy AI Applications

A story we hear from founders goes something like this. A small team adds an AI assistant to the help center of its product. The feature works well. Customers type questions, the model answers in a few seconds, and support tickets go down. A month or so later, someone opens Google Search Console and sees that the help center pages have slid from "Good" to "Poor."

Nothing looks broken. What changed is that the assistant brought a lot of baggage with it: a chat library, a markdown renderer, a code highlighter, an extra analytics script for tracking conversations, and a habit of redrawing the page dozens of times per second while an answer streams in.

That gap between "it works" and "it feels fast" is what Google's Core Web Vitals try to measure. AI features are very good at widening that gap, often in ways a quick speed test won't catch. This guide covers why that happens, how to fix each score, and what happens to those fixes when data goes missing, tools disagree, and real traffic arrives.

The three scores, explained for everyone

Core Web Vitals are three numbers Google collects from real Chrome users visiting your site. Each one stands in for a feeling a visitor has.

Largest Contentful Paint, or LCP, measures how long it takes for the biggest piece of content on the screen to appear. That is usually a headline, a large block of text, or a main image. To a visitor, it answers the question "has the page actually shown up yet?"

Interaction to Next Paint, or INP, measures how long the page takes to visibly react after someone clicks, taps, or types. It replaced an older metric called First Input Delay on March 12, 2024. The older metric only looked at the first interaction. INP watches every interaction during a visit and reports one of the slowest, which makes it much harder to game and much more relevant to chat-style apps where people interact constantly.

Cumulative Layout Shift, or CLS, measures how much things jump around on the screen without the user asking for it. Tapping a button and hitting an ad because the page moved is bad CLS.

Metric

What the visitor feels

Good

Needs improvement

Poor

LCP

"Is the page here yet?"

2.5 seconds or less

2.5 to 4 seconds

Over 4 seconds

INP

"Did my click do anything?"

200 milliseconds or less

200 to 500 milliseconds

Over 500 milliseconds

CLS

"Why did that move?"

0.1 or less

0.1 to 0.25

Over 0.25

One detail matters a lot for everything that follows. Google doesn't judge your page by its average visit. It looks at the 75th percentile over a rolling 28 days. Line up all your visits from fastest to slowest, and Google looks at the one three quarters of the way down. The people on older phones and weak connections decide your score. That is why Core Web Vitals for JavaScript applications so often look fine on a developer's machine and poor in Search Console.

Where the web stands right now

▸    The 2025 Web Almanac from HTTP Archive, using Chrome field data from July 2025, found that 48% of mobile sites and 56% of desktop sites pass all three Core Web Vitals.

▸    A separate DebugBear analysis of October 2025 Chrome data put the figures slightly higher, at 49.7% for mobile and 57.1% for desktop. The two reports use different months and slightly different methods, so treat the true figure as "roughly half."

▸    On mobile, LCP is the hardest score to pass (62% of sites), followed by INP (77%) and CLS (81%), according to the same Web Almanac chapter.

▸    The median mobile home page weighed 2,164 KB in 2025, and 98.1% of pages request at least one JavaScript file (HTTP Archive Web Almanac, 2025).

▸    A 2020 Deloitte study, "Milliseconds Make Millions," found that a 0.1 second improvement in mobile site speed lifted retail conversions by 8.4%. Google commissioned that study, so it has an interest in the result.

Why AI features are especially hard on these numbers

It helps to know about the browser's "main thread." Think of it as the only cashier in a shop, who has to draw the page, run your JavaScript, and respond to clicks. When the cashier is busy with a long job, everyone else in the queue waits, and the visitor sees a page that ignores their taps.

AI features hand that cashier several new jobs, often at the worst moment.

▪       Streaming answers arrive in small pieces called tokens, often many per second. If every token triggers a fresh update of the chat window, the main thread spends most of its time redrawing text.

▪       Many chat interfaces convert the model's markdown into formatted text on every update. Re-reading the entire message from the top each time means the work grows as the answer gets longer.

▪       Code highlighters, math renderers, and chart libraries make answers look good, but some of them are large and slow to run on cheaper phones.

▪       Some products run small models directly in the browser for privacy or cost reasons. These downloads can run from tens to hundreds of megabytes, and preparing them uses a lot of processing power.

▪       Nobody knows how long an answer will be until it finishes. That makes it hard to reserve space on the page, which is how layout shifts happen.

None of this means you should avoid AI features. It means you should treat Core Web Vitals for AI applications as their own problem. Many teams carry habits from years of Javascript Development into AI projects, such as putting every library in one bundle or re-rendering a whole component on any state change. With a model streaming text at the page, those habits get expensive.

Area

Typical JavaScript web app

JavaScript-heavy AI app

Where the main content comes from

Your database or a CMS, often cacheable

A model that may take seconds to respond, usually not cacheable

What keeps the main thread busy

Initial page setup, occasional clicks

Constant updates while answers stream, plus formatting work

How predictable the layout is

Mostly fixed sizes known in advance

Answer length and content type unknown until it finishes

Typical extra scripts

Analytics, ads, chat widget

All of those, plus AI SDKs, conversation tracking, renderers

How long people stay on one page

A minute or two, a few clicks

Long sessions with dozens of interactions on one page

Which score usually suffers first

LCP

INP, then CLS

Fixing LCP: get something meaningful on screen fast

The most common LCP mistake in AI products is letting the model's answer become the largest element on the page. If the biggest thing a visitor sees is generated text, your LCP time now includes the time your model provider takes to respond. A three-second model response guarantees a slow page no matter how lean your code is.

The fix is to send real, useful content before the AI responds: the page frame, headings, product details, or previous conversation, rendered on the server. The AI answer can stream in afterward. In most chat interfaces, the answer only starts after the user types a question, and LCP stops recording at the first interaction, so the streamed answer can't count against you. The risk sits with pages that generate text automatically on load. If that text block ends up bigger than everything else, it becomes the LCP element.

There are pages where the AI output really is the main content, such as an AI-written summary of a product or an article. For those, generate the text ahead of time, or generate it on the first request and store it so later visitors get a saved copy. A common approach is "stale while revalidate": serve the stored version immediately, and refresh it quietly in the background.

Other LCP fixes that matter more in AI apps:

▪       Load the chat code only when it's needed. A JavaScript feature called dynamic import lets you fetch the AI SDK and markdown renderer when someone opens the assistant, or when the browser is idle, instead of on page load.

▪       Don't make your server wait for the model before sending HTML. If your server-side code calls the model and waits, your Time to First Byte (the moment the first piece of the page reaches the browser) grows with every slow response. Send the page first and stream the answer separately.

▪       If the LCP element is an image, give it fetchpriority="high" and never lazy-load it. Lazy loading is great for images further down the page and harmful for the main one.

For Core Web Vitals for JavaScript applications built as single-page apps, there is one more catch. If the page ships an empty HTML file and builds everything with JavaScript, the browser has to download, read, and run your code before anything big appears. Server-side rendering or static generation for at least the first screen usually does more for LCP than any amount of code trimming.

Fixing INP: keep the page responsive while answers stream

INP is where most AI interfaces struggle, because the busiest moment on the page (an answer streaming in) is also when users interact most. They scroll, click "stop generating," or start typing the next question, and each action waits for the main thread.

Browsers treat any single job longer than 50 milliseconds as a "long task." Good INP depends on keeping those long tasks rare and short. Here are the changes that make the biggest difference.

Batch tokens instead of drawing each one

Tokens can arrive faster than a screen refreshes, so drawing each one wastes work. A simple fix is to collect tokens in a buffer and update the screen at most once per frame:

let buffer = "";

let scheduled = false;

 

function onToken(token) {

  buffer += token;

  if (!scheduled) {

    scheduled = true;

    requestAnimationFrame(() => {

      appendToMessage(buffer);

      buffer = "";

      scheduled = false;

    });

  }

}

requestAnimationFrame asks the browser to run the update right before it draws the next frame, so you get one update per frame instead of one per token. Some teams flush every 50 to 100 milliseconds instead, and readers rarely notice.

Only re-render what changed

New text should update only the last paragraph of the last message. Finished messages should stay frozen. In React, that means memoizing completed messages. For markdown, it means splitting the answer into blocks and only re-reading the block that's still growing. Code highlighting can wait until a code block is complete; showing it as plain text for two seconds is fine.

Move heavy work off the main thread

A Web Worker is a separate background thread that can run JavaScript without blocking the page. Markdown parsing, syntax highlighting, counting tokens in a pasted document, and running a small model in the browser can all happen in a worker.

Break up long jobs

Some work can't be moved. For those cases, split it into smaller pieces and let the browser handle user input between them. Chrome supports scheduler.yield() for exactly this purpose. Browsers that don't support it yet can fall back to a short setTimeout.

Respond to the click before the network does

INP measures the time from a click until the next visual update. It does not wait for your server. When a user presses Send, paint their message into the chat and show a "thinking" indicator immediately, then make the request. On chat pages, that one change often moves INP from poor to good. 

Good Core Web Vitals optimization also means looking at the scripts you added for business reasons. Conversation analytics, session recording tools, and A/B testing scripts all compete for the same main thread. Load them after the page settles, and question whether each one earns its cost.

Fixing CLS: give answers room before they arrive

Layout shift in AI apps usually comes from content appearing or growing above where the user is looking: answer bubbles that start at zero height, citation cards that pop in late, feedback buttons that appear at the end, and error banners added at the top.

A detail of how CLS works explains a lot here. Shifts that happen within 500 milliseconds of a user's click or keypress don't count, because the browser assumes the user expected something to change. Streaming answers often run for several seconds, so most of the growth happens long after that grace period. Whether those shifts count depends on whether they move content the user can see.

Practical fixes:

▪       Give the answer area a minimum height as soon as the user sends a question, and let it grow downward.

▪       Keep new content below what the user is reading. Content that pushes existing text down counts as a shift; content added underneath usually doesn't.

▪       Set width and height, or an aspect-ratio, for images, charts, and citation cards inside answers so the browser reserves space before they load.

▪       Reserve a slot for feedback buttons and "copy" controls from the start, even if they stay invisible until the answer completes.

▪       Use fixed positioning or CSS transforms for chat launcher bubbles and cookie banners so they float above the page instead of pushing it around.

CLS also behaves differently in long sessions. Chrome groups shifts into "session windows" of up to five seconds and reports the worst window. In a chat that runs for twenty minutes, one bad moment, such as an error message shoving the conversation down, can define the score for that whole visit. Testing Core Web Vitals for AI applications therefore means testing failure states as carefully as the happy path.

When the measurements are missing, wrong, or arguing with each other

Fixing a slow page is one problem. Knowing whether your fix worked is a separate one, and it is where many teams get stuck.

Data gaps

Google's field data comes from the Chrome User Experience Report, usually shortened to CrUX. It only includes Chrome users who share usage statistics, and it doesn't include iPhones and iPads, because Chrome on iOS runs on Apple's engine and doesn't report to CrUX. If most of your customers use iPhones, your Search Console score describes a minority of your audience.

Low-traffic pages may have no page-level data at all, so a new AI feature on a quiet page can hurt your site-wide score without ever showing up on its own. Pages behind a login rarely get their own record, yet they still feed into your site's overall numbers. And because the data covers a rolling 28 days, a fix you ship today won't fully show up for about four weeks.

Single-page apps add another blind spot. Field data records LCP only on a full page load. When someone moves between screens inside your app, no new LCP is recorded. INP and CLS, meanwhile, keep collecting for the whole visit. Chrome has been experimenting with measuring these in-app navigations, but you shouldn't assume your CrUX numbers reflect them.

The answer is your own measurement, called real user monitoring. Google's open-source web-vitals library reports all three scores from real visits, and its attribution build tells you which element or script caused the problem. Send that data to your analytics with labels for the model used, answer length, device type, and session length. This is the step that turns Core Web Vitals for JavaScript applications from a guessing game into something you can actually manage.

Conflicting signals

Sooner or later, your tools will disagree. These are the conflicts teams run into most:

What you see

Why it happens

What to trust

Lighthouse scores 95, Search Console says INP is poor

Lighthouse loads the page but never clicks anything, so it can't measure INP. It estimates with Total Blocking Time instead.

Field data

Your monitoring says INP is fine, CrUX says it isn't

Different mix of browsers and devices, different sampling, or your tool drops iPhone data less often

Compare on Chrome Android only, then decide

Server rendering fixed LCP but INP got worse

The page now sends more HTML and the browser spends longer "hydrating" it, which means attaching JavaScript to server-built HTML

Hydrate the chat later, or only hydrate interactive parts

Lazy loading the chat improved LCP, but the first click on "Ask AI" feels slow

The click now triggers a large download before anything appears

Open the panel instantly with a loading state, then fetch

Site-wide score passes, one page group fails

Busy pages hide weak ones in the average

Fix by template, not by URL

The general rule is that field data beats lab data. Lab tools are still useful for finding causes. They just can't tell you whether you passed.

Real-time decisions inside the browser

A fast AI app adjusts while it runs, based on what the device can handle:

Signal

What it tells you

A sensible decision

navigator.deviceMemory and hardwareConcurrency

Rough memory and processor count (Chromium browsers only)

On low-end devices, skip live code highlighting and flush tokens less often

navigator.connection.saveData

The user has asked to save data

Don't download an in-browser model; use the server

WebGPU availability

Whether the device can run graphics-card-powered AI in the browser

Run on-device inference only when it's available and memory allows

Long Animation Frames entries

Frames are taking too long to draw right now

Increase the batching interval for streamed text

Some of these signals don't exist in Safari or Firefox, so default to the cheaper experience when a value is missing. Getting this logic right is one of the places where teams that Hire AI Developers with front-end performance experience see results quickly, because the decisions touch the model, the network, and the interface at once.

Edge cases that break good scores

Core Web Vitals for AI applications tend to fail at the edges, in situations that never appear in a demo:

▪       Very long answers. A 400-row table or thousands of lines of code make every later interaction slower. Collapse long outputs behind a "show more" control.

▪       Background tabs. Browsers pause requestAnimationFrame in hidden tabs. Tokens pile up in the buffer, and when the user returns, the page tries to draw all of them at once, right when they're likely to click. Cap how much text you render per flush, or switch to timed flushing when document.hidden is true.

▪       The back button. Open streaming connections can stop a page from being saved in the browser's back/forward cache. Without that cache, pressing Back means a full reload and a fresh LCP. Close streams when the page is hidden and reopen them if the user comes back.

▪       Huge pastes. Counting tokens in a pasted document on every keystroke freezes the input. Move that work to a worker and debounce it.

▪       Screen readers. Announcing every token through a live region overwhelms assistive technology and adds work. Announce the answer once it's complete.

▪       Errors and retries. A timeout banner inserted at the top of the conversation is a layout shift. Show errors inside the space you already reserved for the answer.

How the system behaves under pressure and at scale

When a model provider slows down, any page that waits for the model before sending HTML slows down for every visitor at once. Set strict timeouts and send the page without the answer. Traffic spikes raise server rendering costs, so cache the parts of the page that are the same for everyone at the edge and fill in personal parts afterward.

Connections can also run out. Under the older HTTP/1.1 protocol, browsers open about six connections per site, so several tabs streaming answers can block your images and scripts. HTTP/2 or HTTP/3 avoids most of this.

In long sessions, memory use climbs and the browser pauses more often to clean up, so INP that looks fine at minute one can be poor at minute thirty. Group your monitoring data by session length to catch this.

Growth changes your scores too. Because Google scores the 75th percentile, a marketing push that brings in many visitors on budget Android phones can drop your score without a single code change. Strong Core Web Vitals optimization plans account for where new users are coming from as well as the code you ship.

Scale applies to your codebase too. Performance budgets in your build pipeline, such as a maximum bundle size or a Lighthouse CI check that fails a pull request, catch these regressions before customers do.

A working order for the fixes

If you are starting from a poor score, this sequence tends to give the most improvement for the least effort:

Step 1.    Install real user monitoring with the web-vitals library and tag each report with device type, page template, and AI response length.

Step 2.    Identify your LCP element on your three busiest page templates and make sure none of them is AI-generated text that waits on the model.

Step 3.    Split the AI SDK, markdown renderer, and highlighter out of the main bundle and load them on demand.

Step 4.    Add token batching and paint the user's message immediately on Send.

Step 5.    Reserve space for answers, citation cards, and feedback controls.

Step 6.    Move parsing, highlighting, and token counting into a Web Worker.

Step 7.    Add adaptive behavior for low-end devices and hidden tabs.

Step 8.    Set performance budgets in continuous integration so the gains stay.

Each step can ship on its own. A good Javascript Development practice is to ship one change, wait for monitoring data, and confirm the improvement before stacking the next change on top.

When to bring in outside help

Batching tokens and reserving space are afternoon jobs for a small team. Other parts take more experience: designing a streaming architecture that survives provider outages, running models in the browser without freezing older phones, or rebuilding a large single-page app to render on the server.

Interest in building AI into products is now widespread. The 2025 Stack Overflow Developer Survey found that 84% of respondents use or plan to use AI tools in their development process. Far fewer teams have experience shipping AI features that stay fast on a five-year-old phone. If you decide to Hire AI Developers for this work, ask candidates or agencies how they handled INP in a streaming interface, what they measure in production, and how their design behaves when the model provider times out. Specific answers about batching, workers, and field data are a good sign.

It also helps to pair AI specialists with front-end performance people, since model integration and browser performance are different skills. Strong Javascript Development experience on the team keeps the interface light while the AI work moves ahead. Some companies choose to Hire AI Developers for a short engagement to set up the architecture and monitoring, then let their in-house team maintain it. 

Conclusion

AI features change what a web page does. Instead of loading once and waiting, the page keeps receiving text, formatting it, and growing while the user keeps clicking. Core Web Vitals reward pages that stay calm through all of that.

Most of the fixes are well understood by now. Show real content before the model responds. Keep the main thread free by batching updates and moving heavy work into workers. Reserve space so answers grow without pushing anything around. Then measure with your own data, because Google's numbers arrive late and leave out some of your users. Teams that treat Core Web Vitals for AI applications as an ongoing part of product work, checked with every release, tend to keep both their search visibility and their users' patience.

Nikhil Patel

Nikhil Patel, our dynamic Director, charts our course with innovative fervor and strategic acumen. With a sharp eye for opportunity, he steers our company's ascent with resolute determination. Nikhil's empathetic leadership unites us, igniting a collective drive for greatness and propelling us toward boundless success.

Frequently Asked Questions

Yes. Google uses Core Web Vitals as part of its page experience signals, and that applies to any public page, whether or not it uses AI. Relevance and content quality still matter more, but poor scores can hold back a page that would otherwise compete.

Lighthouse loads your page in a controlled setting but never clicks, taps, or types, so it can't measure INP. It reports Total Blocking Time as an estimate instead. Search Console uses real visits from real devices over 28 days. When the two disagree, the field data in Search Console reflects what users actually experienced.

For most products, the server is the safer default. Browser-based models avoid network delays and keep data on the device, but they require large downloads and heavy processing that can hurt LCP and INP on older phones. A hybrid approach works well: check device memory and WebGPU support at runtime, and only run on-device inference when the device can handle it.

Most Core Web Vitals optimization work shows up in your own real user monitoring within days. Google's field data uses a rolling 28-day window, so Search Console usually takes about four weeks to fully reflect a fix.

Look for people who can explain streaming performance in concrete terms: token batching, Web Workers, layout reservation, and real user monitoring. Ask how they would handle a slow model provider or a 30-minute chat session. Teams that Hire AI Developers with this mix of AI and front-end skills usually avoid the expensive rework that comes from fixing performance after launch.

  • Hourly
  • $20

  • Includes
  • Duration: Hourly Basis
  • Communication: Phone, Skype, Slack, Chat, Email
  • Project Trackers: Daily reports, Basecamp, Jira, Redmi
  • Methodology: Agile