Technical SEO for Developers
By Seth Black · Published · Updated
Most technical SEO writing is aimed at someone who emails a programmer a 40-page PDF and considers the job done. I’ve been on the receiving end of those PDFs. If you’re the person who actually ships the HTML, you need audits that behave like tests. Something that fails loudly when a build breaks, not a quarterly report you skim and file.
Here’s how I think about technical SEO when the person doing the work owns the repo.
Audits belong in the pipeline, not in a quarterly report
If a canonical tag regression ships to production and nobody notices until the next rank tracking check, that’s a process failure, not an SEO failure. Treat SEO checks like any other assertion. A failing check should block the merge.
I run BSA’s CLI against a staging URL on every PR that touches routing, meta components, or the build config. The output is JSON. A small diff script decides what counts as a regression. If a new 404 shows up in the internal link graph, the build fails. Same if canonical coverage drops below a threshold.
- name: Run SEO audit
run: |
black-seo-analyzer --url-to-begin-crawl $STAGING_URL \
--output-type json --output-file audit.json
python scripts/check_regressions.py audit.json baseline.json
The baseline is the last known-good crawl, checked into the repo. When something intentionally changes, you update the baseline in the same PR. Reviewers see the delta. If you want a deeper walkthrough of wiring this up end-to-end, the command-line audit walkthrough covers CI integration and JSON parsing in detail.
The three code-level issues that bite hardest
Minification eating meta tags. A build pipeline I looked at was stripping attributes out of head tags because someone dropped in an HTML minifier and never checked what it did to structured data. The page rendered fine. The JSON-LD was silently invalid. Rich results disappeared and nobody connected the dots for weeks. A rendered crawl would have caught it the day the plugin landed.
Render path mismatches. Your server returns one title tag. Your client-side router replaces it on mount. If you only audit raw HTML, the tool shows you the server version. If you only audit rendered HTML, you miss the wrong title Googlebot sometimes grabs before the router finishes doing its thing. You want both, per URL, with a diff. So crawl twice, once without --spa and once with it, into separate databases (--db-path raw.db, --db-path rendered.db), and compare the titles and canonicals per URL. A few lines of Python beats guessing. This is also exactly the class of problem that all-in-one SEO tools miss when auditing JavaScript-rendered pages.
Meta systems that drift. A component called <PageMeta> starts out clean. Six months later there are three of them, two wrappers, a context provider, and a hook that conditionally overrides the canonical based on a feature flag nobody remembers setting. Audit the output, not the component tree. The output is the only thing Googlebot sees. Standard crawlers won’t surface this kind of drift — it’s one of those site-specific problems that pre-built audit software will never find without custom extraction.
What developer-focused actually means in practice
The tool needs a CLI. The output has to be machine-readable so you can pipe it into whatever check script you want. You should be able to run a technical SEO audit from the command line without a login seat, diff two crawls without touching a browser, and trust that the crawler renders JavaScript the way a real browser does. Half of the real bugs live in the gap between raw HTML and what the DOM actually looks like.
Treating technical SEO like a chore somebody else handles means it breaks between audits and nobody notices until a rank drops. Wire it into your test suite and it stops being a chore.
Start a free trial and point it at whatever section of your app you’re most confident about. The rendered crawl will find something. It always does.
BSA ships a real CLI and JSON output. CLI docs — or grab the trial if you want it in CI.
-Sethers