Main entity of a web page

Target group: Developers

Introduction

A WebPage type provides a property mainEntity, which indicates the primary content of a page. Every type is allowed - although some types doesn't make sense (e.g. a breadcrumb cannot be the primary content).

Note

Technically, there can be more than one main entity at a time. For example, if you have a FAQPage you will usually assign more than one question as mainEntity.

Using the API

The main entity of a web page can be defined with the API. Let's start with an example that specifies a product as the primary content:

$aggregateRating = \Brotkrueml\Schema\Type\TypeFactory::createType('AggregateRating');
   ->setProperty('ratingValue', '4')
   ->setProperty('reviewCount', '126')
;

$product = \Brotkrueml\Schema\Type\TypeFactory::createType('Product')
   ->setProperties([
      'name' => 'Some fancy product',
      'color' => 'blue',
      'material' => 'wood',
      'image' => 'https://example.org/some-fancy-product.jpg',
      'aggregateRating' => $aggregateRating,
   ])
;

$schemaManager->addMainEntityOfWebPage($product);

The above example is rendered as JSON-LD. Let's assume the WebPage type is set to ItemPage - either in the page properties or via the API or a view helper.

{
   "@context": "https://schema.org/",
   "@type": "ItemPage",
   "mainEntity": {
      "@type": "Product",
      "aggregateRating": {
         "@type": "AggregateRating",
         "ratingValue": "4",
         "reviewCount": "126"
      },
      "color": "blue",
      "image": "https://example.org/some-fancy-product.jpg",
      "material": "wood",
      "name": "Some fancy product"
   }
}

Note

If the WebPage type is not defined because the appropriate setting is disabled in the extension configuration, the main entity is rendered as a root type.

Using the view helpers

You can define the main entity also in a view helper:

<schema:type.product
   -as="mainEntity"
   -isMainEntityOfWebPage="1"
   name="Some fancy product"
   color="blue"
   material="wood"
   image="https://example.org/some-fancy-product.jpg"
>
   <schema:type.aggregateRating
      -as="aggregateRating"
      ratingValue="4"
      reviewCount="126"
   />
</schema:type.product>

Remark

You can set the view helper argument -isMainEntityOfWebPage only in the main type view helper, not in a child type view helper.

Prioritisation

New in version 2.2.0.

Main entities can be prioritised. This is sometimes necessary when different main entities are defined in different places (for example in a controller, a Fluid page template or in a content element).

Let's look at an example: In a page template for a blog post, the main entity is defined as type BlogPosting. There are content elements on the page that display questions and answers for a FAQ. The content element sets the web page type to 'FAQPage' and also defines the questions as the main entities (to display as rich snippets on the search results page). However, Google Search Console shows an error because BlogPosting is not allowed as the main entity of a FAQPage.

The main entity of the API example above can be prioritised by setting the second argument to true:

$schemaManager->addMainEntityOfWebPage($product, true);

Let's look at the example described in the introduction. In a page template, a BlogPosting type is defined as the main entity of the page:

<!-- This is defined in a page template -->
<schema:type.blogPosting
   -isMainEntityOfWebPage="1"
   name="A blog post"
/>

And the FAQ is rendered in the template of a content element. To prioritise these types, -isMainEntityOfWebPage is set to 2:

<!-- This is defined in a content element template -->
<schema:type.fAQPage/>
<f:for each="{questions}" as="question">
   <schema:type.question
      -isMainEntityOfWebPage="2"
      name="{question.title}"
   />
</f:for>

This results in the following output:

{
   "@context": "https://schema.org/",
   "@graph": [{
      "@type": "FAQPage",
      "mainEntity":[{
         "@type": "Question",
         "name": "Question #1"
      }, {
         "@type": "Question",
         "name": "Question #2"
      }]
   }, {
      "@type": "BlogPosting",
      "name": "A blog post"
   }]
}