Your page shows the breadcrumb “Home → AI Tools → ChatGPT issues.” Rich Results Test says the BreadcrumbList JSON-LD is valid. But Search Console’s Enhancements report flags it with warnings, or the SERP breadcrumb shows fewer levels or different wording. The cause is usually that JSON-LD is generated independently from the visible UI — different data sources, different label conventions, different locale handling. Google’s rule is that JSON-LD must match the visible breadcrumb in label, URL, and order. Even if both individually validate, mismatch demotes the rich result.
Common causes
Ordered by hit rate, highest first.
1. JSON-LD uses slugs while UI uses display names
{ "name": "ai-tools", "item": "https://site.com/category/ai-tools/" }
Visible UI shows “AI Tools” (with capitalization and space). JSON-LD says ai-tools (slug). Google detects mismatch.
How to spot it: Compare visible label to JSON-LD name exactly. Capitalization matters; spacing matters.
2. URL casing or trailing slash differences
JSON-LD: https://site.com/Category/AI-Tools. Visible link: https://site.com/category/ai-tools/. Same logical destination, different strings.
How to spot it: Inspect anchor tag href vs JSON-LD item. Must be byte-identical.
3. UI omits homepage; JSON-LD includes it (or vice versa)
UI shows “AI Tools → ChatGPT issues” (no home). JSON-LD has Home at position 1. Or UI has Home but JSON-LD doesn’t.
How to spot it: Count visible breadcrumb items vs. JSON-LD itemListElement.length. Should be equal.
4. Localization: JSON-LD untranslated
A non-English locale page shows translated breadcrumb labels in the UI but the JSON-LD still emits the English originals. Google flags the mismatch.
How to spot it: Open a non-default-language page. Compare JSON-LD name fields to visible UI labels.
5. Extra hidden levels for “SEO”
Someone added phantom intermediate levels in JSON-LD (“Home → AI → Tools → AI Tools → ChatGPT”) thinking it improves SEO. UI shows fewer levels. Google considers this misleading and demotes.
How to spot it: Count JSON-LD positions. If > visible UI count + 1, you have phantom levels.
6. BreadcrumbList ordering wrong
position: 1, 2, 3 should map to root → leaf. Reversed or shuffled breaks the rich result.
How to spot it: Check position field in each item. Position 1 should be Home (or root), increment by 1 per level, end at the current page.
Shortest path to fix
Step 1: Compare visible breadcrumb to JSON-LD
Manual diff for one page:
# Extract visible breadcrumb anchor texts and hrefs
curl -s "https://site.com/article/" | grep -oP '<nav[^>]*aria-label="breadcrumb[^>]*>[\s\S]+?</nav>'
# Extract JSON-LD breadcrumb
curl -s "https://site.com/article/" | grep -oP '"@type":"BreadcrumbList[\s\S]+?</script>'
Compare position-by-position.
Step 2: Generate both from one source
Refactor your layout to compute the breadcrumb once and emit both UI and JSON-LD:
---
const breadcrumb = [
{ name: 'Home', url: '/' },
{ name: 'AI Tools', url: '/category/ai-tools/' },
{ name: article.title, url: Astro.url.pathname },
];
const jsonLd = {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": breadcrumb.map((b, i) => ({
"@type": "ListItem",
"position": i + 1,
"name": b.name,
"item": new URL(b.url, Astro.site).toString(),
})),
};
---
<nav aria-label="breadcrumb">
<ol>
{breadcrumb.map((b, i) => (
<li>
{i < breadcrumb.length - 1
? <a href={b.url}>{b.name}</a>
: <span>{b.name}</span>}
</li>
))}
</ol>
</nav>
<script type="application/ld+json" set:html={JSON.stringify(jsonLd)}></script>
One breadcrumb array → both representations. Guaranteed identical.
Step 3: Localize properly
Use your translation helper:
const breadcrumb = [
{ name: t('breadcrumb.home'), url: lang === 'en' ? '/' : `/${lang}/` },
{ name: t(`category.${article.category}`), url: `/${lang}/category/${article.category}/` },
{ name: article.title, url: Astro.url.pathname },
];
Both UI and JSON-LD now show translated labels.
Step 4: Validate via Rich Results Test
After fix, open the URL in Rich Results Test. All breadcrumb items should match the visible breadcrumb 1:1.
Step 5: Add CI check
// scripts/check-breadcrumb.mjs
import fs from 'node:fs';
import { parse } from 'node-html-parser';
for (const file of getDistHtmlFiles()) {
const root = parse(fs.readFileSync(file, 'utf8'));
const visibleLabels = root.querySelectorAll('nav[aria-label="breadcrumb"] a, nav[aria-label="breadcrumb"] span')
.map(el => el.text.trim());
const jsonLd = JSON.parse(root.querySelector('script[type="application/ld+json"]').text);
const jsonLdLabels = jsonLd.itemListElement.map(i => i.name);
if (JSON.stringify(visibleLabels) !== JSON.stringify(jsonLdLabels)) {
console.error(`MISMATCH in ${file}\n visible: ${visibleLabels}\n jsonLd: ${jsonLdLabels}`);
}
}
Step 6: Resubmit to Google
After fix, Search Console → URL Inspection on representative URLs. Wait 1-2 weeks for Enhancement reports to clear.
When this is not on you
Search Console “Breadcrumbs” warnings can lag by days. Trust the source-code alignment first; the report will catch up.
Easy to misdiagnose as
Some teams add extra hidden levels in JSON-LD to “improve” SEO. Google considers this misleading and may suppress the rich result. Match what’s visible — no more, no less.
Prevention
- Generate visible breadcrumb and JSON-LD from one helper function.
- For bilingual sites, both layers must use the same translation source.
- CI assertion: visible breadcrumb text matches JSON-LD
namearray exactly. - Don’t add phantom levels for SEO — Google sees through it.
- When changing URL structure, regenerate both layers; don’t manually patch JSON-LD.
FAQ
- Can I omit the homepage from breadcrumbs? Allowed but inconsistent UX. Usually include it as position 1.
- Should the last item link to the current page? Optional — Google accepts both formats, but consistency within your site matters.
Related
- Structured data warnings
- FAQ schema invalid
- WebSite JSON-LD inconsistency
- Article date vs JSON-LD date mismatch
- Hreflang x-default Confusion in Bilingual Sites
- Twitter Card Image Not Showing When Sharing
- VideoObject Schema Not Recognized in Search Console
- HowTo Schema Deprecated But Template Still Emits It
- Product Schema Review Count Does Not Match Visible Reviews
- Article Schema Missing Required Field author.name
- Sitemap lastmod Is Always Today and Google Stopped Trusting It
Tags: #SEO #Troubleshooting #Debug #Structured data #Breadcrumb #JSON-LD