SEO Checks · On-Page
Heading hierarchy: how our checker reads H1 to H6
Quick answer: Our checker reads every <h1>–<h6> tag in the HTML your server returns and runs three checks on the URL you enter: no H1 (critical), more than one H1 (warning) and skipped levels (warning). Google says heading order doesn't matter to Search. We flag skips because screen-reader users navigate by heading level, and accessibility guidance says not to skip.
What the checker reads
The free audit fetches the page once and parses the HTML as served. No JavaScript runs. From that HTML it collects every h1 to h6 element in document order and keeps its level and its text, with runs of whitespace collapsed and the ends trimmed. That list is all three checks look at. Visibility, CSS and ARIA attributes play no part.
<h1>Main topic of the page</h1>
<h2>First section</h2>
<h3>Detail inside the first section</h3>
<h2>Second section</h2>Indentation in HTML means nothing. Only the tag names count, so the outline above is H1, H2, H3, H2 and passes all three checks.
The three checks
Check 1: H1 missing
ID: onpage-h1-missing · Severity: critical
Fails when the list contains no h1 element. An H1 with no text still counts as present, which is one of the gaps described below. The report lists the text of every H1 it found.
Check 2: Multiple H1 tags
ID: onpage-h1-multiple · Severity: warning
Fails when there are two or more h1 elements, wherever they are. An H1 inside <article> or <section> counts the same as any other. Browsers and screen readers never implemented the old document outline in which sectioning elements lower a heading's level, and MDN recommends one H1 per page. One common cause is a theme that wraps the logo or site name in an H1 on top of the page's own H1.
Check 3: Heading hierarchy skips levels
ID: onpage-heading-hierarchy-skips · Severity: warning
Walks the list in order. A heading is a skip when its level is more than one below the heading before it, as in H2 → H4 or H1 → H3. The first heading on the page is compared with level 0, so any page whose first heading is not an H1 fails, even if a correct H1 follows. Going back up is never a skip: H4 → H2 passes. The report lists every skip with its from and to levels and the heading text.
The rules, applied to real markup:
| Served HTML | What the checker reports |
|---|---|
| <h1>…</h1><h2>…</h2><h4>…</h4> | Skip: H2 → H4 |
| <h1>…</h1><h3>…</h3> | Skip: H1 → H3 |
| <h1>…</h1><h2>…</h2><h3>…</h3><h4>…</h4><h2>…</h2> | Pass (going back up is fine) |
| <h2>Menu</h2><h1>…</h1> | Skip: start → H2 ("Menu") |
| <h2>…</h2><h3>…</h3> (no H1) | H1 missing and skip: start → H2 |
| <h1>Logo</h1> … <h1>Title</h1> | Multiple H1 |
| <article><h1>…</h1></article><section><h1>…</h1></section> | Multiple H1 |
| <h1 style="display:none">…</h1><h1>…</h1> | Multiple H1 (hidden ones count) |
| <h1></h1> or <h1><img alt="Acme"></h1> | Pass: an empty H1 counts as present |
| <div role="heading" aria-level="1">…</div> | H1 missing (only h1–h6 tags count) |
| <template><h1>…</h1></template> | Counted as an H1 |
| <noscript><h1>…</h1></noscript> | Not counted |
| H1 inserted by JavaScript after load | H1 missing |
What Google and accessibility guidance say
- Google Search: its SEO starter guide says semantic heading order is "fantastic for screen readers, but from Google Search perspective, it doesn't matter if you're using them out of order", and that there is no ideal number of headings. A skip warning from us is not a ranking problem.
- Accessibility: the W3C headings tutorial says skipping ranks "can be confusing and should be avoided where possible", and that H2 → H4 should not happen. Screen-reader users jump between headings, and a gap leaves them unsure whether they missed a section.
- One H1: MDN calls several H1s allowed but "not considered a best practice". The same tutorial also says headings in fixed areas such as sidebars should keep the same levels on every page. On some pages that will trip our skip check, and keeping the sidebar consistent is the better choice.
What we see on real sites
On 7 October 2026, the latest report for each of the 54 sites checked with this tool showed:
- 11 of 54 fail the skip check. Of the 21 skips recorded, H2 → H4 is the most common (6). 6 of the 11 have a heading before their first H1, so check what sits above your H1 in the source before reworking your content headings.
- 5 of 54 have no H1 at all. 4 of those 5 also fail the skip check for the same reason: their first heading is an H2 or lower. Adding one H1 at the top clears both.
- 2 of 54 have more than one H1. None has an empty H1.
That is a small sample, 50 of them homepages, and the people who run it are not a random sample of the web. Read the numbers as what our checker finds most often, not as a web-wide rate.
Where our checker and your browser can disagree
We read tags in the served HTML. Browsers and screen readers read the rendered page. In these cases the two can differ:
- Empty H1:
<h1></h1>or an H1 that only wraps a logo image passes our missing-H1 check. A screen reader announces the image's alt text, or nothing if there is none. - Hidden headings: an H1 with
display:noneor thehiddenattribute still counts, so a hidden duplicate makes the page fail the multiple-H1 check. Screen readers skip it. - ARIA headings:
role="heading"andaria-levelare ignored. Adivwithrole="heading" aria-level="1"is a level-1 heading to a screen reader and is not an H1 to us. - Templates: headings inside
<template>count for us but are not on screen until a script uses them. - JavaScript: headings added after load are invisible to us. A single-page app that renders its H1 on the client fails the missing-H1 check.
These are gaps in our checker, documented here rather than left silent. If a heading result surprises you, run the snippet below. Its last line counts each case on your page.
Reproduce what our checker saw
Paste this into the browser console on the page in question. It fetches the HTML as served, applies the same three rules, prints the heading list as a table, and then reads the live page for the cases above:
const html = await (await fetch(location.href)).text();
const doc = new DOMParser().parseFromString(html, 'text/html');
const found = [];
(function walk(node) {
for (const el of node.children) {
if (el.localName === 'noscript') continue;
if (/^h[1-6]$/.test(el.localName)) found.push(el);
walk(el.localName === 'template' ? el.content : el);
}
})(doc);
const hs = found.map(h => ({ level: +h.localName[1], text: h.textContent.replace(/\s+/g, ' ').trim() }));
const h1s = hs.filter(h => h.level === 1);
const skips = [];
let prev = 0;
for (const h of hs) {
if (h.level > prev + 1) skips.push((prev ? 'H' + prev : 'start') + ' -> H' + h.level + ' "' + h.text + '"');
prev = h.level;
}
console.table(hs);
console.log('h1-missing:', h1s.length ? 'pass' : 'FAIL');
console.log('h1-multiple:', h1s.length <= 1 ? 'pass' : 'FAIL', '(' + h1s.length + ' H1)');
console.log('hierarchy-skips:', skips.length ? 'FAIL' : 'pass', skips);
const live = [...document.querySelectorAll('h1,h2,h3,h4,h5,h6')];
console.log('empty H1s we count:', h1s.filter(h => !h.text).length,
'| hidden headings:', live.filter(h => !h.checkVisibility()).length,
'| role="heading" we ignore:', document.querySelectorAll('[role=heading]').length,
'| headings after JS:', live.length, 'vs', hs.length, 'in HTML');If the table is shorter than the outline you see on screen, the missing headings are added by JavaScript. If a skip names a heading you don't recognise, search the page source for its text. Look in the header, the menu and any banners first.
How to fix heading issues (by platform)
Where the H1 comes from on each platform, and how to change it:
For skips, change the tag rather than the look. If an H4 is used because it looks right, make it an H3 and restyle it with CSS. Headings also feed one AI readiness check, which looks at how many are phrased as questions; see AI readiness checks explained. The page's H1 and its title tag are separate elements and are checked separately.
Check your heading structure
The free checker runs all three heading checks on any URL, alongside its on-page, technical and AI-readiness checks. No signup required.
Check your site free →FAQ
Does heading order affect Google rankings?
Google's SEO starter guide says semantic heading order is fantastic for screen readers but that, from Google Search's perspective, it doesn't matter if headings are out of order. We flag skipped levels because of accessibility guidance from W3C and MDN, not because of a ranking rule.
Can a page have more than one H1?
The HTML standard allows it, as long as the H1s are not nested. MDN still recommends a single H1 that describes the page. Our checker warns when it finds more than one, including H1s that are hidden on screen or placed in separate <section> or <article> elements.
Why does my report say the hierarchy skips levels when my H1 looks fine?
The check also fails when any heading comes before the H1 at level 2 or lower. For example, an H2 or H3 in the header, menu or an announcement bar that comes before the main H1 in the HTML. The report lists each skip as from/to levels with the heading text, and a from of 0 means it was the first heading on the page.
Does going back up a level count as a skip?
No. H4 followed by H2 is fine, because it closes the subsection and starts a new section. Only a jump down by more than one level is reported, such as H2 to H4 or H1 to H3.
Keep reading