Latest TweetsVerify any search engine or visitor via CLI Forward-Reverse Lookup perishablepress.com/cli-forwar…
Perishable Press

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('&raquo;','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())) { ?> &raquo; <?php } ?><?php bloginfo('name'); ?></title>

[OR]

<title><?php wp_title(' '); ?><?php if(wp_title(' ', false)) { echo ' &raquo; '; } ?><?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() ) { ?> &raquo; Blog Archive <?php } ?> <?php wp_title(); ?></title>

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

<?php if ( is_single() ) { ?> &raquo; 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('&raquo;','true','right'); ?><?php if ( is_single() ) { ?> Blog Archive &raquo; <?php } ?><?php bloginfo('name'); ?></title>

..and in pre-2.5 versions of WordPress:

<title><?php wp_title(' '); ?><?php if(wp_title(' ', false)) { echo ' &raquo; '; } ?><?php if ( is_single() ) { ?> Blog Archive &raquo; <?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 &quot;'.$tag.'&quot; - '; 

} elseif (is_archive()) { 

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

} elseif (is_search()) { 

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

} 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 &quot;'.$tag.'&quot; - '; 

// 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 &quot;'.wp_specialchars($s).'&quot; - '; 

// 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 &quot;'.$tag.'&quot; - '; } elseif (is_archive()) { wp_title(''); echo ' Archive - '; } elseif (is_search()) { echo 'Search for &quot;'.wp_specialchars($s).'&quot; - '; } 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 &quot;'.$tag.'&quot; - '; } elseif (is_archive()) { wp_title(''); echo ' Archive - '; } elseif (is_search()) { echo 'Search for &quot;'.wp_specialchars($s).'&quot; - '; } 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

Jeff Starr
About the Author Jeff Starr = Creative thinker. Passionate about free and open Web.
Archives
22 responses
  1. Having this “consistency” seems like a bare minimum to me. After all, the title tag is meant to explain the content of the HTML document; to humans and to machines (search engine, parsing programs, etc).

    This post is a very clear explanation of how to have proper titles, but it really is a shame that WordPress does not have this implemented by default.

    I’m currently coding my own little CMS (end user performance oriented, with also an effort on the writing area – making it pretty and relevant) because as time goes, I find WordPress less and less good.

    So, I don’t want to be off-topic, but this post – as great as it is ;) – should not be, because WordPress should have a proper title convention out-of-the-box.

    The last version (2.6) makes everybody scream like a schoolgirl but what on Earth are they amazed by!? WordPress is going even more in the Go-go-gadget fantasy, with shiny new features such as versionning (versionning, seriously? Who needs a blog platform to handle that? They are apps for that, and they will do a far better job).

    I mean, WordPress is just even starting to become secure. The dev are focusing on gadget features while WordPress does not do the basics properly.

    Ok, now that may be off topic, but I had to say this.

    Seriously, good job on this tutorial Jeff, it’s cristal clear as usual.

  2. August Klotz July 21, 2008 @ 3:15 pm

    One thing to watch out for: there are many of these “ultimate” title scripts floating around the Web. Unfortunately, for several of these scripts, the custom title for “Tag Archives” does not work properly in WordPress 2.5+. Something changed, and now the title for the tag archives looks something like: “bananasTag Archive for "bananas" – Blog Title”. It is even more botched in certain scripts. Something to keep in mind when working with WP 2.5+.

    Btw, the various scripts presented in this article perform well in WordPress 2.0, 2.3, and 2.5. I haven’t tested 2.1 or 2.2, but I am confident the scripts will, as you say, work in all versions of WordPress.

  3. Jeff Starr

    @Louis: I have yet to “scream like a schoolgirl” over any version of WordPress. I think version 2.3 is about as good as it gets. I am running newer (and older) versions on some of my other sites and just can’t see what the big deal is. In fact, there are many little things that I really dislike about 2.5, especially where the admin area is concerned. Nonetheless, I have yet to find a superior alternative. WordPress has tons going for it, although I will be keeping my eye out for the next great CMS. Perhaps yours could be the one..? ;)

  4. Jeff Starr

    @August: what are you talking about?! “bananas” is spelled “bananaz” not “bananas”! ;)

  5. Very useful post, I am using this code now. Thanks!

  6. Jeff Starr

    Absolutely my pleasure, Nish! :)

  7. discountgoblin August 20, 2008 @ 4:41 am

    I have noticed that extra spaces are added at the beginning of the title tag if you view the source code of a page. It appears fine in your browser but if you view the source it shows it.

  8. Jeff Starr

    Yes, that is something that has bothered me for quite awhile. I haven’t taken the time to remove all of the whitespace from throughout the script, but I am guessing that it is the source of the empty spaces. In either case, it is as you say, the contents of the title element appear fine in the browser, but the source code looks slightly less than perfect.

  9. Is it just me or does WordPress totally botch the date display using wp_title? I end up with “2008 September 4” or something equally awkward-looking. Looking into the code for wp_title indicates that this is so. I wonder why they don’t simply use the date format specified in the back end for this sort of thing.

  10. Jeff Starr

    Sounds like an excellent opportunity for a new plugin! That is, unless someone has already created one.. Either way, I agree that the default date display in titles should emulate the format specified in the user admin/options area. Good point.

  11. Great script. Thanks. One very minor change that I made to it was to alter $tag to single_tag_title() . That way it shows the pretty name of the tag rather than the computer version (e.g. it has a space in its name rather than a hyphen if it is more than one word).

  12. Jeff Starr

    Sweet tip, Mat8iou — thanks for sharing! :)

[ Comments are closed for this post ]