Page title

Page titles with TYPO3

The generation of a title tag is an important component for the findability in the search engines. With a content management system like TYPO3 a consistent generation of page titles can be guaranteed. Since version 9LTS TYPO3 comes with its own PageTitle API, with which the page titles can be generated very comfortably.

Depending on which SEO expert you ask, a page title in breadcrumb format (forward or reverse) is often desired. Because pages in TYPO3 are basically already created in a hierarchical page tree, all information for this is already available.

It becomes a little more interesting when extensions are used that provide a detailed view. In this case, you usually want the page title to be generated from the displayed data record (possibly enriched with information from the page tree).

The TYPO3 PageTitle API

With the PageTitle API, different PageTitleProviders can be used, which are processed in the configured order. As soon as a PageTitleProvider sets a title, processing is terminated and this title is used. During configuration, you must therefore ensure that the most specific PageTitleProvider comes at the beginning and then becomes more general.

When programming your own PageTitleProvider, you must ensure that the provider does not set a page title if it is not responsible, otherwise it would block the subsequent PageTitleProviders.

The PageTitleProviders can be easily configured in TypoScript:

 

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

 

If the core extension seo is installed, TYPO3 comes with the SeoTitlePageTitleProvider. But for this example I will build my own PageTitleProvider for the page tree on breadcrumb basis and a RecordPageTitleProvider for a detail view.

Links to TYPO3 documentation:

PageTitle API

 

Breadcrumb page titles made easy

We take advantage of the fact that pages in TYPO3 are always sorted hierarchically. We can access this hierarchy very easily via $GLOBALS['TSFE']->rootLine. And thus our PageTitleProvider writes itself almost by itself:

 

namespace MarcWillmann\Sitepackage\PageTitle;

use TYPO3\CMS\Core\PageTitle\AbstractPageTitleProvider;

class PageTitleProvider extends AbstractPageTitleProvider
{
   $this->title = '';
   $rootline = $GLOBALS['TSFE']->rootLine;
   $separator = ' ' ';
   foreach ($rootline as $key => $titlePart) {
      $this->title .= $titlePart['title'];
      if ($key !== 0) {
         $this->title.= $separator;
      }
    }
}

 

Of course you can also reverse the order of the breadcrumbs, append a page title or allow the editor to overwrite the automatically generated title tag with seo_title or or or... The possibilities are unlimited!

and page titles for detail views

For extensions that display records in a detail view, it is desirable that the title tag adapts accordingly. There are basically two ways to do this.

On the one hand, a PageTitleProvider can recognize whether such a detailed view exists (by evaluating the request parameters) and set the corresponding title or not (so that subsequent PageTitleProviders can take over this task). This way always works, but is a bit more complicated to program and causes further database queries. In case you want to extend a third party extension, I would like to mention this way anyway.

 

<?php
declare(strict_types=1);

namespace MarcWillmann\Events\PageTitle;

use TYPO3\CMS\Core\PageTitle\AbstractPageTitleProvider;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Database\ConnectionPool;

class EventTitleProvider extends AbstractPageTitleProvider
{
    public function __construct() {
        $eventUid = (int)$GLOBALS['_GET']['tx_events_events']['event'];
        $table = 'tx_events_domain_model_event';
        // check if this titleProvider is in charge
        if ($eventUid > 0) {
            // collect needed data from the database
            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
                ->getQueryBuilderForTable($table);
            $records = $queryBuilder
                ->select('title')
                ->from($table)
                ->where($queryBuilder->expr()->eq('uid', $eventUid))
                ->setMaxResults(1)
                ->execute()
                ->fetchAll();

            foreach ($records as $record) {
                $this->title = $record['title'];
            }
        }
    }
}

 

The better way from my point of view is that each extension brings its own PageTitleProvider, which can be easily switched on by configuration. This can be done very easily and only needs to implement one method:

 

<?php
declare(strict_types=1);

namespace MarcWillmann\Events\PageTitle;

use TYPO3\CMS\Core\PageTitle\AbstractPageTitleProvider;

class EventTitleProvider extends AbstractPageTitleProvider
{
    public
    function setTitle(
        string $title
    ) {
        $this->title = $title. ' | ';
        $rootline = $GLOBALS['TSFE']->rootLine;
        $separator = ' | ';
        foreach ($rootline as $key => $titlePart) {
            $this->title .= $titlePart['title'];
            if ($key !== 0) {
                $this->title.= $separator;
            }
        }
    }
}

 

In this example, as in the PageTitleProvider above, the page hierarchy is already taken into account. The method setTitle($title) must now only be called in the corresponding controller when the showAction() is processed. The big advantage: The corresponding data set is available without additional database calls and the title can be easily composed of all available fields and relations.

 

public function showAction(\MarcWillmann\Events\Domain\Model\Event $event)
    {
        $titleProvider = GeneralUtility::makeInstance(\MarcWillmann\Events\PageTitle\EventTitleProvider::class);
        $pageTitle = $event->getTitle();
        $titleProvider->setTitle($pageTitle);

        $this->view->assign('event', $event);
       
    }

 

 

In order to use the PageTitle providers we have created, we have to register them with the TYPO3 system. Above we have already learned how to configure the PageTitle Provider:

 

config.pageTitleProviders {
   event {
      provider = MarcWillmann\Sitepackage\PageTitle\EventTitleProvider
      before = pages
   }
   pages {
      provider = MarcWillmann\Sitepackage\PageTitle\PageTitleProvider
      before = seo
   }
   seo {
      provider = TYPO3\CMS\Seo\PageTitle\SeoTitlePageTitleProvider
      before = record
   }
}

 

For each TitleProvider, the sequence can be configured with before or after. You must ensure that the sequence of the various TitleProviders is consistent. If a circle is configured in the sequence, TYPO3 exits with an error message:

#1381960494 UnexpectedValueException Your dependencies have cycles. That will not work out. Cycles found

Who responds to this error message: "#1381960494 UnexpectedValueException. Your dependencies have cycles. That will not work out. Cycles found:", you have to check and fix exactly this order in your configuration. The error message points out the problematic TitleProviders, so that the cause can be found very quickly.

I know that!

The Self Verification Button allows you to measure your own learning progress and compare it with the requirements for official TYPO3 certifications. This functionality is provided by SkillDisplay, registration and use are free for learners. Find out more about SkillDisplay for learners..

 

Comments (2)

  • Clive Beckett
    Clive Beckett
    2 weeks ago
    This contribution has helped me so much, thank you very much! I was looking for a way to use the PageTitle API to get the page tree into the title, but I couldn't find one, so I stuck with my ugly TypoScript solution.

    Only for the news extension I can't get it right. I had played a little bit with the order to read the news titles via the PageTitleProvider of my SitePackage. But this had the consequence that it did not work for any of my other (own) extensions.

    Original text in german; this version was automatically translated with www.DeepL.com/Translator for convenience
    • Marc Willmann
      Marc Willmann
      2 weeks ago
      Hello, Clive,

      thank you for your feedback and I'm glad that you were able to get something out of the article. :)
      The news-Extension does it a little bit different and provides a ViewHelper to overwrite the title. So it is at least tricky and redundant to pass the breadcrumb as well.

      You can either pass the breadcrumb to the news view via a MenuDataProcessor and then pass the title to the ViewHelper. This is relatively simple, but IMHO not quite clean, because you now have two places that generate the title and both of which must be touched when you make a change.

      So I wouldn't use the news titleViewHelper at all and instead teach the PageTitleProvider to respond to news details (see code example above, just below "and page titles for detail views" ;-)

      The NewsTitleProvider must then be called BEFORE the general PageTitleProvider, as described in the text.

Write new comment