# Blog Post Heading Hierarchy Guide

**Last Updated:** 2026-02-11

Complete guide to blog post heading hierarchy requirements, best practices, validation, and fixing procedures.

## Overview

Proper heading hierarchy is critical for SEO, accessibility, and content structure. This guide documents the requirements, common issues, and procedures for maintaining correct heading hierarchy across all blog posts.

## Requirements

### Critical Rules

1. **Post Title is H1**: The post title is displayed as H1 in the `PostHeader.php` component. Content should never contain H1 tags.

2. **First Content Heading is H2**: The first heading in post content must always be H2 (never H3, H4, or other levels).

3. **Sequential Hierarchy**: Headings must follow sequential order:

   - H2 → H3 → H4 (no skipping levels)
   - Never: H2 → H4 (skipped H3)
   - Never: H3 → H2 (backwards hierarchy)

4. **No Backwards Hierarchy**: Headings should never decrease in level:

   - ❌ H3 → H2 (invalid)
   - ❌ H4 → H2 (invalid)
   - ✅ H2 → H3 → H3 (valid - can repeat same level)

5. **Semantic Meaning**: Headings should reflect actual content structure, not just styling preferences.

## Best Practices

### Recommended Structure

```
H1: Post Title (in PostHeader component)
  H2: Main Section 1
    H3: Subsection 1.1
    H3: Subsection 1.2
  H2: Main Section 2
    H3: Subsection 2.1
      H4: Sub-subsection 2.1.1 (if needed)
    H3: Subsection 2.2
  H2: Main Section 3
```

### Level Guidelines

- **H1**: Post title only (in header component)
- **H2**: Main sections (5-10 for most posts; 8-12 for main topics per [CONTENT_DEPTH_GUIDELINES.md](CONTENT_DEPTH_GUIDELINES.md))
- **H3**: Subsections under H2 (optional; use only when they improve structure)
- **H4**: Subsections under H3 (use sparingly)
- **H5-H6**: Avoid if possible

### When H2 Stands Alone

**H2 + paragraphs is valid** when the section is short or flows linearly. H3s are optional—use only when they improve structure and scannability.

- **Short sections:** A single H2 with 2–3 paragraphs is sufficient; no subdivision needed
- **Linear narrative:** Content moves in a straight line; H3s would feel forced
- **Best practice (Yoast, WebAIM):** Headings support the reader, not decorate the page. Don't add H3s for style

### When to Use H3 (Decision Criteria)

**Do not use word count as primary H3 criterion.** Base decisions on structure, TOC value, and scannability. Per Yoast and WebAIM: headings support the reader, not decorate the page.

**Convert bold inline items to H3** when an H2 contains multiple subtopics introduced by bold text (e.g. "**Schichtarbeit:** ... **Kurzarbeit:** ... **Kündigung:** ...") **and each has 2+ sentences**. H3s improve TOC, scannability, and SEO.

**Add H3s for structured sections** when: (1) distinct subtopics (Formel | Was zählt | Beispiel); (2) step-by-step or comparison items; (3) TOC jump links would help readers (PAA, featured-snippet potential). Section length is an optional secondary signal—structure and value matter more than word count. Plan H3s in the outline phase—see [CONTENT_DEPTH_GUIDELINES.md](CONTENT_DEPTH_GUIDELINES.md) for examples and checklist.

**List vs H3:**
- **Brief items (1-2 sentences)** → list with bold lead-in
- **Substantial items (2+ paragraphs)** → H3
- **4+ consecutive brief items** → prefer list over 4+ H3s (Semji)
- **Bold inline + substantial answer (2+ sentences)** → consider H3 when it would improve TOC, scannability, or featured-snippet potential. Applies to questions (PAA, definition, clarification) or any distinct subtopic. Evaluate per context: does a TOC jump link add value? Would it feel forced? Use when it improves structure—not as a rigid rule.

**PAA question + list answer:** When a PAA question (e.g. "Was gehört zum X?", "Was macht man bei X?") is answered by a list under a broader H2, use **H3 for the question** and keep the list as the answer. Do not leave the question as bold inline text. Example: H2 "Ziele und Aufgaben" → H3 "Was gehört zum Wissensmanagement?" → intro paragraph → ordered list. This improves TOC jump links, featured-snippet matching, and voice search.

### When H3 Follows H2: Lead-In Paragraphs

When H3s are used, an intro paragraph between the H2 and the first H3 is valid and often improves flow.

- **Good:** H2 → 1–2 sentences of context or summary → H3 → content
- **Bad:** H2 → H3 immediately when the reader would benefit from context; cheesy "coming up next" phrases

See [CONTENT_WRITING_GUIDELINES.md](CONTENT_WRITING_GUIDELINES.md) for the full pattern and anti-cheesy guidance.

### Common Patterns

**List-Based Posts** (e.g., "5 Tips for..."):

- H2: "Tip 1: Title"
- H2: "Tip 2: Title"
- H2: "Tip 3: Title"

**Guide Posts** (e.g., "How to..."):

- H2: "Introduction"
- H2: "Step 1: Title"
  - H3: "Details"
- H2: "Step 2: Title"
  - H3: "Details"

**FAQ Posts**:

- H2: "Question 1"
- H2: "Question 2"
- H2: "FAQ" (if FAQ section exists)

### Question Format vs Declarative Format for Lexikon & Ratgeber (AEO Best Practice)

**Rule:** Match H2 style to user intent—use question format when a PAA or GSC query matches the section topic; use declarative format when narrative flow, clarity, or instructional structure matters more. Do not force questions everywhere.

**When to use question format:**

- Section directly matches PAA or explicit user query
- Lexikon (definition/explainer) posts where question phrasing improves featured snippet and voice search visibility
- Topics where PAA questions exist in SERPs

**Examples (question):**

- ✅ **GOOD:** "Was ist ein Midijob?", "Ab wann gilt ein Midijob?", "Wie melde ich einen Midijob an?", "Welche Vor- und Nachteile hat ein Midijob?"
- ❌ **BAD:** "Definition von Midijob", "Midijob anmelden", "Vor- und Nachteile eines Midijobs"

**When declarative is preferred:**

- Narrative flow, step-by-step guides, or instructional structure (e.g. "Schritt 1: Erfasse die Mitarbeiter")
- Comparison tables or structured sections (e.g. "Unterschiede zwischen Minijob und Midijob")
- Rechtliche Grundlagen (e.g. "Rechtliche Grundlagen: § 312 SGB III")
- Fazit, Checkliste, or other structural sections (e.g. "Verkürzung und Verhandlungstipps", "Krankheit und Verlängerung der Probezeit")

**Examples (declarative):**

- ✅ **GOOD:** "Rechtliche Grundlagen", "Fazit", "Verkürzung und Verhandlungstipps"
- ❌ **BAD:** Forcing "Was sind rechtliche Grundlagen?" when "Rechtliche Grundlagen" reads more naturally

**Examples from existing posts (declarative vs question mix):**

- **kuendigungsfrist:** Questions (Was ist eine Kündigungsfrist?, Wie berechnet man...?) + declarative (Kündigungsfrist bei verschiedenen Beschäftigungsverhältnissen, Häufige Fehler und Fallstricke, Best Practices und Tipps, Fazit)
- **urlaubsanspruch:** "Der Mindestanspruch laut Bundesurlaubsgesetz", "Der Ordio Urlaubsrechner" (declarative) + question-style H2s (Urlaubsanspruch bei Teilzeitmitarbeitern?, Ab wann hat man Urlaubsanspruch?)
- **midijob:** Mostly questions + "Fazit" (declarative)

**H2 vs FAQ separation:** Use H2s for main sections. FAQs should supplement, not duplicate. Do not add an FAQ whose question is already answered in an H2 section. Prefer unique follow-up questions or different search intents for FAQs. Per Google (2020): duplicate rule applies to cross-page duplication only. Per John Mueller (2022): FAQ schema can mark up Q&A visible anywhere on the page, including H2 sections. We avoid duplicate accordion content for UX. See [FAQ_H2_SEPARATION_GUIDELINES.md](FAQ_H2_SEPARATION_GUIDELINES.md) and run `check-h2-faq-overlap.php` before finalizing.

## Common Issues

### Issue 1: Wrong First Level

**Problem**: Content starts with H3 or H4 instead of H2.

**Example**:

```html
<!-- ❌ Wrong -->
<h3>First Section</h3>

<!-- ✅ Correct -->
<h2>First Section</h2>
```

**Fix**: Convert first heading to H2, adjust subsequent headings proportionally.

### Issue 2: Backwards Hierarchy

**Problem**: Heading level decreases (e.g., H3 → H2).

**Example**:

```html
<!-- ❌ Wrong -->
<h2>Main Section</h2>
<h3>Subsection</h3>
<h2>Another Main Section</h2>
<!-- Backwards! -->

<!-- ✅ Correct -->
<h2>Main Section</h2>
<h3>Subsection</h3>
<h3>Another Subsection</h3>
<!-- Same level or deeper -->
```

**Fix**: Adjust backwards headings to maintain or increase level.

### Issue 3: Skipped Levels

**Problem**: Heading skips a level (e.g., H2 → H4).

**Example**:

```html
<!-- ❌ Wrong -->
<h2>Main Section</h2>
<h4>Subsection</h4>
<!-- Skipped H3! -->

<!-- ✅ Correct -->
<h2>Main Section</h2>
<h3>Subsection</h3>
```

**Fix**: Insert missing level (H2 → H4 becomes H2 → H3).

### Issue 4: All Same Level

**Problem**: All headings are the same level when they should be hierarchical.

**Example**:

```html
<!-- ❌ Wrong (if these should be hierarchical) -->
<h3>Section 1</h3>
<h3>Section 2</h3>
<h3>Section 3</h3>

<!-- ✅ Correct -->
<h2>Section 1</h2>
<h2>Section 2</h2>
<h2>Section 3</h2>
```

**Fix**: Convert all to appropriate level (typically H2 for main sections).

## Validation Tools

### Analysis Script

**Location**: `v2/scripts/blog/analyze-heading-hierarchy.py`

**Usage**:

```bash
python3 v2/scripts/blog/analyze-heading-hierarchy.py
```

**Output**:

- Summary of issues by type
- Detailed report per post
- JSON report saved to `docs/data/blog-heading-hierarchy-analysis-*.json`

### Validation Script

**Location**: `v2/scripts/blog/validate-heading-fixes.py`

**Usage**:

```bash
python3 v2/scripts/blog/validate-heading-fixes.py
```

**Output**:

- Summary of validation results
- List of posts with issues (if any)
- Exit code 0 if all valid, 1 if issues found

### Fix Script

**Location**: `v2/scripts/blog/fix-heading-hierarchy.py`

**Usage**:

```bash
# Dry run (no changes)
python3 v2/scripts/blog/fix-heading-hierarchy.py --dry-run --batch all

# Fix all posts (with backup)
python3 v2/scripts/blog/fix-heading-hierarchy.py --backup --batch all

# Fix specific batch
python3 v2/scripts/blog/fix-heading-hierarchy.py --backup --batch wrong_first
python3 v2/scripts/blog/fix-heading-hierarchy.py --backup --batch backwards

# Fix single file
python3 v2/scripts/blog/fix-heading-hierarchy.py --backup --file lexikon/haccp.json
```

**Options**:

- `--dry-run`: Preview changes without modifying files
- `--backup`: Create backup before fixing
- `--batch`: Process batch (`wrong_first`, `backwards`, `all`)
- `--file`: Fix single file (relative to posts dir)

## Fix Algorithm

The fix script uses the following algorithm:

1. **Extract all headings** from HTML content
2. **Calculate offset** needed (if starts with H3, offset = -1 to make H2)
3. **Apply initial offset** to all headings
4. **Fix backwards hierarchies**: If heading decreases, make it same level as previous
5. **Fix skipped levels**: If heading skips level, make it one level deeper than previous
6. **Ensure bounds**: Minimum H2, maximum H6
7. **Replace headings** in HTML while preserving all attributes and content

## Backup & Recovery

### Creating Backups

Backups are automatically created when using `--backup` flag:

**Location**: `docs/backups/blog-heading-fixes/{timestamp}/`

**Structure**: Mirrors `v2/data/blog/posts/` directory structure

### Restoring from Backup

```bash
# Restore from specific backup
BACKUP_DIR="docs/backups/blog-heading-fixes/20260110-212617"
cp -r "$BACKUP_DIR"/* v2/data/blog/posts/
```

## SEO & Accessibility Impact

### SEO Benefits

- **Search Engine Understanding**: Proper hierarchy helps search engines understand content structure
- **Featured Snippets**: Well-structured headings improve chances of appearing in featured snippets
- **Content Organization**: Clear hierarchy signals quality content

### Accessibility Benefits

- **Screen Reader Navigation**: Users can navigate by headings
- **Document Outline**: Screen readers generate table of contents from headings
- **Keyboard Navigation**: Proper hierarchy enables efficient keyboard navigation

## Maintenance

### Regular Validation

Run validation script periodically to catch issues early:

```bash
# Weekly validation
python3 v2/scripts/blog/validate-heading-fixes.py
```

### When Adding New Posts

1. Ensure first heading is H2
2. Maintain sequential hierarchy
3. Avoid backwards or skipped levels
4. Validate with analysis script before publishing

### When Migrating Content

1. Run analysis script to identify issues
2. Fix issues before migration
3. Validate after migration
4. Document any manual fixes needed

## Related Documentation

- `docs/content/blog/BLOG_TEMPLATE_BEST_PRACTICES.md` - Best practices including heading hierarchy
- `.cursor/rules/blog-templates.mdc` - Cursor rules for blog templates
- `docs/content/blog/TEMPLATE_DEVELOPMENT_GUIDE.md` - Template development guide

## Scripts Reference

- `v2/scripts/blog/analyze-heading-hierarchy.py` - Analysis script
- `v2/scripts/blog/fix-heading-hierarchy.py` - Fix script
- `v2/scripts/blog/validate-heading-fixes.py` - Validation script
