# Semantic HTML for AI agents: landmarks, one h1, lang and alt text

> Semantic structure means a product page has one main landmark and a nav, exactly one h1 with the product name, a lang attribute on the html element, and alt text on images. AI agents use these to skip site chrome, confirm they are on the right product, and understand images they can't see.

- Source: https://is-agentic-storefront.com/checks/semantic-structure
- Updated: 2026-10-15
- Category: Operability (20% of score)
- Impact: Low
- Spec: [WAI landmark regions](https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/)
- Scanner check: Landmarks, one h1, page language and image alt text

## Why it matters for AI agents

Semantic HTML is the cheapest way to make a page legible to machines. Browser agents read the accessibility tree, and the tree is built from your HTML elements: `<main>` becomes a `main` landmark, `<nav>` a `navigation` landmark, `<h1>` a level-1 heading ([web.dev: the accessibility tree](https://web.dev/articles/the-accessibility-tree)). Text-only agents use the same elements when converting HTML to text.

Each of the four signals the scanner checks serves a specific purpose for an AI shopping agent:

- **Landmarks** ([WAI landmark regions](https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/)) let an agent jump straight to the product content and skip mega-menus, banners and footers.
- **One `<h1>`** tells the agent which product the page is about. Pages with a logo in an `h1`, or a separate `h1` for every section, make that ambiguous.
- **`<html lang>`** ([WCAG 3.1.1](https://www.w3.org/TR/WCAG22/#language-of-page)) tells the agent which language the content is in, which matters for translation and for stores with several locales.
- **Image alt text** ([WCAG 1.1.1](https://www.w3.org/TR/WCAG22/#non-text-content)) lets agents without vision confirm the color or style shown, and gives image links a name.

This is a low-weight check in the Operability category: it improves comprehension rather than unblocking an action like [add-to-cart](https://is-agentic-storefront.com/checks/add-to-cart) does.

## What the scanner checks

The scanner inspects the server HTML of the first sampled product page (or the homepage if no product page loaded) and runs four sub-checks:

| Sub-check | Passes when                                                                               |
| --------- | ----------------------------------------------------------------------------------------- |
| Landmarks | Exactly one `<main>` (or `role="main"`) and at least one `<nav>` (or `role="navigation"`) |
| Heading   | Exactly one `<h1>`                                                                        |
| Language  | `<html>` has a `lang` attribute                                                           |
| Images    | At least 90% of `<img>` elements have an `alt` attribute (empty `alt=""` counts)          |

| Result           | When                                                               |
| ---------------- | ------------------------------------------------------------------ |
| **Pass**         | All 4 sub-checks pass                                              |
| **Partial**      | 2 or 3 pass; the score is proportional (for example 3 of 4 = 0.75) |
| **Fail**         | 0 or 1 pass                                                        |
| **Inconclusive** | No page loaded to test                                             |

## How to fix it

A product page skeleton that passes all four sub-checks:

```html
<!doctype html>
<html lang="en-US">
  <body>
    <header>
      <a href="/"><img src="/logo.svg" alt="Example Outfitters home" /></a>
      <nav aria-label="Main">…</nav>
    </header>
    <main>
      <h1>Merino Crew Sock</h1>
      <img src="/img/sock-navy.jpg" alt="Merino crew sock in navy, side view" />
      <img src="/img/divider.svg" alt="" />
      <h2>Details</h2>
      …
      <h2>Reviews</h2>
      …
    </main>
    <footer>…</footer>
  </body>
</html>
```

1. Wrap the primary content in exactly one `<main>`; use `<nav>`, `<header>` and `<footer>` for site chrome.
2. Use exactly one `<h1>` with the product (or page) name. Demote the logo, promo banners and section titles to other elements or `h2`–`h6`.
3. Set `<html lang>` to the page language, such as `en-US` or `fr-CA`, and update it per locale.
4. Give every `<img>` an `alt` attribute: a description for product images, `alt=""` for decorative ones.

## Common mistakes

- **Two `<main>` elements**, often one from the layout and one from a page template.
- **The logo wrapped in an `<h1>`** on every page, plus the product name in another `<h1>`.
- **Lazy-loaded gallery images** whose `alt` is only set by JavaScript after load, so the server HTML has none.
- **Alt text that repeats the file name**, like `alt="IMG_2041.jpg"`. It passes the check but tells the agent nothing.

## How to fix it on Medusa

On Medusa's [DTC starter](https://github.com/medusajs/dtc-starter) (observed October 2026), product pages already include `<header>`, `<nav>`, `<main>` and `<footer>`. When you customize the storefront:

- Keep exactly one `<h1>` with the product title on the product page.
- Set `lang` on the `<html>` element in the root layout, and match it to the region or locale you serve ([Next.js root layout](https://nextjs.org/docs/app/api-reference/file-conventions/layout#root-layout)).
- Give product images an `alt` that describes the product, for example from the product title and variant.

## Sources

- [WAI-ARIA APG: landmark regions](https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/)
- [WCAG 2.2 SC 1.3.1 Info and Relationships](https://www.w3.org/TR/WCAG22/#info-and-relationships)
- [WCAG 2.2 SC 3.1.1 Language of Page](https://www.w3.org/TR/WCAG22/#language-of-page)
- [WCAG 2.2 SC 1.1.1 Non-text Content](https://www.w3.org/TR/WCAG22/#non-text-content)
- [web.dev: the accessibility tree](https://web.dev/articles/the-accessibility-tree)

## Frequently asked questions

### Does semantic HTML help AI agents?

Yes. Agents that read the accessibility tree use landmarks to jump to the main content, the h1 to confirm which product a page is about, and alt text to learn what images show. Text-only agents get the same cues from the HTML.

### Should a product page have only one h1?

Yes, one h1 containing the product name is the clearest signal of what the page is about. Use h2 and lower for sections like reviews and recommendations.

### Do decorative images need alt text?

They need an alt attribute, but it should be empty (alt="") so agents and screen readers skip them. Product images need a real description, including color or variant.

## Run your store on a platform built for agentic commerce

Medusa is open-source, headless commerce with a full Store API agents can call and storefronts you control end to end.

### Deploy on Medusa Cloud

Open-source commerce with a full Store API, hosted and scaled for you. Your storefront, your data model.

- [Deploy on Medusa Cloud](https://cloud.medusajs.com?utm_source=agent-friendly-scorer&utm_medium=referral&utm_campaign=markdown-cta&utm_content=%2Fchecks%2Fsemantic-structure)
- [Medusa Cloud docs](https://docs.medusajs.com/cloud?utm_source=agent-friendly-scorer&utm_medium=referral&utm_campaign=markdown-cta&utm_content=%2Fchecks%2Fsemantic-structure)

### Storefront skills for coding agents

Teach Claude Code, Cursor or Codex to build storefronts with the patterns these checks look for.

```bash
npx skills add medusajs/medusa-agent-skills
```

[View the skill on GitHub](https://github.com/medusajs/medusa-agent-skills/tree/main/plugins/ecommerce-storefront/skills/storefront-best-practices)

---

Scan your store for free at https://is-agentic-storefront.com/