SEO Fix Agent
← All articles
Technical SEO11 min read

The Technical SEO Checklist for Developers: 36 Checks, Ordered by What They Cost You

Every technical SEO check that moves outcomes, weighted so you fix the expensive things first: HTTPS to llms.txt, with the HTML that passes each one.


Most SEO checklists are lists. Everything on them is presented as equally important, so the person working through one spends the same twenty minutes on the favicon as on the canonical tag, and the site launches with a beautiful favicon and every page canonicalised to the homepage. This checklist is weighted. The checks are the 36 that the audit engine on this site runs on every page, each with the weight it carries in the score, and the order within each section is the order in which failures cost you.

The weights are deliberately coarse: 3 for things that can remove a page from search entirely, 2 for things that materially change how it ranks or is shown, 1 for hygiene that is worth doing and rarely decisive, 0.5 for things that matter mostly to humans, and 0 for checks that are reported but never scored, because they are decisions rather than defects. A page's score is the weighted proportion of checks that pass; a warning earns half its weight, a failure none. If you have limited time, do the threes on every page before you do the ones on any page.

Technical (12 checks)

HTTPS — weight 3. The page is served over TLS and the http version redirects to it with a single 301. HTTPS has been a ranking signal since 2014 and browsers now mark http pages as not secure. Failure mode in production: the canonical or the sitemap still points at http URLs after a migration, so every page declares that its real version is the insecure one.

Page is indexable — weight 3. No <meta name="robots" content="noindex"> and no X-Robots-Tag: noindex header. This is the check that catches staging configuration reaching production. The header form is the one people miss, because it is invisible in view-source; curl -I shows it. If the page should be noindexed, this check reads as informational.

Site not blocked by robots.txt — weight 3. The audited path is not disallowed for general crawlers. Note that robots.txt blocks crawling, not indexing: a blocked page can still be indexed from external links, with no snippet. Which mechanism does which is its own article.

HTTP status code — weight 3. The final URL after redirects returns 200. Anything else is either not a page (4xx, 5xx) or not this page (a redirect). A 200 that renders a "not found" message is a soft 404 and the worst version, because nothing automated will catch it.

Server response time — weight 2. Time to first byte of the final response. Under 800 ms is fine, over 1.8 s is a problem. This is the one check in the list that is not deterministic: it is one network sample, and it can flip between runs on a page that sits near the threshold. It is also the only check here that overlaps with Core Web Vitals, where TTFB is a diagnostic rather than a vital.

Mobile viewport configured — weight 2. <meta name="viewport" content="width=device-width, initial-scale=1">. Without it, mobile browsers render the page at desktop width and shrink it, and Google's mobile-first indexing evaluates that shrunken page. A missing viewport on a responsive site is a build mistake; on a non-responsive site it is the least of the problems.

Character encoding declared — weight 1. <meta charset="utf-8"> as the first thing inside <head>, or a Content-Type header with a charset. Browsers guess correctly most of the time, which is why this is a 1 and not a 3, but a wrong guess produces mojibake in titles and snippets.

Text compression — weight 1. The HTML is served with Content-Encoding: br or gzip. Every CDN does this by default; the check catches the origin that is serving directly, or the misconfigured proxy that strips it.

HTML document size — weight 1. The raw HTML is under a sane limit. The median real-world page is around 100 KB of HTML; a page that ships 3 MB of it usually has a rendering problem (inlined data, an entire dataset in a script tag, a serialised store) that also hurts LCP.

robots.txt present — weight 1. The file exists at the root and returns 200. A missing robots.txt is treated as allow-all, so the cost is small, but a robots.txt that returns 5xx makes Googlebot stop crawling the site until it recovers, which is why it is worth having a real, static one.

XML sitemap reachable — weight 1. Declared in robots.txt or present at /sitemap.xml, returns 200, parses. Sitemaps are discovery hints, not ranking factors. Their real value is the lastmod date on each URL, which Google uses to prioritise recrawling, and which is worthless if every URL carries today's date.

Favicon present — weight 0.5. A <link rel="icon"> that resolves. Google shows favicons in mobile results; a missing one shows a generic globe. Half a point because it is about clicks, not rankings.

Meta (6 checks)

Title tag — weight 3. Present, unique to the page, and 30 to 60 characters. The title is one of the few on-page texts search engines have said they weigh, and the one they rewrite most often when it is too long, too generic or stuffed. Titles and descriptions covers pixel widths and the rewrite triggers. The common production failure is a template: {{ site.name }} — {{ page.title }} — {{ tagline }} produces 90-character titles with the unique part truncated.

Canonical URL — weight 2. A single <link rel="canonical"> pointing at the URL itself (or deliberately at the primary version). Canonicals fail silently and expensively: one wrong template value and every page on the site declares itself a duplicate of the homepage. Eight canonical mistakes lists the ways this happens; the one to check first is any canonical set in a layout rather than a page.

Meta description — weight 2. Present, 70 to 160 characters, and written for the query. Not a ranking factor since 2009; a click-through factor, and one Google replaces with a body passage about half the time. Two points because a missing description is a missed click on every impression.

HTML lang attribute — weight 1. <html lang="en">. Used by screen readers, translation prompts and, indirectly, by language-targeting. Wrong is worse than missing: a site with lang="en" on Bulgarian pages is telling every consumer the opposite of the truth.

Title keyword stuffing — weight 0.5. No word repeated in the title. SEO Tools | Best SEO Tools | SEO Tool Reviews is the pattern. It reads as spam to humans and is one of the documented triggers for Google rewriting the title.

hreflang annotations — weight 0. Reported when present, never scored, because most pages do not need it and a page without it is not wrong. When you do have language variants, the rules are strict: every variant must list every other variant including itself, and the annotations must be reciprocal, or Google ignores the set.

Content (5 checks)

Content length — weight 2. Enough visible text to be about something. Under 250 words is thin for anything that is not a form or a tool; the number is a floor, not a target, and the mistake is writing to a word count. The audit reads the rendered text with scripts and navigation removed, so a page that ships 5,000 words of boilerplate and 80 words of content fails this check correctly.

H1 heading — weight 2. Exactly one, and it describes the page. Multiple H1s are not a ranking problem, whatever older guides say, but they are usually a symptom: a logo wrapped in an H1, a component library defaulting to H1. What headings actually do is longer than you would expect.

Heading hierarchy — weight 1. No skipped levels: H2 follows H1, H3 follows H2. This is an accessibility requirement more than a ranking one, and screen reader users navigate by heading level, so a jump from H1 to H4 is a real defect for them. Search engines use the heading text; they are indifferent to the levels.

Image alt text — weight 1. Every <img> that conveys information has an alt; decorative images have alt="". Alt text is how image search understands images and how screen readers describe them. The failure is not missing alts on the hero image, it is a CMS that emits alt="image" on every upload.

Image lazy loading — weight 0.5. Below-the-fold images carry loading="lazy"; the LCP image does not. Getting this backwards, lazy-loading the hero, is a common Core Web Vitals regression.

Links (3 checks)

Internal linking — weight 2. The page links to other pages on the site, and other pages link to it. A page with zero internal links out is a dead end; one with zero in is an orphan. Both are reported. The number is a floor: three contextual links in the body beat thirty in a footer.

Descriptive anchor text — weight 1. No links whose only content is "click here", "read more", or nothing at all (an icon with no accessible name). Anchor text is a statement about the destination; empty anchors are a statement about nothing, and an accessibility failure.

Outbound links — weight 0. Reported, never scored. There is no "link out or be penalised" rule, and there is no "linking out leaks PageRank" rule either. Link to sources when a reader would want them.

Social (2 checks)

Open Graph tags — weight 1. og:title, og:description and og:image, with the image at 1200×630 and an absolute URL. These control how the page appears when shared anywhere: Slack, iMessage, LinkedIn, every chat app. Not a ranking factor; a distribution factor. The failure is an og:image set to a relative path, which most scrapers cannot resolve.

Twitter/X card — weight 0.5. twitter:card set to summary_large_image. X falls back to Open Graph for the rest, so this one tag is the whole job.

AI Search / GEO (8 checks)

This section is what separates a 2026 checklist from a 2020 one. Answer engines retrieve pages and quote passages; what they need from a page is different from what a ranking algorithm needs, and mostly it is structure and access.

Structured data (JSON-LD) — weight 2. A valid JSON-LD block describing the page type: Article, Product, FAQPage, Organization, SoftwareApplication. This is the one machine-readable statement of what the page is, and both rich results and retrieval systems read it. Which types earn visible results is worth reading before adding any; most schema on the web describes types nothing consumes.

Authorship and E-E-A-T signals — weight 1. An author or organisation stated in the markup: author in the Article schema, a Person or Organization node, or rel="author". Google's quality guidelines lean on who wrote a thing; an anonymous page is at a disadvantage on topics where expertise matters.

AI answer engines can fetch this page — weight 3. The retrieval crawlers, OAI-SearchBot, Claude-SearchBot, PerplexityBot and the user-triggered fetchers, are not blocked by robots.txt for this path. This is a 3 because blocking them removes the page from every AI answer, permanently, and because it is frequently done by accident: a User-agent: * disallow, or a "block all AI" rule copied from a 2023 blog post. How to block the training crawlers without blocking these is the article for this check.

FAQ / Q&A schema — weight 0. Informational. FAQPage markup rarely produces a visible rich result any more, but question-and-answer structure on the page is exactly the shape retrieval systems extract from, so it is reported for pages that have it.

Answer-first content — weight 1. The first substantive paragraph answers the question the title poses, in one or two sentences, before the background. Passages are retrieved out of context; a page whose answer is in paragraph nine after eight of throat-clearing is retrievable, but the passage that gets quoted will be someone else's. How engines pick what to cite goes into why.

AI training crawler stance — weight 0. Whether GPTBot, ClaudeBot, Google-Extended and the other training tokens are allowed. Reported, never scored, in either direction: this is a licensing decision, and a checklist has no business telling you which way to make it.

llms.txt present — weight 1 where it exists. Reported for every page; scored only when the site has one, and then on whether it follows the spec. What llms.txt is and who reads it is an honest accounting, and the honest summary is that it is cheap and its consumers are mostly humans and agents who are pointed at it deliberately.

Content freshness signals — weight 1 on article-shaped pages. A datePublished and dateModified in the schema, and a visible date. Retrieval systems and Google both prefer a page that says when it was last true. Scored only on pages that look like articles; a pricing page does not need a byline.

Using this as a process

The order to work in on an existing site:

  1. Crawl the whole site and sort pages by score, worst first. The three-weight failures cluster: a page with a bad canonical usually shares a template with fifty others.
  2. Fix by template, not by page. Almost every technical failure lives in a layout, a component or a CMS setting. Fixing the template fixes the class.
  3. Re-crawl and diff. A fix that cleared a failure on one page and introduced a warning on another is a normal outcome, and only a diff shows it.
  4. Then, and only then, the content checks, which are per-page work and cannot be templated.

For a new site, run the list top to bottom on the templates before there is any content, and again on the first five real pages after launch. The weight-3 checks are all things a framework default or a deploy setting can get wrong on day one, and Next.js in particular has a list of them.

Everything above is what the free audit on this site checks on a single page, with the weights shown next to each result. If you are handing the fixes to a coding agent rather than a person, this workflow is how to turn the list into instructions it can execute without inventing work.

#checklist#technical-seo#developers#on-page-seo#ai-search

Audit your page, then ship the fix

SEO Fix Agent runs 36 weighted technical, content and AI-search checks on a page, then compiles every finding into a severity-ordered prompt your coding agent can execute. 50 free credits, no card.

Start free — 50 credits

Keep reading