PageSpeed ExporterAIReportLighthouseTutorialAI Agents

How to Get the Most Out of PageSpeed Exporter

Get better PageSpeed Exporter results: audit the right URL, follow scorePlan, prompt the agent on real files, and re-scan until each lab target is met.

PageSpeed Exporter Team··11 min read

To get the most out of PageSpeed Exporter, treat each scan as one pass in a loop: audit a public URL, hand the agent the stripped AIReport, change the metric with the most points at risk, and re-scan until that metric's numericValue reaches targetFor90. The download is already sorted for that loop. Chasing the largest savings.ms number, or pasting a raw PageSpeed Insights dump, spends the same report and produces a weaker fix.

The file you want is the AIReport: scores, a score plan, CrUX when Google has it, and the failing rows. Screenshots and passing-audit bodies are already gone, so the file stays under 50KB and fits next to your source in ChatGPT, Claude, or Cursor.


The loop that actually moves the score

Lighthouse's performance score is a weighted average of five lab metrics. An issue changes that score only when one of those metrics gets faster or more stable. PageSpeed Exporter writes that rule into every export as scorePlan.note.

Work in this order:

  1. Run the URL people actually load, on the device that matches the decision.
  2. Open scorePlan and name the metric with the highest pointsAtRisk.
  3. Edit only the issues whose affectsMetrics includes that metric, using fixLocation and details for the exact surface.
  4. Skip every id in passedAuditIds.
  5. Click Re-scan and compare numericValue to targetFor90. Repeat until that metric is done, then take the next one.
fieldData is real-user Chrome data (CrUX). It will not move on the next lab run. Search Console can take weeks to reflect a fix. Use the lab number to know whether the code change worked. Interaction to Next Paint is field-only. The lab stand-in for interactivity is Total Blocking Time.

Audit the page people load

Google PageSpeed Insights can only fetch a public http or https URL. Localhost, a private IP, and a staging host behind a login all fail before a report is built. Deploy a preview, or audit production.

Pick a URL that represents a template, not a one-off query string:

  • The homepage, if that is what ranks and converts.
  • One product, collection, or article URL if those templates differ.
  • The URL after redirects. The results page shows Final URL when it differs from what you typed. Audit that address next time so the agent is not fixing a redirect hop.

A blog post and a checkout rarely share the same LCP element. One report per template is enough. Scanning every URL in a sitemap burns the monthly allowance and hands the agent the same findings again.


Choose the device that matches the decision

Mobile is the default, and it is the right first pass. Core Web Vitals for ranking come from real phones, and Lighthouse's mobile run uses a slow CPU and a simulated slow network. A desktop 95 with a mobile 42 is a mobile problem.

  • Mobile is on every plan, including the anonymous preview. Use it for the score you will re-check and for Search.
  • Desktop is on Starter and Pro. Use it when a large share of sessions is desktop, or when a metric already passes on mobile and still fails on the tighter desktop targets.
  • Both is on Starter and Pro. It runs mobile and desktop and returns one AIReport. The form notes the extra scan time. It counts as two reports on the website and on MCP, because each device is a separate call to Google.

On a Both export, metrics stays the mobile set. Read scorePlan.strategies for each device, and metricsByStrategy when you need the desktop numbers beside the mobile ones. Do not average the two scores into one target.


Hand the agent the AIReport, not the raw dump

On the results page, use Copy Prompt + JSON or Download AIReport (JSON). Copy Prompt bundles a template with the stripped JSON. The download is the same JSON if you want to attach a file.

What the agent receives:

{
  "meta": { "url": "https://example.com/", "strategy": "mobile" },
  "scorePlan": {
    "strategies": [
      {
        "strategy": "mobile",
        "performanceScore": 54,
        "metrics": [
          {
            "id": "total-blocking-time",
            "displayValue": "780 ms",
            "numericValue": 780,
            "weight": 30,
            "pointsAtRisk": 21.4,
            "targetFor90": 200
          }
        ]
      }
    ]
  },
  "issues": [],
  "passedAuditIds": ["viewport"]
}
pointsAtRisk is weight × (1 − metric score), rounded to one decimal. A Total Blocking Time near 0 can cost about 21 of the 30 points that metric carries. A metric already near 90 costs 2 or 3. Start there.

Mobile finish lines in targetFor90:

  • Total Blocking Time: 200 ms (weight 30)
  • Largest Contentful Paint: 2500 ms (weight 25)
  • Cumulative Layout Shift: 0.1 (weight 25)
  • First Contentful Paint: 1800 ms (weight 10)
  • Speed Index: 3387 ms (weight 10)

Desktop finish lines are tighter: TBT 150 ms, LCP 1200 ms, FCP 934 ms, Speed Index 1311 ms. CLS stays 0.1.

A raw PSI response is often 500KB to 2MB of screenshots, filmstrips, and passing audits. Models skim it and then "fix" something that already scores 90. The difference is spelled out in stripped JSON versus raw PageSpeed Insights.


Pick the prompt that matches the job

The results page ships five templates. Free includes the first two. Starter and Pro include all five. The template text already tells the model to follow scorePlan and to ignore passedAuditIds.

  • Full Analysis — every issue that still has points at risk, with the element, module, or request named from details. Best default when a coding agent has the repo open.
  • Plain English — a non-technical brief and a checklist for a developer or agency. Use this in chat when you will not edit the code yourself.
  • Quick Wins — the metric with the most points at risk, then three issues that affect it. Use this when you want one sitting of work.
  • Code Diffs — a concrete diff per issue, using stackPacks for the framework. Use this in Cursor, Claude Code, or Copilot.
  • Performance Score — performance issues only. Accessibility, best practices, and SEO stay out of the list. Use this when the Lighthouse performance score is the goal.

If you write your own prompt, paste this after the JSON:

Start with scorePlan. Fix the metric with the highest pointsAtRisk until numericValue reaches targetFor90.
Use issues whose affectsMetrics includes that metric. Name the exact URL, selector, module, or entity from details.
Respect fixLocation. If thirdParty is true, change how that service loads. Do not invent an edit to its remote file.
Skip passedAuditIds. Do not sort by savings.ms.
Then stop and tell me to re-scan. Do not start the next metric in this turn.

One metric per turn keeps the diff reviewable. A prompt that asks for every audit at once tends to produce a long plan and a small, wrong edit.


Edit the control surface the report names

Each issue may include fixLocation. That field is the likely place you can actually change:

  • code — a component, template, or handler in your project.
  • build-config — the bundler, framework config, or image pipeline.
  • server-cdn — caching, compression, or the HTML response.
  • asset — a specific file's bytes or format.
  • third-party — a tag, app, or widget you load. Change the loading policy. The remote script is not yours to rewrite.
details is already slim: URLs, wasted bytes, selectors, source lines, top unused modules, LCP subpart timings, a discovery checklist, and a third-party entity. Cap your attention on those rows. Bounding boxes and screenshots were removed because they do not tell an agent which file to open. stackPacks names the detected stack and Lighthouse's hint for it. On WordPress, Shopify, or Next.js, point the agent at that hint before it invents a generic webpack change.

A before-and-after that counts looks like this in the next AIReport, not like a paragraph of estimated savings:

total-blocking-time
  before: numericValue 780, pointsAtRisk 21.4, targetFor90 200
  after:  numericValue 180, pointsAtRisk 0,    targetFor90 200

The 780 ms to 180 ms move is the result. An unused-JavaScript row that still says savings.ms: 400 did not cause it unless TBT's numericValue moved.


Keep the project open, or call the audit from the editor

Two ways to run the loop. Use the one that can see your files.

Download or copy. Run the audit on the site, then attach the AIReport in a chat that has the repository. Coding agents should use Full Analysis or Code Diffs. A marketer sending work to an agency should use Plain English. Setup for each assistant is on the tools pages. MCP. Signed-in accounts create one token on the dashboard. Cursor, Claude, and other MCP clients send it as Authorization: Bearer. The tool is analyze_url with url and an optional strategy (mobile by default). The prompt fix_all_issues tells the agent to audit, edit the project, and call the tool again until every pointsAtRisk metric has reached targetFor90 and no accessibility, best-practices, or SEO issue remains. initialize, tools/list, and prompts/get do not call PageSpeed and are not billed. Each analyze_url call uses the same monthly allowance as the website. There is no separate MCP price. At the cap, the error links to pricing, and the same token picks up a higher plan after that account subscribes. The walkthrough is How to Use Cursor to Fix Core Web Vitals.

Ask the agent to re-audit after the edit, not to guess the new score. Lab scores commonly move about ±5 points between identical runs. Treat a 3-point bump as noise. Treat a metric that crosses targetFor90, and stays there on a second run, as the change you shipped.

On the results page, Re-scan runs the same URL and strategy again. When the earlier run is still in this browser, the page shows a before/after comparison of category scores and which audits cleared. That comparison is the check. A model saying "this should be worth 15 points" is not.


Spend reports on pages that teach you something

Allowances are shared by the website and MCP:

  • Anonymous preview: 2 reports per 30 days
  • Free: 5 per month, mobile only, Full Analysis and Plain English
  • Starter ($9): 50 per month, desktop and Both, all five prompts, saved history
  • Pro ($29): 200 per month, plus a ZIP of selected reports from dashboard history for a client handoff

A Both scan spends two of those reports. Re-scan spends another. That is the right spend when you are confirming a fix. It is the wrong spend when you are auditing ten URLs that share one template.

If the goal is one metric, say so in the prompt. fix_all_issues keeps going through accessibility, best practices, and SEO after the performance targets are met. That is the right prompt for a full Lighthouse cleanup. It is the wrong prompt when you only have budget to move LCP.


Mistakes that waste a good report

  • Sorting the issues array by savings.ms and "fixing" unused CSS while LCP is the metric with 20 points at risk.
  • Asking the model to improve audits listed in passedAuditIds. Those already score 90 or above.
  • Pasting the raw PSI JSON, then wondering why the answer talks about screenshots.
  • Running desktop only, then comparing the score to a mobile Search Console report.
  • Editing a third-party file the report marked thirdParty: true.
  • Treating CrUX fieldData as something the next lab run will update.
  • Celebrating a score that moved 4 points once. Run it again.
  • Leaving the repo closed, so the agent writes a generic snippet that matches none of your files.

Metric-specific loops, once the score plan says which metric is first: fix Largest Contentful Paint with AI and fix Cumulative Layout Shift with AI.


Further reading

Sources

  • Lighthouse performance scoring — weights and the lab metric score curves that targetFor90 is taken from.
  • PageSpeed Insights — the API PageSpeed Exporter calls. The only key sent to Google is the server key.
  • Chrome UX Report — the field data behind fieldData. It is a 28-day window of real Chrome users, not the next lab run.
  • Core Web Vitals — LCP, INP, and CLS thresholds. INP is measured in the field. Lighthouse reports Total Blocking Time in the lab.

Further reading

Try it yourself

Run a free Lighthouse audit on any URL and get the full JSON report for your AI agent — no account required.

Analyze a URL for free