Fall Sale! Code FALL2024 takes 25% OFF our Pro Plugins & Books »
Web Dev + WordPress + Security

How to Generate Perfect WordPress Title Tags without a Plugin

[ Perfect Title Tags ] Keeping an eye on all things WordPress, I have noticed an ongoing fascination with configuring the ultimate WordPress <title> tags. Many bloggers use various plugins to generate differently configured <title> tags depending on particular page views. A good example of this is seen in the All in One SEO Pack, which, among many other things, enables users to specify custom titles for several different types of pages. While there is nothing wrong with this approach, some of us prefer to run WordPress with as few plugins as possible. If you want to create perfect WordPress title tags without a plugin, this post will certainly help you do it. First we’ll explore some of the basics, continue with some common examples, and then conclude with a comprehensive, highly flexible script for generating distinct page titles. All of the techniques presented in this article should work well with virtually all versions of WordPress.

The Basics

The <title> tag is used within the <head> section of (X)HTML pages to communicate the title of the document to both humans (your visitors) and machines (search engines). For dynamically generated sites, such as those powered by WordPress, many different types of pages exist, including:

  • The Home page
  • Individual pages
  • Single post views
  • Archived post views
  • Date-based archives
  • Category archives
  • Author archives
  • 404 error pages
  • Search results
  • Tag archives

..and so on. Producing optimally configured titles for each of these page types is generally accomplished in the theme’s header.php file using a combination of (X)HTML and PHP. Here is a very basic example:

<title><?php bloginfo('name'); ?><?php wp_title(); ?></title>

..which is taken directly from the “Classic” theme that comes bundled with WordPress. With that code in place, every title for the Classic theme will be displayed with the following format:

Blog Name » Title of Displayed Page

Of course, this configuration does the job, but it could definitely be improved. For example, it has been reported that placing the page title before the blog title improves the SEO value of the page. This also improves usability, as the purpose of the page is more clearly communicated to visitors, who are more than likely searching for a specific article, not the name of your blog. Here is how to reverse the order of the blog name and page title in WordPress 2.5+:

<title><?php wp_title('»','true','right'); ?><?php bloginfo('name'); ?></title>

..which will output this title sequence for every page except the home page:

Title of Displayed Page » Blog Name

With this code, the home page will simply display the name of the blog. Alternately, to generate the same title formats for pre-2.5 versions of WordPress, we need to employ an alternate method. Something similar to either of these examples should work just fine:

<title><?php wp_title(''); ?><?php if (!(is_404()) && (is_single()) || (is_page()) || (is_archive())) { ?> » <?php } ?><?php bloginfo('name'); ?></title>

[OR]

<title><?php wp_title(' '); ?><?php if(wp_title(' ', false)) { echo ' » '; } ?><?php bloginfo('name'); ?></title>

The additional code seen in either of these two methods is required in pre-2.5 WP to ensure that the separator is not displayed on the home page (i.e., when no preceding title is present). In WordPress 2.5, this is handled more eloquently via the new seplocation parameter1. All versions of WordPress, however, support the sep and echo parameters for the wp_title() tag. Here is the new, 2.5+ version of the wp_title tag; the first two parameters are available to all versions of WordPress, while the seplocation parameter is only useful in 2.5+:

wp_title('sep','echo','seplocation')

  • sep — string value indicating the separator displayed before the title
  • echo — boolean value determining whether or not the title is displayed
  • seplocation — specifies the position of sep string

By default, the wp_title() tag displays the following information, depending on page type:

  • The Home page — no output
  • Individual pages — page title
  • Single post views — post title
  • Archived post views — no output
  • Date-based archives — year and/or month
  • Category archives — category title
  • Author archives — public username
  • 404 error pages — no output
  • Search results — no output
  • Tag archives — tag name

So, we have already seen one way of optimizing the traditional <title> tag configuration. Let’s wade out a little deeper and see what else we can come up with..

Getting Specific

Going beyond the rudimentary title tag of the Classic WordPress theme, let’s have a look at the slightly more advanced title configuration of the ubiquitous “Default” WordPress theme. Here it is:

<title><?php bloginfo('name'); ?> <?php if ( is_single() ) { ?> » Blog Archive <?php } ?> <?php wp_title(); ?></title>

This code advances the Classic configuration with the addition of this PHP snippet:

<?php if ( is_single() ) { ?> » Blog Archive <?php } ?>

..which inserts additional information if the page is a single post. Thus, in the default theme, any page that is not single will feature a title formatted exactly as in the Classic theme:

Blog Name » Title of Displayed Page

If the page is a single-post view, the Default theme generates this title instead:

Blog Name » Blog Archive » Title of Displayed Page

To better optimize the Default theme’s title tags, we can reverse the order of the blog name and page title in WordPress 2.5+:

<title><?php wp_title('»','true','right'); ?><?php if ( is_single() ) { ?> Blog Archive » <?php } ?><?php bloginfo('name'); ?></title>

..and in pre-2.5 versions of WordPress:

<title><?php wp_title(' '); ?><?php if(wp_title(' ', false)) { echo ' » '; } ?><?php if ( is_single() ) { ?> Blog Archive » <?php } ?><?php bloginfo('name'); ?></title>

Either of these methods will produce the following SEO-optimized titles:

Single post views:
Title of Displayed Page » Blog Archive » Blog Name

All other supported views:
Title of Displayed Page » Blog Name

So now we have seen how to optimize WordPress titles while using PHP to enhance their specificity. Next, we’ll examine how to generate comprehensive, highly flexible title configurations..

Custom-Fit Title tags

While it’s helpful to display custom titles for single-post views, it would be even better to display customized titles for each different type of page. Using a few native WordPress tags and a dash of PHP, we can automatically generate customized <title> tags for each of the following page types:

  • Home page
  • Tag archives
  • Search results
  • 404 error pages
  • Individual pages and single posts
  • Archived post, date, category, and author pages

By expanding on the basic principles outlined above, we summon an extremely flexible script for generating customized title tags. Here is what this script looks like when exploded into multi-line format:

<title>

<?php 

if (function_exists('is_tag') && is_tag()) { 

	echo 'Tag Archive for "'.$tag.'" - '; 

} elseif (is_archive()) { 

	wp_title(''); echo ' Archive - '; 

} elseif (is_search()) { 

	echo 'Search for "'.wp_specialchars($s).'" - '; 

} elseif (!(is_404()) && (is_single()) || (is_page())) { 

	wp_title(''); echo ' - '; 

} elseif (is_404()) {

	echo 'Not Found - '; 

}
bloginfo('name'); 

?>

</title>

For those of us who understand PHP, this script speaks for itself; however, for those who would benefit from a brief explanation, here is a commented version of the same script:

<title>

<?php // WordPress custom title script

// is the current page a tag archive page?
if (function_exists('is_tag') && is_tag()) { 

	// if so, display this custom title
	echo 'Tag Archive for "'.$tag.'" - '; 

// or, is the page an archive page?
} elseif (is_archive()) { 

	// if so, display this custom title
	wp_title(''); echo ' Archive - '; 

// or, is the page a search page?
} elseif (is_search()) { 

	// if so, display this custom title
	echo 'Search for "'.wp_specialchars($s).'" - '; 

// or, is the page a single post or a literal page?
} elseif (!(is_404()) && (is_single()) || (is_page())) { 

	// if so, display this custom title
	wp_title(''); echo ' - '; 

// or, is the page an error page?
} elseif (is_404()) {

	// yep, you guessed it
	echo 'Not Found - '; 

}
// finally, display the blog name for all page types
bloginfo('name'); 

?>

</title>

Hopefully, this provides enough insight for you to customize the function to suit your specific needs. For example, you may want to use a different type of separator in your titles, or perhaps you need to rephrase a particular title — whatever! The point is to learn how custom titles are generated so that you will be able to create your own.

Also, although you may use the expanded, multi-line version of the script in your pages, consolidating it into a single line saves space and provides greater control over your page’s source-code output. To see what I mean, compare the expanded version to the following condensed version:

<title><?php if (function_exists('is_tag') && is_tag()) { echo 'Tag Archive for "'.$tag.'" - '; } elseif (is_archive()) { wp_title(''); echo ' Archive - '; } elseif (is_search()) { echo 'Search for "'.wp_specialchars($s).'" - '; } elseif (!(is_404()) && (is_single()) || (is_page())) { wp_title(''); echo ' - '; } elseif (is_404()) { echo 'Not Found - '; } bloginfo('name'); ?></title>

Once in place, either version of this code will generate the following title formats:

// Home page:
Blog Name

// Tag archives:
Tag Archive for "tag name" - Blog Name

// Search results:
Search for "search string" - Blog Name

// 404 error pages:
Not Found - Blog Name

// Individual pages and single posts:
Post or Page Title - Blog Name

// Archived post, date, category, and author pages:
Date, Category, or Author - Blog Name

Of course, the title for each of these different page types is completely customizable by simply editing the title script. For example, let’s say you wanted to “spice up” the title of the home page by adding the blog description. No sweat — simply replace the single instance of bloginfo('name'); with this conditional snippet:

if (is_home()) { 

	bloginfo('name'); echo ' - '; bloginfo('description'); 

} else { 

	bloginfo('name'); 

}

It’s as easy as that. Once in place, the title for your home page will now include your blog’s definition:

Blog Name - Blog Description

You know, I could go on and on with this stuff, but instead, allow me to finish by presenting the complete, condensed version of the title script, which includes the additional description for the home page. In my opinion, this is as close to the perfect WordPress title script as it gets:

<title><?php if (function_exists('is_tag') && is_tag()) { echo 'Tag Archive for "'.$tag.'" - '; } elseif (is_archive()) { wp_title(''); echo ' Archive - '; } elseif (is_search()) { echo 'Search for "'.wp_specialchars($s).'" - '; } elseif (!(is_404()) && (is_single()) || (is_page())) { wp_title(''); echo ' - '; } elseif (is_404()) { echo 'Not Found - '; } if (is_home()) { bloginfo('name'); echo ' - '; bloginfo('description'); } else { bloginfo('name'); } ?></title>

Wrapping up..

In conclusion, allow me to reiterate the importance of maximizing your title tags. In doing so, you will enjoy greater search-engine benefits and improve navigational consistency and site usability. Using the techniques described in this article, WordPress users are well-equipped to create their own distinctive title tags without a plugin.

Footnotes

About the Author
Jeff Starr = Web Developer. Book Author. Secretly Important.
USP Pro: Unlimited front-end forms for user-submitted posts and more.

22 responses to “How to Generate Perfect WordPress Title Tags without a Plugin”

  1. Another suggestion, as I’m still tinkering with my titles is to add the page number to the end of the title if it is an archive or whatever that has multiple pages. This way you avoid any duplicate titles (which apparently are not advisable for search engines).

    The code I used for this is very simple:

    if ($paged>1) {
         echo '- page ', $paged;
    }

    I put the code right at the end after everything else.

  2. Jeff Starr 2008/10/26 8:59 am

    Another excellent tip! I had never considered the duplicate archive page titles.. They probably don’t hurt very much (in terms of PR), but they certainly aren’t helping! Thanks for waking me up to this situation; I will be updating my title tags (again) very soon! ;)

  3. I came to this post when I was googling for solution to display title tags for author archives. Although you didn’t specifically mention how to fix it, your post made me understand that the author title tags can be called using ‘is_archive’. Thank you so much, you saved my day!

  4. Jeff Starr 2008/11/09 5:12 pm

    Excellent Chris! Glad to hear the article helped you out. Thanks for the positive feedback! :)

  5. Josh Jensen 2009/01/27 10:43 am

    Thank you so much — exactly what I needed.

  6. Great article! I have a question, though. I am using a specific page for my blog (and it’s not my home page, either). However, on this page, I don’t want the blog name to display. I designed my title tag to look like “[php generated name] – Site Name.” However, my blog name is the same, so it just duplicates, and ends up reading “Site Name – Site Name.” Is there any way that I can write a static title into the title tag to display for the blog page? What I want is for it to read “Blog – Site Name.” Any help would be awesome.

  7. Jeff Starr 2009/03/16 9:51 am

    @Jon: Sure, you could always add another elseif() condition to the script to account for the specific page. Something like:

    } elseif (is_page('77')) {
           echo 'Blog - Site Name';
    }

    ..inserted between any of the other elseif() conditions should work perfectly. Edit the page ID from “77” to whatever and edit the echoed title to meet your needs.

  8. @Jeff. Thanks for the reply! I gave it a shot, and added the echo ifelse; however, it seemed that WordPress was overriding the condition in favor of the full site name.

    I added 340 in place of 77, and changed the echo to read “Blog – 944 Turbo Resource,” however it had no effect. But, I figured that perhaps editing the tag that was actually informing WordPress to tag the page as the full site title might work. So I changed the following from:

    if (is_home () ) { bloginfo(‘name’);}

    to:

    if (is_home () ) { echo 'Blog';}

    and that did the trick! The title tag now displays exactly what I wanted (not the full site title, which really has nothing to do with the blog specifically). Thanks a lot for the help – I would have never figured it out if not for your incite! And keep up the good work!

  9. Great tutorial! Very well written, I only have little knowledge of PHP and I understood everything perfectly. You helped a bunch!

  10. Jeff Starr 2009/03/22 8:08 am

    @Jon: Excellent! Glad to hear you found a solution, and thank you for sharing it! Cheers!

    @Dan: I am glad the article is useful for you! Thank you for the positive feedback! :)

Comments are closed for this post. Something to add? Let me know.
Welcome
Perishable Press is operated by Jeff Starr, a professional web developer and book author with two decades of experience. Here you will find posts about web development, WordPress, security, and more »
WP Themes In Depth: Build and sell awesome WordPress themes.
Thoughts
I disabled AI in Google search results. It was making me lazy.
Went out walking today and soaked up some sunshine. It felt good.
I have an original box/packaging for 2010 iMac if anyone wants it free let me know.
Always ask AI to cite its sources. Also: “The Web” is not a valid answer.
All free plugins updated and ready for WP 6.6 dropping next week. Pro plugin updates in the works also complete :)
99% of video thumbnail/previews are pure cringe. Goofy faces = Clickbait.
RIP ICQ
Newsletter
Get news, updates, deals & tips via email.
Email kept private. Easy unsubscribe anytime.