Drupal 7 Development: How to Set Field Based Page Titles and Meta Descriptions in template.php
This script has been updated to work with multilingual sites too! See http://www.milesjcarter.co.uk/blog/web-design-development/drupal-7-seo-page-titles-meta-elements-theme-layer-multilingual/. All further development will be with the new version
Drupal 6 was great for manual control of page titles, either with the page_title module, or with control at the theme layer.
In Drupal 6, I used a small snippet of code like this in the page.tpl.php to set a custom page title, simply because it was simple and sufficient for most sites:
<title><?php
if ( arg(0) == 'node' && is_numeric(arg(1)) ) {
$node = node_load(arg(1));
if ( $node->type == 'page' && !empty($node->field_title[0]) ) {
// Output CCK Title
print content_format('field_title', $node->field_title[0]);
}
}
else {
print $head_title;
}
?></title>field_title being a field called “title” I added with CCK to the ‘page’ content type or any other content type that should have hand-written page titles. A similar snippet also did the trick for the Meta description.
However, Drupal 7 makes this a lot trickier – whereas the title and other head elements are declared individually in page.tpl.php in Drupal 6, the replacement for Drupal 7 is:
<?php print render($page['header']); ?>;In Drupal 7, anything to be inserted into the head at the theme layer (by my understanding) has to be done through preprocess functions in template.php.
As an aside, notice in the previous the use of the render() function to output the header – this is a common source of confusion amongst those new to Drupal 7 theme development, where just print is needed to output regions in Drupal 6.
This is made doubly tricky by node variables not being directly available in template.php as they are in page.tpl.php.
I tried out the page_title module for Drupal 7, and this does work to an extent, but it breaks completely with panel pages. You could, according to a post on drupal.org use panels as a template to display nodes, but for a single page usage (as in a homepage only use) this seems like something not straighforward. It’s also another module to keep maintained, and with field tokens currently broken and not much progress being made the page_title module is a lot less useful than it was in Drupal 6.
A Drupal 7 Solution:
I was inspired by this post by Sivaji Ganesh, containing this line:
$vars['head_title'] = implode(' | ', array(drupal_get_title(), variable_get('site_name', ''), variable_get('site_slogan', '')));For setting a title at the theme layer as “title (as in the h1 title) | site_name | site_slogan”
This gave me a base to work from. The code I finally came up with (after about 8hr of perserverance) was this:
/* --- DRUPAL SEO: FIELD BASED PAGE TITLES & META DESCRIPTIONS ---
* Ver: 0.9c
* By Miles J Carter
* http://www.milesjcarter.co.uk/blog
* Tested with Drupal versions 7.3, 7.4, 7.7
* licensed under the GPL license:
* http://www.gnu.org/licenses/gpl.html
*
* Works for content types that have text fields created
* named "title" and "meta_desc".
* INSERT INTO YOUR
* function THEME_preprocess_html(&$vars) {
* in template.php
*/
// Find Node ID
$node = $vars['page']['content']['system_main'];
if (isset($node['nodes'])) {
$node = $node['nodes'];
// Extract key value for node ID
if (list($key, $val) = each($node)) {
// Create node object variable
$node = ($node[$key]['#node']);
// Creat page title field content variable, if set
if (isset($node->field_title)) {
$node_title = $node->field_title;
if (isset($node_title['und']['0']['value'])) {
$seo_title = $node_title['und']['0']['value'];
}
}
}
// If manual field title for SEO has been set, set the title to [seo-title] | [site-name]
if (isset($seo_title)){
$vars['head_title'] = implode(' | ', array($seo_title, variable_get('site_name', ''), ));
}
}
/* If SEO title field not set, or content type not page,
use an automatic [current-page-title] | [site-name] scheme */
else {
$vars['head_title'] = implode(' | ', array(drupal_get_title(), variable_get('site_name', ''), ));
}
// ----- Custom Meta Description -----
// Create meta_desc field content variable, if set
if (isset($node->field_meta_desc)) {
$node_desc = $node->field_meta_desc;
if (isset($node_desc['und']['0']['value'])) {
$seo_desc = $node_desc['und']['0']['value'];
// Create meta description element array for insertion into head
$element = array(
'#tag' => 'meta',
'#attributes' => array(
'name' => 'description',
'content' => "$seo_desc",
),
);
// Insert element into <head> (if field has a value)
drupal_add_html_head($element, 'meta_description');
}
}
// ------- END SEO CODE ---------This allows a field created called “title” to manually set the page title. If this field is not set, or the page is a view or any other non-node page, the title will be “get_title() | site_name”, with get_title() the h1 title. Other fields could easily be incorporated into the script by minor modification.
Once the title was figured out, it was pretty easy to set up a field based meta description too.
As this issue had been holding me up from developing with Drupal 7, I hope the above code is useful to other SEOs and developers.
9 Comments
I’ve been trying to go in a similar direction with my page titles, and page_title module did not really do the job. This post has been very helpful. Thanks Miles.
Thanks for sharing, worked perfectly for me
Thank you so much! Worked great for me. Now I just have to figure out how to do with the views template. Any ideas?
Hi Erik, glad this has been of use. Not sure that this will be possible to modify the script to work with views templates, as they would not meet the conditions for being a node. The same is true of panel templates, but they can somehow express a particular node virtually which allows it to work. Also, please try the new version of the script, see the link at the top of the page.
how cam this be done for taxonomy pages?
thanks for sharing, useful for me
It is working fine for me. Thanks.
Useful post, just replace $var_name['und']['0']['value'] with $var_name[LANGUAGE_NONE]['0']['value'].
Community Documentation : http://drupal.org/update/modules/6/7#drupal_language_none
Thanks
@drupix – Thanks for letting me know, I am a bit lapse on coding standards! I will test for myself to make sure it still works and update accordingly. Also note there is a newer multilingual version of this script (that still works with single/undefined language sites) for only a few more LOC
One Trackback
[...] Descriptions from template.php This is an update of a previous post on this blog from July 2011 Drupal 7 SEO: Controlling Page Titles and Meta Elements at the Theme Layer. The script allows the setting of custom page titles and Meta descriptions from defined fields in [...]