How to change page title (from a plugin) in twentytwentyone theme

First, is it even possible to change the page title from a plugin (specifically, from a shortcode defined in a plugin)? This answer says no, but there are certainly reasonable use cases for it. Like, say, my use case (the shortcode displays detail page content for an item of a collection ... so, I put the shortcode on a page; what's the page title supposed to be? It depends on the detail item.).

I have tried every method I can find:

$_SESSION['custom_page_title'] = $eventData['eventtitle'];


//attempt 1
add_filter('document_title_parts', 'my_custom_title');
function my_custom_title( $title ) {
  // $title is an array of title parts, including one called `title`

  $title['title'] = stripslashes($_SESSION['custom_page_title']);

  return $title;
}


//attempt 2
add_filter(pre_get_document_title, my_callback);
function my_callback($old_title){
    return stripslashes($_SESSION['custom_page_title']);
}


//attempt 3
add_filter('the_title','some_callback');
function some_callback($data){
    return stripslashes($_SESSION['custom_page_title']);

}


//attempt 4
add_filter( 'wp_title', 'custom_titles', 10, 2 );
function custom_titles( $title, $sep ) {

    //Check if custom titles are enabled from your option framework
    if ( ot_get_option( 'enable_custom_titles' ) === 'on' ||  (1 == 1)) {
        $title = stripslashes($_SESSION['custom_page_title']);
    }

    return $title;
}

But none of them work (with default twentytwentyone theme).

The plugin is a custom one made by me. The use case is simply to change the page title, based on data that the plugin knows. It's pretty simple in concept. Not really another way to do it.

The shortcode defined in the plugin is displaying the detail for one specific entity (something like /individual_display?id=5 ) and the page should be titled accordingly. The page shouldn't be titled Individual Display or whatever, it should be titled Actual Name of The Individual Thing That Happens to Have ID #5

Is it possible, and if so, how?

Topic theme-twenty-twenty-one title shortcode Wordpress

Category Web


this code should do the trick, add it to your theme functions.php, or to your functions file in the plugin

add_filter("pre_get_document_title", "dynamic_page_title");
function dynamic_page_title(){
    if(isset($_SESSION['custom_page_title'])){
        return stripslashes($_SESSION['custom_page_title']);
    }
}

this will only change the page title for the pages that have a $_SESSION['custom_page_title'], the others pages title will remain the same. if the code isnt working you need to check if your page that change the products or posts dynamic is attributing to $_SESSION['custom_page_tile'] = "the title desired". or like in your code

$_SESSION['custom_page_title'] = $eventData['eventtitle'];

also is only possible to atribute a php session a variable if the session is open, please check that. I know the code works, now you just need to check in your dynamic page if you already have the $_SESSION['custom_page_title'] = "your desired dynamic title";


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 [caption] 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.)

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.