Change page title from plugin

Is possible to change page title on the fly from plugin?

I’ve try global $post, but seem like plugin runs after.

Read More

Any Ideas?

Edit:
Im writting some pages on the fly, based on same page / post, so every page show the same title.
Looking a way to do via shortcode or writting my own plugin/function

Related posts

Leave a Reply

3 comments

  1. There’s a filter for that:

    function wpse_alter_title( $title, $id )
    {
        // $id = $post->ID;
        // alter the title here
        return $title;
    }
    

    If you want to alter the “Protected” and “Private” titles, then you need other filters:

    // Preserve the "%s" - else the title will be removed.
    function wpse_alter_protected_title_format( $title )
    {
        return __( 'Protected: %s' );
    }
    
    function wpse_alter_private_title_format( $title )
    {
        return __( 'Private: %s' );
    }
    

    Last but not least, you must add your filter callbacks early enough.

    function wpse_load_alter_title()
    {
        add_filter( 'the_title', 'wpse_alter_title', 20, 2 );
        add_filter( 'protected_title_format', 'wpse_alter_protected_title_format' );
        add_filter( 'private_title_format', 'wpse_alter_private_title_format' );
    }
    add_action( 'init', 'wpse_load_alter_title' );
    
  2. This depends on the context your page title is being rendered in and how the data is being fed into it.

    Consider the following:

    <h2><?php the_title(); ?></h2>
    

    Solution would involve hooking to the the_title filter and alter it in a breeze.

    How about this?

    <h2><?php echo $post->post_title; ?></h2> // not nice!
    

    And it’s not nice due to the problems with altering it. It’s hard to know how the $post got populated in the first place. Consider:

    foreach( get_posts( ... ) as $post ):
        ...
    

    No place to hook there, at first glance. But it can be done inside the actual posts query. Check out the found_posts filter.

    However, consider the following:

    $post = $wpdb->get_row( "SELECT .... " );
    echo "<h2>$post->post_title</h2>"
    

    That’s insane.

    Point is, depending on your situation there’s probably a good solution. Check the template file, see how the title is being rendered. Fix it to be comfortable or make your plugin work a little harder.

    And you will never ever be able to alter the title via a plugin if mysql_query() is used directly to retrieve the title. Yes, I’ve actually seen this done. Some people go as far as hard code it in the template even. Like front-page.php will contain <h2>Home</h2> and never even use the $post->post_title or ever query the database.

    So, depends on the context and the situation.

  3. I’m building a plugin that is heavily reliant on a front end shortcode. This shortcode is responsible for gathering data which I need to use in the page tab <title> tag. Using a shortcode made it difficult to tie in with the wordpress hooks and filters so I ended up using JavaScript to sort out the page tab title.

    Easily done like this:

    var newTitle = document.createElement("title")
    newTitle.innerText = "New tab title here"
    window.onload = function() {  // only add this to the DOM after it has finished loading
        document.head.prepend(newTitle)
    }
    

    And to be really good I also tidied up the DOM by removing any other <title> elements:

    var newTitle = document.createElement("title")
    newTitle.innerText = "New tab title here"
    window.onload = function() {  // only add this to the DOM after it has finished loading
        let allTitles = document.getElementsByTagName("title"); 
        for (let i=0; i<allTitles.length; i++ ) { // loop through all <title> elements
            allTitles[i].remove() // ... and remove them
        }
        document.head.prepend(newTitle)
    }
    

    I actually echoed this out in PHP which made it simpler to add my PHP variables into the mix:

    <?php
    $newtitle = "New Tab Title Here";
    echo '<script type="text/javascript">
        var newTitle = document.createElement("title")
        newTitle.innerText = "' . $newtitle . '"
        window.onload = function() {
            let allTitles = document.getElementsByTagName("title"); 
            for (let i=0; i<allTitles.length; i++ ) {
                allTitles[i].remove()
            }
            document.head.prepend(newTitle)
        }
        </script>';
    ?>
    

    Hope this helps someone 🙂