Page title

Seitentitel mit TYPO3

Die Generierung eines title Tags ist für die Auffindbarkeit in den Suchmaschinen ein wichtiger Baustein. Mit einem Content Management System wie TYPO3 ist eine konsistente Generierung von Seitentitel gut sicherzustellen. Seit der Version 9LTS bringt TYPO3 eine eigene PageTitle API mit, mit der sich die Seitentitel sehr komfortabel generieren lassen. 

Je nachdem, welchen SEO-Experten man fragt, wird häufig ein Seitentitel im Brotkrumen-Format (vorwärts oder umgekehrt) gewünscht. Weil die Seiten in TYPO3 schon grundsätzlich in einem hierarchischen Seitenbaum angelegt sind, sind alle Informationen hierfür schon vorhanden. 

Ein wenig interessanter wird es, wenn Extensions zum Einsatz kommen, die eine Detailansicht zur Verfügung stellen. In diesem Fall möchte man meist, dass der Seitentitel aus dem angezeigten Datensatz generiert wird (ggf. angereichert mit Informationen aus dem Seitenbaum). 

Die TYPO3 PageTitle API

Mit der PageTitle API können verschiedene PageTitleProvider verwendet werden, die in der konfigurierten Reihenfolge abgearbeitet werden. Sobald ein PageTitleProvider einen Titel setzt, wird die Verarbeitung abgebrochen und dieser Titel verwendet. Bei der Konfiguration muss daher darauf geachtet werden, dass der speziellste PageTitleProvider zu Beginn kommt und es dann immer allgemeiner wird.

Beim Programmieren eines eigenen PageTitleProvider muss darauf geachtet werden, dass der Provider keinen Seitentitel setzt, wenn er nicht zuständig ist, da er andernfalls die nachfolgenden PageTitleProvider blockieren würde.

Die PageTitleProvider können im TypoScript ganz einfach konfiguriert werden: 

 

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

 

Sofern die Core-Extension seo installiert ist, bringt TYPO3 den SeoTitlePageTitleProvider mit. Für dieses Beispiel baue ich aber einen eigenen PageTitleProvider für den Seitenbaum auf Brotkrumen-Basis sowie einen RecordPageTitleProvider für einen Detailview auf.

Links zur TYPO3-Dokumentation:

PageTitle API 

 

Breadcrumb-Seitentitel leicht gemacht

Wir machen uns zunutze, dass die Seiten in TYPO3 immer hierarchisch sortiert sind. Auf diese Hierarchie können wir via $GLOBALS['TSFE']->rootLine sehr einfach zugreifen. Und damit schreibt sich unser PageTitleProvider fast von selbst: 

 

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;
      }
    }
}

 

Natürlich kann man die Reihenfolge der Brotkrumen auch umkehren, einen Seitentitel anzuhängen oder dem Redakteur erlauben, mit seo_title den automatisch generierten title tag zu überschreiben oder oder oder... Die Möglichkeiten sind unbegrenzt!

und Seitentitel für Detailansichten

Bei Extensions, die Datensätze in einer Detailansicht anzeigen, ist es wünschenswert, wenn sich der title tag entsprechend anpasst. Hierfür gibt es prinzipiell zwei Wege. 

Zum einen kann ein PageTitleProvider erkennen, ob eine solche Detailansicht vorliegt (indem die Request-Parameter ausgewertet werden) und den entsprechenden Titel setzen oder eben nicht (damit nachfolgende PageTitleProvider diese Aufgabe übernehmen können). Dieser Weg funktioniert immer, ist aber etwas umständlicher zu programmieren und verursacht weitere Datenbankabfragen. Für den Fall, dass aber eine Extension eines Drittanbieters entsprechend erweitert werden soll, möchte ich diesen Weg trotzdem erwähnen. 

 

<?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'];
            }
        }
    }
}

 

Der aus meiner Sicht bessere Weg ist, dass jede Extension einen eigenen PageTitleProvider mitbringt, der dann einfach per Konfiguration eingeschaltet werden kann. Dieser kann sehr einfach sein und muss nur eine einzige Methode implementieren: 

 

<?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 diesem Beispiel wird wie im PageTitleProvider weiter oben auch die Seitenhierarchie bereits berücksichtigt. Die Methode setTitle($title) muss nun nur noch im entsprechenden Controller aufgerufen werden, wenn die showAction() abgearbeitet wird. Der große Vorteil: Der entsprechende Datensatz steht ohne zusätzliche Datenbankaufrufe zur Verfügung und der Titel kann entsprechend einfach aus allen verfügbaren Feldern und Relationen zusammengesetzt werden. 

 

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);
       
    }

 

 

Damit die von uns erstellten PageTitle Provider auch verwendet werden, müssen wir diese am TYPO3-System anmelden. Weiter oben haben wir bereits gelernt, wie die PageTitle Provider konfiguriert werden: 

 

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
   }
}

 

Für jeden TitleProvider kann die Reihenfolge mit before oder after konfiguriert werden. Dabei muss sichergestellt werden, dass die Reihenfolge der verschiedenen TitleProvider konsistent ist. Wird ein Kreis in der Reihenfolge konfiguriert, steigt TYPO3 mit einer Fehlermeldung aus: 

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

Wer auf diese Fehlermeldung: "#1381960494 UnexpectedValueException. Your dependencies have cycles. That will not work out. Cycles found:" stößt, muss also genau diese Reihenfolge in seiner Konfiguration prüfen uns sie beheben. In der Fehlermeldung wird auf die problematischen TitleProvider hingeweisen, so dass die Ursache sehr schnell gefunden werden kann.

Ich kann das!

Der Self Verification Button ermöglicht Dir, Deinen eigenen Lernfortschritt zu messen und mit der Anforderung für offizielle TYPO3 Zertifizierungen zu vergleichen. Diese Funktionalität wird von SkillDisplay bereitgestellt, Registrierung und Nutzung sind für Lernende kostenfrei. Finde mehr über SkillDisplay für Lernende heraus.

 

Kommentare (10)

  • Clive Beckett
    Clive Beckett
    am 12.05.2020
    Dieser Beitrag hat mir so geholfen, vielen Dank! Ich hatte damals nach einer Möglichkeit gesucht, mithilfe der PageTitle API den Seitenbaum in den Titel zu bekommen, doch keine gefunden und bin so bei meiner hässlichen TypoScript-Lösung geblieben.

    Nur für die News-Extension bekomme ich es nicht hin. Ich hatte mit den Reihenfolgen etwas gespielt, um gegebenenfalls die News-Titel über den PageTitleProvider meines SitePackages auszulesen. Das hatte aber zur Folge, dass es für keine meiner anderen (eigenen) Extensions mehr funktioniert hatte.
    • Marc Willmann
      Marc Willmann
      am 14.05.2020
      Hallo Clive,

      danke für Deine Rückmeldung und schön, dass Du Dir aus dem Beitrag was ziehen konntest. :)
      Die news-Extension macht das ja etwas anders und liefert einen ViewHelper mit, mit dem der Titel überschrieben wird. Da ist es dann zumindest knifflig und redundant, den Breadcrumb auch mit zu übergeben.

      Du kannst entweder den Breadcrumb z.B. über einen MenuDataProcessor an den News-View mitliefern und dort dann den Titel an den ViewHelper übergeben. Das ist relativ einfach; allerdings IMHO nicht ganz sauber, weil Du nun zwei Stellen hast, die den Titel generieren und die bei einer Änderung beide angefasst werden müssen.

      Daher würde ich den News-TitleViewHelper gar nicht benutzen und stattdessen dem PageTitleProvider beibringen, dass er auf News-Details reagiert (s. Codebeispiel oben, direkt unterhalb von "und Seitentitel für Detailansichten").

      Dabei muss dann der NewsTitleProvider VOR dem generellen PageTitleProvider aufgerufen werden, wie im Text beschrieben.
    • Julian
      Julian
      am 14.12.2022
      Danke für die Snippets, Marc.

      Habe eben ne Weile lang gesucht, warum PHPStorm mir nach dem Kopieren wilde Syntax-Fehler meldet - füge doch in den ersten PageTitleProvider noch eine Funktion ein, dann tut das auch ;-)
    • Marc Willmann
      Marc Willmann
      am 14.12.2022
      LOL. Ach, Details! Danke für den Hinweis!
  • Armin
    Armin
    am 20.09.2023
    Vielen Dank für den Beitrag.

    Ich habe einen eigenen PageTitle Provider geschrieben und will diesen generell für alle Seiten verwenden.

    Typo3 kommt aber nicht in die Klasse rein. Ich habe folgendes in meiner Provider Extension in die setup.txt geschrieben:
    config.pageTitleProviders {
    pages {
    provider = Vender\Sitepackage\Seo\GeneralTitleProvider
    before = seo
    }
    }
    }

    Hast du vielleicht eine Idee warum Typo3 diese Klasse nicht findet? Typo3 Version 11. In der autoload_classmap ist die Klasse vorhanden.

    Vielen Dank voarb
    • Marc Willmann
      Marc Willmann
      am 20.09.2023
      Die TypoScript-Files müssen auf .typoscript enden; also setup.typoscript statt wie früher setup.txt. Vermutlich liegt's schon daran.

      Du kannst im TSOB (TypoScript Object Browser) prüfen, ob Dein TypoScript aktiv ist.
    • Armin
      Armin
      am 20.09.2023
      Super vielen Dank. Jetzt wird es mir im TSOB angezeigt und meine Klasse wird aufgerufen.

      Jetzt habe ich noch eine Frage: Wie bekomme ich den websiteTitle davor weg?

      Den kann ich nicht entfernen über meine Klasse:
      $this->title = $GLOBALS['TSFE']->page['title'];
    • Marc Willmann
    • Armin
      Armin
      am 20.09.2023
      Dein Link ist weiß und nicht zu erkennen.

      config.noPageTitle = 1 entfernt nur den Seitentitel und nicht den websiteTitle. config.noPageTitle = 2 entfernt das komplette title-Tag im Frontend.

      Ich bekomme den websiteTitle einfach nicht raus! Noch eine Idee?
      Vielen Dank bis dahin
  • Armin
    Armin
    am 22.09.2023
    Bei mir hat nur folgender Patch geholfen, um den websiteTitle aus dem title-Tag zu entfernen:
    https://forge.typo3.org/issues/97653

Neue Antwort auf Kommentar schreiben