MJC SEO & Web Development Blog > Drupal 7 SEO: Custom Page Titles and Meta Elements at the Theme Layer – Now Multilingual

Drupal 7 SEO: Custom Page Titles and Meta Elements at the Theme Layer – Now Multilingual

Drupal 7 Development: Multilingual Field Based Page Titles and Meta 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 content types with no modules needed and consistent performance

Being able to set custom page titles and Meta descriptions is an important part of SEO for many sites, vital to establishing topical relevancy and therefore rankings in the case of the former, and clickthrough rates from search results in the latter.


Drupal 7 does not support custom page titles or Meta descriptions out of the box and I have found this script to be extremely useful on a number of sites and still find it to be a more robust alternative than using multiple modules. It works with Panel pages which has continued to be an issue with the page_title module. If no custom page title is found, it falls back on a basic “drupal title | site name” scheme. The script could be edited to support other patterns.

At the end of last year I was working on adding multilingual functionality to a Drupal 7 site and needed to get this script to work with multiple languages. It now allows the setting of field-based custom titles and Meta descriptions for different languages, with each node translation being able to have it’s own unique title and Meta description.

It works on single/undefined language sites too so this replaces the old version of the script entirely.


Simply create new fields for your content type(s) called “title” and “meta_desc”, then paste the following code into your THEME_preprocess_html function in template.php:

 * Ver: 1.05
 * By Miles J Carter
 * http://www.milesjcarter.co.uk/blog
 * Tested with Drupal versions 7.3, 7.4, 7.8, 7.9, 7.12, 7.14
 * licensed under the GPL license:
 * http://www.gnu.org/licenses/gpl.html
 * Works with all content types that have
 * text fields created named "title" and "meta_desc".
 * Insert into THEME_preprocess_html function in template.php

// Extract language value for multilingual sites
global  $language;
        $lang = $language->language;

// 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))  {
    // Node object variable
    $node = ($node[$key]['#node']);            
        // Assign page title field content variable, if set            
        if (isset($node->field_title)) {
          $node_title = $node->field_title;
                if (isset($node_title[$lang]['0']['value'])) {
                  $seo_title = $node_title[$lang]['0']['value'];
                // Fall back on undefined language if nothing set for this language
                        elseif (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)) {
          if (strlen($seo_title)<65) {        
  $vars['head_title'] = implode(' | ', array($seo_title, variable_get('site_name', ''),  ));
          else {        
  $vars['head_title'] = $seo_title;
// If SEO title field not set, use an automatic [current-page-title] | [site-name] scheme
        else {  
  $vars['head_title'] = implode(' | ', array(drupal_get_title(), variable_get('site_name', ''), ));  
// Uncomment to set custom pattern for non-node content
#       else {  
#  $vars['head_title'] = implode(' | ', array(drupal_get_title(), variable_get('site_name', ''), ));  
#       }

// ----- Custom Meta Description (uses $node variable from previous code) -----

// Assign meta_desc field content variable, if set
if (isset($node->field_meta_desc)) {
  $node_desc = $node->field_meta_desc;

        if (isset($node_desc[$lang]['0']['value'])) {
            $seo_desc = $node_desc[$lang]['0']['value'];
                 elseif (isset($node_desc['und']['0']['value'])) {
                        $seo_desc = $node_desc['und']['0']['value'];

if (isset($seo_desc)) {
// 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 ---------

If nothing changes, flush your caches.

I hope this is useful to other SEOs and Drupal developers – follow me on Twitter to stay tuned for updates (I may see if it’s possible to turn this into a module). Please report any bugs in the comments.


1.03 – 30/5/2012 – Minor tidying of code and comments, fall-back pattern now applies to nodes with no title set rather than non-node content (moved a parenthesis to where it should have been)

1.04 – 31/5/2012 – Addition of optional custom pattern for non-node content (commented out by default)

1.05 – 24/7/2012 – Only shows ” | sitename” on the end of the custom title if the custom title is less than 65 characters in length (to help prevent title overflow in search results) – let me know if you think this is not improved functionality.


  1. simon
    Posted August 22, 2012 at 7:53 am | Permalink

    how can this be done on taxonomy pages?

  2. Miles Carter
    Posted August 22, 2012 at 9:51 am | Permalink

    Hi Simon, my thoughts are that this should be possible by modifying the script.

    I think it would be this code section that a taxonomy page wouldn’t satisfy – adding a taxonomy variable with another condition and adjusting the logic structure should get it to work.

    $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)) {

    Presuming you’ve created fields in the taxonomy with the right names.

    I will add this functionality to my to do list, in the meantime if you have any success let me know.

  3. Posted January 16, 2014 at 3:32 pm | Permalink

    Hi Miles Carter!

    Error: “Notice: Undefined variable: vars in swiss_process_html()”

    Help me!
    Many Thanks

  4. Miles Carter
    Posted January 16, 2014 at 7:56 pm | Permalink

    Hi Duong, I’ve noticed that a few themes (e.g) Omega don’t use $variables, they use a differently named/ structured array – the script needs a minor adjustment to the functions that call this. I did it at work and meant to update this version so it works on all themes I’ve tested but not got round to it yet, thanks for the reminder though, check back in a couple of days and hopefully I will have updated it.

One Trackback

  1. [...] original post here: Drupal 7 SEO: Custom Page Titles and Meta Elements at the Theme … Posted in Seo, Seo Iso | Tagged custom-titles, easier-way, for-each, pages-and, php, seo, [...]

Post a Comment

Your email is never shared. Required fields are marked *