Product Comparison Tool

Client: “Now that we have all of our product data loaded into the new site, I want a tool where users can select multiple products and compare them side by side.”

Gulp….“Let me think about that one for a bit…”

 
Download the EE Code for Product Comparison Tool

Not an unreasonable request, right?  As a consumer I’ve often used such tools to quickly compare multiple products I was interested in purchasing.  Comparison tables can quickly help you find differences and similarities that would be tough to see bouncing around different product-specific pages.

But how to pull this off on an ExpressionEngine based site?

As is so often the case with EE, what looks difficult at first blush turns out to not be too difficult.  Let me show you the front end of what I came up with so you can better tell if it’s close to what you need:

There is a short screencast here that requires Flash, but isn’t crucial to the tutorial.

 

Overview

  • The drop-downs are dynamically populated from channel:entries tags so if our client adds or deletes products he won’t have to worry about replicating those edits for the drop-downs.
  • While the drop-downs display entry titles, you are really choosing entry_ids.
  • When you click “Compare” a bit of javascript grabs the entry_id’s from the 3 drop-downs, appends them onto the URL and reloads the template.
  • Additional channel:entries loops then see those entry_id’s and use them to retrieve the content for the chosen entry.
  • Each column is actually its own HTML table, floated using CSS to create the side-by-side view.

Main releases/compare Template
Let’s work through the main template (available as a download):

<!doctype html>
<
html>
<
head>
    <
title>Compare Releases</title>
    <
meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <
script type="text/javascript">
        <!-- 
Begin
        site 
"http://localhost:8888/index.php/releases/compare/";
        function 
combineMenus(frmproduct_1product_2product_3{
            with 
(frm{
            str 
product_1.options[product_1.selectedIndex].value;
            
str += product_2.options[product_2.selectedIndex].value;
            
str += product_3.options[product_3.selectedIndex].value;
            
url site str;
            
window.location.href url;
           
}
        }
        
//  End -->
    
</script> 

This is the javascript that assembles the expected page URL including the 3 entry_id’s from the selected products.  If you use this code make sure to change the site= parameter to the URL to your comparison template.

<style type="text/css">
    
table.compare {width:170pxfloatleft;}
    td {text
-alignleftpadding2pxheight28px;}
    td
.label {text-align:rightpadding5px 4px 0px 0px}    
    th {height
80px;
    form
#compare_form {padding: 0px 0px 0px 100px;}
    
select {width167px;}
</style>
</
head

Just some basic CSS mainly to get the result tables to line up by floating.  I went this route because it made exception-handling much easier (what if user selects an option only from the first and third boxes, etc). 

<body>
<
h1>Compare Record Releases</h1>        
<
form name="compare_releases" id="compare_form" method="post" action="http://localhost:8888/index.php/releases/compare/">
    <
input type="button" class="compare_form" value="Compare" onclick="combineMenus(this.form, this.form.product_1, this.form.product_2, this.form.product_3)" />
    <
select name="product_1">
        <
option value="">Choose Release</option>
        
{exp:channel:entries channel="releases"" dynamic="no" disable="trackbacks|categories|member_data|pagination|custom_fields"}
            <option value ="
{entry_id}/" {if segment_3==entry_id}selected="selected"{/if} >{title}</option>
        {/exp:channel:entries}
    </select>    

    <select name="
product_2">
        <option value="">Choose Release</option>
        {exp:channel:entries channel="
releases"" dynamic="no" disable="trackbacks|categories|member_data|pagination|custom_fields"}
            
<option value ="{entry_id}/" {if segment_4==entry_id}selected="selected"{/if} >{title}</option>
        
{/exp:channel:entries}
    
</select>    

    <
select name="product_3">
        <
option value="">Choose Release</option>
        
{exp:channel:entries channel="releases"" dynamic="no" disable="trackbacks|categories|member_data|pagination|custom_fields"}
            <option value ="
{entry_id}/" {if segment_5==entry_id}selected="selected"{/if} >{title}</option>
        {/exp:channel:entries}
    </select>    
</form> 

These are the dynamically-generated drop-downs.  It may or may not make sense to chunk these out into a reusable embedded template or snippet, but since they are pretty simple I just left them this way. All we need are the default fields from the channel so our disable parameter can disable everything else for best performance.

{if segment_3 !="" OR segment_4 !="" OR segment_5 !=""}
    
<table class="compare">
        <
thead><tr><th>&nbsp;</th></tr></thead>
        <
tbody>
            <
tr><td class="label">Title</td></tr>
            <
tr><td class="label"># of Tracks</td></tr>
            
<tr><td class="label">Formats</td></tr>            
        </
tbody>
    </
table>
{/if} 


This conditional displays the comparison table labels if the template has been loaded with entry_id’s showing in the URL.

{if segment_3 !=""}
    {embed
="embeds/comparison_column" the_segment="{segment_3}"}
{
/if}    

{if segment_4 
!=""}
    {embed
="embeds/comparison_column" the_segment="{segment_4}"}
{
/if}    

{if segment_5 
!=""}
    {embed
="embeds/comparison_column" the_segment="{segment_5}"}
{
/if}    
</body>
</
html

These conditionals pull in the embedded template that displays a column.  Since the columns need to be identical and only need to look at a different segment for the right entry_id to pull content for, I created an embedded template and just pass the segment variable as an embed variable.  While the comparison column in this tutorial is simple, the odds are that on a production site it would be much more complex and you might as well only create that table once.

The embeds/comparsion_column Template

{exp:channel:entries weblog="releases" limit="1" entry_id="{embed:the_segment}" disable="trackbacks|categories|member_data|pagination" dynamic="no"}
    
<table class="compare" border="1">
        <
thead>
            <
tr><th><img src="{releases_album_thumb}" title="{title}" alt="{title}" /></th></tr>
        </
thead>
        <
tbody>
            <
tr><td><a href="{url_title_path='releases/detail'}">{title}</a></td></tr>
            <
tr><td>{releases_number_tracks}</td></tr>
            <
tr><td>
                
{releases_formats}
                    {if item
=="MP3"}<img src="{site_url}images/interface/release_itunes.png" alt="MP3" />{/if}
                    {if item
=="CD"}<img src="{site_url}images/interface/release_cd.png" alt="CD" />{/if}
                    {if item
=="LP"}<img src="{site_url}images/interface/release_lp.png" alt="LP" />{/if}
                {
/releases_formats}
            
</td></tr>
        </
tbody>
    </
table>
{/exp:channel:entries} 

Pretty straightforward here, we just use the passed-in variable to determine what URL segment to grab the entry_id from. 

Wrapping Up
So there you have it - with a small bit of javascript together with native ExpressionEngine tools like segment variables, conditionals, embedded templates, and embed variables, you can pretty quickly pull entries from a channel and display them in a side-by-side comparison table for happy users.

Category Navigation

<< Previous Entry   

Next Entry >>

 

Previous Comments

Picture of Shane

by Shane

Date: Saturday, February 4th, 2012
Comment: #1

This is awesome Mike. Thank you for sharing.

Mike Boyink

by Mike Boyink (Author)

Date: Saturday, February 4th, 2012
Comment: #2

My pleasure!

Picture of Dan

by Dan

Date: Tuesday, February 14th, 2012
Comment: #3

So simple, but so effective. I am only put off by the fact that with 5 entry ID’s in the URL (comparing 5 products), it starts to make the URL look ugly, so may change to use the entry_id instead.

Will also sort the entry ID’s alphabetically to ensure only 1 URL is possible per combination.

Picture of Mel

by Mel

Date: Wednesday, February 29th, 2012
Comment: #4

This is awesome Mike and exactly what I was looking for.  Sometimes it really almost seems impossible to do until you break it down.

Picture of tyas

by tyas

Date: Saturday, June 2nd, 2012
Comment: #5

Thanks mike, allready bookmark this. Someday i’ll need it for my ecommerce site :)

Picture of Boyink

by Boyink

Date: Sunday, June 3rd, 2012
Comment: #6

Glad to hear it’s helpful..;)

Picture of Timur

by Timur

Date: Monday, July 2nd, 2012
Comment: #7

This looks really interesting. I have a couple of questions:

1. Would this allow a user to select the products?

(from knowing EE a little, I wouldn’t use Search as the URL wouldn’t have IDs in it, could you use a shopping basket type selection of products to result in a comparison?)

I’m talking about looking at a list of products and the user picks (checkbox?) Product A, D, F to compare. Next page shows that comparison… that would be great functionality :-)

2.Can you think of a way to limit the number of comparisons? (ie. to 3)

Any thoughts?

Thanks.

Timur

Picture of Boyink

by Boyink

Date: Monday, July 2nd, 2012
Comment: #8

Timur - did you view this page on a Flash-enabled device?  There’s a screencast which answers most of your questions.

Picture of Timur

by Timur

Date: Monday, July 2nd, 2012
Comment: #9

I didn’t apologies :-) will do when I get a chance!

Picture of Andy

by Andy

Date: Tuesday, October 9th, 2012
Comment: #10

Hi Mike,
Thanks for sharing the product comparison above! It’s exactly what I need for a project I’m working on using wordpress. Sadly I don’t seem to be able to get it working with the code you posted above.

I’ve created a wp page /compare/ and added the column code from you download. I’ve changed the url parameters to point to that wp page and also added the comparison_column html to the webserver.

It looks pretty good apart from not returning anything when I make a selection.

Maybe you can let me know what I’m missing here.

Thanks in advance,
Andy

Picture of Boyink

by Boyink

Date: Tuesday, October 9th, 2012
Comment: #11

?

This is an ExpressionEngine tutorial.

Picture of Andy

by Andy

Date: Tuesday, October 9th, 2012
Comment: #12

Yeah I worked it out by now. I don’t have experience with exp and figured I would get it working on wp as well.

Thanks though.

Picture of Boyink

by Boyink

Date: Tuesday, October 9th, 2012
Comment: #13

OK- so just for reference in the future I know nothing about WP…and really only support the content I have here as it relates to EE. ;)

Picture of Riverboy

by Riverboy

Date: Wednesday, January 28th, 2015
Comment: #14

Hi. Very cool. I only wonder how to use this type of settings if there is like 100+ products from to choose. Those dropdown lists comes annoying.

Do you have some idea how to handle this when there is more than just few products from to choose and compare?

Add Your Comment

Commenting is not available in this channel entry.

Unless otherwise stated all content is © Michael Boyink of Train-ee.com & Boyink Interactive. Please don't steal - I've got kids to feed...

dy>