PageSpeed
PageSpeed
Run an official Google PageSpeed Insights audit on every prospect's website. The output ranks the list by site quality, exposes the weakest performers, and surfaces an angle worth pitching: a slow or broken site is a concrete improvement to offer.
The module never crawls a site directly. It delegates the measurement to Google, which keeps the signal comparable across prospects.
Inputs
The job accepts an array of POI dictionaries. The only field actually used is site_web; any other field is carried through to the output unchanged.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
list[dict] |
yes | 1 to 10,000 POIs. Rows without site_web are kept and marked. |
source_job_id |
string |
no | UUID of the upstream job (typically a Google Maps scrap). |
{
"nom": "Studio Atlas",
"adresse": "12 rue de Rivoli, 75001 Paris",
"site_web": "https://studio-atlas.fr"
}
Outputs
One row per input POI. Empty cells signal that PSI could not score the URL (see Errors).
| Column | Type | Description |
|---|---|---|
perf_score_mobile |
int 0-100 | Lighthouse performance score, mobile profile. |
perf_score_desktop |
int 0-100 | Lighthouse performance score, desktop profile. |
lcp_ms |
int | Largest Contentful Paint in milliseconds. Good < 2500. |
cls |
float | Cumulative Layout Shift. Good < 0.1. |
accessibility_score |
int 0-100 | Lighthouse accessibility score. |
seo_score |
int 0-100 | Lighthouse SEO score. |
suggestions[] |
list[string] | Top Lighthouse audits flagged as failing, ready to quote in an outreach message. |
The CSV export also carries best_practices_score, fcp_ms, tbt_ms, and inp_ms for completeness.
Lifecycle
Standard outsend job lifecycle; see /docs/concepts/jobs-lifecycle. Progress is reported in sites; result count in audits.
Pipeline
needs: site_web
produces: perf_score, accessibility_score, seo_score,
best_practices_score, lcp, cls, inp
PageSpeed is a check module: it consumes a list and returns the same list enriched. Typical pattern: start from a scrap job, then run pagespeed against the resulting POIs.
Endpoints
Create a job
POST /api/jobs/pagespeed
Content-Type: application/json
{
"items": [
{ "nom": "Studio Atlas", "site_web": "https://studio-atlas.fr" }
],
"source_job_id": "8b1f...-uuid"
}
Response: a JobPublic envelope carrying the job UUID, its status, and the EF cost reserved for tracking.
Read a job
GET /api/jobs/{job_id}
GET /api/jobs/{job_id}/results
GET /api/jobs/{job_id}/export.csv
The CSV export is available once the job is completed.
Limits
See /docs/concepts/limits. Upstream is the Google PSI v5 free tier (one URL per request); bursts above the per-key quota are retried inside the job rather than failed.
Errors
| Condition | Behaviour |
|---|---|
POI has no site_web |
Row kept, audit columns empty, suggestions[] set to a single explanatory entry. |
| URL unreachable or returns a non-HTML page | Row kept, scores empty, error noted on the row. |
| PSI quota exhausted | Affected URLs are re-queued inside the job; if the quota stays exhausted the row is marked failed and the rest continues. |
| Site blocks the PSI fetcher | Row marked failed with the upstream error code; the job itself stays healthy. |
items empty |
400 Bad Request, no job created. |
Missing PAGESPEED_API_KEY server-side |
Job created but moves straight to failed. |
A failed row never blocks the job: the contract is "every input POI gets one output row, scored or explained".
What's next
techstack— detect the CMS, analytics, and frameworks behind each site. A weak PageSpeed score combined with a known-slow stack is a sharper angle than either signal alone.ads_intelligence— check whether the prospect is actively spending on ads. Paying for traffic that lands on a slow page is the highest-conviction pitch this module enables.