Product comparison in Drupal

  • strict warning: Non-static method view::load() should not be called statically in /home/tomkaname/jan.tomka.name/sites/all/modules/views/views.module on line 906.
  • strict warning: Declaration of views_handler_field_comment::init() should be compatible with views_handler_field::init(&$view, $options) in /home/tomkaname/jan.tomka.name/sites/all/modules/views/modules/comment/views_handler_field_comment.inc on line 49.
  • strict warning: Declaration of views_handler_filter::options_validate() should be compatible with views_handler::options_validate($form, &$form_state) in /home/tomkaname/jan.tomka.name/sites/all/modules/views/handlers/views_handler_filter.inc on line 607.
  • strict warning: Declaration of views_handler_filter::options_submit() should be compatible with views_handler::options_submit($form, &$form_state) in /home/tomkaname/jan.tomka.name/sites/all/modules/views/handlers/views_handler_filter.inc on line 607.
  • strict warning: Declaration of views_handler_filter_node_status::operator_form() should be compatible with views_handler_filter::operator_form(&$form, &$form_state) in /home/tomkaname/jan.tomka.name/sites/all/modules/views/modules/node/views_handler_filter_node_status.inc on line 13.
  • strict warning: Declaration of views_plugin_row::options_validate() should be compatible with views_plugin::options_validate(&$form, &$form_state) in /home/tomkaname/jan.tomka.name/sites/all/modules/views/plugins/views_plugin_row.inc on line 134.
  • strict warning: Declaration of views_plugin_row::options_submit() should be compatible with views_plugin::options_submit(&$form, &$form_state) in /home/tomkaname/jan.tomka.name/sites/all/modules/views/plugins/views_plugin_row.inc on line 134.
  • strict warning: Non-static method view::load() should not be called statically in /home/tomkaname/jan.tomka.name/sites/all/modules/views/views.module on line 906.
  • strict warning: Declaration of views_handler_argument::init() should be compatible with views_handler::init(&$view, $options) in /home/tomkaname/jan.tomka.name/sites/all/modules/views/handlers/views_handler_argument.inc on line 744.
  • strict warning: Declaration of views_handler_filter_boolean_operator::value_validate() should be compatible with views_handler_filter::value_validate($form, &$form_state) in /home/tomkaname/jan.tomka.name/sites/all/modules/views/handlers/views_handler_filter_boolean_operator.inc on line 159.
  • strict warning: Non-static method view::load() should not be called statically in /home/tomkaname/jan.tomka.name/sites/all/modules/views/views.module on line 906.
  • strict warning: Non-static method view::load() should not be called statically in /home/tomkaname/jan.tomka.name/sites/all/modules/views/views.module on line 906.
  • strict warning: Declaration of calendar_plugin_display_page::options_submit() should be compatible with views_plugin_display_page::options_submit(&$form, &$form_state) in /home/tomkaname/jan.tomka.name/sites/all/modules/calendar/includes/calendar_plugin_display_page.inc on line 297.
  • strict warning: Declaration of calendar_plugin_display_page::options() should be compatible with views_object::options() in /home/tomkaname/jan.tomka.name/sites/all/modules/calendar/includes/calendar_plugin_display_page.inc on line 297.
  • strict warning: Declaration of calendar_plugin_display_block::options() should be compatible with views_object::options() in /home/tomkaname/jan.tomka.name/sites/all/modules/calendar/includes/calendar_plugin_display_block.inc on line 78.
  • strict warning: Declaration of calendar_plugin_display_attachment::options_submit() should be compatible with views_plugin_display_attachment::options_submit(&$form, &$form_state) in /home/tomkaname/jan.tomka.name/sites/all/modules/calendar/includes/calendar_plugin_display_attachment.inc on line 242.
  • strict warning: Declaration of calendar_plugin_display_attachment::options() should be compatible with views_object::options() in /home/tomkaname/jan.tomka.name/sites/all/modules/calendar/includes/calendar_plugin_display_attachment.inc on line 242.
  • strict warning: Declaration of date_api_argument_handler::init() should be compatible with views_handler_argument::init(&$view, &$options) in /home/tomkaname/jan.tomka.name/sites/all/modules/date/includes/date_api_argument_handler.inc on line 398.
  • strict warning: Declaration of calendar_view_plugin_style::options() should be compatible with views_object::options() in /home/tomkaname/jan.tomka.name/sites/all/modules/calendar/includes/calendar_view_plugin_style.inc on line 173.

A few months ago, when I was writing about creating a List of recently viewed nodes in Drupal I mentioned a few other uses for the couple of modules, Flag and Views. One of them, I'm going to expand on today, is the product comparison functionality.

Compare products

There are several ways to implement product comparison functionality as found on websites throughout the Internet. Perhaps the most common is the one where there is just a few products to be compared, like service subscription options, and they can all be displayed on a page without the need of giving user a way to select the products to compare. Only a simple tabular view would be needed to implement such a comparision page, which would list individual product fields.

Include in comparison

Today, though, we're going to have a look at a slightly more complex product comparison type, the one where user marks products to be included for comparison as they browse the website. When they're done choosing products, they visit the comparison page itself.

For those who know their way around Flag and Views modules, we will create an Include in comparison per-user node flag, which users will use to mark the interesting nodes. Then, we will create a table view with the nodes previously marked. That's the long story short, let's get on with it.

Flag module

Flag configuration 1

Flag name
product_comparison
Flag title
Product comparison
Flag type
Nodes

Submit and continue editing.

Global flag
no (instead, we want a per-user flag)
Flag link text
Include in comparison
Unflag link text
Exclude from comparison
Roles that may use this flag
authenticated users (or whatever user roles you want to track recently viewed items for).
What nodes this flag may be used on:
your Product type (or any node types which you want to enable for comparison)
Link type
JavaScript toggle
Display link on node teaser
no
Display link on node page
no
Display checkbox on node edit form
no

I chose to not display link on either node teaser, or node page. If you want to keep things simple, you can leave either of these checkboxes enabled.

If you want to be a bit more flexible, though, and display the link inside the node content or a block for that matter, here's how to do it. Just include the following lines of code (appropriately customized for your needs) wherever you want the flag/unflag link to be displayed:

$node = node_load(arg(1));
print flag_create_link('product_comparison', $node->nid);

Flag configuration 2

Views module

Views configuration

View name
product_comparison
View type
Node
Style
Table (or Flipeed Table)
Path
product-comparison (or any other path)
Add relationships Flags: Node flag
Include only flagged content
yes
Flag
Product comparison
By
Current user
Add sort criteria Flags: Flagged time
Relationship
flag
Sort order
Descending
Granularity
Second
Add fields Node: Title
Label
Product title
Link this field to its node
yes

At this point, add all the product content type fields you want to be displayed in the comparison, such as product features and price.

Views configuration 2

Screenshots of the result

Homepage with the product teasers. Note the Exclude from comparison link under the products included for comparison and listed in the Product comparsion block.

Homepage

Product comparison page itself. This is an unthemed flipped table. With an image added and a bit of designer's love, you could turn it into pretty much anything there is out there:

Product comparison

Anonymous users

If you're using Flag version 2 and also have installed SessionAPI module, you will be able to select anonymous user in the flag configuration and make the product comparison available for anonymous users as well.

Flipped Table

To switch columns and rows of the table view style, use module called Views Flipped Table which is part of Views Hacks.

I came across a bug in views_flipped_table, though. When there are no products marked for comparison, instead of the Empty text, it comes up with an error. The fix is easy. Inside the theme file views_hacks/views_flipped_table/views-flipped-table.tpl.php just enclose the generated <table> in an if(!empty($rows)) block.

The Features package

While taking screenshots for this post and testing the configuration, I figured I would just create a Feature package with the whole thing ready for you to install and use right away.

Please, find the package attached to this page and feel free to use it as you see fit. You will need Flag version 2 to make use of this package.

AttachmentSize
Product comparison Features package16 KB
Product comparison View1.54 KB

Comments

Nice post Jan, I had been

Nice post Jan, I had been looking around for something like this for a while but hadn't seen your post so ended up achieving it in almost the same way a week after your post.
http://tinyurl.com/2fmklfg

Yep, pretty much the same

Yep, pretty much the same thing. Good job! Also, have a look at the Views Hacks module.

Awesome! I'm a little lost on

Awesome!

I'm a little lost on making the product comparison button though... and the page that would go to.

I have my 2 sample products showing up on the home page with my include/exclude links... but I'm kind of lost from there.

I'm using 7.x otherwise I would try the module files you've provided.

I setup a second drupal 6

I setup a second drupal 6 site and this works perfect. I'm just trying to figure out what the page yoursite.com/product-comparison is or how it's made so I can do it in drupal 7.

It's a view set up using the

It's a view set up using the Views module. The URL is configurable in each page display's Page settings section. Enable the Views UI module and you can access it under Site building » Views.

Thanks, the View Hacks /

Thanks, the View Hacks / Flipped Table (http://drupal.org/project/views_hacks) was just what I needed. I've got my price comparison table working now, though it did take quite a few CSS tricks to get it to look right. Let me know what you think (http://sites.crossunion.com/pricing).

Great tutorial. I have a

Great tutorial.

I have a doubt. I created the views with several fields. Some of them might be empty depending on the product. So when I use the compare, the field is always showing even if both or more products in compare is empty.

Do you have any idea of how I can filter fields that are completely empty out and leave it on if at least one of them has data.

thank you in advance if you can help.

In the field configuration,

In the field configuration, tick Hide if emtpy checkbox.

Please, note the actual behavior will still depend on the selected view style's implementation. E.g. this will work with HTML list, but not with Flipped table. You may want to choose a different style or override the desired one to hide labels for empty fields.

For the Flipped table module, this quick and dirty preprocess function comes to mind, which removes the teaser row if all teasers are empty:

function MYTHEME_preprocess_views_flipped_table(&$vars) {
  if ($vars['view']->name == 'product_comparison') {
    $hide_row = TRUE;
    foreach ($vars['rows'] as $row) {
      if (! empty($row['teaser'])) {
        // At least one Teaser field is nonempty.
        $hide_row = FALSE;
        break;
      }
    }
    if ($hide_row) {
      // All Teaser fields are empty, remove from header and rows.
      foreach (array_keys($vars['rows']) as $key)
        unset($vars['rows'][$key]['teaser']);
      unset($vars['header']['teaser']);
    }
  }
}

Place this function in your MYTHEME/template.php file, replace teaser with whatever you want it to work for and give it a shot.

thank you for you quick

thank you for you quick reply. I will take a shot at it. Thanks

Thank you for this

Thank you for this information!! has been very useful for me!!!

:P sorry for my bad english.

No worries at all, I'm not a

No worries at all, I'm not a native speaker myself. ;-)

I have implemented the

I have implemented the product comparison in my site. I have a block that shows the flagged products and am able to remove the product from compare in the block. I also have a compare and remove on each product page.

I am trying to add a flag "button" to add and remove from the compare products at the Product Catalog Grid (like when I click a main category and it shows all the products in that category). I tried to add a flag in the uc_products.

Do you know if it is possible to put the product compare button on each product? http://www.mtek.net.br/catalog/2

Note that uc_products view

Note that uc_products view (path starting with /products) is different from the Catalog taxonomy page (path starting with /catalog).

To change the catalog theming, you may want to override a theme function defined by the uc_catalog module, most likely the uc_catalog_product_grid.

Hey, how did you get the flagged list refreshing done in the Comparar block?

I added the ajax and

I added the ajax and ajax_views_refresh module and turned the ajax on in the compare-product views.

and also the module

and also the module views_flag_refresh

Awesome tutorial my friend,

Awesome tutorial my friend, I've set up a nice product comparison in my uc-based store thanks to your help!

I have two questions I hope you can guide me. First, how can I limit the product comparison to items belonging to the same category (associated to the same taxonomy term)? Because does not make sense to compare t-shirts and TVs... I have SessionAPI enabled to allow anonymous comparison as per your suggestion.

The second one I'm afraid is tricky: how can I assign a class to identical fields among compared products, or any other way to stress out common fields with a different background color?

Thanks a lot for all your help!

Ideas? Is it possible at all

Ideas? Is it possible at all using this type of product comparison?

Hi Jan, great tutorial.

Hi Jan,

great tutorial. Thanks a lot.

I build the comparsion table in D7, and it works great, except for one thing. When changing the template file to the one described here http://drupal.org/node/1256078 just the last product added to the comparsion appears.

When using the no flipped table all appear.

Any idea?

Thanx Christian

I've been gone getting

I've been gone getting married. Sorry guys! :-)

Christian, I'd have to see your code to be able to tell what the problem could be. From what you're saying it looks like a for cycle gone wrong, rewriting the output variable or something similar. Most probably just a minor thing, although easily overlooked.

Actually both of them are

Actually both of them are quite tricky.

For the term specific product comparison, I would consider saving the first selected product's term in a session variable. I would then include a filter in my view with a piece of PHP to retrieve that value, and would only display the comparison link for products with the same term.

I haven't tried it myself, but it sounds easy said so I guess it won't be that easy to implement. Let me know if you come up with a solution.

The latter one I would find easier to achieve. I believe it is just a matter of view theming. When you're going through the table style template, just compare individual fields and -- in case the values are all identical -- add a class to the entire row.

Thanks for your answer, and

Thanks for your answer, and congratulations for your marriage.

I do not understand how to save the session variable for the first selected term. Do I need a custom module for this? Actually I'm afraid I didn't get your idea at all.

Concerning the second issue, I'm now editing the view template (rather a copy in my theme of course) and will come back with comments about the results.

Cheers, Karl! You could use

Cheers, Karl!

You could use Rules module. Flags include support for Rules which makes it possible for you to fire actions when content is flagged/unflagged with the Include in comparison flag. Now the action here would be a short PHP snippet to assign the node's term to a $_SESSION variable.

I don't have access to a testing platform from where I am now, but give it a thought and let me know if you'll be able to work it out.

Hi Jan, Congratulation for

Hi Jan, Congratulation for your marriage.

Your tutorial is very helpful and i successfully managed to create a product comparison that allow products to be flagged while traveling thru site and then listing them all in nice table (thanks to view hacks). All good.

After achieving this, i am wondering if we can do one notch higher version of providing dropdown too on comparison matrix page to add more products without user have to travel again to add more products to comparison matrix page???

www.carnity.com/carnity. go to >> car details >> Audi >> Audi A1 add product and use comparison button on top menu to load flagged products.

prototype example (but non working): http://carnity.com/carnity/?q=compare

Thanks Gaurav! Sorry, the

Thanks Gaurav!

Sorry, the page is failing on me. It displays all Audis and more cars cannot be added. Whatever I add it just comes up with an empty page...

Anyway, you should be able to do what you're after in the submit handler of the Add Car form. Just flag the selected car's node like so

flag('flag', 'comparison', $nid);

When the page loads back, you should have the new node in the table.

You'll either have to implement it in a module of your own, or you might be able to use the Rules Forms Support module for it.

Thanks Jan, i will give it a

Thanks Jan, i will give it a try. Got the Rules and Rules forms, but cant find place to access rules. Could you give me heads up where to dig them, so that i can configure them as needed.

Second, how to access "Add car"submit handler, cant find any option to edit. Should i go to back end and edit that line of code in PHP file??? If yes little heads up needed there as well to understand the back end structure of Drupal.

Many thanks.

To access Rules

To access Rules administration you'll need to enable both Rules and Rules Administration UI modules. A new Rules item will show up in your navigation menu.

To write your own form submit handler, you'll need to create a custom module. The best source of information on developing modules and using Drupal's Form API would be http://drupal.org/developing/modules and http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html.

Sorry I can't give you a ready to go code, I'd have to set up the whole thing locally to see if it even works. But as I keep thinking about a solution to your problem, I am confident the one I suggested would work. On the form submission, you just flag the selected node with the comparison flag.

I hope that helps, let me know how you go.

hi jan, first of all thanks

hi jan, first of all thanks for this tutorial, i learned quite a few things!!
but unfortunately this set up just won't work for me.. i'm getting frustrated.

i did everything exactly like described, but when i open the views page for the "product comaprison" i always get an empty page. neither the little menu with "edit export clone" appears, that usually shows up when hovering over a view, nor the empty text for a view without any results.

it does work though when i change the setting in views-relationships from "only current user" to "any user". but this just not what i need.. :(
i even tried to import your view, but without any luck.
do you have or does anyone else has an idea what my problem could be?

help much appreciated!! thanks again!

Hi Pirmin I had a working

Hi Pirmin
I had a working workflow of flags and views until the views security update 6.2.13 came up, which broke the views functionality...

Thank you for this tutorial.

Thank you for this tutorial. It has saved me a lot of time.

I have made a 'block' view to show the flagged products. Is there a way to refresh the block when the products are flagged or unflagged?

'Views flag refresh' module

'Views flag refresh' module here http://drupal.org/project/views_flag_refresh came handy. It refreshes the block view whenever a flag action occurs.

I did it. you can see it in

I did it. you can see it in action here http://tabpc.in

Is there a way to create permalinks for the comparison page. some thing like doman.com/compare/product1-vs-product2

anonymous don't use this

anonymous don't use this module , please help me ?

Are you saying anonymous

Are you saying anonymous users are unable to flag? If yes, install and enable session api module to allow anonymous users to flag http://drupal.org/project/session_api

Also make sure that you have

Also make sure that you have selected anonymous users in the flag settings.

i use version flag 6.x-1.3

i use version flag 6.x-1.3 ,but it's not premision anonymous, it's ok,

but version 6.x-2.0-beta6, it's have premision anonymous , i already use session api , but error querry .....

error : return

error :

return db_result(db_query("SELECT fid FROM {flag_content} WHERE fid = %d AND uid = %d AND sid = %d AND content_id = %d", $this->fid, $uid, $sid, $content_id));

please help me?

Thank you sow much for this

Thank you sow much for this tutorial, You helped me allot,
But I still have a problem. I guess an action can help but I just don't know where to start.

I have parent - child nodes.
You can flag the parent nodes to compare them, but I wont to display child information also.
Because these nodes are not flagged they don't display in the views area.

Even with the relationship set correctly.
Know I think I have to perform an action that when a parent node is flagged it's child nodes are also. Am I taking rubbish of those these make sense?

Can you help me with this? How do I start, or do I need to put PHP inhere to get this work?

All of this functionality is

All of this functionality is pre-built into a module called 'drupal properties'. http://drupal.org/project/properties

what a great tutorial! Bless

what a great tutorial! Bless you!