A simple way to create a 'related posts' block using Views 2 in Drupal 6

Date: Thu Jan 14 2010 Drupal Tutorial »»»» Drupal Views »»»» Drupal Planet

Looking at the traffic data google Analytics collects on my web sites I see a high "bounce" rate which means many visitors leave right away. It means they come to the site, then look only at the one page, presumably to go elsewhere. I've been pondering what might be a good way to entice them to stay and look around. After all, my websites exist to instruct people, so the more pages they look at on my sites the more instruction I'm able to impart. Oh, and there's a higher chance they'll click on an ad or something. In any case there's high value that can derive from getting a visitor to stay longer than one page.

It turns out many of the things one might do to entice a visitor to stick around depends on the content of the specific page they land on. It might be to rework the page so it looks prettier and they might decide to read until the end. Or it might be to include links in the article to other articles, on the same site. However there is a rather simple thing that can automagically generate a list of related articles. That is, if you've done a good job with your vocabulary terms.

The idea is to collect all the vocabulary terms on a given node, construct arguments for a view, and the view lists nodes based on the terms it is given. If you've done a good job defining vocabulary terms then terms sharing common terms should be similar, yes? Again, if you've done a good job defining the vocabulary terms on your site.

The first step is to define a view, which I called related_posts. The view takes a taxonomy term ID argument and provides a list of nodes. It's a very simple view, the details are given below. In filters specify "node: published = true". In the Fields list the node Title and Teaser. In Arguments use 'Term ID' specifying the vocabularies to draw on, and allowing multiple terms. I made two displays, one the Default display, the other a Page display. In the Default display the Teaser is set to be suppressed, and the style is a Table with just one column (the Title), and it uses the 'more' link. The Page version is set to show both Title and Teaser, to use a pager, etc.

The second step is to have PHP code run in the context of the node rendering that invokes this view. The way I did it is probably not the best but it works. I modified node.tpl.php to have the following

<?php
  $terms = array();
  foreach ($node->taxonomy as $term) {
    $terms[] = "".$term->tid."";
  }
?>
<div class="content clearfix">
    <div style="float: right; margin: 0; padding: 0 1em .25em 0; width: 250px;">
        <?php
        if (!$teaser) {
        $view = views_get_view('related_posts');
        $view->set_arguments($terms);
        $view->set_use_pager(false);
        print $view->render();
        }
        ?>
    </div>
    <?php print $content; ?>
</div>

The above invokes the view given all the terms in the node, and makes the view float to the right as if it were a sidebar. The view generates a list of node titles, and at the bottom is a 'more' link. The 'more' link goes to the Page version of the view which is at a URL like: http://www.7gen.com/relatedposts/2853/2854/2857/2855/2848/1946/120/2856/306 ... each of those after "relatedposts" is a term ID.

It means that not only do the visitors have a list of relevant posts in front of their noses .. it also means that your site now has a number of views generated pages listing what are hopefully highly related articles. These pages could be thought of as automatically generated topic hubs. I foresee positive SEO benefit.

$view = new view;
$view->name = 'related_posts';
$view->description = 'Related Posts';
$view->tag = '';
$view->view_php = '';
$view->base_table = 'node';
$view->is_cacheable = FALSE;
$view->api_version = 2;
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
$handler = $view->new_display('default', 'Defaults', 'default');
$handler->override_option('fields', array(
  'title' => array(
    'label' => '',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'strip_tags' => 0,
      'html' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'link_to_node' => 1,
    'exclude' => 0,
    'id' => 'title',
    'table' => 'node',
    'field' => 'title',
    'relationship' => 'none',
  ),
  'teaser' => array(
    'label' => 'Teaser',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 1,
      'max_length' => '140',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'strip_tags' => 1,
      'html' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'exclude' => 1,
    'id' => 'teaser',
    'table' => 'node_revisions',
    'field' => 'teaser',
    'relationship' => 'none',
  ),
));
$handler->override_option('arguments', array(
  'tid' => array(
    'default_action' => 'empty',
    'style_plugin' => 'default_summary',
    'style_options' => array(),
    'wildcard' => 'all',
    'wildcard_substitution' => 'All',
    'title' => '',
    'breadcrumb' => '',
    'default_argument_type' => 'fixed',
    'default_argument' => '',
    'validate_type' => 'taxonomy_term',
    'validate_fail' => 'empty',
    'break_phrase' => 1,
    'add_table' => 0,
    'require_value' => 0,
    'reduce_duplicates' => 1,
    'set_breadcrumb' => 1,
    'id' => 'tid',
    'table' => 'term_node',
    'field' => 'tid',
    'validate_user_argument_type' => 'uid',
    'validate_user_roles' => array(
      '2' => 0,
      '3' => 0,
    ),
    'relationship' => 'none',
    'default_options_div_prefix' => '',
    'default_argument_user' => 0,
    'default_argument_fixed' => '',
    'default_argument_php' => '',
    'validate_argument_node_type' => array(
      'blog' => 0,
      'poll' => 0,
      'ad' => 0,
      'panel' => 0,
      'affiliate_product' => 0,
      'book' => 0,
      'content_website' => 0,
      'feed' => 0,
      'feed_item' => 0,
      'news_article_summary' => 0,
      'page' => 0,
      'principle' => 0,
      'section_header' => 0,
      'shopping_coupon' => 0,
      'simplenews' => 0,
      'topichub' => 0,
      'what_is' => 0,
      'wikipedia' => 0,
    ),
    'validate_argument_node_access' => 0,
    'validate_argument_nid_type' => 'nid',
    'validate_argument_vocabulary' => array(
      '18' => 18,
      '57' => 57,
      '19' => 19,
      '20' => 20,
      '21' => 21,
      '22' => 22,
      '23' => 23,
      '24' => 24,
      '25' => 25,
      '4' => 4,
      '58' => 58,
      '26' => 26,
      '27' => 27,
      '28' => 28,
      '10' => 10,
      '9' => 9,
      '8' => 8,
      '29' => 29,
      '30' => 30,
      '31' => 31,
      '32' => 32,
      '33' => 33,
      '34' => 34,
      '35' => 35,
      '36' => 36,
      '37' => 37,
      '16' => 16,
      '38' => 38,
      '39' => 39,
      '40' => 40,
      '41' => 41,
      '42' => 42,
      '43' => 43,
      '44' => 44,
      '45' => 45,
      '46' => 46,
      '47' => 47,
      '48' => 48,
      '49' => 49,
      '13' => 13,
      '15' => 15,
      '50' => 50,
      '51' => 51,
      '52' => 52,
      '53' => 53,
      '1' => 1,
      '54' => 54,
      '55' => 55,
      '3' => 3,
      '17' => 0,
      '56' => 0,
    ),
    'validate_argument_type' => 'tids',
    'validate_argument_transform' => 0,
    'validate_user_restrict_roles' => 0,
    'validate_argument_php' => '',
  ),
));
$handler->override_option('filters', array(
  'status' => array(
    'operator' => '=',
    'value' => '1',
    'group' => '0',
    'exposed' => FALSE,
    'expose' => array(
      'operator' => FALSE,
      'label' => '',
    ),
    'id' => 'status',
    'table' => 'node',
    'field' => 'status',
    'relationship' => 'none',
  ),
));
$handler->override_option('access', array(
  'type' => 'none',
));
$handler->override_option('cache', array(
  'type' => 'none',
));
$handler->override_option('items_per_page', 5);
$handler->override_option('use_pager', '0');
$handler->override_option('use_more', 1);
$handler->override_option('style_plugin', 'table');
$handler->override_option('style_options', array(
  'grouping' => '',
  'override' => 1,
  'sticky' => 0,
  'order' => 'asc',
  'columns' => array(
    'title' => 'title',
    'teaser' => 'teaser',
  ),
  'info' => array(
    'title' => array(
      'sortable' => 0,
      'separator' => '',
    ),
    'teaser' => array(
      'separator' => '',
    ),
  ),
  'default' => 'title',
));
$handler = $view->new_display('page', 'Page', 'page_1');
$handler->override_option('fields', array(
  'title' => array(
    'label' => 'Title',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'strip_tags' => 0,
      'html' => 0,
    ),
    'link_to_node' => 1,
    'exclude' => 0,
    'id' => 'title',
    'table' => 'node',
    'field' => 'title',
    'relationship' => 'none',
  ),
  'teaser' => array(
    'label' => 'Teaser',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 1,
      'max_length' => '140',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'strip_tags' => 1,
      'html' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'exclude' => 0,
    'id' => 'teaser',
    'table' => 'node_revisions',
    'field' => 'teaser',
    'relationship' => 'none',
    'override' => array(
      'button' => 'Use default',
    ),
  ),
));
$handler->override_option('items_per_page', 30);
$handler->override_option('use_pager', '1');
$handler->override_option('style_options', array(
  'grouping' => '',
  'override' => 1,
  'sticky' => 0,
  'order' => 'asc',
  'columns' => array(
    'title' => 'title',
    'teaser' => 'teaser',
  ),
  'info' => array(
    'title' => array(
      'sortable' => 1,
      'separator' => '',
    ),
    'teaser' => array(
      'separator' => '',
    ),
  ),
  'default' => 'title',
));
$handler->override_option('path', 'relatedposts/%');
$handler->override_option('menu', array(
  'type' => 'none',
  'title' => '',
  'description' => '',
  'weight' => 0,
  'name' => 'navigation',
));
$handler->override_option('tab_options', array(
  'type' => 'none',
  'title' => '',
  'description' => '',
  'weight' => 0,
));