citelity.Join waitlist →
June 17, 2026·17 min read·BreadcrumbList

BreadcrumbList schema: working implementation patterns and the mistakes that break them

BreadcrumbList schema replaces the URL line in Google's mobile SERP with your breadcrumb trail — a small but visible win when implemented correctly. Here's the working JSON pattern, the two acceptable formats and when to use each, platform-specific examples for WordPress, Next.js, Webflow, and headless setups, plus the position numbering errors that quietly break the implementation.

BreadcrumbList schema gets less attention than FAQPage or Article markup, but it has a specific visible benefit — it replaces the URL line in Google's mobile SERP with your breadcrumb trail, improving both UX and how prominently your result displays. The implementation is simple in concept and trips up surprisingly often in practice: position numbering errors, wrong format choices, and inconsistency with the visible breadcrumb on the page. This piece covers the working JSON pattern, the two acceptable formats and when each makes sense, platform-specific implementations for the systems most content sites use, and the common mistakes that quietly break the schema even when validators say it's fine.

What BreadcrumbList actually does

Three real functions, in order of practical impact:

Function 1: Replaces URL display in mobile SERPs. On mobile, Google replaces the URL line of your search result with the breadcrumb trail when BreadcrumbList schema is present and valid. Instead of seeing yoursite.com › blog › post-slug (the URL path), users see Home › Category › Article Title (the breadcrumb). This is the most visible benefit and the one most easily verified — search for one of your pages on mobile and check the result display.

Function 2: Helps Google understand site hierarchy. Even without producing the visible SERP feature, BreadcrumbList signals the logical structure of your site to Google's crawler and indexing systems. Pages with clear breadcrumb schema get categorized more accurately, which affects how they're surfaced for queries related to the category.

Function 3: Contributes to topical authority signaling. When Google sees a page within a clear breadcrumb hierarchy (Home → Category → Subcategory → Article), it interprets the page as part of an organized content cluster rather than an orphan article. This contributes to the topical authority signals AI engines use when deciding which sources to cite.

What BreadcrumbList doesn't do:

  • It doesn't replace site navigation. Breadcrumbs should match the logical hierarchy, not your menu structure.
  • It doesn't help with knowledge panels or featured snippets directly.
  • It doesn't appear in desktop SERPs as a visual feature in most cases — the visible benefit is mobile-focused.

The two acceptable formats

Google accepts BreadcrumbList in two slightly different JSON-LD formats. Both validate; the choice matters for maintainability rather than correctness.

Format 1: Long form with Thing wrapper.

{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "item": {
        "@type": "Thing",
        "@id": "https://yoursite.com/",
        "name": "Home"
      }
    },
    {
      "@type": "ListItem",
      "position": 2,
      "item": {
        "@type": "Thing",
        "@id": "https://yoursite.com/blog",
        "name": "Blog"
      }
    },
    {
      "@type": "ListItem",
      "position": 3,
      "item": {
        "@type": "Thing",
        "@id": "https://yoursite.com/blog/article-slug",
        "name": "Article Title"
      }
    }
  ]
}

Format 2: Short form with name and URL string.

{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "Home",
      "item": "https://yoursite.com/"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "Blog",
      "item": "https://yoursite.com/blog"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "Article Title",
      "item": "https://yoursite.com/blog/article-slug"
    }
  ]
}

When to use each:

The short form is preferred for most implementations. It's more compact, easier to generate programmatically, and produces identical rich result behavior. Most modern schema generators output this format by default.

The long form becomes useful when you're already using @graph syntax to connect multiple schema types and want to reference breadcrumb items by @id from other schema entities. If you have a complex schema graph where Article, Person, and Organization all reference each other, matching the breadcrumb items into that pattern with @id references can make the graph more coherent.

For 90% of content sites: use the short form. It's cleaner.

AI
Free tool · No signup
Free Schema Validator
Paste any URL → full AEO audit across 12 factors with ready-to-paste JSON-LD fixes.
Check your schema

Position numbering rules

The single most common error in BreadcrumbList implementation. The rules:

Position 1 is the top of the hierarchy. This is almost always your homepage. Some implementations skip the homepage and start at the category page — that's technically valid in schema.org's spec but causes display issues in Google's SERP because Google expects the first position to be the root.

Positions must be sequential integers starting at 1. Skipping numbers (1, 3, 4) or starting at 0 both cause validation issues in some parsers and rich result failures in Google's.

The last position is the current page. This page should NOT be a clickable link in the visible breadcrumb on the page (browsers shouldn't navigate to it because you're already there), but the schema still includes the URL.

Hierarchy depth: 2-5 levels typically. A single-item BreadcrumbList provides no rich result benefit because there's no trail to display. More than 5 levels usually indicates a site structure that's too deep — consider consolidating categories.

Common position errors:

  • Starting position at 0 (some developers default to zero-indexed arrays and forget to add 1)
  • Skipping the homepage position
  • Numbering items out of order (the array order should match position order, but parsers will read the position field — keep them aligned to avoid confusion)
  • Using string positions ("1", "2") instead of integers (1, 2)

The complete working example

Here's the full pattern I recommend for blog posts, using the short form with @graph integration so it connects to your other schema:

{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "BreadcrumbList",
      "@id": "https://yoursite.com/blog/article-slug#breadcrumb",
      "itemListElement": [
        {
          "@type": "ListItem",
          "position": 1,
          "name": "Home",
          "item": "https://yoursite.com/"
        },
        {
          "@type": "ListItem",
          "position": 2,
          "name": "Blog",
          "item": "https://yoursite.com/blog"
        },
        {
          "@type": "ListItem",
          "position": 3,
          "name": "AEO Optimization",
          "item": "https://yoursite.com/blog/category/aeo"
        },
        {
          "@type": "ListItem",
          "position": 4,
          "name": "BreadcrumbList Schema Implementation",
          "item": "https://yoursite.com/blog/breadcrumb-schema-implementation"
        }
      ]
    },
    {
      "@type": "Article",
      "@id": "https://yoursite.com/blog/article-slug#article",
      "headline": "BreadcrumbList Schema Implementation",
      "breadcrumb": {
        "@id": "https://yoursite.com/blog/article-slug#breadcrumb"
      }
    }
  ]
}

The Article references the BreadcrumbList via @id in the breadcrumb field. This connection isn't strictly required for validation, but it strengthens the relationship for Google's parser. I covered the broader Article schema pattern in the Article schema E-E-A-T tutorial; BreadcrumbList integrates naturally into the same graph.

Implementation by platform

The schema is identical across platforms, but how you generate and deploy it varies significantly.

WordPress

Yoast SEO and RankMath both generate BreadcrumbList schema automatically if you've configured breadcrumb settings in the plugin and added the breadcrumb display to your theme.

For Yoast:

  1. SEO → Search Appearance → Breadcrumbs → Enable
  2. Verify your theme calls yoast_breadcrumb() in the appropriate template files (single.php, page.php, etc.)
  3. The plugin outputs BreadcrumbList JSON-LD automatically; check page source to verify

For RankMath:

  1. Titles & Meta → Misc → Breadcrumbs → Enable
  2. Configure the homepage label and separator
  3. Add the breadcrumb display via shortcode [rank_math_breadcrumb] or PHP <?php do_action( 'rank_math/frontend/breadcrumb' ); ?> in templates
  4. Schema is generated automatically

Common WordPress problems:

  • Both Yoast AND RankMath active simultaneously → duplicate BreadcrumbList blocks. Disable breadcrumb features in one plugin.
  • Theme has hardcoded breadcrumb HTML but no schema → schema must be generated separately or via the SEO plugin
  • Custom post types without proper hierarchy settings → breadcrumbs default to flat (Home → Post) instead of the proper category structure

Next.js (App Router and Pages Router)

For Next.js sites, the cleanest pattern is generating the schema server-side in your page component and rendering it inline.

// app/blog/[slug]/page.tsx (App Router) or similar pattern

function generateBreadcrumbSchema(post) {
  return {
    "@context": "https://schema.org",
    "@type": "BreadcrumbList",
    "itemListElement": [
      {
        "@type": "ListItem",
        "position": 1,
        "name": "Home",
        "item": "https://yoursite.com/"
      },
      {
        "@type": "ListItem",
        "position": 2,
        "name": "Blog",
        "item": "https://yoursite.com/blog"
      },
      {
        "@type": "ListItem",
        "position": 3,
        "name": post.category,
        "item": `https://yoursite.com/blog/category/${post.categorySlug}`
      },
      {
        "@type": "ListItem",
        "position": 4,
        "name": post.title,
        "item": `https://yoursite.com/blog/${post.slug}`
      }
    ]
  };
}

export default function BlogPost({ post }) {
  const breadcrumbSchema = generateBreadcrumbSchema(post);
  
  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbSchema) }}
      />
      {/* rest of your component */}
    </>
  );
}

Common Next.js problems:

  • Client-side rendering the schema with useEffect instead of server-rendering → bots don't see it
  • Using next-seo plugin defaults without customizing for your URL structure → breadcrumb positions and names don't match the actual site hierarchy
  • Generating breadcrumbs from the URL path alone → loses the visible category names that should appear in breadcrumb display

Webflow

Webflow doesn't generate BreadcrumbList schema natively. The typical implementation:

  1. Add Custom Code embed inside the page (Page Settings → Custom Code → Before </body> tag)
  2. Hardcode the BreadcrumbList JSON-LD for each page or template
  3. For CMS Collection pages, use Webflow's CMS field bindings inside the script tag

The challenge is that Webflow's CMS bindings work in static content but require JavaScript for dynamic schema generation, and JavaScript-rendered schema doesn't work reliably for SEO.

The recommended pattern: use Webflow's templating in the Page Settings rather than relying on JavaScript:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "Home",
      "item": "https://yoursite.com/"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "Blog",
      "item": "https://yoursite.com/blog"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "{{Name}}",
      "item": "https://yoursite.com/blog/{{Slug}}"
    }
  ]
}
</script>

Where {{Name}} and {{Slug}} are Webflow CMS field bindings that get rendered server-side.

Headless CMS (Contentful, Sanity, Strapi)

For headless setups, the BreadcrumbList generation happens in the frontend rendering layer (Next.js, Gatsby, Astro, etc.), pulling category and title data from the CMS.

The pattern is identical to the Next.js example above, but with the data source being the CMS API rather than a local content directory. The key implementation detail: make sure category and breadcrumb labels are explicit fields in your content model, not derived from slugs. Slug-derived labels often produce ugly breadcrumbs ("aeo-tools" instead of "AEO Tools").

Static site generators (Astro, Hugo, Eleventy)

These usually have templating systems that can generate BreadcrumbList from page metadata. For Astro:

---
const breadcrumbs = [
  { name: "Home", url: "https://yoursite.com/" },
  { name: "Blog", url: "https://yoursite.com/blog" },
  { name: Astro.props.title, url: Astro.url.href }
];

const schema = {
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": breadcrumbs.map((item, i) => ({
    "@type": "ListItem",
    "position": i + 1,
    "name": item.name,
    "item": item.url
  }))
};
---

<script type="application/ld+json" set:html={JSON.stringify(schema)} />

Hugo and Eleventy have similar patterns using their respective templating languages.

AI
Free tool · No signup
Free Schema Validator
Paste any URL → full AEO audit across 12 factors with ready-to-paste JSON-LD fixes.
Check your schema

Six common mistakes and fixes

Mistake 1: BreadcrumbList doesn't match the visible breadcrumb on the page. Schema declares Home → Blog → Article; visible breadcrumb on the page shows Home → Article (skipping Blog). Google's parser checks for this consistency. Either update the visible breadcrumb to match or update the schema to match — don't leave them disagreeing.

Fix: Sync them. The visible breadcrumb HTML and the schema should describe the same hierarchy with the same labels.

Mistake 2: Multiple BreadcrumbList blocks on the same page. Common when an SEO plugin generates one and a theme widget generates another. The parser doesn't know which to use and may show none.

Fix: View page source, search for "@type": "BreadcrumbList". If there are multiple, disable the redundant sources.

Mistake 3: Single-item BreadcrumbList. Page has only one item in the breadcrumb (typically just the page itself). This validates but produces no rich result because there's no trail to display.

Fix: Ensure your hierarchy includes at least 2 levels — homepage plus the current page minimum. For category-less pages, the pattern Home → Page Title is acceptable; for blog posts, Home → Blog → Article is the minimum useful pattern.

Mistake 4: Including external URLs in the breadcrumb chain. The breadcrumb should reflect the path within your site only. External links break the "logical hierarchy from your site root" pattern that the parser expects.

Fix: Remove any external URLs from breadcrumb items. If you legitimately want to reference an external resource on the page, do it in body content, not in breadcrumbs.

Mistake 5: JavaScript-rendered breadcrumb schema. Schema added via React state, jQuery DOM insertion, or any client-side method after page load. Bots that don't execute JavaScript reliably (which includes some of Google's crawler modes) don't see the schema.

Fix: Render schema server-side, in the initial HTML response. Verify by viewing page source (not Inspector) — the schema should be present in the raw HTML.

Mistake 6: Position field as string instead of integer. Some schema generators output "position": "1" (string) instead of "position": 1 (integer). JSON validators accept both but Google's parser specifically requires integers for position.

Fix: Ensure your schema generation outputs integers. In JavaScript, this means parseInt(i, 10) or numeric literals, not string concatenation.

How to verify it's working

Three checks, in order:

Check 1: JSON validates. Paste your full BreadcrumbList JSON into the JSON-LD playground at jsonld.org/playground. It should parse without errors. If JSON itself is broken, nothing else matters.

Check 2: Schema validates against schema.org. Run your page through validator.schema.org. It should report no errors. If errors appear, fix those before continuing.

Check 3: Google's Rich Results Test passes. This is the one that matters for SEO. Run the URL through Google's Rich Results Test at search.google.com/test/rich-results. The Breadcrumbs section should appear with all your items listed and no errors. If errors appear, the test output tells you exactly which field is problematic.

Check 4 (post-deployment): Mobile SERP display. After deploying and waiting 2-3 weeks for Google to re-crawl, search for one of your pages on a mobile device. The URL line in the result should show your breadcrumb trail instead of the raw URL path. If it doesn't, either the schema isn't being detected (re-check the validation steps) or Google hasn't re-crawled the page yet (use URL Inspection's Request Indexing to speed it up).

Connection to AI Overview citation

BreadcrumbList isn't a major factor in AI Overview citation in the way FAQPage or Article+Person are, but it's not zero-impact either. SE Ranking's analysis found about 65% of pages cited by Google AI Mode include structured data markup. BreadcrumbList is part of the typical "structured data is present" signal that contributes to that 65% figure.

More substantively: BreadcrumbList helps the AI parser understand which content cluster your page belongs to. When a query about "AEO optimization" triggers the citation evaluation, pages within a clear /blog/aeo hierarchy that's confirmed by BreadcrumbList schema get categorized correctly. Pages without breadcrumb schema rely on URL inference, which is less reliable.

If you've worked through the seven failure patterns for AI Overview citation and ruled out the major issues, adding BreadcrumbList is a small marginal improvement worth implementing — but it's not the difference between citation and no-citation in most cases.

AI
Free tool · No signup
Free AEO Content Score
Paste content or URL → 0-100 score across 10 AEO factors + 3 prioritized quick wins.
Score your content

FAQ

Do I need BreadcrumbList schema if my site doesn't show visible breadcrumbs to users?
Technically yes, you can add BreadcrumbList schema without visible breadcrumbs on the page — but it's not recommended. Google's parser cross-checks structured data against visible page content, and BreadcrumbList declaring a hierarchy that doesn't appear visually triggers content-schema mismatch signals. If you want the SEO and AI citation benefits of BreadcrumbList, add visible breadcrumbs to your templates first, then generate matching schema. Schema without visible counterpart is weaker signal at best, suspicious-looking signal at worst.
Should the last breadcrumb item link to the current page or not?
The schema's item field should include the URL of the current page (Google's parser expects a complete chain with URLs at every level). However, the visible breadcrumb on the page typically shouldn't have the current page as a clickable link — browsers shouldn't navigate to a page you're already on. This is the most common consistency mismatch: the visible breadcrumb shows the current page as plain text (not a link), but the schema includes the URL. That's correct and expected — the schema describes the logical hierarchy; the visible presentation reflects current navigation state.
How deep should my breadcrumb hierarchy go?
Two to five levels is the practical range. Two levels (Home → Page) is the minimum useful — single-item BreadcrumbList produces no rich result. Three to four levels is typical for blog posts (Home → Blog → Category → Article). Five levels works for deeply categorized content like documentation. Beyond five, your site structure is probably too deep and the breadcrumb display becomes cluttered in mobile SERPs (Google may truncate it). If you find you need six or more breadcrumb levels, consider whether the underlying category structure could be flattened.
Can BreadcrumbList schema hurt my SEO if implemented incorrectly?
In most cases no — incorrect BreadcrumbList just doesn't produce the rich result benefit. It rarely causes active harm. The exception is when BreadcrumbList declares URLs that don't exist (broken internal links), in which case it sends Google's crawler to 404 pages, wasting crawl budget. Another exception is BreadcrumbList declaring a completely different site structure than your visible navigation, which can confuse Google's understanding of your site hierarchy. Both of these are content-quality problems that BreadcrumbList exposes rather than creates.
What's the difference between BreadcrumbList schema and HTML breadcrumb navigation?
BreadcrumbList schema is structured data in JSON-LD format that describes the logical hierarchy to search engines and AI parsers. HTML breadcrumb navigation is the visible UI element on your page that users click. Both should exist together and match. The HTML serves humans; the schema serves machines. Implementing only one of them means losing half the benefit — visible breadcrumbs without schema don't trigger the SERP rich feature; schema without visible breadcrumbs creates a content-schema mismatch that the parser may penalize.
If I use breadcrumbs in my site navigation, do I still need separate BreadcrumbList schema?
Yes. Site navigation menus serve a different function than breadcrumb hierarchy, and HTML navigation elements aren't automatically interpreted as BreadcrumbList by search engines. You need to explicitly mark up the breadcrumb structure with BreadcrumbList JSON-LD even if your visible UI already shows the same hierarchy. Some HTML patterns (like nav elements with aria-label='breadcrumb') help screen readers and accessibility tools but don't replace the need for structured data.
Can BreadcrumbList replace URL pattern signals like clean URLs and category-based site structure?
No, it works alongside them. Clean URLs (yoursite.com/blog/category/article-slug) provide one set of signals about site hierarchy that crawlers use independently. BreadcrumbList provides explicit confirmation of the hierarchy. The two reinforce each other — pages with both clean URLs matching the breadcrumb structure get the strongest hierarchy signals. Pages with mismatched URLs and breadcrumbs (e.g., URL says /blog/article-slug but breadcrumb says Home → Tech → Reviews → Article) confuse Google about which structure to trust. Sync them.
How long does it take for breadcrumb-enabled SERP results to appear after adding the schema?
One to four weeks typically. Google needs to re-crawl the page (1-7 days with URL Inspection's Request Indexing, longer without), parse the new schema, validate it against the visible content, and update its cached SERP display. Mobile SERPs update somewhat faster than desktop SERPs for this specific feature. If after 6 weeks your mobile SERP still doesn't show the breadcrumb trail, the issue is usually one of the six common mistakes covered above (schema-content mismatch, multiple BreadcrumbList blocks, single-item breadcrumb, etc.) rather than timing.

Sources cited in this piece

  • Schema.org official BreadcrumbList specification (schema.org/BreadcrumbList)
  • Google's structured data documentation for breadcrumbs (developers.google.com/search/docs)
  • Google's Rich Results Test parsing behavior (observable from running schemas through the public tool)
  • SE Ranking (post-January 2026): Gemini 3 analysis (65% schema rate among AI-cited pages)
  • WordPress plugin documentation (Yoast, RankMath) for BreadcrumbList output specifics

If you've implemented BreadcrumbList and the mobile SERP isn't showing the breadcrumb trail after 4+ weeks, send the page URL on X at @edgrows. I'll run it through the validators and identify which of the common mistakes is most likely.

Written by
Ed Grows
Solo founder of citelity. Building AEO tools. Documenting what works (and what breaks) on aivario.com.
← Back to all posts