---
title: "Семантична верстка для AI: що насправді читають краулери"
description: "Що таке семантична верстка і що з неї читає AI. У скані 41 сторінки з видачі Google 78% не мають кількох h1 і пропусків рівнів: це радше поріг, ніж перевага."
date: 2026-10-18
translationOf: semantic-html-for-machines-heading-hierarchy
tags: [aeo, ai-search, html]
---

# Семантична верстка для AI: що насправді читають краулери

Прослухати: [аудіо, 16:17](https://alexturik.com/audio/uk/semantychnyi-html-dlia-ai.mp3)

Семантична верстка для AI означає, що теги HTML описують роль блоку, а не вигляд, а заголовки `h1`-`h6` є в сирому HTML без пропусків рівнів. За Vercel і MERJ, GPTBot, ClaudeBot і PerplexityBot не виконують JavaScript і бачать лише HTML-код. У моєму скані 41 сторінки з видачі Google один `h1` без пропусків мали 32 (78%), тож це радше поріг, ніж перевага.

## Коротко: що з цього читає AI

- За даними Vercel і MERJ (грудень 2024), краулери для AI (штучного інтелекту) GPTBot, ClaudeBot, PerplexityBot не рендерять JavaScript, а Gemini та AppleBot рендерять.
- Сторінки OpenAI, Anthropic, Perplexity про їхніх краулерів не описують розбір `h1`-`h6`, тож дерево заголовків до оцінки абзаців тут лише робоче припущення.
- Скан 41 сторінки з англомовної видачі Google (США), зібраний 9 вересня 2026 року: 32 сторінки (78%) мають один `h1` і жодного пропущеного рівня.
- Дев'ять сторінок (22%) з кількома `h1` чи пропущеним рівнем все одно ранжуються, тож чиста структура заголовків виглядає порогом, який більшість топу вже подолала, а не важелем.
- Третя вада, перший заголовок у DOM (об'єктній моделі документа) не `h1`, є на 9 сторінках (22%); без жодної з трьох вад лишається 26 сторінок (63%).
- Правило для структури заголовків коротке: один `h1`, жодного стрибка вниз більш ніж на один рівень, а підйом угору завжди припустимий.

## Що таке семантична верстка?

Семантична верстка означає, що теги HTML (мови розмітки) описують роль елемента на сторінці, а не його вигляд: `h1` позначає головний заголовок, `nav` навігацію, `article` самостійну статтю. Вигляд задає CSS (каскадні таблиці стилів), тому блок зі стилями заголовка лише виглядає як заголовок і ролі заголовка не має, як пояснює [документація Mozilla](https://developer.mozilla.org/en-US/docs/Glossary/Semantics).

## Чи читають AI-краулери структуру HTML?

Краулери GPTBot, ClaudeBot, PerplexityBot, за незалежними вимірами, беруть сирий HTML і не виконують JavaScript, а чи будують із нього дерево заголовків, вендори не документують. Станом на 18 жовтня 2026 року сторінки [OpenAI](https://developers.openai.com/api/docs/bots), [Anthropic](https://support.claude.com/en/articles/8896518) і [Perplexity](https://docs.perplexity.ai/docs/resources/perplexity-crawlers) про їхніх ботів не описують ні виконання JavaScript, ні розбір `h1`-`h6`. Тому фраза "краулер будує дерево заголовків до оцінки абзацу" є в цій статті робочим описом механізму, а не фактом, який хтось із трьох проголосив.

За даними [Vercel і MERJ](https://vercel.com/blog/the-rise-of-the-ai-crawler) від 17 грудня 2024 року, JavaScript не рендерять GPTBot, ClaudeBot і PerplexityBot, а Gemini та AppleBot рендерять. Краулери ChatGPT і Claude завантажують файли JavaScript у 11,50% і 23,84% запитів відповідно, але не виконують їх. Новіших незалежних вимірів у цій статті немає.

У [документації Google про основи JavaScript SEO](https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics) для Googlebot описано іншу схему: сторінка потрапляє в чергу на рендер, де браузер Chromium без інтерфейсу (headless) виконує JavaScript. Якщо ваші `h1` і `h2` збирає скрипт у браузері, краулер без виконання JavaScript (за Vercel це GPTBot, ClaudeBot, PerplexityBot) не знайде їх у HTML-коді. Googlebot побачить їх після рендеру. Про цю пастку я писав окремо: [The JavaScript Trap](/blog/the-javascript-trap-why-ai-bots-see-empty-pages) (англійською). У [списку AI-краулерів 2026](/uk/aeo/spysok-ai-kraulertiv-2026) описано, які ще боти існують і як їх називає `robots.txt`.

## Як AI-пошук ріже сторінку на фрагменти?

У конвеєрах RAG (генерації з пошуком) текст ділять на фрагменти, або чанки. Наприклад, сплітер (модуль, що ділить текст на фрагменти) `MarkdownHeaderTextSplitter` у LangChain [ділить markdown за заданими заголовками](https://docs.langchain.com/oss/python/integrations/splitters/markdown_header_metadata_splitter) і зберігає їх у метаданих кожного фрагмента. Чи так само влаштований пошук конкретного вендора, вендори не документують, тож далі це робоче припущення. Термін чанкінг пояснено в [глосарії термінів AI-пошуку](/uk/aeo/glossary).

Погана структура ламає дві речі:

1. **Фрагмент потрапляє не під того батька.** Пропущений рівень ніщо не виправляє: алгоритм структури документа з HTML5 (document outline), який міг би вставити неявний `h3`, не підтримує жоден браузер, як показують [тести Адріана Розеллі](https://adrianroselli.com/2016/08/there-is-no-document-outline-algorithm.html). У липні 2022 року його прибрали й зі [специфікації HTML](https://html.spec.whatwg.org/multipage/sections.html#headings-and-outlines), а [MDN (Mozilla Developer Network)](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/Heading_Elements) нині радить не пропускати рівні. Сплітер, який ділить за рівнями (як у [коді LangChain](https://github.com/langchain-ai/langchain/blob/master/libs/text-splitters/langchain_text_splitters/markdown.py)), прикріпить `h4` до найближчого заголовка над ним: після `h2` фрагмент успадкує `h2`, але втратить пропущений `h3`, під яким мав стояти.
2. **Два `h1` розколюють відповідь.** Для сплітера, що ділить за заголовками, два `h1` на сторінці означають два кореневі розділи, тож відповідь, яка мала б лишитися цілою, розпадається.

## Що показав скан 41 сторінки?

У гайдах, які я переглянув, ієрархію заголовків пояснюють від принципів, а що віддали сторінки, які вже ранжуються за темою, не перевіряють. Тому 9 вересня 2026 року я перевірив це на практиці.

Я взяв топ-20 органічної видачі Google (США, англійською мовою) за трьома запитами: semantic html for ai crawlers, heading hierarchy seo ai і do ai crawlers read html structure. Сирий HTML кожної сторінки я завантажив через `curl` без виконання JavaScript, а заголовки `h1`-`h6` витягнув регулярним виразом. Пропуском рівня вважав стрибок вниз більш ніж на один рівень. З вибірки прибрав соцмережі та відео, що віддають порожню оболонку односторінкового застосунку (YouTube, Facebook, LinkedIn, Reddit), і дві сторінки, які віддали Cloudflare 403 (Stack Overflow та ще один невеликий сайт). Лишилася 41 сторінка.

| Показник | Значення |
|---|---|
| Сторінок у вибірці | 41 |
| Один `h1` і жодного пропущеного рівня | 32 (78%) |
| Кілька `h1` або пропущений рівень | 9 (22%) |
| Перший заголовок у DOM не `h1` | 9 (22%) |
| Жодної з трьох вад (кілька `h1`, пропущений рівень, перший заголовок не `h1`) | 26 (63%) |
| Хоча б одна з трьох вад | 15 (37%) |
| Медіана заголовків на сторінку | 18 (від 1 до 104) |

Один `h1` і жодного пропущеного рівня мають 32 з 41 сторінки (78%). Решта дев'ять мають дві вади, що перетинаються: шість сторінок містять кілька `h1`, а шість пропускають рівень, найчастіше з `h2` на `h4` (4 сторінки), рідше з `h1` на `h3` (3 сторінки). Три сторінки мають обидві вади. Якщо рахувати ще й перший заголовок не `h1`, хоча б одну з трьох вад мають 15 сторінок (37%).

На 9 з 41 сторінки першим заголовком у сирому DOM є не `h1`. Імовірно, мітка або позначка "featured" у верхньому блоці сторінки використовує тег заголовка раніше за тему сторінки, але скан фіксує лише рівень першого заголовка, тож це лишається припущенням. Лише три з цих дев'яти сторінок мають також кілька `h1` або пропущений рівень, решта шість чисті за іншими показниками. Приклади зі скану від 9 вересня 2026 року, які 18 жовтня 2026 року я перевірив повторно, без оцінки сайтів:

- **Сторінка finsweet.com/seo/article/heading-structure:** один `h1`, 22 заголовки, пропуск із `h2` на `h4`.
- **Сторінка advancedwebranking.com/blog/what-ai-search-crawlers-read:** три `h1`, 36 заголовків, пропуски з `h3` на `h5`, а також з `h4` на `h6`.

### Чи допомагає чиста ієрархія заголовків ранжуванню?

Чесне прочитання цих чисел таке: гігієна, а не важіль. Чисту структуру заголовків має більшість сторінок: 32 з 41 (78%) за двома ознаками й 26 з 41 (63%) за всіма трьома. Дев'ять сторінок із кількома `h1` чи пропущеним рівнем потрапили у видачу попри ці вади. Коли більшість топу це вже має, перевага від цього, найімовірніше, мала. Така структура навряд чи відрізняє позицію 2 від позиції 11: позицій у моїх даних немає, але нею ділиться забагато сторінок. Три межі звужують це прочитання, а не пом'якшують його:

- **Один зріз, один ринок, один день.** Скан пройшов 9 вересня 2026 року лише на англомовній видачі Google (США). Це не тренд, і він нічого не каже про іншу дату, про українську видачу чи про інший набір запитів.
- **Сирий HTML без рендеру.** `curl` не виконує JavaScript, тому сторінка, що збирає заголовки в браузері, у цих даних виглядає гірше, ніж її бачить Googlebot після рендеру. [Документація Google](https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics) описує обхід і рендер окремими кроками, а скан відтворює лише перший.
- **Поширеність, а не кореляція.** Скан виміряв, скільки сторінок видачі мають один `h1` і жодного пропущеного рівня, а не чи випереджають такі сторінки решту. Для цього потрібні позиції для всіх 41 рядків датасету, яких там немає.

## Що таке H1, H2 і H3 у SEO?

Теги `h1`-`h6` задають [шість рівнів заголовків](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/Heading_Elements): `h1` найвищий, `h6` найнижчий, а рівень визначає число в назві тега. Для машини це не розмір шрифту, а заява про місце фрагмента в документі. Чи піднімає чиста ієрархія сторінку у видачі, мій скан не показав. Якщо прийняти робоче припущення з початку статті, кожен рівень заявляє системі пошуку фрагментів ось що:

| Тег | Що він заявляє системі пошуку фрагментів | Що ламається при неправильному вжитку |
|---|---|---|
| `h1` | Про що ця сторінка | Два `h1`, і в сторінки немає єдиної теми, з якою можна зіставити запит |
| `h2` | Розділ верхнього рівня, придатний до цитування окремо | Якщо `h2` пропущено, `h3` лишається без розділу верхнього рівня |
| `h3` | Підрозділ `h2` над ним | `h3` без батьківського `h2` стає фрагментом-сиротою без контексту |
| `div` зі стилями заголовка | Нічого | Розділ невидимий для сплітера, його текст зливається з попереднім |

Останній рядок найдорожчий. Блок `div` зі стилем `text-2xl font-bold` для читача в браузері виглядає як заголовок, а для парсера як абзац, тож розділ, який він відкриває, приклеюється до того, що було перед ним.

Заголовки називають розділ для машини, а [розмітка JSON-LD (структуровані дані)](/uk/aeo/json-ld-dlia-ai) типізує те, що в ньому лежить, для індексаторів на кшталт Google. Заголовки відповідають на питання, до якого місця належить уривок, а розмітка на питання, що це за об'єкт.

### Коли використовувати H1, H2, H3, H4, H5, H6?

Правило коротке: один `h1` на сторінку, жодних пропусків рівнів під час спуску вниз, а повернення вгору завжди припустиме. [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/Heading_Elements) радить один `h1`, що описує вміст сторінки, і вкладати заголовки без пропусків. [W3C](https://www.w3.org/WAI/tutorials/page-structure/headings/) додає, що пропущені рівні плутають, а закриваючи підрозділ, рівні пропускати можна. Ось як виглядає правильна структура сторінки продукту:

```html title="product-page.html"
<header>
  <a href="/" aria-label="На головну">
    <img src="/logo.svg" alt="Логотип компанії">
  </a>
</header>

<main>
  <article>
    <h1>Платформа автоматизації для інженерних команд</h1>

    <section aria-labelledby="features">
      <h2 id="features">Можливості</h2>

      <h3>Швидкість</h3>
      <p>Завдання виконуються паралельно.</p>

      <h3>Безпека</h3>
      <p>Дані шифруються під час передавання й зберігання.</p>

      <h4>Журнали аудиту</h4>
      <p>Журнали можна експортувати у зовнішню систему.</p>
    </section>

    <section aria-labelledby="pricing">
      <h2 id="pricing">Ціни</h2>

      <h3>Тариф для малих команд</h3>
      <p>Для команд до п'яти людей.</p>

      <h3>Тариф для великих команд</h3>
      <p>Для команд без обмежень на кількість людей.</p>
    </section>
  </article>
</main>
```

- **Логотип у `header` не є `h1`.** Це посилання з `aria-label`. Воно повторюється на кожній сторінці й не описує тему конкретного документа.
- **Тег `h1` лежить у `main` і називає сторінку точно.** Не "Ласкаво просимо", а конкретна тема, яку можна проіндексувати.
- **Тег `h4` вкладений у `h3` "Безпека", а не висить сам.** Якби поставити цей `h4` просто під `h2` "Можливості", ніхто не вигадав би пропущений `h3`, а фрагмент прикріпився б до "Можливостей", а не до "Безпеки".

## Типові помилки й як їх знайти

Відкрийте будь-яку сторінку, перейдіть на вкладку Console в інструментах розробника (DevTools) і виконайте цей код. Він використовує сучасні стандарти й не потребує jQuery.

```js title="audit-headings.js"
const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
const headingsData = Array.from(headings).map((heading, index) => {
  return {
    order: index,
    level: heading.tagName,
    text: heading.innerText.trim().slice(0, 60),
    hidden:
      heading.classList.contains('sr-only') ||
      heading.offsetParent === null,
  };
});

console.table(headingsData);
```

Нижче типові помилки та спосіб знайти кожну, від найчастіших у скані до тих, яких скан не міряв:

1. **Перший заголовок у DOM не `h1`** (9 з 41 сторінки у скані). Як знайти: перший рядок таблиці має бути `H1`.
2. **Кілька `h1`** (6 з 41). Як знайти: у колонці `level` має бути рівно один `H1`.
3. **Пропущений рівень** (6 з 41, найчастіше з `h2` на `h4`). Як знайти: кожен наступний рівень у колонці `level` не глибший за попередній більш ніж на один.
4. **Заголовок зроблено з `div`.** Читач бачить заголовок, парсер бачить абзац. Як знайти: код такий елемент пропустить, тож звіряйте таблицю з макетом.
5. **Заголовок сховано через `display: none`.** Елемент зникає з дерева доступності й не озвучується програмою екранного читання (скрінрідером), як [пише MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/display). Як знайти: перегляньте рядки з `hidden: true`.
6. **Заголовки з'являються лише після виконання скриптів сторінки.** Наш код бачить DOM уже після них, тож цього не покаже. Як знайти: порівняйте таблицю з сирим HTML у `view-source:`.

Заголовок, якого не видно за дизайном, ховайте класом `sr-only`: за [документацією Tailwind](https://tailwindcss.com/docs/screen-readers) він ховає елемент візуально, але не від скрінрідерів. Варіант із Tailwind v4 виглядає так:

```css title="sr-only-tailwind-v4.css"
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border-width: 0;
}
```

Якщо знайшлася хоч одна з помилок вище, є два шляхи. Основний: переписати DOM так, щоб структура відповідала логіці контенту. Тимчасовий: додати заголовки `sr-only` там, де потрібен смисловий місток між рівнями, доки не дійшла черга до рефакторингу.

## Чек-лист: семантична верстка для AI

1. Відкрийте `view-source:` сторінки й переконайтеся, що заголовки є в HTML ще до виконання JavaScript.
2. Перевірте, що на сторінці рівно один `h1` і він називає тему подібно до `title`.
3. Переконайтеся, що перший заголовок у DOM це `h1`, а не мітка з верхнього блоку сторінки.
4. Пройдіть заголовки зверху вниз і знайдіть кожен стрибок вниз більш ніж на один рівень.
5. Замініть `div` зі стилями заголовка на справжній тег заголовка.
6. Навігацію називайте атрибутом `aria-label`, наприклад `<nav aria-label="Основна навігація">`. Прихований заголовок `sr-only` (а не `display: none`) ставте лише в блоки після `h1`, як-от футер чи бічна панель: заголовок у шапці стане першим у DOM і порушить пункт 3.
7. Прочитайте заголовки підряд як зміст: якщо як список вони не мають сенсу, то й як дерево фрагментів не матимуть. Розширення [AEO Checker](/extensions/aeo-checker) перевіряє ієрархію заголовків відкритої сторінки: рівно один `h1` і жодного пропущеного рівня.

## FAQ

### Навіщо використовувати семантичний HTML?

Семантичний HTML дає краулеру заяву про тему в `h1`, карту батьків і нащадків у `h2`-`h6` та опору для дерева доступності. Якщо AI-краулер ділить сторінку за заголовками, саме ця карта визначає, до якого розділу потрапить абзац. Користувачам програм екранного читання заголовки теж потрібні, бо вони переходять від заголовка до заголовка, щоб зрозуміти зміст сторінки.

### Які є приклади семантичних тегів HTML?

Основний набір: `header`, `nav`, `main`, `article`, `section`, `aside` та `footer`. Для підписаних медіа додайте `figure` із `figcaption`, а для дат, придатних для машини, `time`. Теги заголовків `h1`-`h6` теж семантичні: кожен позначає рівень у структурі заголовків, а не розмір шрифту. Усі вони описують роль блоку, а не його вигляд.

### Чи шкодить стрибок з h2 одразу на h4?

Для структури документа так. W3C пише, що пропущені рівні можуть плутати, а MDN радить їх не пропускати. Модуль, що ділить текст за рівнями заголовків (як `MarkdownHeaderTextSplitter` у LangChain), лишить такому `h4` контекст `h2`, але без пропущеного `h3`. Без жодного контексту фрагмент опиняється лише тоді, коли над заголовком немає предка. Чи штрафує за це ранжування, мій скан не показав: чотири сторінки з таким пропуском ранжуються.

Частина кластера [Answer Engine Optimization](/uk/aeo) (AEO): повний порядок читання і [глосарій](/uk/aeo/glossary) усіх термінів, що трапляються в цих статтях.

---

**Чи виявив аудит структури проблеми на вашому сайті?**

Підписуйтесь у [LinkedIn](https://linkedin.com/in/alexturik), щоб стежити за технічним боком оптимізації сайтів для AI-пошуку. Якщо проєкту потрібен архітектурний огляд, чиста семантична міграція чи Next.js з урахуванням AEO, [напишіть мені на пошту](mailto:alexturik@gmail.com).
