Drupal SEO: gestire il tag title con pathauto e token personalizzati

Il titolo è uno degli elementi più importanti di una pagina, non solo dal punto di vista SEO, ma anche per l'utente. Il titolo (tag title) di una pagina è la prima cosa che si vede nei risultati di una ricerca su Google. Perciò, è molto importante che questo titolo dia all'utente una idea il più precissa possibile sul contenuto della pagina.

Risultato della ricerca "come scrivere un titolo"

Questo articolo di Google contiene alcuni consigli per la gestione dei titoli, tra cui:

  • evitare titoli poco descrittivi. Nè troppo corti (come "Home" o "Profile") nè troppo lunghi
  • le parole chieve ben utilizzate possono aiutare nella creazione di un titolo descrittivo, evitando però l'abuso e la ripetizione delle parole

Alcuni esempi di titoli nella rete

schaeffler-group.com

schaeffler-group.com

Nel sito schaeffler-group.com troviamo un menu a 3 livelli

  1. Divisions and Products
  2. Automotive
  3. Product Highlights

Queste pagine hanno i seguenti titoli:

  1. Schaeffler AG | Divisions and Products
  2. Schaeffler AG | Divisions and Products | Automotive
  3. Schaeffler AG | Divisions and Products | Product Highlights

Forse il titolo della seconda pagina è troppo corto. Nel terzo titolo la parola product viene ripetuta e non è specificato l'argomento. Come si fa a capire che i product highligts sono referiti al settore automotive? Inoltre, il brand sarebbe meglio spostarlo alla fine del titolo. Aprendo più di una scheda di questo sito non si riesce più ad individuare le diverse pagine.

Schaeffler AG - Divis...?

tenaris.com

Tenaris - Products

Nel sito della Tenaris invece possiamo vedere una soluzione migliore sempre con un menu a 3 livelli

  1. Products
  2. Automotive
  3. Transmission Parts

I titoli di queste pagine sono:

  1. Products - Tenaris
  2. Automotive Industry – Tenaris
  3. Tubes for Transmission Parts - Automotive - Tenaris

Nel sito della Tenaris, il titolo della terza pagina include una parola chiave che ci aiuta a capire l'argomento di cui si sta parlando: Automotive.

Gestione del tag title in Drupal

Un modulo fondamentale per la gestione dei titoli in Drupal 7 è pathauto. Questo modulo ci permette d'impostare facilmente il tag title per ogni tipo di contenuto utilizzando i token.

Configurazione di Pathauto

La configurazione predefinita di pathauto per i titoli è: Drupal SEO: gestire il tag title con pathauto e token personalizzati | minestron. Per riuscire a creare titoli più descrittivi dovremo aggiungere un'altro token per indicare l'argomento di cui si sta parlando, come abbiamo visto nel sito della Tenaris. Due soluzioni possibili sono:

  1. Creare un campo di testo "field_topic" nel tipo di contenuto
  2. Creare un token personalizzato che ci permetta di selezionare i punti di menu che iniziano un nuovo argomento (topic)

Soluzione 1: creare il campo field_topic

  1. Creare un vocabulario... ad esempio: topic
  2. Creare un campo di tipo term reference e selezionare il widget Autocomplete term widget (tagging)
  3. Aprire la configurare di pathauto e impostare il titolo del tipo di contenuto corrispondente aggiungendo [node:field-topic]

Soluzione 2: creare un token personalizzato

Per questa soluzione bisogna creare un modulo personalizzato. Molto semplice e con poche funzioni. L'idea è di poter selezionare i punti di menu che iniziano con un nuovo argomento creando un formulario con un checkbox per ogni punto di menu. Questo "argomento" sarà utilizzato da tutte le pagine "figlie" del punto di menu selezionato. Il modulo lo chiameremo token menu topics.

Configurazione di "Token menu topics"

Una volta selezionati i punti di menu, dovremo aggiungere il token [node:title_prefix].

token_menu_topics.info

name = Token menu topics
description = A custom token that make menu items become topics
package = SEO
core = 7.x
dependencies[] = token

token_menu_topics.module

<?php

/**
 * Implements hook_token_info().
 */
function token_menu_topics_token_info() {
  $info['tokens']['node']['title_prefix'] = array(
    'name' => t('Title prefix'),
    'description' => t('SEO title prefix.'),
  );
  return $info;
}


/**
 * Implements hook_tokens().
 */
function token_menu_topics_tokens ($type, $tokens, array $data = array(), array $options = array()) {
  $replacements = array();
  $sanitize = !empty($options['sanitize']);
  if ($type == 'node' && !empty($data['node'])) {
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'title_prefix':

          // get menu tree from page and it's name
          $menu_trail = menu_get_active_trail();
          $menu_name_machine = str_replace("-", "_", $menu_trail[1]['menu_name']);
          // get menu father from that menu
          $menu_fathers = array_filter(variable_get('token_menu_topics_menu_'.$menu_name_machine, array()));
          // invert tree to select first father.. not granma
          array_pop($menu_trail);
          $menu_trail = array_reverse($menu_trail);
          foreach($menu_trail as $key => $value) {
            if (!isset($value['mlid'])) {
              continue;
            }
            if (in_array($value['mlid'], $menu_fathers)) {
              $replacements[$original] = variable_get('token_menu_topics_menu_prefix', null) . $value['link_title'] . variable_get('token_menu_topics_menu_suffix', null);
              return $replacements;
            }
          }
          // si este hijo no tiene padre, el token es nulo
          $replacements[$original] = "";
          break;
      }
    }
  }
  return $replacements;
}


/**
 * Construct select options from menu items
 */
function _get_menu_tree ($menu_name = 'main-menu', $tree = array()) {
  if (count($tree) == 0) {
    $tree = menu_tree_all_data($menu_name);
    $options_menu_items = array();
  }
  
  foreach($tree as $key => $item) {
    $options_menu_items[] = array(
      'key'      => $item['link']['mlid'],
      'value'    => str_repeat(" - ", $item['link']['depth']) . $item['link']['link_title'],
      'disabled' => $item['link']['hidden']
    );
    if (count($item['below']) > 0) {
      $options_menu_items = array_merge($options_menu_items, _get_menu_tree($menu_name, $item['below']));
    }
  }
  return $options_menu_items;
}

/**
 *
 */
function token_menu_topics_admin($form, &$form_state) {
  $form = array();
  $menus = menu_get_names();
  foreach($menus as $key => $name){
    $menu_options[$name] = $name;
  }

  $count = count($menus);
  $form['token_menu_topics_menus'] = array(
    '#type'          => 'checkboxes',
    '#title'         => t('Select menus'),
    '#description'   => t("Seleccionar los menu que quieras configurar más adelante."),
    '#default_value' => variable_get('token_menu_topics_menus', array()),
    '#required'      => TRUE,
    '#options'       => drupal_map_assoc(menu_get_names()),
    '#size'          => ($count > 12 ? 12 : $count),
    '#ajax' => array(
      'callback' => 'token_menu_topics_menu_items_callback',
      'wrapper' => 'menu-items-div',
      'method' => 'replace',
      'effect' => 'fade',
    ),
  );
  $form['token_menu_topics_fieldset'] = array(
    '#title' => t("Menu items"),
    // The prefix/suffix provide the div that we're replacing, named by
    // #ajax['wrapper'] above.
    '#prefix' => '<div id="menu-items-div">',
    '#suffix' => '</div>',
    '#type' => 'fieldset',
    '#description' => t('This is where we get automatically generated checkboxes'),
  );

  // ajax?
  if (isset($form_state['values']['token_menu_topics_menus'])) {
    $selected_menus = $form_state['values']['token_menu_topics_menus'];
  } else {
    $selected_menus = variable_get('token_menu_topics_menus', array());
  }

  // menu items
  foreach ($selected_menus as $key => $menu_name) {
    if ($menu_name === 0) {
      continue;
    }
    // re-order menu array
    $options_menu_items = _get_menu_tree($menu_name);
    $options_menu_items_ = array();
    $options_menu_items_disabled = array();
    foreach($options_menu_items as $key => $value) {
      $options_menu_items_[$value['key']] = $value['value'];
      if ($value['disabled'] == 1) {
        $options_menu_items_disabled[] = $value['key'];
      }
    }
    $count = count($options_menu_items_);

    $menu_name_machine = str_replace("-", "_", $menu_name);

    $form['token_menu_topics_fieldset']['token_menu_topics_menu_'.$menu_name_machine] = array(
      '#type'          => 'checkboxes',
      '#title'         => t("Select items from @menu menu", array('@menu' => $menu_name_machine)),
      '#default_value' => variable_get('token_menu_topics_menu_'.$menu_name_machine, array()),
      '#description'   => t("Menu items topic fathers."),
      '#required'      => FALSE,
      '#multiple'      => TRUE,
      '#options'       => $options_menu_items_,
      '#size'          => ($count > 12 ? 12 : $count),
    );
    // disable hidden elements
    foreach($options_menu_items_disabled as $_key => $disabled_key){
      $form['token_menu_topics_fieldset']['token_menu_topics_menu_'.$menu_name_machine][$disabled_key] = array(
        '#disabled' => TRUE,
      );
    }
  }

  $form['token_menu_topics_menu_prefix'] = array(
    '#type'          => 'textfield',
    '#title'         => t('Prefix'),
    '#default_value' => variable_get('token_menu_topics_menu_prefix', null),
    '#size'          => 50,
    '#maxlength'     => 50,
    '#description'   => t("Token prefix."),
    '#required'      => FALSE,
  );

  $form['token_menu_topics_menu_suffix'] = array(
    '#type'          => 'textfield',
    '#title'         => t('Suffix'),
    '#default_value' => variable_get('token_menu_topics_menu_suffix', null),
    '#size'          => 50,
    '#maxlength'     => 50,
    '#description'   => t("Token suffix."),
    '#required'      => FALSE,
  );
  return system_settings_form($form);
}


/**
* Callback element needs only select the portion of the form to be updated.
* Since #ajax['callback'] return can be HTML or a renderable array (or an
* array of commands), we can just return a piece of the form.
*/
function token_menu_topics_menu_items_callback($form, $form_state) {
  return $form['token_menu_topics_fieldset'];
}


/**
 * Implements hook_menu().
 */
function token_menu_topics_menu() {
  $items = array();
  $items['admin/config/search/token_menu_topics'] = array(
    'title'            => 'Token title prefix settings',
    'description'      => 'Description of your On this date settings page',
    'page callback'    => 'drupal_get_form',
    'page arguments'   => array('token_menu_topics_admin'),
    'access arguments' => array('administer onthisdate settings'),
    'type'             => MENU_NORMAL_ITEM,
   );
  return $items;
}

Per ora questo è tutto!