For coders TYPO3 Tech Corner

Set title and meta tags via Fluid in TYPO3

Set title and meta tags via Fluid in TYPO3

We have already described in another blog post how you can set meta tags, titles or other code in the head area of the frontend output directly via PHP. But we are going one step further here and want to set these tags directly in the fluid in the future.

Oldschool - with TypoScript

Tags in the head area of the HTML via TypoScript: Many of you probably already know this way. It then looked something like this:

config.noPageTitle = 1 page.headerData { 10 = TEXT 10 { wrap3 = <title>|</title> noTrimWrap = ||: company - any claim| data = page:title } 20 = TEXT 20.value ( <link rel="apple-touch-icon" sizes="180x180" href="/typo3conf/ ext/in2template/Resources/Public/apple.png"> ) 30 = TEXT 30.value ( <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="/rss.html"> ) }

Modern - directly in Fluid in an HTML file

In the future, however, we want to make it possible to maintain these types of tags directly in the HTML. This is not only more intuitive, but also easier to use if assets are no longer accessible via "/typo3conf/ext/" in TYPO3 12 at the latest, but are located in the "vendor" directory.

For this we can embed a partial directly in the page template that takes care of all header data:

<in2template:meta.title> {data.title} - company claim </in2template:meta.title> <in2template:meta.addHeaderData> <link rel="stylesheet" sizes="180x180" href="{f:uri.resource(path:'Css/basic.css',extensionName:'In2template')}"> <link rel="apple-touch-icon" sizes="180x180" href="{f:uri.resource(path:'Favicons/apple-touch-icon.png',extensionName:'In2template')}"> <link rel="shortcut icon" href="{f:uri.resource(path:'Favicons/favicon.ico',extensionName:'In2template')}"> <meta name="msapplication-config" content="{f:uri.resource(path:'Favicons/browserconfig.xml',extensionName:'In2template')}"> <meta name="theme-color" content="#a5c85a"> <link rel="alternate" type="application/rss+xml" title="RSS Feed von in2code - Wir leben TYPO3" href="/rss.html"> <style> :root { --in2-modal-brand-color: #a5c85a; } </style> <script>var requireJsBasePath="{f:uri.resource(path:'JavaScripts/',extensionName:'In2template')}"</script> </in2template:meta.addHeaderData> <in2template:meta.addFooterData> <script async="" data-main="{f:uri.resource(path:'JavaScripts/',extensionName:'In2template')}main" src="{f:uri.resource(path:'JavaScripts/',extensionName:'In2template')}Vendor/require.js"></script> </in2template:meta.addFooterData>

In order for this to work, it still needs three ViewHelpers (and a small TitleProvider configuration). In all of the following examples, our sitepackage extension is called "in2template". You can use the namespace to find out where the files are located.

AddHeaderDataViewHelper to write any tags in the head area:

<?php declare(strict_types=1); namespace In2code\In2template\ViewHelpers\Meta; use Closure; use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; class AddHeaderDataViewHelper extends AbstractViewHelper { /** * @param array $arguments * @param Closure $renderChildrenClosure * @param RenderingContextInterface $renderingContext * @return void */ public static function renderStatic( array $arguments, Closure $renderChildrenClosure, RenderingContextInterface $renderingContext ) { $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); $pageRenderer->addHeaderData(self::removeWhitespaceBetweenTags($renderChildrenClosure())); } protected static function removeWhitespaceBetweenTags(string $html): string { return preg_replace('~\>\s+\<~m', '><', $html); } }

AddFooterDataViewHelper to write any tags last inside the body tag:

<?php declare(strict_types=1); namespace In2code\In2template\ViewHelpers\Meta; use Closure; use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; class AddFooterDataViewHelper extends AbstractViewHelper { /** * @param array $arguments * @param Closure $renderChildrenClosure * @param RenderingContextInterface $renderingContext * @return void */ public static function renderStatic( array $arguments, Closure $renderChildrenClosure, RenderingContextInterface $renderingContext ) { $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); $pageRenderer->addFooterData(self::removeWhitespaceBetweenTags($renderChildrenClosure())); } protected static function removeWhitespaceBetweenTags(string $html): string { return preg_replace('~\>\s+\<~m', '><', $html); } }

TitleViewHelper helps to set a title:

<?php declare(strict_types=1); namespace In2code\In2template\ViewHelpers\Meta; use Closure; use In2code\In2template\PageTitle\Provider; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; class TitleViewHelper extends AbstractViewHelper { public function initializeArguments() { parent::initializeArguments(); $this->registerArgument('title', 'string', 'Any title for title tag', false); } /** * @param array $arguments * @param Closure $renderChildrenClosure * @param RenderingContextInterface $renderingContext * @return void */ public static function renderStatic( array $arguments, Closure $renderChildrenClosure, RenderingContextInterface $renderingContext ) { $title = $arguments['title'] ?? $renderChildrenClosure(); $titleProvider = GeneralUtility::makeInstance(Provider::class); $titleProvider->setTitle(trim($title)); } }

For this, a TitleProvider must be registered via TypoScript (setup):

config.pageTitleProviders { page { provider = In2code\In2template\PageTitle\Provider after = seo,news before = record,altPageTitle } }

And the provider itself consists only of a setter:

<?php declare(strict_types = 1); namespace In2code\In2template\PageTitle; use TYPO3\CMS\Core\PageTitle\AbstractPageTitleProvider; class Provider extends AbstractPageTitleProvider { public function setTitle(string $title): void { $this->title = $title; } }

Notes:

1) In this example - as so often - we left out a few things that you probably already know anyway (namespace declaration in FLUID of the ViewHelper, the variable {data} in FLUID with all values pages.*, etc... )

2) Make sure you don't have "config.noPageTitle" set if you want to set the page title via a provider

3) If you don't want the postfix of your title, you should simply leave the value "websiteTitle" empty in the SiteConfiguration

Happy TYPO3 Coding

Back

"Code faster, look at the time" - does this sound familiar to you?

How about time and respect for code quality? Working in a team? Automated tests?

Join us