The breadcrumb markup
Target group: Developers
Table of Contents
Introduction
A breadcrumb is an essential part of a web page. It gives the user an idea of where he is on the web site. He can also navigate to parent pages. But for search engines a breadcrumb is also essential to understand the structure of a web site. Last but not least, the breadcrumb is shown in the search result snippet if structured markup for the breadcrumb is available.
There can also be more than one breadcrumb on a page, Google gives an example in his guidelines for a breadcrumb.
Using the API
You can define a breadcrumb with the API as you may already guessed. For example, you have defined a breadcrumb somewhere:
$breadcrumb = [
'Some product category' => 'https://example.org/some-product-category/',
'Some product subcategory' => 'https://example.org/some-product-subcategory/',
'Some fancy product' => 'https://example.org/some-fancy-product/',
];
Now you can iterate over the pages:
<?php
declare(strict_types=1);
namespace MyVendor\MyExtension\Controller;
use Brotkrueml\Schema\Manager\SchemaManager;
use Brotkrueml\Schema\Type\TypeFactory;
final class MyController
{
public function __construct(
private readonly SchemaManager $schemaManager,
private readonly TypeFactory $typeFactory,
) {}
public function createBreadcrumb(array $breadcrumb): void
{
// ...
$breadcrumbList = $this->typeFactory->create('BreadcrumbList');
$counter = 0;
foreach ($breadcrumb as $name => $url) {
$counter++;
$breadcrumbList->addProperty(
'itemListElement',
$this->typeFactory->create('ListItem')
->setProperties([
'name' => $name,
'item' => $url,
'position' => $counter,
]),
);
}
$this->schemaManager->addType($breadcrumbList);
// ...
}
}
This results in the following schema markup:
{
"@context": "https://schema.org/",
"@type": "WebPage",
"breadcrumb": {
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"item": "https://example.org/some-product-category/",
"name": "Some product category",
"position": "1"
},
{
"@type": "ListItem",
"item": "https://example.org/some-product-subcategory/",
"name": "Some product subcategory",
"position": "2"
},
{
"@type": "ListItem",
"item": "https://example.org/some-fancy-product/",
"name": "Some fancy product",
"position": "3"
}
]
}
}
As you can see, the breadcrumb is embedded in a Web
automatically.
Using the view helpers
View helper <schema:type.breadcrumbList>
The schema markup can also be achieved by a view helper in a Fluid template:
<schema:type.breadcrumbList>
<f:for each="{breadcrumb}" as="item" iteration="iterator">
<schema:type.listItem
-as="itemListElement"
name="{item.title}"
item="{item.link}"
position="{iterator.cycle}"
/>
</f:for>
</schema:type.breadcrumbList>
It is also possible to use it in combination with one of the Web
types:
<schema:type.itemPage>
<schema:type.breadcrumbList -as="breadcrumb">
<f:for each="{breadcrumb}" as="item" iteration="iterator">
<schema:type.listItem
-as="itemListElement"
name="{item.title}"
item="{item.link}"
position="{iterator.cycle}"
/>
</f:for>
</schema:type.breadcrumbList>
</schema:type.itemPage>
View helper <schema:breadcrumb>
But mostly you will have the breadcrumb structure in a Fluid variable created by a MenuProcessor in TypoScript:
page = PAGE
page {
# ... some other configuration ...
10 = FLUIDTEMPLATE
10 {
# ... some other configuration ...
dataProcessing {
10 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
10 {
special = rootline
as = breadcrumb
}
}
}
}
Wouldn't it be cool to use this variable as input for the schema markup without iterating over the structure? So, let's use the breadcrumb view helper for that:
<schema:breadcrumb breadcrumb="{breadcrumb}"/>
That is it.
The best place to use this view helper is in the template where you generate the visual representation of the breadcrumb for your users.
Normally the home page is part of the generated breadcrumb, but this is not
necessary for the schema markup - so the home page is omitted. But if you really
want to have it in the markup (or you have a breadcrumb generated on your own
without the home page), you can use the attribute render
and
set it to 1
:
<schema:breadcrumb breadcrumb="{breadcrumb}" renderFirstItem="1"/>
You can build your own breadcrumb array and assign it to the template. It should have the following structure:
$breadcrumb = [
[
'title' => 'Home page',
'link' => '/',
'data' => [
'tx_schema_webpagetype' => 'WebPage',
],
],
[
'title' => 'Some product category',
'link' => '/some-product-category/',
'data' => [
'tx_schema_webpagetype' => 'CollectionPage',
],
],
[
'title' => 'Some product subcategory',
'link' => '/some-product-subcategory/',
'data' => [
'tx_schema_webpagetype' => 'CollectionPage',
],
],
[
'title' => 'Some fancy product',
'link' => '/some-fancy-product/',
'data' => [
'tx_schema_webpagetype' => 'ItemPage',
],
],
];
If the key tx_
is omitted, it defaults to Web
.
Remarks
- The home page should not be included into the markup.
- Please keep in mind that according to the Google Structured Data Testing Tool,
only the type
Breadcrumb
is allowed for the breadcrumb property - either the schema.org definition allows strings. Other types than the BreadcrumbList are ignored by the schema manager.List - It is intended that the breadcrumb is not automatically rendered out of the page structure of your TYPO3 installation, because it is possible to extend the breadcrumb with own MenuProcessors like in the news extension.