Build SEO-Friendly Breadcrumbs with MenuProcessor/Fluid in TYPO3

Breadcrumbs help users navigate your site and boost SEO rankings. But many TYPO3 sites either skip them or implement them wrong.

This guide shows you how to build proper breadcrumbs using TYPO3's MenuProcessor and Fluid templates. You'll get clean markup, structured data, and better search visibility.

What Are Breadcrumbs in TYPO3?

Breadcrumbs are small navigation aids that show users where they are on your website. In TYPO3, they can be built using MenuProcessor and Fluid templates to generate both the HTML navigation trail and the structured data (Schema.org) that search engines understand.

Why Breadcrumbs Are  Important for SEO & UX?

  • Better User Experience – Users can easily go back to higher-level pages without hitting “back” multiple times.
  • SEO Benefits – Google often replaces page URLs in search results with breadcrumb paths, making them cleaner and more clickable.
  • Structured Data Advantage – JSON-LD breadcrumbs help search engines understand your site hierarchy, increasing chances of rich snippets.
  • Lower Bounce Rate – Visitors are more likely to explore other pages.

What Makes Breadcrumbs SEO-Friendly?

Good breadcrumbs need three things:

  • Semantic HTML - Use proper list markup and microdata
  • Structured data - JSON-LD schema for search engines
  • Clean URLs - Real page links, not JavaScript

Most breadcrumb tutorials miss the structured data part. Search engines love it.

How to Create SEO-Friendly Breadcrumbs in TYPO3

Here’s the step-by-step method combining Fluid and MenuProcessor:

Setting Up the MenuProcessor

First, configure the breadcrumb menu in your page TypoScript. Add this to your page object:

page = PAGE
page {
    10 = FLUIDTEMPLATE
    10 {
        dataProcessing {
            20 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
            20 {
                menuLevelStart = 0
                menuLevelEnd = 10
                includeSpacer = 1
                as = breadcrumb
                special = rootline
                special.range = 0|-1
            }
        }
    }
}

Key settings explained:

  • special = rootline builds the page hierarchy path
  • special.range = 0|-1 includes root page to current page
  • includeSpacer = 1 includes spacer pages in navigation
  • as = breadcrumb makes data available as {breadcrumb} in Fluid

Creating the Fluid Template

Now build the breadcrumb HTML in your Fluid template:

<f:if condition="{breadcrumb}">
    <nav aria-label="Breadcrumb" class="breadcrumb-nav">
        <ol class="breadcrumb" itemscope itemtype="https://schema.org/BreadcrumbList">
            <f:for each="{breadcrumb}" as="item" iteration="iteration">
                <f:if condition="{iteration.isLast}">
                    <f:then>
                        <li class="breadcrumb-item active" 
                            itemprop="itemListElement" 
                            itemscope 
                            itemtype="https://schema.org/ListItem">
                            <span itemprop="name">{item.title}</span>
                            <meta itemprop="position" content="{iteration.index}" />
                        </li>
                    </f:then>
                    <f:else>
                        <li class="breadcrumb-item" 
                            itemprop="itemListElement" 
                            itemscope 
                            itemtype="https://schema.org/ListItem">
                            <f:link.page pageUid="{item.uid}" itemprop="item">
                                <span itemprop="name">{item.title}</span>
                            </f:link.page>
                            <meta itemprop="position" content="{iteration.index}" />
                        </li>
                    </f:else>
                </f:if>
            </f:for>
        </ol>
    </nav>
</f:if>

This template handles:

  • Accessibility - aria-label and semantic <nav> element
  • Microdata - Schema.org BreadcrumbList markup
  • Current page - No link on the active page
  • Position data - Each item gets a position number

Adding JSON-LD Structured Data

Microdata is good, but JSON-LD is better for SEO. Add this to your template:

<f:if condition="{breadcrumb}">
    <script type="application/ld+json">
    {
        "@context": "https://schema.org",
        "@type": "BreadcrumbList",
        "itemListElement": [
            <f:for each="{breadcrumb}" as="item" iteration="iteration">
            {
                "@type": "ListItem",
                "position": {iteration.index},
                "name": "<f:format.htmlentities>{item.title}</f:format.htmlentities>",
                "item": "<f:uri.page pageUid='{item.uid}' absolute='1' />"
            }<f:if condition="{iteration.isLast}"><f:else>,</f:else></f:if>
            </f:for>
        ]
    }
    </script>
</f:if>

Important notes:

  • Use absolute='1' for full URLs in JSON-LD
  • Escape HTML entities in the title
  • Don't add a comma after the last item

Basic CSS Styling

Add some basic styles to make breadcrumbs look decent:

.breadcrumb-nav {
    margin-bottom: 1rem;
    font-size: 0.875rem;
}

.breadcrumb {
    display: flex;
    flex-wrap: wrap;
    list-style: none;
    margin: 0;
    padding: 0;
}

.breadcrumb-item {
    display: flex;
    align-items: center;
}

.breadcrumb-item + .breadcrumb-item::before {
    content: "/";
    margin: 0 0.5rem;
    color: #6c757d;
}

.breadcrumb-item.active {
    color: #6c757d;
}

.breadcrumb-item a {
    text-decoration: none;
    color: #007bff;
}

.breadcrumb-item a:hover {
    text-decoration: underline;
}

Advanced Configuration Options

Skip Root Page

Don't want "Home" in every breadcrumb? Modify the range:

special.range = 1|-1

Custom Page Titles

Use different titles in breadcrumbs than page titles:

20 {
    dataProcessing {
        10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
        10 {
            table = pages
            pidInList.field = uid
            selectFields = uid, title, nav_title
            as = pageData
        }
    }
}

Then in Fluid:
<span itemprop="name">
    <f:if condition="{item.nav_title}">
        <f:then>{item.nav_title}</f:then>
        <f:else>{item.title}</f:else>
    </f:if>
</span>

Hide Specific Page Types

Exclude certain page types from breadcrumbs:

20 {
    excludePages = 199,254
    excludeDoktypes = 199,254
}

How to test your TYPO3 Website Breadcrumbs

Use these tools to verify everything works:

  • Google Rich Results Test - Check structured data
  • Browser DevTools - Inspect HTML markup
  • WAVE - Test accessibility compliance

Common issues to watch for:

  • Missing position numbers in structured data
  • Broken links to hidden or deleted pages
  • JavaScript errors from malformed JSON-LD

Performance Considerations

MenuProcessor caches menu data automatically. But you can optimize further:

20 {
    cache {
        key = breadcrumb_{page:uid}
        lifetime = 86400
        tags = pages
    }
}

This caches breadcrumbs for 24 hours and clears when pages change.

Troubleshooting Common Problems

Breadcrumbs not showing?

  • Check if pages are hidden in navigation
  • Verify MenuProcessor configuration
  • Look for Fluid template errors

Missing structured data?

  • Validate JSON syntax
  • Check absolute URL generation
  • Test with Google's tool

Wrong page hierarchy?

  • Review the page tree structure
  • Check rootline special configuration
  • Verify page shortcuts aren't breaking paths

Validating Your Breadcrumbs for TYPO3 Sites

  • Google Rich Results TestCheck here
  • Schema.org ValidatorTest schema
  • Accessibility Audit – Use WAVE or Lighthouse.

Wrapping Up

You now have SEO-friendly breadcrumbs that work with TYPO3's caching and provide rich search data. The combination of proper HTML markup, microdata, and JSON-LD gives you the best chance of enhanced search results.

The key is keeping it simple. Don't over-engineer breadcrumbs. Focus on clear navigation and clean markup.

Post a Comment

×

    Got answer to the question you were looking for?