Page Speed Analyzer Example: 72/100 Mobile Performance
This example shows the aiwebpageseo Page Speed Analyzer for a marketing homepage. Performance is 72/100 on mobile with LCP at 3.1 seconds, blocked by render-blocking CSS from two Google Fonts requests. Desktop scores 91/100. Specific Lighthouse opportunities are listed with estimated savings.
| Metric | Mobile | Desktop | Status |
|---|---|---|---|
| FCP — First Contentful Paint | 2.1s | 0.6s | Needs Work |
| LCP — Largest Contentful Paint | 3.1s | 1.2s | Needs Work |
| TBT — Total Blocking Time | 280ms | 40ms | Needs Work |
| CLS — Cumulative Layout Shift | 0.02 | 0.01 | Good |
| TTI — Time to Interactive | 4.8s | 1.4s | Needs Work |
Eliminate render-blocking resources
2 render-blocking CSS files (Google Fonts, analytics.css) delay First Contentful Paint by 1.2 seconds. Use <link rel="preload"> for critical CSS and defer non-critical CSS with media="print" onload swap.
Properly size images — 4 oversized images
4 images are served at 2× their display size. Serving correctly sized images would save approximately 0.8 seconds and 340KB of bandwidth. Use srcset to serve different sizes for different viewports.
Reduce unused JavaScript — 280KB unused
280KB of JavaScript is never executed on this page. Use code splitting to defer unused code. The main candidate is the dashboard.js bundle which loads on every page but is only needed in the app.
Use efficient cache policy — 8 resources
8 static assets have no cache-control header or a max-age below 1 year. Set Cache-Control: max-age=31536000, immutable for all versioned static assets.
This is the single most important thing to understand about a Lighthouse report, and almost every conversation about page speed gets it wrong.
Everything above is lab data — a single synthetic load, on a simulated mid-range Android phone, on a throttled network, in a data centre. It is a controlled experiment, and it is invaluable for finding problems.
Google's page experience signals do not come from this. They come from the Chrome User Experience Report: real Chrome users, on their real devices and real networks, assessed at the 75th percentile over a 28-day rolling window. That is field data, and it is the only thing that feeds ranking.
The Performance score itself is not a ranking factor
Not 72. Not 100. Google has never used the Lighthouse composite as a ranking signal. What it uses is the three Core Web Vitals, measured in the field. A page scoring 72 in the lab with good field vitals is fine. A page scoring 95 in the lab with poor field vitals is not. Chasing the number in isolation is optimising a proxy while ignoring the thing it is a proxy for.
The Performance score is a weighted composite of five lab metrics — it is not an average, and the weights are wildly uneven. This matters because it tells you which number to attack if you want the score to move.
| Metric | Weight | What it measures |
|---|---|---|
| TBT — Total Blocking Time | ~30% | Main thread blocked by long JavaScript tasks |
| LCP — Largest Contentful Paint | ~25% | When the main content appears |
| CLS — Cumulative Layout Shift | ~25% | How much the page moves under the reader |
| FCP — First Contentful Paint | ~10% | When anything at all appears |
| Speed Index | ~10% | How quickly content visibly populates |
TBT at 280ms is doing most of the damage here, because it carries the heaviest weight and it is the metric furthest from good. CLS is already 0.02 — excellent, and there is nothing to win there. Attacking the JavaScript is where the score is.
This is the trap in every Lighthouse report and it catches experienced developers.
INP — Interaction to Next Paint — is the Core Web Vital for responsiveness, and it replaced FID in March 2024. It cannot be measured in a lab test, because measuring it requires somebody to actually interact with the page. Lighthouse therefore reports TBT instead: a proxy that measures how long the main thread was blocked during load, on the reasonable assumption that a blocked thread would have been slow to respond had anyone tried.
The assumption holds often and not always. A page can have an acceptable TBT and a terrible INP, because the expensive JavaScript runs in response to the interaction rather than during load — a heavy filter, a re-render, a search-as-you-type handler. None of that is visible to a load-time test.
| Core Web Vital | Good | Poor |
|---|---|---|
| LCP | ≤ 2.5s | > 4.0s |
| INP | ≤ 200ms | > 500ms |
| CLS | ≤ 0.1 | > 0.25 |
TTI is a lab-only metric with no field equivalent at all, and Google has steadily de-emphasised it. Do not build a business case on it.
"LCP is 3.1 seconds" is not actionable. LCP decomposes into four sequential phases, and the fix is completely different depending on which one is consuming the time:
| Phase | If this is the problem |
|---|---|
| 1. Time to First Byte | Server, database, or no caching. Target under 800ms. Nothing on the front end can fix a slow server. |
| 2. Resource load delay | The browser found out about the LCP image late. Preload it. This is the phase the report's render-blocking CSS is inflating. |
| 3. Resource load duration | The image itself is too big. Compress it, resize it, serve modern formats. |
| 4. Element render delay | The main thread was busy with JavaScript and could not paint. Same root cause as your TBT. |
First, identify which element the LCP actually is. On a marketing homepage it is usually the hero image or the headline. People routinely optimise an image that was never the LCP element and are baffled when nothing improves.
Never lazy-load the LCP image
loading="lazy" is right for everything below the fold and actively harmful on the hero. It defers the fetch of the very element whose paint time is being measured. Instead: fetchpriority="high", and a <link rel="preload"> so the browser learns about it in the first bytes of the document rather than after the CSS has parsed.
The report attributes 1.2 seconds to two render-blocking CSS files, one of them Google Fonts. The mechanism is worth understanding because it is a chain of serial round trips, and each link is on the critical path:
- The browser must fetch and parse the stylesheet before it can render anything at all.
- The
@font-facerule pointing at the font file lives inside that stylesheet — so the browser cannot even discover the font URL until the CSS has arrived. - Only then does it request the font. From a different origin, requiring a fresh DNS lookup, TCP handshake and TLS negotiation.
- Text that depends on the font cannot paint until it arrives.
That is at minimum two serial round trips before a word appears, and none of it is under your control.
Self-host the fonts. It removes the third-party origin entirely, it removes a GDPR exposure — a German court ruled in 2022 that loading fonts from Google's servers transmitted visitors' IP addresses unlawfully without consent — and it lets you preload the font from your own domain, where the browser's preload scanner finds it immediately. If you do preload a font, the crossorigin attribute is mandatory even for same-origin files; without it the browser fetches the font twice and you have made things worse.
The four opportunities list savings of 1.2s, 0.8s, 0.6s and 0.4s. Two warnings:
They do not sum
Fixing all four will not save 3.0 seconds. The savings overlap — several of them are competing for the same critical path — and each is modelled independently, assuming the others are unchanged. Treat the list as a priority order, not a budget.
The score fluctuates between runs
Network variance, CPU contention on the test machine, third-party scripts responding at different speeds, A/B tests serving different pages. A five-point swing between two runs of the same URL is normal and means nothing. Run it three times and take the median, and never celebrate or panic over a single-digit change.
The "280KB of unused JavaScript" is the most valuable line in the report, and not because of the 0.6s. Unused JavaScript is not just a download — the browser must parse and compile it, on the main thread, which is exactly what TBT is measuring. It is one defect showing up in two places, and the report has already identified the culprit: a dashboard bundle loading on a page that has no dashboard.
This gap is expected and it is not a bug. Lighthouse's mobile test applies deliberate CPU throttling and a simulated slow network to approximate a mid-range Android phone. Desktop is tested unthrottled. The same page, the same code — a very different machine.
Optimise for the mobile number. Google indexes with a mobile user-agent and assesses Core Web Vitals separately for mobile and desktop. The desktop 91 is reassuring and it is not the score being judged.
And note where the gap is concentrated: TBT is 280ms on mobile and 40ms on desktop — a sevenfold difference. That is the signature of a CPU-bound problem, not a network one. The JavaScript is not too large to download; it is too expensive to execute on a phone. Sending less of it is the fix; a faster CDN is not.
What is a good PageSpeed score?
90–100 is considered Good. 50–89 is Needs Improvement. Below 50 is Poor. The most important score for SEO is the mobile Performance score as Google uses mobile-first indexing. Focus on the Core Web Vitals within the report (LCP, CLS, INP) as these are direct Google ranking signals.
What causes a poor LCP score?
The most common LCP causes are: unoptimised hero images (too large, wrong format, not preloaded), render-blocking resources preventing early rendering, slow server response times (TTFB above 600ms), and CSS that delays critical content from displaying.
How do I fix render-blocking resources?
Render-blocking resources are CSS and JavaScript that prevent the page from displaying until they finish loading. Fix by: adding rel='preload' for critical CSS, deferring non-critical CSS to load after paint, using defer or async on non-critical JavaScript, and inlining critical above-the-fold CSS directly in the HTML.
Is the Lighthouse Performance score a Google ranking factor?
No. Google has never used the Lighthouse composite score as a ranking signal. It uses the three Core Web Vitals — LCP, INP and CLS — measured in the field via the Chrome User Experience Report, at the 75th percentile of real visits over a 28-day rolling window. A page scoring 72 in the lab with good field vitals is fine; one scoring 95 with poor field vitals is not.
Why does Lighthouse report TBT instead of INP?
Because INP cannot be measured without somebody actually interacting with the page, and a lab test has no user. TBT is a load-time proxy: it measures how long the main thread was blocked, on the assumption that a blocked thread would also have been slow to respond. The assumption often holds and sometimes does not — a page can have acceptable TBT and poor INP when the expensive JavaScript runs in response to the interaction rather than during load.
Do the estimated savings add up?
No. Fixing all the listed opportunities will not save their combined total, because the savings overlap — several compete for the same critical path — and each is modelled independently assuming the others are unchanged. Treat the list as a priority order rather than a budget. Scores also fluctuate several points between runs of the same URL, so take the median of three runs and ignore single-digit changes.
Why is my mobile score so much worse than desktop?
Because the mobile test deliberately throttles the CPU and network to approximate a mid-range Android phone, while desktop is tested unthrottled. The gap is expected. Where TBT is dramatically worse on mobile than desktop, the problem is CPU-bound rather than network-bound — the JavaScript is not too large to download, it is too expensive to execute on a phone. Sending less of it is the fix; a faster CDN is not.
Related Demo Reports
Run Page Speed Analyzer on Your Own Site
Get your real audit report with specific issues, fixes and actionable improvements.