You can do it like so:
function filterDocumentTitle(string $title): string
{
// don't change title on admin pages or when global $post is not loaded
if (is_admin() || get_the_ID() === false) {
return $title;
}
// don't change title if shortcode is not present in content
if (!has_shortcode(get_the_content(), 'caption')) {
return $title;
}
return 'special title';
}
add_filter('pre_get_document_title', 'filterDocumentTitle');
If you’re using Yoast’s SEO plugin, you’ll also need add_filter('wpseo_title', 'filterDocumentTitle');
, since the plugin doesn’t play nicely with pre_get_document_title
alone. Other SEO plugins might need similar fixes.
In the above code I check for shortcode, which I used locally to test it, replace this with your real shortcode name (without
[
and ]
).
With this you’ll know when your shortcode is part of a page or not. Now what is left to do, is getting the value you want for your title. For lack of more information I’ll assume that your shortcode looks something like this
add_shortcode('myshortcode', function () {
$id = intval($_GET['item']);
$eventData = /* .. get event data via ID */;
return 'some contents depending on $eventData';
});
So that you don’t have to duplicate your code, let’s refactor this a bit to the following
function gholmesGetEventData(): array {
if (empty($_GET['item'])) {
throw new Exception('Only supported when item is provided.');
}
$id = intval($_GET['item']);
$eventData = /* .. get event data via ID, throw Exception if not found */;
return $eventData;
}
add_shortcode('myshortcode', function (): ?string {
try {
$eventData = gholmesGetEventData();
return 'some contents depending on $eventData';
} catch (Exception $e) {
// do something with the exception
return null;
}
});
function gholmesFilterDocumentTitle(string $title): string
{
// don't change title on admin pages or when global $post is not loaded
if (is_admin() || get_the_ID() === false) {
return $title;
}
// don't change title if shortcode is not present in content
if (!has_shortcode(get_the_content(), 'caption')) {
return $title;
}
try {
$eventData = gholmesGetEventData();
return $eventData['eventtitle'];
} catch (Exception $e) {
return $title;
}
}
add_filter('pre_get_document_title', 'gholmesFilterDocumentTitle');
With this setup you’ll call gholmesGetEventData()
twice. Once in the title once in the shortcode body. To optimize this, you can use WordPress’ object cache’s set and get methods inside gholmesGetEventData()
to minimize DB requests. (So the second call would just return the cached result.)