Skip to content
← Back to Snippets
Code

Heading Outline Integrity Check

Audits a page heading sequence for missing H1 tags, skipped levels, and duplicate top-level headings.

Purpose

Audits a page heading sequence for missing H1 tags, skipped levels, and duplicate top-level headings.

Snippet details

ContextSeoLevelAdvancedCopy-and-paste statusMarked safe after review.

Categories

  • Security

Code

<?php

/*
 * Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
 * Free for personal and internal use. Paid project use requires visible credit
 * to Jeffery L. Paris. Corporate use requires a paid license fee unless a
 * separate written license states otherwise.
 */

/**
 * Heading Outline Integrity Check.
 *
 * Purpose:
 * Audits a page heading sequence for missing H1 tags, skipped levels, and duplicate top-level headings.
 *
 * @param array $headings Ordered heading rows with level and text.
 * @return array Heading audit report.
 */
function ogSnippetHeadingOutlineIntegrityCheck(array $headings): array {
	$issues = array();
	$h1_count = 0;
	$previous_level = 0;
	$seen_h1 = array();

	foreach ($headings as $index => $heading) {
		$level = 0;
		if (isset($heading['level'])) {
			$level = (int) $heading['level'];
		}

		$text = '';
		if (isset($heading['text'])) {
			$text = trim((string) $heading['text']);
		}

		if ($level === 1) {
			$h1_count++;
			if (isset($seen_h1[$text])) {
				$issues[] = 'Duplicate H1 at row '.$index.': '.$text;
			}
			$seen_h1[$text] = true;
		}

		if ($previous_level > 0 && $level > ($previous_level + 1)) {
			$issues[] = 'Skipped heading level before row '.$index;
		}

		if ($text === '') {
			$issues[] = 'Empty heading text at row '.$index;
		}

		$previous_level = $level;
	}

	if ($h1_count === 0) {
		$issues[] = 'Missing H1 heading';
	}

	if ($h1_count > 1) {
		$issues[] = 'Multiple H1 headings found: '.$h1_count;
	}

	return array(
		'ok' => count($issues) === 0,
		'issues' => $issues,
		'h1_count' => $h1_count
	);
}

$galactica_headings = array(
	array('level' => 1, 'text' => 'Fleet Status'),
	array('level' => 3, 'text' => 'Jump Coordinates'),
	array('level' => 2, 'text' => 'Civilian Ships')
);

$outline_report = ogSnippetHeadingOutlineIntegrityCheck($galactica_headings);
echo 'Heading issues: '.count($outline_report['issues']);