SEO
BreadcrumbList without errors: positions, URLs, tests
BreadcrumbList is an ordered list of steps from home to the current page. Three properties matter: itemListElement, position and item; the rest is decoration.
Key points
- BreadcrumbList is an ordered list: it needs itemListElement, and every ListItem needs a position and an item that is a URL.
- This site's article page declares 3 items, the first being Home pointing at /it, read on 1 November 2026.
- A trail in the markup that differs from the visible trail is misleading markup, and it almost always comes from a template.
BreadcrumbList is the markup that tells Google where the page sits in the site hierarchy: an ordered list that starts at the home page and ends on the current one. You add it as JSON-LD and it has to match the trail people see.
The three properties that matter
The documentation on breadcrumbs, read on 1 November 2026, asks for itemListElement as an ordered array. Each ListItem carries position and item, the URL of the page it represents; name is the label people read. The same page says Google uses breadcrumb markup in the body of a page to categorise the content in results, and that the feature is available on desktop in every language and region where Search exists.
A correct block
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://ui.eneawork.it/it"
},
{
"@type": "ListItem",
"position": 2,
"name": "Blog",
"item": "https://ui.eneawork.it/it/blog"
},
{
"@type": "ListItem",
"position": 3,
"name": "BreadcrumbList senza errori",
"item": "https://ui.eneawork.it/it/blog/breadcrumb-schema-guida"
}
]
}
Three items are the smallest useful shape: home, section, page. Positions run consecutively from 1, the name is what the reader sees, the URL returns 200. The last item gets an item like the others: it is the current page, and the current page has a URL.
Checking positions and URLs
cat > check-breadcrumb.mjs ]*application\/ld\+json[^>]*>([\s\S]*?)/g)];
const nodes = blocks.flatMap(([, raw]) => {
const data = JSON.parse(raw);
return data["@graph"] || [data];
});
const crumbs = nodes.find((n) => n["@type"] === "BreadcrumbList");
if (!crumbs) {
console.log("no BreadcrumbList");
process.exit(1);
}
let expected = 1;
for (const item of crumbs.itemListElement) {
if (item.position !== expected) console.log(`position ${item.position}, expected ${expected}`);
if (!item.name || !item.item) console.log(`item at ${item.position} misses name or item`);
expected += 1;
}
console.log(`${crumbs.itemListElement.length} crumbs, positions ${expected - 1} checked`);
EOF
node check-breadcrumb.mjs https://ui.eneawork.it/blog/come-aggiungere-schema-markup
The script extracts the BreadcrumbList, checks that positions run consecutively from 1, and checks that every item has a name and a URL. A wrong position does not break the page: it makes the list ambiguous, and Google can drop the markup without telling you.
The errors you see in templates
- Position starts at 0 because the array starts at 0: position is a schema.org number, not an index.
- The last item is the current page but has no item, because “it is obviously this one”: item is needed on the last item too.
- The visible trail says “Blog” and the markup says “Articles”: two trails, and only one of them is true.
- The trail includes the site name as its first element: home is already home, the brand belongs in Organization.
- The markup is built from a category array that changes with filters: a filtered page is not an extra level of the hierarchy.
The live record
In the catalogue the trail already exists as navigation: menu, navbar and /blocks show the same two-level shape. When the visible menu and the markup tell the same hierarchy, the breadcrumb is not extra data: it is the same information written twice. Checked on 1 November 2026.
The limitation
The breadcrumb is not guaranteed: Google may show the trail or the bare URL, and on a phone screen there is often no room. The markup stays useful because it describes the hierarchy, not because it draws a line in the result. On a site where one page has two possible trails, the documentation asks you to declare the one people see.
Where to continue
The link structure is in hub-and-spoke internal links; the canonical address of the page is in canonicalisation; the list Google reads is in sitemap index or single file. If the hierarchy comes from routes, the framework changes it: the comparison is in Remix or Next.js.
Frequently asked questions
Must the visible breadcrumb match the markup?
Yes. Google asks the markup to describe what people see: a trail in the markup that differs from the page is the definition of misleading markup.
How many levels can a breadcrumb have?
The schema.org vocabulary sets no limit, but a readable trail has two or three levels beyond home. Past that, readers stop reading and the result does not show it.
Does every page need a breadcrumb?
It is needed where a page has a parent. The home page has no trail, and a list of one item adds no information.
Can I generate the breadcrumb from the router?
Yes, and that is the most reliable way: nested routes already carry the hierarchy. Watch filters and parameters, which are not levels.
Does the breadcrumb improve ranking?
No, it is not a ranking factor. It changes how the result displays the trail and helps Google understand the site hierarchy.