You want to change what a theme outputs at a specific point. The obvious approach is a custom template hook with type replace. Install the application and the log says:
Data truncated for column 'template_hookpoint_type' at row 1
The application installs, the hook does not, and nothing on the front end changes.
The four types
The column is an enum:
template_hookpoint_type enum('before','inside-start','inside-end','after')
That is the whole list. The string 'replace' does appear in core's own PHP, which is what sends you down this path, but it is not a storable value for a custom template hook. Theme hooks in Invision Community 5 are insert-only. You can add before, at the start, at the end, or after — you cannot swap an element out.
Which matters most for the <title>
The title is emitted like this:
<title data-ips-hook="title">{expression="output.getTitle( $title )"}</title>
There is a hook point right there, and every option is wrong:
inside-start/inside-end— appends to the existing title:<title>Old New</title>.before/after— emits a second<title>. Browsers and crawlers take the first one, so which wins depends on which side you picked, and having two is wrong regardless.
The seam that does work
Read Output::getTitle():
public function getTitle( ?string $title ): string
{
if( $this->metaTagsTitle )
{
$title = $this->metaTagsTitle; // <- used verbatim
}
else
{
$title = htmlspecialchars( $title, ENT_DISALLOWED, 'UTF-8', FALSE );
}
...
metaTagsTitle wins outright. It is the same field the Meta Tags manager writes to, so using it is the sanctioned route rather than a workaround. Set it from an inside-start hook on <head>, which the template renders two lines before <title>:
{
"hookpoint": "core/front/global/globalTemplate:head",
"type": "inside-start",
"content": "{expression=\"\\IPS\\yourapp\\Meta\\Tags::apply()\"}"
}
Your apply() returns an empty string and its only job is the assignment. Two things to get right:
- Escape it yourself.
getTitle()escapes only in the else branch — ametaTagsTitleis emitted raw. - Bail if it is already set. Somebody using the Meta Tags manager has said exactly what they want; do not overwrite it.
A content listener is too early
The tempting alternative is onItemView. It does not work, and the reason is ordering. In Content\Controller:
Event::fire( 'onItemView', $item ); // your listener runs here ... $this->_setBreadcrumbAndTitle( $item, FALSE ); // title composed here
The title has not been built yet when your listener runs, so anything you write is overwritten a moment later — silently, because nothing errors and the page renders fine with the wrong title.
Why bother
Invision Community chains the page, its section and the site name: "Some long article title - Invision Community 5 - example.com". On a real article that is 120+ characters and Google shows about 60, so the words a searcher is looking for are the ones cut off — and the site name is already displayed beside the result, so it is being paid for twice. Dropping to {title} · {site} took a 120-character title to 97, and a forum topic from 72 to 57.
Recommended Comments