pagetrace—anSEOlockfileforCI
A CLI and library that records your site's SEO and AEO surface into a committed lockfile, then diffs every build against it. It classifies by transition rather than state, so a reworded title is noise and a removed canonical fails the build.

pagetrace
Existing SEO tools score a page as it is right now. None of them tell you that this deploy dropped the canonical from 400 pages, that a layout refactor added noindex, or that a CMS migration quietly stripped your Product schema. Those regressions are silent for weeks, until traffic moves.
npm install -D pagetrace
Snapshot, then diff
Record a baseline from your build output and commit it:
npx pagetrace snapshot --dir ./out
git add pagetrace.lock.json
Check every build against it:
npx pagetrace check --dir ./out
Severity is about transition, not state
This is the idea the whole tool is built around. A reworded title is info. A removed canonical is error. So you can fail a build on real regressions without drowning in noise from ordinary content edits.
| Code | Severity | Fires when |
| --- | --- | --- |
| canonical.removed | error | A page lost its canonical tag |
| robots.noindex.added | error | A page became noindex |
| jsonld.entity.removed | error | A structured data entity disappeared |
| canonical.offsite | error | A canonical points at another host |
| aeo.crawler.newly_blocked | error | robots.txt started blocking an AI crawler |
| title.changed | info | Ordinary copy edit |
Answer engines, not just search
It records llms.txt, per-agent crawlability for GPTBot, ClaudeBot, PerplexityBot and others, and whether a page opens with something quotable. Blocking an AI crawler by accident is a regression like any other.
In a pull request
A GitHub Action diffs the branch against the baseline on main and comments the result, so nobody has to remember to look.
- uses: shyamexe/pagetrace@v1
with:
dir: ./out
baseline-branch: main
Auditing a site you did not build
audit needs no lockfile and works against a live URL. Findings roll up by issue rather than by page, so one template defect on 400 pages reads as a single item, and each one carries why it matters and how to fix it — with WordPress or Next.js specifics where the platform is detectable.
npx pagetrace audit --url https://example.com --format html --out audit.html
Built deliberately small
Pure functions over plain objects. Three dependencies, all small and boring. No JavaScript execution, no Lighthouse, no ranking data — those exist elsewhere and would dilute the one thing this does that nothing else does.
Why I built it
I wrote up the bug that started it, a missing og:image on my own homepage that no test would ever have caught: I shipped a bug to my own homepage and only caught it by building a tool to find it.