A page an agent has fetched is one node. Where that node sits in the site, which section it belongs to, what its parent is, how far it is from the root, is not in the page unless something puts it there. Two things can: a breadcrumb trail, and a URL whose path carries the structure. Check C2 spends its fourth point on whether a site provides either. This post covers what that point measures, why it is tested on an interior page rather than the homepage, and how our own page header produces a visible trail and matching BreadcrumbList schema from one array, so the two cannot disagree.
The first three points of C2 have their own posts: links that are links covers the two points for real anchors, and the contextless link problem covers the point for link text. This is the last one.
Why an agent wants the shape of the site
An agent lands on a page from a search result, a citation or a link in a conversation, and it usually lands somewhere in the middle. To decide whether the page answers the question it was given, it often needs the neighbours: the parent that summarises the section, the siblings that offer the alternatives, the root that says what the organisation is. The page's links are one route to them, but a page can carry two hundred links and nothing in the markup says which three of them are "up".
A breadcrumb says exactly that: an ordered list from the root to the current page, each step a link, one element to read. A URL hierarchy says it more cheaply still. If the page is at /services/implementation, the agent can strip the last segment and fetch /services without reading anything. For a person, breadcrumbs are a courtesy. For a machine they are a map of the site that does not require a crawl to draw.
What the scanner measures
C2 is worth four points and rated Medium effort. The fourth point is awarded when the site shows either a breadcrumb or a URL hierarchy, and the scanner deliberately looks for it away from the homepage.
The crawl covers up to six pages, the homepage first and then up to five others chosen from its links, as described on /bot. C2 takes every crawled page that returned 200 with a body, treats the first as the homepage and the rest as interior pages. The hierarchy point passes if any interior page carries a breadcrumb, or if any interior page's URL path has more than one segment. If no interior page came back at all, the scanner falls back to the homepage's own breadcrumb, or to any crawled URL, successful or not, with a deeper path.
The reason for scoring on interior pages is written into the check itself. A homepage correctly has no breadcrumb; it is the root, and a trail there would be a single item pointing at itself. Testing for one on the homepage would mark every well-built site down for doing the right thing.
A page counts as having a breadcrumb if any one of these signals is present in its raw HTML, before any JavaScript runs:
- an element with
aria-label="Breadcrumb", or the lowercasearia-label="breadcrumb"; - an element with the class
breadcrumb; - the text
"@type": "BreadcrumbList"anywhere in the document, which is how JSON-LD is caught.
The URL test splits the path on / and passes if there are more than two pieces. /pricing splits into an empty string and pricing, two pieces, so it does not count; /services/implementation splits into three and does. One consequence of that arithmetic is that a trailing slash on a single-segment path, /pricing/, also produces three pieces and passes. That is a limitation of the current test rather than a feature, and not something to build for.
The evidence block reports anchors, genericLinks, genericRatio, clickableNonAnchors and hasBreadcrumb. Note that hasBreadcrumb is the homepage's value; the point itself is decided on the interior pages, and when it is lost the fix text says no breadcrumbs or clear URL hierarchy.
Because the check depends on which five pages the crawler picked, a site whose homepage links only to flat single-segment pages, none carrying a trail, loses the point even if a deeper section exists somewhere. The remedy is the same either way: put the trail in the template, so every interior page has it.
The first way, a breadcrumb trail in the HTML
The trail should be an ordered list of real anchors inside a nav labelled as a breadcrumb. Ordered, because the sequence is the information; anchors, because an agent that cannot follow a div cannot follow one here either; labelled, because a page may have several nav elements and the label is how a machine, or a screen reader, tells this one apart. The ARIA Authoring Practices Guide has a breadcrumb pattern that sets out the same structure.
<nav aria-label="Breadcrumb">
<ol>
<li><a href="/">Home</a></li>
<li><a href="/services">Services</a></li>
<li><span aria-current="page">Implementation</span></li>
</ol>
</nav>
The current page is the last item and is not a link. A link to the page you are already on is noise to a person and a wasted fetch for an agent; aria-current="page" says which item is the destination. Separators, if you want them, belong in CSS or in an element marked aria-hidden="true" so they do not become part of the link text.
The second way, BreadcrumbList schema
The same trail can be published as JSON-LD using the BreadcrumbList type. Each step is a ListItem with a one-based position, a name and an item URL. The URLs should be absolute, because the schema block may be read on its own, away from the page it came from.
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com/" },
{ "@type": "ListItem", "position": 2, "name": "Services", "item": "https://example.com/services" },
{ "@type": "ListItem", "position": 3, "name": "Implementation", "item": "https://example.com/services/implementation" }
]
}
The scanner accepts the schema on its own, because its breadcrumb test matches the BreadcrumbList type anywhere in the document. Publishing both is still the better choice: the visible trail is what a person and a rendering agent use, and the schema is what a parser that reads structured data first will find. When both come from the same source they cost nothing extra to keep in step.
The third way, a URL hierarchy
A path that carries the structure passes the test without any markup, and it has a property the other two lack: it works on a page the crawler never fetched. If every page under a section lives at /section/page, an agent knows the parent of any page it meets.
The condition that makes this useful, rather than merely deep, is that the parent must exist. Stripping a segment from /services/implementation should land on a real /services page, not a 404. A hierarchy whose intermediate paths return nothing is a decoration, and a machine that trusts it will be misled. If your platform generates paths such as /p/48213 or puts everything at the root, the breadcrumb trail supplies what the URL does not.
How our page header does it
Every interior page on this site is rendered by one header component, and it takes a trail: an array of { name, path } pairs. From that array it renders a nav labelled Breadcrumb, containing an ol, with every item but the last as an a with an href and the last as a span carrying aria-current="page". The separator between items is a span marked aria-hidden="true". That is the first way, exactly as shown above, and it is server-rendered, so it is in the raw fetch.
The same array goes to a small function that builds the schema. It maps each pair to a ListItem with position, name and an absolute item URL, wrapped in a BreadcrumbList. On a blog post that block is emitted in the same @graph as the Article schema, so the page carries one ld+json block containing both. The trail for the post you are reading is Home, then Blog, then the Actionability category, then this article's short title, and both the visible list and the schema were generated from that one array. Neither can drift from the other; there is one source and two renderings of it.
Our paths carry the hierarchy as well. Service pages sit under /services and articles under /blog, and both of those intermediate paths are real pages. Any one of the three would satisfy the check. We publish all three because they answer different readers, and once the template does it the cost is nil.
Check your own site
Run the free scan and look at the C2 evidence for hasBreadcrumb and the fix text; if the hierarchy point is missing, the trail in the template above is a Medium-effort fix. The full scoring for C2 is on the methodology page under actionability.