Ubercart Taxonomy Catalog

There are many ways to build a product catalog with Ubercart. We have used almost every method possible, Ubercart Catalog, Views, and even Apache Solr. I want to show what we think is a great alternative to the Ubercart Catalog and Views catalog. This will not get you the performance and facets that an Apache Solr catalog will get you. We will leave that for another post.

I refer to this method I am going to show you as the Ubercart Taxonomy Catalog.

The Ubercart Catalog module had some great features and configuration options our of the box, however customizing it it sometimes where most people see the wall at the end of the road. People often then try and replicate the catalog module in views which is a great start but leaves a big gap in terms of SEO and user friendliness.

The problem comes from the general concept of having duplicate content between your product catalog and the taxonomy pages. Also when a user clicks on a term on a product page they are directed to the taxonomy page rather that the product catalog for that term.

The best thing we could do is to make the taxonomy pages the actual product catalog. This reduces duplicate content and solves the problem of user clicking on the taxonomy terms and being thrown into the ugly river of product teasers.

Let me walk you through the painless process.

Step 1 - Setup your taxonomy structure the way you want it.

Don’t limit yourself to one vocabulary here. We suggest product type, manufacturer, and any other major divisions in your products. We suggest multi select where it makes sense, stay away from the required and tag options for this catalog use case.

Step 2 - Create your taxonomy term header view.

For my example I am using a simple table with the term image and term description. You will need the term image module installed for this wo work. This is Views import code.

$view = new view;
$view->name = 'taxonomy_term_header';
$view->description = '';
$view->tag = '';
$view->view_php = '';
$view->base_table = 'term_data';
$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(
  'tid' => array(
    'label' => '',
    '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,
    ),
    'imagecache_preset' => 'product_list',
    'link_to_taxonomy' => 0,
    'exclude' => 0,
    'id' => 'tid',
    'table' => 'term_image',
    'field' => 'tid',
    'relationship' => 'none',
  ),
  'description' => array(
    'label' => '',
    '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,
    ),
    'exclude' => 0,
    'id' => 'description',
    'table' => 'term_data',
    'field' => 'description',
    'relationship' => 'none',
  ),
));
$handler->override_option('arguments', array(
  'tid' => array(
    'default_action' => 'not found',
    'style_plugin' => 'default_summary',
    'style_options' => array(),
    'wildcard' => 'all',
    'wildcard_substitution' => 'All',
    'title' => '',
    'breadcrumb' => '',
    'default_argument_type' => 'fixed',
    'default_argument' => '',
    'validate_type' => 'none',
    'validate_fail' => 'not found',
    'break_phrase' => 0,
    'not' => 0,
    'id' => 'tid',
    'table' => 'term_data',
    'field' => 'tid',
    'validate_user_argument_type' => 'uid',
    'validate_user_roles' => array(
      '2' => 0,
    ),
    'relationship' => 'none',
    'default_options_div_prefix' => '',
    'default_argument_user' => 0,
    'default_argument_fixed' => '',
    'default_argument_php' => '',
    'validate_argument_node_type' => array(
      'product' => 0,
      'page' => 0,
    ),
    'validate_argument_node_access' => 0,
    'validate_argument_nid_type' => 'nid',
    'validate_argument_vocabulary' => array(
      '4' => 0,
      '2' => 0,
      '3' => 0,
    ),
    'validate_argument_type' => 'tid',
    'validate_argument_transform' => 0,
    'validate_user_restrict_roles' => 0,
    'validate_argument_php' => '',
  ),
));
$handler->override_option('access', array(
  'type' => 'none',
));
$handler->override_option('cache', array(
  'type' => 'none',
));
$handler->override_option('style_plugin', 'table');
$handler->override_option('style_options', array(
  'grouping' => '',
  'override' => 1,
  'sticky' => 0,
  'order' => 'asc',
  'columns' => array(
    'description' => 'description',
    'tid' => 'tid',
  ),
  'info' => array(
    'description' => array(
      'separator' => '',
    ),
    'tid' => array(
      'separator' => '',
    ),
  ),
  'default' => '-1',
));

Step 3 - Create your product grid view.

For this example I am creating a node view of products in a grid format.
This is Views import code.

$view = new view;
$view->name = 'product_grid_view';
$view->description = '';
$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' => '',
      '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',
  ),
  'model' => array(
    'label' => '',
    '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' => 0,
    'exclude' => 0,
    'id' => 'model',
    'table' => 'uc_products',
    'field' => 'model',
    'relationship' => 'none',
  ),
  'sell_price' => array(
    'label' => '',
    '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,
    ),
    'exclude' => 0,
    'id' => 'sell_price',
    'table' => 'uc_products',
    'field' => 'sell_price',
    'relationship' => 'none',
  ),
  'addtocartlink' => array(
    'label' => '',
    '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,
    ),
    'exclude' => 0,
    'id' => 'addtocartlink',
    'table' => 'uc_products',
    'field' => 'addtocartlink',
    'relationship' => 'none',
  ),
));
$handler->override_option('arguments', array(
  'tid' => array(
    'default_action' => 'not found',
    'style_plugin' => 'default_summary',
    'style_options' => array(),
    'wildcard' => 'all',
    'wildcard_substitution' => 'All',
    'title' => '',
    'breadcrumb' => '',
    'default_argument_type' => 'fixed',
    'default_argument' => '',
    'validate_type' => 'none',
    'validate_fail' => 'not found',
    'break_phrase' => 0,
    'add_table' => 0,
    'require_value' => 0,
    'reduce_duplicates' => 0,
    'set_breadcrumb' => 0,
    'id' => 'tid',
    'table' => 'term_node',
    'field' => 'tid',
    'validate_user_argument_type' => 'uid',
    'validate_user_roles' => array(
      '2' => 0,
    ),
    'relationship' => 'none',
    'default_options_div_prefix' => '',
    'default_argument_user' => 0,
    'default_argument_fixed' => '',
    'default_argument_php' => '',
    'validate_argument_node_type' => array(
      'product' => 0,
      'page' => 0,
    ),
    'validate_argument_node_access' => 0,
    'validate_argument_nid_type' => 'nid',
    'validate_argument_vocabulary' => array(
      '4' => 0,
      '2' => 0,
      '3' => 0,
    ),
    'validate_argument_type' => 'tid',
    'validate_argument_transform' => 0,
    'validate_user_restrict_roles' => 0,
    'validate_argument_php' => '',
  ),
));
$handler->override_option('filters', array(
  'is_product' => array(
    'operator' => '=',
    'value' => '1',
    'group' => '0',
    'exposed' => FALSE,
    'expose' => array(
      'operator' => FALSE,
      'label' => '',
    ),
    'id' => 'is_product',
    'table' => 'uc_products',
    'field' => 'is_product',
    'relationship' => 'none',
  ),
  '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', 12);
$handler->override_option('style_plugin', 'grid');

Step 4 - Override the taxonomy page theme function

At the bottom of your themes template.php file add the following code.

function MYTHEME_taxonomy_term_page($tids, $result) {
$output = '';

// we use this view to render the content rather than normal taxonmy behaviour
$output .= views_embed_view('taxonomy_term_header', 'default', $tids[0]);
$output .= views_embed_view('product_grid_view', 'default', $tids[0]);

return $output;
}

Tim's picture
Tim Hill

Tim was the co-founder of Commerce Guys with Mike in 2008. Tim considers himself an EntreLeader by having the drive and motivation of an entrepreneur and the strength and vision of a leader, all rolled into one. Tim first got into e-commerce by working his way up in a large e-commerce company and then helping launch a new company selling retail products online. Tim has immersed himself into e-commerce on Drupal since 2006. Tim works within the company to manage the HR, travel and events, and accounting departments.

Comments

This is great, and exactly

This is great, and exactly what I've been looking for over the last week. My question is, where in the world do you put this code?? Do I use Views and it creates this.

It's great, I'm just missing the key part about what to do with code now that I have it.

THANK YOU!

This is views import code,

This is views import code, instead of creating a new view you can use this code to import one i created.

Alright Tim, I did this and

Alright Tim, I did this and got it into views. But, now how do I see the catalog? Is the UC Catalog still enabled or is this a completely separate thing?

I just want to have more control over the catalog than is currently available with Ubercart. Specifically, they linking that gets you to a listing of products from the catalog, instead of to one particular product.

Thanks -- it sure seems like this is the solution. I feel like I'm just missing a couple basic things.

Don't forget to replace

Don't forget to replace MYTHEME with the name of your theme. And yes, disable the Ubercart catalog module.

An alternative method is to use
http://drupal.org/project/views_catalog with
http://drupal.org/project/taxonomy_redirect

Hi, I like your tutorials

Hi,

I like your tutorials very much. Please keep on writing. I've used your code here above, but there is something strange going on with the term image. It keeps showing up as uc_thumbnail, even though I've changed the imagecache preset to other things. I've cleared all caches several times, flushed the presets,...

Please help me.

Using this method, are you

Using this method, are you disabling the "catalog" module and relying on your own set of taxonomy and views? I just watched a podcast over at MustardSeedMedia about taxonomy and was thinking of following their suggestions to create an Ubercart site. It seems like this is another good method.

Thanks for the help. I have

Thanks for the help. I have been looking for this for about the last 6 hours. I didn't think about overiding the Taxonomy theme.

I believe that quite a few people have been struggling with this, so I will try to post a few links back to this post on the ubercart forums etc.

Hi Guys, thanks for this

Hi Guys,

thanks for this walkthrough!
fits me to a tee..

Im keeping the UC_Catalog, but this view is allowing me to have a manufacturers page that is useful..

now i just have to work out how to only show the manufacturers taxonomy, not include the other taxonmys.. im sure ill get there.

Thanks again!

Just a quick edit. If you

Just a quick edit. If you copy and past all of the code, you will need to change the bit in template.php

<?php
$output
.= views_embed_view('taxonomy_term_header', 'default', $tids[0]);
$output .= views_embed_view('product_grid_view', 'default', $tids[0]);
?>

change to

<?php
$output
.= views_embed_view('taxonomy_term_header', 'default', $tids[0]);
$output .= views_embed_view('taxonomy_term_product', 'default', $tids[0]);
?>

Obviously change the MYTHEME bit too.

Great article. I confirm that

Great article. I confirm that this method works and isn't that hard to implement.

One useful thing to add: if you want your view to display products tagged with descendent terms of the displayed term, use "Term ID (with depth)" instead of "Term ID."