Every technical audit we run at Houston DOD includes a heading pass, and the same seven problems show up again and again. Not because developers are careless, but because headings do two jobs at once: they style text visually and they describe document structure to machines. When teams optimize for the first job and ignore the second, heading hierarchy SEO breaks quietly. Nothing turns red in Search Console. Rankings just drift, featured snippets go to competitors, and AI-generated answers quote someone else’s page. It is argued more carefully on yoast.com.
This post is a diagnostic. For each mistake you get the broken HTML we typically find, the corrected version, and a plain explanation of how the error affects crawler parsing, passage extraction, and snippet eligibility.
Quick answer: what correct heading hierarchy looks like
A correct heading structure is an outline, not a set of font sizes. One H1 states the page topic. H2s divide the page into main sections. H3s divide those sections. H4 to H6 handle deeper nesting, which most pages never need.
| Tag | Job on the page | How many per page |
|---|---|---|
| H1 | Main topic of the page, usually matching the visible title | One |
| H2 | Main sections and primary subtopics | 3 to 8 on most pages |
| H3 | Sub-points inside an H2 section | As needed |
| H4 to H6 | Deep nesting: specs, steps inside steps, documentation | Rare, use sparingly |
Google’s own documentation says to organize content hierarchically, give each page a unique H1, and avoid skipping levels. You will also see people on forums claim headings are “only cosmetic” and not a ranking factor. Both statements can be true at the same time, and that nuance is the whole point of this article.
Headings are not a ranking factor, but they are a parsing factor
There is no slider in Google’s system labeled “heading quality”. What headings actually control is how your page gets segmented. Search engines and AI answer systems break long documents into passages, and heading boundaries are one of the strongest signals for where a passage starts and stops. That segmentation drives:
- Featured snippet eligibility, especially paragraph and list snippets pulled from the text directly under a heading that matches the query
- Jump-to-section links and “Sites named” style deep links in results
- Passage-level retrieval for AI Overviews and chat assistants that quote a specific section
- Accessibility, since screen reader users navigate by heading level, and accessibility failures increasingly overlap with usability signals
So the honest framing is this: fixing headings rarely produces an overnight ranking jump. It produces cleaner extraction, which is what wins snippets and citations. Now let’s look at what goes wrong.

Mistake 1: Multiple H1s used for styling
The classic version: a logo wrapped in an H1, the page title in another H1, and a hero call to action in a third, all because H1 was the fastest way to get big text.
Before
<header>
<h1><a href='/'><img src='logo.svg' alt='Acme'></a></h1>
</header>
<section class='hero'>
<h1>Commercial HVAC Repair in Houston</h1>
<h1 class='cta-big'>Call Now for Same-Day Service</h1>
</section>
After
<header>
<a href='/' class='logo'><img src='logo.svg' alt='Acme'></a>
</header>
<section class='hero'>
<h1>Commercial HVAC Repair in Houston</h1>
<p class='cta-big'><a href='tel:+17135550100'>Call now for same-day service</a></p>
</section>
Why it hurts
HTML5 technically permits multiple H1s inside sectioning elements, but the document outline algorithm that was supposed to make that work was never implemented by browsers or assistive tech. In practice, three H1s means three competing statements about what the page is about. Crawlers have to guess which one is the topic, and “Call Now for Same-Day Service” is a terrible topic statement. Dilution here also weakens your chances of matching a query intent cleanly enough to earn a snippet.
Fix rule: one H1 per page, describing the content, not the brand and not the button. Style everything else with CSS classes.
Mistake 2: Skipped heading levels
Someone wanted a smaller-looking subhead, so they jumped from H2 straight to H4, or worse, from H1 to H3 across the whole template.
Before
<h1>Roof Replacement Cost Guide</h1>
<h2>Average Cost by Material</h2>
<h4>Asphalt Shingles</h4>
<h4>Standing Seam Metal</h4>
<h5>Labor Factors</h5>
After
<h1>Roof Replacement Cost Guide</h1>
<h2>Average Cost by Material</h2>
<h3>Asphalt Shingles</h3>
<h3>Standing Seam Metal</h3>
<h3>Labor Factors</h3>
Why it hurts
A skipped level creates an ambiguous parent-child relationship. Is “Labor Factors” a sub-point of standing seam metal, or a sibling section about all materials? A parser building a content tree has to make an assumption, and when the assumption is wrong, the passage boundary is wrong too. That is how you end up with a snippet that quotes half of one section and the heading from another. Screen readers announce the same confusion out loud.
Fix rule: heading levels may go down one step at a time. They can jump back up any number of steps when a new section starts.

Mistake 3: Headings wrapped around navigation, sidebars, and widgets
This is the single most common issue we find on WordPress and Webflow builds, usually because a theme or widget ships with H2 or H3 baked into its title element.
Before
<nav>
<h2>Main Menu</h2>
<ul><li><a href='/services'>Services</a></li></ul>
</nav>
<aside>
<h2>Recent Posts</h2>
<h3>Newsletter Signup</h3>
<h2>Categories</h2>
</aside>
<footer><h2>Quick Links</h2></footer>
After
<nav aria-label='Main'>
<ul><li><a href='/services'>Services</a></li></ul>
</nav>
<aside aria-label='Sidebar'>
<p class='widget-title'>Recent posts</p>
<p class='widget-title'>Newsletter signup</p>
<p class='widget-title'>Categories</p>
</aside>
<footer><p class='widget-title'>Quick links</p></footer>
Why it hurts
Boilerplate headings appear on every single page of the site. That means every page shares an identical partial outline, and your unique article headings get buried among repeated ones. Worse, sidebar H2s frequently sit between body H2s in the DOM order, which chops your main content into fragments that make no logical sense. When a crawler tries to extract a clean answer block, it may hit “Newsletter Signup” as the section boundary.
Fix rule: use headings only for content sections. For navigation and widget labels, use a paragraph or span with a CSS class, or if a landmark genuinely needs a label for accessibility, use aria-label or a visually hidden heading placed at the correct level. SEO Headings: Do Header Tags Matter Anymore is a useful companion to this.
Mistake 4: Empty, icon-only, or decorative headings
Page builders love to leave empty heading blocks behind, and designers sometimes wrap an icon or a divider graphic in a heading tag.
Before
<h2></h2>
<h3><i class='icon-star'></i></h3>
<h2><img src='divider.png' alt=''></h2>
<h2> </h2>
After
<h2>What our maintenance plan includes</h2>
<p class='icon-row'><i class='icon-star' aria-hidden='true'></i></p>
<hr class='divider'>
Why it hurts
An empty heading is a section boundary with no label. It tells the parser “a new topic starts here” and then refuses to say what the topic is. Content that follows an unlabeled heading is effectively orphaned: it has no descriptive anchor to be matched against a query. Empty headings also fail WCAG 2.4.6 and show up in accessibility audits, which matters if your site has any compliance requirement.
Mistake 5: Real headings marked up as bold divs
The inverse problem. The page looks perfectly structured to a human, but every subhead is a div or a strong with a big font size, so the machine-readable outline is a single H1 and nothing else.
Before
<h1>Water Damage Restoration Process</h1>
<div class='big-bold'>Step 1: Emergency Water Extraction</div>
<p>...</p>
<p><strong>Step 2: Structural Drying</strong></p>
<p>...</p>
After
<h1>Water Damage Restoration Process</h1>
<h2>Step 1: Emergency water extraction</h2>
<p>...</p>
<h2>Step 2: Structural drying</h2>
<p>...</p>
Why it hurts
Bold text carries almost no structural weight. Without heading tags, your 2,000-word guide is one undifferentiated block, and list-style featured snippets become far harder to earn because there are no step boundaries to enumerate. If you want Google to build a numbered-list snippet from your process, the steps need to be headings.
Note the styling stays identical. You keep the CSS class on the h2 if you need the exact same look:
<h2 class='big-bold'>Step 1: Emergency water extraction</h2>

Mistake 6: Vague, duplicated, or keyword-stuffed headings
Structure can be perfect while the text inside it says nothing useful.
Before
<h1>Houston Plumbing Services | Plumber Houston | Best Plumber</h1>
<h2>Overview</h2>
<h2>More Info</h2>
<h2>Houston Plumbing Services</h2>
<h2>Houston Plumbing Services</h2>
After
<h1>Houston Plumbing Services</h1>
<h2>What a plumbing inspection includes</h2>
<h2>Average repair cost in Harris County</h2>
<h2>How fast can a plumber get to you</h2>
<h2>When to repipe instead of repair</h2>
Why it hurts
Duplicate and generic headings give the extraction system nothing to match. “Overview” matches no query. Repeating the same phrase four times reads as manipulation and, more practically, means four sections are indistinguishable from each other. The corrected version turns each heading into a question or entity a real user searches for, which is exactly the input a snippet or an AI answer needs.
Practical heading-writing rules:
- Keep headings under about 70 characters so they read cleanly in a table of contents
- Phrase at least a few H2s or H3s as natural questions
- Put the answer in the first 40 to 60 words directly under the heading
- Use one clear idea per heading, no pipes or keyword lists
- Vary phrasing across sections instead of repeating the target keyword
Mistake 7: DOM order that does not match visual order
CSS Grid, Flexbox order, and absolute positioning make it easy to display headings in one sequence while the source code says something completely different. Tabs and accordions add another layer: content that is visually hidden but present in the DOM, or headings that only get injected after a JavaScript interaction. This is the sort of thing a solid web design agency ships without fuss.
Before
<div class='grid'>
<h2 style='order:3'>Pricing</h2>
<h2 style='order:1'>How It Works</h2>
<h2 style='order:2'>Who It Is For</h2>
</div>
<div class='tab-panel' hidden>
<h2>Frequently Asked Questions</h2>
</div>
After
<div class='grid'>
<h2>How it works</h2>
<h2>Who it is for</h2>
<h2>Pricing</h2>
</div>
<section class='faq'>
<h2>Frequently asked questions</h2>
<h3>Do you offer weekend service?</h3>
<p>Yes...</p>
</section>
Why it hurts
Crawlers read source order and the rendered accessibility tree, not your visual layout. A mismatch means the outline the engine builds does not match the experience users get, which undermines the whole point of hierarchy. Content locked behind a click is still indexable in most cases, but content injected only after a click may not be, and headings buried in collapsed panels rarely win snippets. If a section matters for search, put it in the initial HTML in the correct order and let CSS handle presentation without reordering.

Diagnostic summary table
| Mistake | Main impact | Fix in one line |
|---|---|---|
| Multiple H1s for styling | Topic dilution, weaker query matching | One content H1, style the rest with CSS |
| Skipped levels | Broken parent-child relationships | Descend one level at a time |
| Headings on nav, sidebar, footer | Boilerplate fragments the outline | Use paragraphs or aria-label instead |
| Empty or icon-only headings | Unlabeled sections, WCAG failure | Delete them or add real text |
| Headings marked up as bold divs | No section boundaries, no list snippets | Convert to real h2 or h3, keep the class |
| Vague or duplicated headings | Nothing to match a query against | Write descriptive, question-style headings |
| DOM order differs from visual order | Outline does not match the page | Fix source order, style without reordering |
How to audit heading hierarchy on your own site
- Check the rendered outline, not the source. Open Chrome DevTools, go to Elements, then the Accessibility pane, and inspect the accessibility tree. This shows what assistive tech and, broadly, what parsers see after JavaScript runs.
- Run a browser extension pass. HeadingsMap or the WAVE toolbar will render a visual outline in seconds and flag skipped levels and empty headings.
- Crawl the whole site. Screaming Frog, Sitebulb, or Semrush Site Audit will report missing H1s, multiple H1s, duplicate H1s across URLs, and H1 length in bulk. Sort by template to find the systemic issues.
- Isolate template noise. Compare a blog post to a service page. Any heading that appears on both is boilerplate and probably should not be a heading.
- Score each page against intent. Read only the headings. If you cannot summarize the page from that outline alone, neither can a crawler or a language model.
- Re-request indexing on high-value URLs after the fix and track snippet ownership for the target queries over the following four to eight weeks.
A realistic expectation for results
On a page that already ranks in positions 3 to 10, restructuring headings so a section directly answers the query is one of the more reliable ways to move into the snippet or into an AI answer citation. On a page that is not ranking at all, headings will not save it. Treat heading hierarchy as an amplifier for content that already deserves to rank, not as a growth tactic on its own.
Frequently asked questions
When should I use H1, H2, H3, H4, H5 and H6?
Use one H1 for the page topic, H2s for main sections, and H3s for subsections inside those H2s. H4 through H6 are for deeper nesting such as specifications, sub-steps, or documentation reference. Most marketing and blog pages never need to go past H3.
Is it ever acceptable to have more than one H1?
The HTML spec allows it, and Google has said multiple H1s will not break your page. But because the outline algorithm was never implemented in browsers, a single H1 remains the clearest and safest choice for both crawlers and screen readers. Keep one.
Does heading hierarchy affect featured snippets?
Indirectly but meaningfully. Snippets are usually extracted from a heading plus the text immediately below it. A clear question-style heading followed by a concise 40 to 60 word answer makes your passage far easier to lift than the same information buried mid-paragraph with no heading above it.
Should the H1 match the title tag exactly?
They should cover the same topic but do not need to be identical. The title tag is written for the results page and click-through, often with a brand suffix. The H1 is written for the person who already landed on the page. Keep the primary keyword in both, phrased naturally.
Do headings still matter for AI search and chat assistants?
Yes, arguably more than before. Retrieval systems chunk documents into passages before ranking them, and headings are a primary chunking signal. A well-structured page produces clean, self-contained passages that are easier to retrieve and quote accurately.
What is the fastest way to check heading structure for free?
Install the HeadingsMap extension for Chrome or Firefox and open it on any page. It renders the full H1 to H6 outline and flags skipped levels immediately. For sitewide checks, the free tier of Screaming Frog covers up to 500 URLs.
Need a second set of eyes on your site structure?
Heading problems are usually template problems, which means fixing one page fixes hundreds. If you want a full technical audit that covers heading hierarchy, internal linking, and snippet opportunities across your site, get in touch with the Houston DOD team and we will walk through your current outline with you.