Skip to content
← Back to Functions
Code

Heading Outline Auditor

Checks H1/H2/H3 structure for missing, duplicate, or illogical headings.

Function signature

ogAuditHeadingOutline(html)

Categories

  • SEO and Routing

Parameters

htmlHTML fragment to inspect for heading outline problems.

Return value

Public-safe status string returned by the function for controller branching or logging.

  • success
  • message
  • data

Compatibility

Existing function name, slug, path, and call order preserved; advertised metadata corrected to the actual source behavior.

Minimum PHP version: 7.4

Security notes

Use caller-owned allowlists and context-specific escaping; validate file paths, routes, email tokens, cart totals, discount rules, and tax-region rules before production use.

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.
 */

/**
 * Checks H1/H2/H3 structure for missing, duplicate, or illogical headings.
 *
 * Primary use case: SEO/content QA.
 * Typical inputs: HTML or parsed headings.
 * Typical output: outline report.
 *
 * Implementation note: Use as audit; do not auto-rewrite content blindly.
 *
 * @param string $html HTML content to audit.
 * @return array Heading outline audit report.
 */
function ogAuditHeadingOutline($html) {
	$result = array(
		'success' => false,
		'message' => '',
		'data' => array()
	);

	$html = (string)$html;
	if (empty($html)) {
		$result['message'] = 'HTML content is required.';
		return $result;
	}

	$matches = array();
	preg_match_all('/<h([1-3])[^>]*>(.*?)<\/h\1>/is', $html, $matches, PREG_SET_ORDER);
	$headings = array();
	$warnings = array();
	$h1_count = 0;
	$last_level = 0;

	foreach ($matches as $match) {
		$level = (int)$match[1];
		$text = trim(strip_tags($match[2]));
		if ($level == 1) {
			$h1_count++;
		}
		if ($last_level > 0 && $level > ($last_level + 1)) {
			$warnings[] = 'Heading level jumps from H' . $last_level . ' to H' . $level . '.';
		}
		$last_level = $level;
		$headings[] = array('level' => $level, 'text' => $text);
	}

	if ($h1_count == 0) {
		$warnings[] = 'Missing H1 heading.';
	}
	if ($h1_count > 1) {
		$warnings[] = 'Multiple H1 headings detected.';
	}

	$result['success'] = true;
	$result['message'] = 'Heading outline audited.';
	$result['data'] = array(
		'headings' => $headings,
		'h1_count' => $h1_count,
		'warnings' => $warnings
	);

	return $result;
}