FR
Copied
Modules

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 Exemple",
  "adresse": "1 rue de l'Exemple, 00000 Exempleville",
  "site_web": "https://example.com"
}

Outputs

One row per input row, with the original columns kept. Empty cells mean the URL could not be scored (see Errors). The test runs with the mobile profile.

Column Type Description
tested_url, strategy, fetch_time string URL tested, profile used (mobile) and time of the test.
perf_score int 0-100 Lighthouse performance score.
seo_score int 0-100 Lighthouse SEO score.
a11y_score int 0-100 Lighthouse accessibility score.
best_practices_score int 0-100 Lighthouse best-practices score.
perf_verdict string À refondre below 50, À améliorer below 90, OK otherwise.
lcp_ms, fcp_ms, tti_ms, tbt_ms, speed_index_ms, ttfb_lab_ms int Lab timings in milliseconds. Good LCP is under 2500.
cls float Cumulative Layout Shift. Good is under 0.1.
crux_overall, crux_lcp_p75_ms, crux_fcp_p75_ms, crux_cls_p75, crux_inp_p75_ms mixed Field data from real Chrome users for this URL, when Google has enough traffic. INP only exists here.
origin_crux_overall, origin_crux_lcp_p75_ms mixed Same field data for the whole site.
top_opportunity_1, top_opportunity_2, top_opportunity_3 string The three failing audits with the largest estimated saving, ready to quote in a message.
error string Why the row could not be scored, if applicable.

The file also carries page weight (total_byte_weight_kb, weight_*_kb), estimated savings (savings_*), technical flags (uses_*, has_*), HTTP and security headers, cookies, TLS certificate, meta tags and DOM counts, DNS records (MX, SPF, DMARC), a security grade (mozilla_grade, mozilla_score) and the presence of robots.txt and sitemap.xml. The registry lists accessibility_score, lcp and inp under produces: these are signal names for a11y_score, lcp_ms and crux_inp_p75_ms.

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 Exemple", "site_web": "https://example.com" }
  ],
  "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, error set to URL absente ou invalide.
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