Missing H1 and skipped heading levels: fixing a page outline
Heading levels are not font sizes. They are the only structural outline a document carries, and the reason this check exists is that CSS made them look interchangeable. A page can look perfectly organised and have no outline at all.
The short answer
A page needs exactly one H1 naming what it is about, then H2s and H3s in order with no levels skipped. The outline is how a screen reader user navigates and how an extraction system decides where sections begin and end. Visual builders break this constantly by choosing heading levels for their font size.
What an outline is for
Two things consume heading levels and neither of them can see your layout. A screen reader builds a navigable list of headings so a user can jump through a page without hearing all of it. A crawler builds a hierarchy to work out which passages belong to which topic.
Both depend on the same property: a level says what contains what. An H3 is a subsection of the H2 above it. When a level is skipped, that containment claim becomes unreadable, and the machine reading it has to guess. When there is no H1, the document has no root.
What a valid outline has to satisfy
One H1 per page, and no level entering more than one step deeper than the level before it. Going back up is always fine: H3 followed by H2 simply closes a subsection and opens a new section. Going down two at once is the defect, because there is no parent for the deeper level to belong to.
Notice what is not being measured: wording, length, keyword content, or how many headings the page has. A page with four headings and a clean hierarchy passes. A page with forty and one skip does not.
Check one page for an H1
Paste a URL. This reports whether the page has an H1 and what it says. The full crawl is what catches skipped levels further down, and the widget says so rather than implying it checked.
No signup required. Each free search audits one page, paste any URL to see it in action.
Why visual builders break this so reliably
In a page builder, a heading is a styling choice made by someone choosing how text should look. The control says "Heading 3" and it is sitting in a panel next to font size, so it reads as a size. Nobody picking it is thinking about document structure, because nothing in the interface suggests that is what they are picking.
The result is consistent across tools. Webflow and Elementor sections default to H2 or H3 regardless of nesting, so a page assembled from three section templates often has three H2s and no H1. Shopify sections behave the same way, with the theme's H1 frequently spent on the store name in the header rather than the page title. And a WordPress theme that renders the site title as an H1 leaves every post with two.
The tell is a page whose largest visible text is not a heading at all.
Fixing it without restyling anything
The objection to fixing this is always the same: the H1 is too big. That is a CSS problem being solved with markup, and it is worth separating the two once, because the fix takes a single rule.
<!-- Styled to look right, structurally rootless.
The "heading" is a div, and the first real
heading is an H3. -->
<div class="hero-title">Stainless steel widgets</div>
<h3>Specifications</h3>
<h3>Shipping</h3>
<h2>Related products</h2><!-- Correct outline. Appearance is a class, not a
level, so nothing about the design changes. -->
<h1 class="hero-title">Stainless steel widgets</h1>
<h2>Specifications</h2>
<h2>Shipping</h2>
<h2>Related products</h2>/* Decouple size from level once, and the argument
about H1 being "too big" goes away permanently. */
h1, h2, h3, h4, h5, h6 { font-size: inherit; font-weight: 600; }
.hero-title { font-size: 2.5rem; line-height: 1.1; }
.section-title { font-size: 1.5rem; }
.sub-title { font-size: 1.125rem; }After that, a level is chosen for what it means and a class is chosen for how it looks, which is the separation the elements were designed around in the first place.
The fix, as your agent receives it
This is the actual export for this check, generated by the audit API from a real crawl, with the site replaced by example.com and nothing else edited. It is what you get when you export the failure rather than a description of what such a file might contain.
Note what it does and does not assume. It tells the agent what string to search for rather than naming a file, because the crawler cannot see your repository layout. It states the skip that was actually observed. And it gives a safe default for the wording of the new heading, since that is the one part requiring judgement.
# Fix: Heading Hierarchy Skip
**Site:** https://example.com
**Check:** `seo-heading-hierarchy-broken` · **Severity:** warning · **Category:** SEO · **Affected pages:** 1
## What's wrong
The heading hierarchy on the page https://example.com/ is broken, with a skip from H1 to H3 without an intervening H2. The crawler observed this skip, which is reported as "H1 → H3 (skipped H2)". This defect is detected by the "seo-heading-hierarchy-broken" check. The page's current heading structure does not follow the standard hierarchical order.
## Why it matters
The broken heading hierarchy hurts accessibility and SEO structure, making it difficult for screen readers and search engines to understand the content structure. This can lead to a poor user experience, especially for users relying on assistive technologies. Proper heading hierarchy is essential for conveying the organization and importance of content.
## How to fix
1. Find the code responsible for generating the headings on the page https://example.com/ by searching for the string "H1" and "H3" in the HTML template or rendering code.
2. Insert an H2 heading between the existing H1 and H3 headings to maintain the correct hierarchical order.
3. Ensure the final HTML output includes the corrected heading structure, such as: `<h1>...</h1><h2>...</h2><h3>...</h3>`.
4. If the wording or content of the new H2 heading requires human judgement, use a safe default such as "Introduction" or "Overview" to maintain the hierarchical structure.
## Acceptance criteria
- [ ] The page https://example.com/ has a corrected heading hierarchy with no skipped levels.
- [ ] The HTML source of the page includes an H2 heading between the H1 and H3 headings.
- [ ] The page's heading structure follows the standard order: H1 → H2 → H3.
## Affected pages
| # | URL | Observed value |
| --- | --- | --- |
| 1 | `https://example.com/` | `H1 → H3 (skipped H2)` |
## Ground rules for the agent
- Start by identifying the stack yourself (package manifest, config files, template extensions) and adapt every step below to it. The steps describe the required output, not the framework.
- Treat the URLs and observed values above as facts from a real crawl. Do not invent additional affected pages.
- Prefer fixing the shared template or layout over patching one page, then confirm the change reaches every affected URL listed.
- Change content and templates, not URLs — renaming a route creates redirects and breaks inbound links.
- If a fix needs copy written (titles, descriptions), draft it from the page's existing content rather than inventing claims about the product.
- Make one issue-type change per commit so a regression can be bisected.
- Do not mark an item complete until its acceptance criterion is actually verifiable.When more than one H1 is acceptable
The HTML5 specification permits multiple H1 elements, one per sectioning element, and for years the advice was that this was fine. The outline algorithm that would have made it work was never implemented by any browser or assistive technology, and it has since been removed from the specification.
So the practical position is narrower than the theoretical one. A single H1 is what screen readers and crawlers actually behave well with, and multiple H1s are tolerated rather than understood. The genuine exception is a page that is a list of independent items, a feed or a search results page, where each entry is its own document and the containing page has a title of its own.
If you are unsure whether your case is the exception, it is not.
The cost of one H1 is nothing, and the cost of being wrong about sectioning is an outline no tool reads correctly. Reserve the exception for genuine feeds.
Why a broken outline stops short of Critical
Because the page still gets indexed, still ranks, and still reads correctly to anyone looking at it. The damage is to two audiences who are not looking at it: assistive technology users, for whom a broken outline is a real navigation failure, and machines parsing structure.
The reason it is not merely Refinement is that heading structure is an input to how passages get extracted, which is a growing use of your content rather than a shrinking one. The severity scale is weighing a present accessibility cost against a future extraction cost, and Important is where that lands.
Does this affect AI search?
Yes, and this is one of the few head-and-structure checks where the AI answer is stronger than the search answer. The mechanism is passage selection. A model answering a question about your page has to decide which chunk of it to quote, and headings are the most reliable boundary markers available for splitting a document into chunks that stand alone.
Retrieval systems commonly split documents on heading boundaries precisely because a heading marks a topic change. A page with no headings is one undifferentiated block, and a page with a broken hierarchy produces chunks whose boundaries do not match their content: an H3 with no H2 parent gets grouped with whatever preceded it, which may be a different subject entirely.
So the practical advice is to write headings that would work as standalone labels for the passage beneath them. That serves the crawler, the screen reader and the retrieval pipeline with one piece of work, which is unusual enough to be worth prioritising. The rest of the AI search group covers the checks that decide whether a model gets that far.
Confirming the outline
Do not read the markup for this. Use the accessibility tree in your browser's developer tools, which shows the outline as a machine assembles it, or run a headings extension and look at the resulting list. A list that reads as a sensible table of contents is the pass condition; one with gaps in it is the defect, whatever the source says.
Then re-crawl, because the skip case is the half a single page cannot self-report. Also worth checking after any template change: this is a defect that returns the moment someone adds a section component with its own hardcoded level.
Questions this check raises
- Can a page have more than one H1?
- HTML5 permits it and screen readers handle it, but on a normal content page it is a symptom rather than a choice: two H1s usually means the site name is marked as one and the page title as another. A page that genuinely holds two independent articles, such as a feed, is the case where two are defensible.
- Does skipping from H2 to H4 actually hurt anything?
- It breaks the outline that assistive technology and extraction systems both rely on. A screen reader user jumping by heading level lands in a section whose parent does not exist, and a system chunking the page for retrieval cannot tell whether the H4 is a subsection of the H2 or a sibling. Neither is a ranking penalty; both make the page harder to use and harder to quote.
- Should headings be chosen for how they look?
- No, and this is the single most common cause of a broken outline. Heading level is structure and font size is presentation, so pick the level the outline needs and set the size in CSS. Page builders invert this by naming their styles Heading 1 through Heading 6, which turns a typography choice into a semantic one.