1

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?

5
  • 1
    It's not possible from a shortcode, because the title has already been generated/output before the shortcode is ever run. Since you mentioned a plugin, I suggest talking to its authors. There might be a way that doesn't rely on the shortcode, but that would depend on the plugin. May 4, 2021 at 4:11
  • 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 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"
    – GHolmes
    May 6, 2021 at 18:58
  • Did you check that: wordpress.stackexchange.com/questions/46707/… May 6, 2021 at 21:53
  • Do you only care for first occurrence of the shortcode? If its in the page multiple times, which one should be considered?
    – kero
    Nov 10, 2021 at 16:22
  • The shortcode is only used one time on a page. It gets an id number from the querystring, it looks up data from a custom database table, and it displays it on the page. The logical thing to do would be to also change the page title to have the title of the item that was looked up. Like if it is /page?item=5 then we look in the db for item 5, among the data for it it's title is "Great Title", well, we should make the page title be "Great Title"
    – GHolmes
    Nov 10, 2021 at 20:26

2 Answers 2

2
+50

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.)

5
  • The problem is that 'special_title' is a dynamic piece of data that the shortcode looks up. How can I send it to this function?
    – GHolmes
    Nov 10, 2021 at 15:46
  • Also, using pre_get_document_title was my "attempt #2" described in my question.
    – GHolmes
    Nov 10, 2021 at 16:06
  • Sorry, I missed that in the original question. Can you edit the question to give a short example of shortcode usage and how the handler works? If possible, add the complete add_shortcode() part you currently have.
    – kero
    Nov 10, 2021 at 16:22
  • @GHolmes Please see updated code
    – kero
    Nov 11, 2021 at 9:55
  • 1
    Yes, that's it! Have to look it up when the page is loading, not wait for the shortcode to do it. Thank you!
    – GHolmes
    Nov 12, 2021 at 14:48
0

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

6
  • But if the $_SESSION['custom_page_title'] = $eventData['eventtitle']; call happens, after the title is already generated, it will have no effect. Or will it? And how would you unset the variable? As it stands right now, once the session variable is set, all titles will get that special title, no?
    – kero
    Nov 12, 2021 at 11:42
  • if you change the inside of the function , remove the if statement, and return only return 'My New Title', all the pages will have that name Nov 12, 2021 at 17:29
  • My understanding of the question was that that $_SESSION variable was the one that was mutable, dynamic, had a different string for each product. thats why that code changes the title. Nov 12, 2021 at 17:36
  • whats you dynamic title, and where is it formed ? Nov 12, 2021 at 17:36
  • to your question, yes, the dynamic variable that has the title can be formed after the page original title is set, can be formed in the body, doenst matter. Nov 12, 2021 at 17:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.