Fixing Slow Rendering That Makes AI Agents Give Up
A browser-driving AI agent waits for a page to look ready, then acts.
If the page shows a spinner for several seconds, draws buttons that do nothing until scripts finish, hides everything behind an experiment snippet or keeps shifting as ads and widgets arrive, the agent either clicks too soon and gets it wrong or runs out of patience and moves on. This guide is about that gap between a page appearing and a page being usable and stable. It shows how to measure it, what usually causes it, and how server rendering, fewer scripts and reserved space close it.
What "ready" means to an agent
A person looking at a page makes allowances. They see a spinner and wait, see a button and try it, notice the layout jump and click again. An agent is less forgiving. Browser-driving agents typically wait for the page to settle, take a screenshot, read the accessibility tree, decide on an action and carry it out. Each of those points can go wrong on a page that is still busy:
- Too little to read. If the first screenshot shows a loader or an empty frame, the agent has to decide whether to wait or leave. Different agents make that choice differently, and none of them publish a fixed time limit you can design to.
- Controls that look ready but are not. A button drawn by server-rendered HTML may do nothing until the page's JavaScript has loaded and attached its handlers. The agent clicks, nothing happens, and it concludes the button is broken.
- A moving target. The agent works out where to click from a screenshot. If a banner, image or widget arrives between that screenshot and the click, the target has moved and the click lands on something else.
- A page that never settles. Chat widgets, analytics beacons, live polling and animated carousels keep the page busy indefinitely, so an agent waiting for things to go quiet waits in vain.
Agents that fetch HTML without running scripts have a simpler problem: whatever is not in the first response does not exist. That side, including server response time and caching, is covered in slow pages for AI crawlers. This guide concentrates on what happens in the browser after the HTML arrives.
Measuring the gap
You need to see the page change over time, not just a single score. Three tools do this well.
The Performance panel in Chrome or Edge
Open developer tools, choose Performance, set CPU throttling to a slower setting and network to a fast mobile connection, and record a page load. The screenshot strip across the top shows what the page looked like at each moment. The main thread track shows long tasks, marked with a red corner, which are periods when the browser cannot respond to a click. Layout shifts are marked in their own track.
WebPageTest
Run a test from a location near your audience and look at the filmstrip view. It shows the page frame by frame, which makes a spinner that lasts three seconds, or a hero image that pushes everything down at the four second mark, easy to see and easy to show to whoever built the site.
PageSpeed Insights field data
The field data at the top of PageSpeed Insights comes from real Chrome users. The two figures that matter most here are Interaction to Next Paint, which reflects how quickly the page responds to clicks and should be 200 milliseconds or less at the 75th percentile, and Cumulative Layout Shift, which should be 0.1 or less. Poor figures for real people almost always mean a poor experience for agents too.
| What you see | What it usually means | Where to look |
|---|---|---|
| Blank or white page for a second or more, then everything at once | An anti-flicker snippet or a client-rendered app | Head of the page source; first HTML response |
| Spinner or skeleton that lasts several seconds | Content fetched by script after load, often from a slow API | Network panel, requests after the document |
| Buttons visible but clicks ignored for a while | Hydration or scripts still loading; handlers not attached | Performance panel, main thread |
| Content jumps as images, ads or banners arrive | Missing dimensions, injected banners, late web fonts | Layout shift track; Lighthouse CLS diagnostics |
| Page never goes quiet | Polling, chat widgets, auto-playing carousels | Network panel left open for a minute |
Dead clicks and the hydration gap
Many modern sites render HTML on the server, then load JavaScript that "hydrates" the page by attaching behaviour to it. Between the two, the page looks complete but its buttons do nothing. On a fast laptop the gap is short. On a busy cloud browser with limited CPU, which is where many agents run, it can be long enough for the agent to click, see no result and give up on that control.
There are two ways to close the gap: make it shorter, and make controls work without waiting for it.
Make controls work without scripts
A form with a real action and a submit button works the moment the HTML arrives. A link
with a real href works the moment it is drawn. Script can then improve the experience, for
example by submitting in the background, but the basic action does not depend on it.
<!-- Dead until the script loads -->
<button type="button" class="js-add-to-basket" data-sku="KT-204">Add to basket</button>
<!-- Works immediately; script can enhance it later -->
<form action="/basket/add" method="post">
<input type="hidden" name="sku" value="KT-204">
<label for="qty">Quantity</label>
<input id="qty" name="qty" type="number" value="1" min="1">
<button type="submit">Add to basket</button>
</form>
Frameworks increasingly support this directly. Remix and React Router form handling, Next.js server actions used with forms, SvelteKit form actions and Nuxt server routes can all accept a normal form post before client code has loaded.
Make the gap shorter
- Ship less JavaScript to the pages agents use most: product, service, booking and contact pages.
- Hydrate only the parts that need it. Island approaches, as used by Astro and similar tools, leave most of the page as plain HTML and only load script for interactive pieces.
- Load the script for the main action first, and push reviews, recommendations and chat further back.
Loaders and snippets that hide the page
Anti-flicker snippets
Many A/B testing and personalisation tools ask you to add a small snippet to the head that hides the whole page, usually by setting its opacity to zero, until the experiment script has loaded and made its changes. The idea is to stop visitors seeing the original version flash before the variant. The effect for an agent is a blank page for as long as the testing script takes, up to whatever timeout the snippet sets.
If you still run experiments, ask whether the snippet is needed at all. Server-side testing, where the variant is chosen before the HTML is sent, avoids it entirely. If you must keep it, shorten the timeout, limit it to the pages actually in a test, and remove it from pages with no running experiment. Check the head of your page source for any leftover snippet from a tool you no longer use; they often outlive the tool.
Full-page loaders and splash screens
Some themes add a loading overlay that covers the page until every image and script has loaded, sometimes with an animation. It serves no purpose for the visitor and hides a page that is often usable well before the overlay lifts. Remove it.
Spinners in place of content
A spinner where the price, stock level or opening hours should be means that information is fetched by script after load. If the fetch is slow, or blocked for an automated visitor, the agent sees a spinner indefinitely. Put that information in the server-rendered HTML and refresh it with script afterwards if it changes often. The JavaScript-only content guide covers the details.
The fix, step by step
Step 1
Record what happens between first paint and ready
Run the AI Agent Compatibility audit on your main journey pages, then record each page in the browser Performance panel with CPU throttling turned on and in WebPageTest with the filmstrip view. Note when meaningful content first appears, when the main button first responds to a click, when the layout stops moving, and whether the network ever goes quiet. Those four moments are what you are trying to bring closer together.
Step 2
Send usable HTML from the server
View the raw page source and check that the heading, main text, prices, stock and key calls to action are in it, rather than a nearly empty container waiting for script. If they are missing, switch the page to server rendering or static generation in your framework, or move the data fetch to the server side of your template. Keep client-side fetching for things that genuinely change second by second.
Step 3
Make controls work before scripts finish
For each important action on the page, such as add to basket, search, enquire or book,
check it still works with JavaScript disabled in developer tools. Where it does not, wrap the control
in a form with a real action and method, or turn it into a link with a real
address, then let your script enhance it. Reduce the JavaScript loaded on these pages so hydration finishes
sooner.
Step 4
Remove page-hiding snippets and endless loaders
Search the head of the page for anti-flicker code from testing or personalisation tools and remove it from pages that are not in a live experiment, or cut its timeout sharply. Remove any full-page loading overlay from the theme. Replace spinners that stand in for prices, stock or hours with the real values in the HTML, updated by script afterwards only when necessary.
Step 5
Reserve space so nothing moves under a click
Give every image, video and embed width and height attributes
or a CSS aspect-ratio, and reserve fixed space for ad slots, review widgets and cookie or
promotion banners instead of letting them push content down. Use font-display: swap with
a similar fallback font so text does not reflow badly. Aim for a Cumulative Layout Shift of 0.1 or less
for real visitors, and check the layout shift track again.
Step 6
Cut and defer third-party scripts
List
every third-party script the page loads, from tag managers, chat widgets, heatmaps, review badges and
social embeds, and remove any nobody uses. Load the rest with defer or after the page has
become usable, and load chat widgets only when someone opens them. Stop carousels from auto-playing,
and check the network panel settles after load rather than polling for ever.
Step 7
Break up long tasks and retest
In the Performance panel, find tasks longer than 50 milliseconds on the main thread and trace them to their scripts. Split heavy work into smaller pieces, yielding back to the browser between them, and move non-urgent work until after the first interaction. Then record the page again, compare the four moments from step one, re-run the audit and give an AI agent a real task on the page.
Third-party scripts and layout shifts in practice
On most small business sites, the site's own code is not the main problem. Third-party scripts are. Each one is small on its own, and together they fill the main thread during the first seconds of the visit, exactly when an agent is trying to act.
| Script | Usual effect | Better approach |
|---|---|---|
| Tag manager with many tags | Long tasks early in the load | Audit tags twice a year; fire non-essential tags after load |
| Live chat widget | Heavy script, constant network activity | Show a light button and load the widget on click |
| Review or rating badge | Arrives late and pushes content down | Reserve its space; render key rating text on the server |
| Social media embeds | Large frames and scripts per embed | Show a static preview that loads the embed on click |
| Cookie consent banner | Slides in and moves content or covers controls | Fixed position overlay at the bottom; fixed height |
| A/B testing tool | Page hidden until the script runs | Server-side tests; remove snippet from untested pages |
A reusable CSS rule for reserving space for a late widget:
.reviews-summary {
min-height: 3.5rem; /* the height the widget takes once loaded */
}
.hero img {
aspect-ratio: 16 / 9;
width: 100%;
height: auto;
}
scheduler.yield() for this; where
it is not available, setTimeout with a zero delay is the common fallback.Platform notes
- WordPress. Page builders and themes often add a preloader and several sliders; remove the preloader and replace sliders with a single static image. Cache plugins that delay all JavaScript until interaction can leave buttons dead on first load; exclude the scripts your key actions depend on. The WordPress guide covers this.
- Shopify. The theme usually renders well; slowdowns come from app embeds. Turn embeds off one at a time in the theme editor to find the heavy ones, and see the Shopify guide.
- React, Vue and other frameworks. Use the framework's server rendering or static generation for public pages, keep client-only components for genuinely interactive parts, and split code by route so each page loads only what it needs.
- Static sites. Usually fast already. Watch for third-party embeds and web fonts, which are then the main cause of delay and movement.
1. How long will an AI agent wait for my page to load?
There is no published figure that applies to all agents, and it varies by product and by task. What is clear is that agents run in cloud browsers with limited resources and are built to move on rather than wait indefinitely. Treat the Core Web Vitals thresholds as a sensible target: content visible within about 2.5 seconds, responses to clicks within 200 milliseconds and very little layout shift. A page that meets those rarely loses an agent to slowness.
2. My page loads fast in Lighthouse. Why does the audit say rendering is a problem?
Lighthouse measures a single load in controlled conditions and gives a summary score. Agents care about specific moments: whether the page is hidden behind a snippet, whether the main button works when it first appears, whether content shifts while they are about to click and whether the page ever goes quiet. A page can score well and still have a dead add to basket button for two seconds, so check the filmstrip and the main thread, not only the score.
3. What is a dead click and why does it matter for agents?
A dead click is a click on something that looks interactive but does nothing, usually because its JavaScript has not loaded yet. People tend to click again after a moment. An agent may record that the control does not work and try another route, or report back that the task could not be done. Making the control a real form or link means it works even before scripts load, which removes the problem at its source.
4. Should I remove my A/B testing tool?
Not necessarily, but look hard at the snippet that hides the page while the tool loads. It makes every visitor, human or agent, stare at a blank screen for as long as the testing script takes. Remove it from pages that are not in a live test, shorten its timeout, or move to server-side testing where the variant is chosen before the page is sent. Also remove snippets left behind by tools you no longer use.
5. Does layout shift really cause agents to click the wrong thing?
It can. Many agents decide where to click by looking at a screenshot, then send the click a moment later. If a banner, image or widget arrives in between and pushes the page down, the click lands on whatever is now in that spot. People sometimes make the same mistake, which is why Cumulative Layout Shift is a Core Web Vital. Reserving space for late-arriving elements fixes it for both.
6. Is server-side rendering required for agent compatibility?
Not strictly, because agents that drive a browser can run JavaScript. But server rendering helps in two ways that matter: agents that only fetch HTML can read the page at all, and browser agents see real content immediately instead of a loader. It also makes the gap before hydration less harmful, because links and forms in the HTML work straight away. For public pages that agents are likely to use, it is the most effective single change.
7. Will these fixes help my Core Web Vitals and SEO?
Most of them will. Reserving space reduces Cumulative Layout Shift, breaking up long tasks and trimming third-party scripts improves Interaction to Next Paint, and server rendering with fewer blocking scripts helps Largest Contentful Paint. Core Web Vitals are part of the page experience signals Google uses, although good content matters far more for rankings. The main benefit here is that real visitors and agents both get a page that responds when they use it.
The AI Agent Compatibility audit tests your page for bot blocks, content hidden behind JavaScript, unlabelled forms and controls, navigation agents cannot follow and missing structured data, and links each finding to the guide that fixes it.
Open AI Agent Compatibility Fixes โ