Skip to content

Latest commit

 

History

History
116 lines (94 loc) · 9.05 KB

output.md

File metadata and controls

116 lines (94 loc) · 9.05 KB

Output

Project output written to --out. Default is out/analytics.json for pend-analytics audit. Shape is AuditRun in src/types.ts.

When a PageSpeed key is set, Lighthouse screenshots go under dirname(--out)/psi-shots/ and each lab row records the relative path as analytics.psi.pages[].screenshot. Paths only - image bytes never go into the JSON.

Input · Output (this page) · Analytics · Security


Unscored on purpose

This engine does not rate traffic. The score object is kept so consumers that already read a Pendulum envelope still parse. Do not treat the band as a readiness claim.

pages and findings are always empty arrays. There is no check catalog.

namevalue exampledescription / info
Automated readiness0Always zero.
Worst page score0Always zero.
Band"Good"Always this label so the envelope does not look like a failed audit. Not a traffic rating.
Issue burdenall zerosAlways zeros.
Manual completion0 / 0Always empty.

Analytics pull

Fields written to --out (default out/analytics.json) for pend-analytics audit. Missing values are omitted, never invented defaults.

The payload is run.analytics. Provider failures stay in errors[] and the process still exits 0. Setup and troubleshooting: analytics.md.

namevalue exampledescription / info
version1AuditRun envelope. Not the package version.
tool"@pendulumdev/analytics"Producer id.
generatedAt"2026-09-11T10:00:00.000Z"ISO timestamp when the pull finished.
project"Example Project"From config project.
standard"Pendulum_Analytics_v1"From config standard.
baseUrl"https://example.com"From config when set.
scoreUnscored zeros. See above.
pages[]Always empty.
findings[]Always empty.
analytics.rangeResolved primary window, plus previous window when compare is on.
start / end"2026-01-01"Inclusive YYYY-MM-DD.
previousStart / previousEnd"2025-12-04"Present when comparePrevious is on.
analytics.gscSearch Console daily rows, top pages, top queries, totals.
analytics.ga4Sessions, landing pages, channels, devices, new vs returning.
analytics.googleSetupPublic tags. Unique snippets (each with destinations and the pages they appear on), optional GTM containers, collisions.
googleSetup.urls["https://example.com/"]Pages fetched for the tag scan, homepage first.
googleSetup.snippetsDeduped by fingerprint. Destinations are the IDs read from that snippet.
kind"gtag"gtm, gtag, ua, or other.
location"head"head, body, or unknown.
text"https://www.googletagmanager.com/gtag/js?id=G-…"Truncated snippet or loader URL.
fingerprint"8b417677"Stable hash of text.
destinations[{ "family": "ga4", "id": "G-CDEC0MPC01" }]IDs found in this snippet.
pages["https://example.com/", "https://example.com/about"]Scanned URLs this snippet was found on.
analytics.eventsDeclared vs received (and optional observed) event names.
analytics.cruxOrigin Chrome UX Report field vitals, when a PageSpeed key is set.
reason"not-found"Present when vitals are missing. not-found (no field record), empty (record with no p75s), or error.
detail"chrome ux report data not found"Google or transport message for not-found and error.
analytics.psiHomepage lab rows (mobile and desktop), when a PageSpeed key is set.
analytics.rivalsNamed rival origins: homepage CrUX and PageSpeed lab, when a PageSpeed key is set.
analytics.insightsPeriod signals. Omitted rows mean the threshold was not met. See the table below.
id"gsc-clicks-drop-action"Stable insight id.
response"action"watch (monitor the next window) or action (take steps now). Not a score or how bad the number is.
title"Organic clicks dropped sharply"Short label.
detailPeriod numbers for this run.
remediationengineer and client copy.
analytics.errorsProvider, auth, tags, observe, CrUX, or PSI soft-failures.
source"psi"gsc, ga4, auth, tags, observe, crux, psi, or rival.
message"https://…/ (mobile): Timed out"Human-readable failure.
host"https://pendulumdev.co.uk"Origin for psi, crux, and rival rows so the site and named rivals stay distinguishable.
timingWall time for the pull. Browser and crawl times stay zero.

Insights

Period signals, not a check catalog. A row appears only when its threshold is crossed. An empty list means nothing notable this window, not that everything passed.

response is what to do next, not how severe the metric is. watch means monitor over the next window. action means take steps now.

idresponsetitle
gsc-clicks-drop-actionactionOrganic clicks dropped sharply
gsc-clicks-drop-watchwatchOrganic clicks trended down
gsc-impressions-drop-actionactionSearch impressions dropped sharply
gsc-impressions-drop-watchwatchSearch impressions trended down
gsc-low-ctr-queriesactionHigh-impression queries with low CTR
gsc-position-worsewatchAverage position worsened
ga4-sessions-drop-actionactionSessions dropped sharply
ga4-sessions-drop-watchwatchSessions trended down

Period drop rows need comparePrevious and a previous window. action is a 25%+ fall vs the prior period; watch is a 10-25% fall. Low-CTR needs queries in the top 10 with at least 100 impressions and CTR under 2%. Position watch fires when average position is 1.5 or more worse and impressions stayed within 10%.


Reading a stored run

readRunJson() requires score, analytics, and pages, then hands back a typed AuditRun. Re-reading a run written by an older version is the common failure, and it is better to fail with a clear message than to render half a report.