skip to Main Content

Context: WordPress 5.4.5 and Yoast SEO 3.7.1

I’m a plugin developer who has access to the client’s site. The site has Yoast 3.7.1 installed. Is that significant, because no matter what I do I can’t change the 404 page’s title?

Now on other pages on Stack Overflow, where similar questions have been posed (here, here and here for example), those answering have asked if the header.php is correctly embedding a call to wp_title(). Here’s what’s in the current theme’s header.php at that point:

<title><?php wp_title( '|', true, 'right' ); ?></title>

Interestingly, on my 404.php page, wp_get_document_title() tells me that the document title is Page not found – XXXX even though the wp_title call above specifies the separator as |. Yoast’s rewriting of titles has been disabled, so I’m not at all sure where that dash is coming from.

My plugin does a REST call and pulls in content from off-site for inclusion in the page. Part of that content is the text to be used in the title.

On previous client sites, I’ve been able to do the following:

add_filter('wp_title', 'change_404_title');
function change_404_title($title) {
    if (is_404())
    {
        global $plugin_title;
        if (!empty($plugin_title))
        {
             $title = $plugin_title;
        }
    }
    return $title;
}

However, on this site, that’s not working.

I have tried, based on the version of WordPress being used, hooking the pre_get_document_title filter, viz

add_filter('pre_get_document_title', 'change_404_title');

but again to no avail. I am currently reading up on Yoast…

3

Answers


  1. wp_title has been deprecated since version 4.4. So we should use the new filter pre_get_document_title. Your code looks fine, but I am confused about global $plugin_title. I would rather ask you to try this first:

    add_filter('pre_get_document_title', 'change_404_title');
    
    function change_404_title($title) {
        if (is_404()) {
            return 'My Custom Title';
        }
        return $title;
    }
    

    If it doesn’t work then try changing the priority to execute your function late.

    add_filter('pre_get_document_title', 'change_404_title', 50);
    
    Login or Signup to reply.
  2. Add this to your functions.php

    function custom_wp_title($title) {
    
        if ( is_404() ) {
            $title = 'Custom 404 Title';
        }
        return $title;
    }
    add_filter( 'wp_title', 'custom_wp_title', 10, 2 );
    

    10 – is priority change to overwrite other plugins like SEO

    Login or Signup to reply.
  3. How the document title is generated has changed since WordPress v4.4.0. Now wp_get_document_title dictates how the title is generated:

    /**
     * Displays title tag with content.
     *
     * @ignore
     * @since 4.1.0
     * @since 4.4.0 Improved title output replaced `wp_title()`.
     * @access private
     */
    function _wp_render_title_tag() {
        if ( ! current_theme_supports( 'title-tag' ) ) {
            return;
        }
    
        echo '<title>' . wp_get_document_title() . '</title>' . "n";
    }
    

    Here is the code from v5.4.2. These are the filters you can use to manipulate the title tag:

    function wp_get_document_title() {
        /**
        * Filters the document title before it is generated.
        *
        * Passing a non-empty value will short-circuit wp_get_document_title(),
        * returning that value instead.
        *
        * @since 4.4.0
        *
        * @param string $title The document title. Default empty string.
        */
        $title = apply_filters( 'pre_get_document_title', '' );
        if ( ! empty( $title ) ) {
            return $title;
        }
        // --- snipped ---
        /**
        * Filters the separator for the document title.
        *
        * @since 4.4.0
        *
        * @param string $sep Document title separator. Default '-'.
        */
        $sep = apply_filters( 'document_title_separator', '-' );
    
        /**
        * Filters the parts of the document title.
        *
        * @since 4.4.0
        *
        * @param array $title {
        *     The document title parts.
        *
        *     @type string $title   Title of the viewed page.
        *     @type string $page    Optional. Page number if paginated.
        *     @type string $tagline Optional. Site description when on home page.
        *     @type string $site    Optional. Site title when not on home page.
        * }
        */
        $title = apply_filters( 'document_title_parts', $title );
        // --- snipped ---
        return $title;
    }
    

    So here are two ways you can do it.

    The first one uses the pre_get_document_title filter which short circuits the title generation and is hence more performant if you are not going make changes on the current title:

    function custom_document_title( $title ) {
        return 'Here is the new title';
    }
    
    add_filter( 'pre_get_document_title', 'custom_document_title', 10 );
    

    The second way uses the document_title_separator and document_title_parts hooks for the title and the title separator that are executed later in the function, after the title is generated using functions like single_term_title or post_type_archive_title depending on the page, and just before the title tags is about to be outputted:

    // Custom function should return a string
    function custom_seperator( $sep ) {
       return '>';
    }
    add_filter( 'document_title_separator', 'custom_seperator', 10 );
    
    // Custom function should return an array
    function custom_html_title( $title ) {
       return array(
         'title' => 'Custom Title',
         'site'  => 'Custom Site'
        );
    }
    add_filter( 'document_title_parts', 'custom_html_title', 10 );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search