Page title API

In order to keep setting the page titles in control, you can use the PageTitle API. The API uses page title providers to define the page title based on page record and the content on the page.

Based on the priority of the providers, the \TYPO3\CMS\Core\PageTitle\PageTitleProviderManager will check the providers if a title is given by the provider. It will start with the highest priority and will end with the lowest priority.

By default, the Core ships two providers. If you have installed the system extension SEO, the provider with the (by default) highest priority will be the \TYPO3\CMS\Seo\PageTitle\SeoTitlePageTitleProvider. When an editor has set a value for the SEO title in the page properties of the page, this provider will provide that title to the PageTitleProviderManager. If you have not installed the SEO system extension, the field and provider are not available.

The fallback provider with the lowest priority is the \TYPO3\CMS\Core\PageTitle\RecordPageTitleProvider. When no other title is set by a provider, this provider will return the title of the page.

Besides the providers shipped by the Core, you can add own providers. An integrator can define the priority of the providers for his project.

Create your own page title provider

Extension developers may want to have an own provider for page titles. For example, if you have an extension with records and a detail view, the title of the page record will not be the correct title. To make sure to display the correct page title, you have to create your own page title provider. It is quite easy to create one.

Example: Set the page title from your extension's controller

First, create a PHP class in your extension that implements the \TYPO3\CMS\Core\PageTitle\PageTitleProviderInterface, for example by extending \TYPO3\CMS\Core\PageTitle\AbstractPageTitleProvider. Within this method you can create your own logic to define the correct title.

EXT:my_extension/Classes/PageTitle/MyOwnPageTitleProvider.php
<?php

declare(strict_types=1);

namespace MyVendor\MySitepackage\PageTitle;

use TYPO3\CMS\Core\PageTitle\AbstractPageTitleProvider;

final class MyOwnPageTitleProvider extends AbstractPageTitleProvider
{
    public function setTitle(string $title): void
    {
        $this->title = $title;
    }
}

Usage example in an Extbase controller:

EXT:my_extension/Classes/Controller/SomeController.php
<?php

use MyVendor\MySitepackage\PageTitle\MyOwnPageTitleProvider;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

final class SomeController extends ActionController
{
    public function __construct(
        private readonly MyOwnPageTitleProvider $titleProvider
    ) {
    }

    public function someAction(): ResponseInterface
    {
        $this->titleProvider->setTitle('Title from controller action');
        // do something
        return $this->htmlResponse();
    }
}

Configure the new page title provider in your TypoScript setup:

EXT:my_sitepackage/Configuration/TypoScript/setup.typoscript
config {
  pageTitleProviders {
    sitepackage {
      provider = MyVendor\MySitepackage\PageTitle\MyOwnPageTitleProvider
      before = record
    }
  }
}

Example: Use values from the site configuration in the page title

If you want to use data from the site configuration, for example the site title, you can implement a page title provider as follows:

EXT:my_sitepackage/Classes/PageTitle/WebsiteTitleProvider.php
<?php

declare(strict_types=1);

namespace MyVendor\MySitepackage\PageTitle;

use TYPO3\CMS\Core\PageTitle\PageTitleProviderInterface;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;

final class WebsiteTitleProvider implements PageTitleProviderInterface
{
    public function __construct(
        private readonly SiteFinder $siteFinder
    ) {
    }

    public function getTitle(): string
    {
        $site = $this->siteFinder->getSiteByPageId($this->getTypoScriptFrontendController()->page['uid']);
        $titles = [
            $this->getTypoScriptFrontendController()->page['title'],
            $this->$site->getAttribute('websiteTitle'),
        ];

        // do something
        return implode(' - ', $titles);
    }

    private function getTypoScriptFrontendController(): TypoScriptFrontendController
    {
        return $GLOBALS['TSFE'];
    }
}

As we need to inject the class SiteFinder to retrieve the current site configuration, we must make the new page title provider public:

EXT:my_sitepackage/Configuration/Services.yaml
services:
  _defaults:
    autowire: true
    autoconfigure: true
    public: false

  MyVendor\MySitepackge\PageTitle\WebsiteTitleProvider:
    public: true

Then flush the cache in Admin Tools > Maintenance > Flush TYPO3 and PHP Cache.

Configure the new page title provider to be used in your TypoScript setup:

EXT:my_sitepackage/Configuration/TypoScript/setup.typoscript
config {
  pageTitleProviders {
    sitepackage {
      provider = MyVendor\MySitepackage\PageTitle\WebsiteTitleProvider
      before = record
      after = seo
    }
  }
}

The registered page title providers are called after each other in the configured order. The first provider that returns a non-empty value is used, the providers later in the order are ignored.

Therefore our custom provider should be loaded before record, the default provider which always returns a value. If the system extension EXT:seo is loaded the default SEO Title has a particular format, you can change this by loading your custom provider before seo.

Define the priority of PageTitleProviders

The priority of the providers is set by the TypoScript property config.pageTitleProviders. This way an integrator is able to set the priorities for his project and can even have conditions in place.

By default, the Core has the following setup:

config.pageTitleProviders {
    record {
        provider = TYPO3\CMS\Core\PageTitle\RecordPageTitleProvider
    }
}

The sorting of the providers is based on the before and after parameters. If you want a provider to be handled before a specific other provider, just set that provider in the before, do the same with after.

If you have installed the system extension SEO, you will also get a second provider. The configuration will be:

config.pageTitleProviders {
    record {
        provider = TYPO3\CMS\Core\PageTitle\RecordPageTitleProvider
    }
    seo {
        provider = TYPO3\CMS\Seo\PageTitle\SeoTitlePageTitleProvider
        before = record
    }
}

First the SeoTitlePageTitleProvider (because it will be handled before record) and, if this providers did not provide a title, the RecordPageTitleProvider will be checked.

You can override these settings within your own installation. You can add as many providers as you want. Be aware that if a provider returns a non-empty value, all provider with a lower priority will not be checked.