Recently I had to add basic shopping cart functionality to a site that had been built with ExpressionEngine (my CMS of choice). “No problem,” I thought; I can use the Simple Commerce Module (SCM), which as the names suggests, is ideally suited to simple ecommerce requirements, and which I had used before on other EE sites.
But it turns out the requirements for this ‘store’ were a little more complicated and not something that could be done by the SCM ‘out of the box’. The store was selling prints of photos with each photo available in three different sizes. Searching on the EE forums revealed that being able to have different options or variations (size, colour etc.) for products was something that a few people had been trying to achieve. The SCM integrates with PayPal standard website payments and passing options to PayPal is something that can be done but it requires some custom coding to do so.
My problem was that I not only had different sizes, but each size was actually a different price which isn’t always the case for different options (for example T-shirts in small, medium or large aren’t always different prices, and different colours certainly wouldn’t involve a price change).
The way the SCM is set up, you create an entry in a weblog or section, and then you select that entry for adding to the shopping cart and you set a price for it. So in order to have three variations of size at different prices with the standard functionality offered by the SCM, I was faced with having to create three nearly identical products with the same name and same image (which would also require uploading the same image three times), with the only difference being the size.
From the website’s owner point of view this wasn’t an ideal solution as they had to keeping replicating entries; and from the site visitor’s point of view it wasn’t that great either because they’d be presented with three products that looked nearly identical and would have to look more closely to work out what the actual difference was (at which point they’d probably ask: “Why didn’t they just group them all together like other stores do?”)
Related entries to the rescue
The answer to the problem turned out to be with related entries (beefed up with the Multi Relationship extension by Mark Huot) and a bit of custom coding of the form that gets sent to PayPal.
First of all I needed to create a store section (I’ll call them sections from here because I never refer to them as ‘weblogs’) for which I then created custom fields for the product’s description, a file upload field (also courtesy of a Mark Huot extension) for the product image, and one for the size (I’ll come back to this one).
I then created another section for the sizes which also had custom fields, this time with just one field for the price (the name of the size being held in the entry’s title field). I then created three entries for this section with the entries for the small, medium and large sizes with their associated prices. Coming back to the custom fields for the store section, I made the field type for the sizes Multi Relationship which is added to the list of options after installing the Multi Relationship extension. So then when I created the entries for the store, I was able to select all three sizes (or I could have only chosen some of them for particular products if I wanted to). The image below shows what the publishing form for a store entry with the related entries field looks like.

Having created the products and assigned sizes and images to each of them, it was then time to add them to the store. To do this you need to first install the SCM, navigate to the extension’s home page (I like to create a new tab for it so it’s easy to get to) and then select Add Item. This takes you to a table of entries that looks like what you see when you choose the Edit tab, except that here after you’ve checked the checkboxes of the items you want to add, when you hit the submit button, you’re adding the items to the store.
The next window you’re presented with is where you fill in the price and sale price. You actually have to enter both or the entry won’t be created correctly, but you only use the sale price if you check the box that says Use Sale Price? I enter the same price for both fields but really I’m only entering a price here for the item to be submitted to the store correctly. The prices that get displayed in the template and sent to PayPal don’t come from the SCM but from the sizes section. I actually think using a related entries section for prices in this way can make things easier on the store owner when it comes to updating prices, because if you have a large number of products all with the same price and you want to increase the price, using the SCM way, you’d have to select all the products you wanted to edit and manually change the price for each one. Using a related entry, you just edit the entry in the options/prices section once and it’ll automatically get applied to all products that are related to that option.
Creating the template
The first thing we need to do is pull in all the entries from the ‘store’ section and for that we’ll use an ordinary weblog entries tag (s_desc is the field name I’ve given to the custom field for the product description):
{exp:weblog:entries weblog="store" disable="member_data|trackbacks"}
<h2>{title}</h2>
<p>{s_desc}</p>
At its most basic, the tag used for creating a SCM entry in a template looks like this:
{exp:simple_commerce:purchase entry_id="{entry_id}" success="site/success" cancel="site/index"}
{title}
<p><strong>Price: {item_sale_price}</strong></p>
<p><a href="{buy_now_url}" onclick="window.open(this.href);return false;">Buy Now</a></p>
<p><a href="{add_to_cart_url}" onclick="window.open(this.href);return false;">Add to Cart</a></p>
<p><a href="{view_cart_url}" onclick="window.open(this.href);return false;">View Cart</a></p>
{/exp:simple_commerce:purchase}
This will automatically create links with query strings that include all the parameters that need to be passed to PayPal. But when creating different options, we’ll need to create our own form and not leave it up to the module to generate it for us. We’ll still use the simple_commerce tag pair, but we’ll code the form tags ourselves. First we need a form tag with an action that points to PayPal (note that this URL is for Australian PayPal accounts; for US accounts leave the /au/ out):
<form action="https://www.paypal.com/au/cgi-bin/webscr" method="post" target="paypal">
Then we need a series of hidden inputs for passing the relevant information to PayPal (you can find out more about the different variables at the PayPal Developer Center):
<input type="hidden" name="cmd" value="_xclick"/>
<input type="hidden" value="http://www.yoursite.com/?ACT=20" name="notify_url"/>
<input type="hidden" value="http://www.yoursite.com/store/success" name="return"/>
<input type="hidden" value="http://www.yoursite.com/store/" name="cancel_return"/>
<input type="hidden" name="business" value="youremail@yoursite.com"/>
<input type="hidden" name="currency_code" value="AUD"/> <!-- Change this to whatever your currency is -->
<input type="hidden" name="item_name" value="{title}"/>
<input type="hidden" name="item_number" value="{item_id}"/>
<input type="hidden" name="add" value="1"/>
<input type="hidden" name="upload" value="1"/>
<input type="hidden" name="no_shipping" value="2"/>
<input type="hidden" name="no_note" value="1"/>
<input type="hidden" name="undefined_quantity" value="1"/>
Then we need to create a dropdown which enables shoppers to choose which option they want and this is where the related entries tag comes in:
<label for="amount">Size:</label>
<select name="amount">
<option value="">Please choose</option>
{related_entries id="s_size"}
<option value="{size_price}">{title} ${size_price}</option>
{/related_entries}
</select>
The id in the related_entries tag pair is the name of the field that is pulling in the related entries and instead of using the item_sale_price as the price for the item, we’ll take the price from the related entry – size_price (the name I’ve used in my custom field; you can call it whatever you like).
And then finally, a Buy Now button:
<input type="submit" name="buy_now" id="buy_now_{entry_id}" value="Buy Now">
But there’s one thing missing from the variables being passed to PayPal and that’s the actual name of the size being chosen. Because the select dropdown is being used to manipulate the price, the name of the size isn’t actually being passed. So I’ve used a bit of javascript to populate another hidden field when an option in the select is chosen. So instead, the select opening tag will now look like:
<select name="amount" onchange="setSize(this, this.form)">
That’s also the reason why there is a ‘Please choose’ option so that the shopper has to change to an option with a price before proceeding. The name of the option is passed to PayPal with:
<input type="hidden" name="on0" value="Size">
and the associated javascript:
<script type="text/javascript">
<!--
function setSize(selObj, formObj) {
for (var i = 0; i < selObj.length; i++)
if (selObj.options[i].selected && i != 0) {
{related_entries id="s_size"}
if (selObj.options[i].value == '{size_price}') { formObj.elements['os0'].value = '{title}'; }
{/related_entries}
}
}
//-->
</script>
automatically fills in this hidden field:
<input type="hidden" name="os0">
The related entries tag is being used here too to dynamically fill the options which means that the site owner can edit their options and prices without the template needing to be edited again.
Putting it all together
The whole template should now look like this:
<ul class="store">
{exp:weblog:entries weblog="store" disable="categories|member_data|pagination|trackbacks" sort="asc"}
{exp:simple_commerce:purchase entry_id="{entry_id}" success="store/success" cancel="store/index"}
<li>
<h2>{title}</h2>
<p>{s_desc}</p>
<form action="https://www.paypal.com/au/cgi-bin/webscr" method="post" target="paypal">
<input type="hidden" name="cmd" value="_xclick"/>
<input type="hidden" value="http://www.yoursite.com/?ACT=20" name="notify_url"/>
<input type="hidden" value="http://www.yoursite.com/store/success" name="return"/>
<input type="hidden" value="http://www.yoursite.com/store/" name="cancel_return"/>
<input type="hidden" name="business" value="youremail@yoursite.com"/>
<input type="hidden" name="currency_code" value="AUD"/>
<input type="hidden" name="item_name" value="{title}"/>
<input type="hidden" name="item_number" value="{item_id}"/>
<input type="hidden" name="add" value="1"/>
<input type="hidden" name="upload" value="1"/>
<input type="hidden" name="no_shipping" value="2"/>
<input type="hidden" name="no_note" value="1"/>
<input type="hidden" name="undefined_quantity" value="1"/>
<label for="amount">Size:</label>
<script type="text/javascript">
<!--
function setSize(selObj, formObj) {
for (var i = 0; i < selObj.length; i++)
if (selObj.options[i].selected && i != 0) {
{related_entries id="s_size"}
if (selObj.options[i].value == '{size_price}') { formObj.elements['os0'].value = '{title}'; }
{/related_entries}
}
}
//-->
</script>
<input type="hidden" name="on0" value="Size">
<input type="hidden" name="os0">
<select name="amount" onchange="setSize(this, this.form)">
<option value="">Please choose</option>
{related_entries id="s_size"}
<option value="{size_price}">{title} ${size_price}</option>
{/related_entries}
</select>
<input class="btn" type="submit" name="buy_now" id="buy_now_{entry_id}" value="Buy Now">
</form>
</li>
{/exp:simple_commerce:purchase}
{/exp:weblog:entries}
</ul>
So the store owner can now set up different options or variations for products without having to create duplicate store entries, and can now manage these options and their prices in one location; and the store will now give site visitors the ability to choose their preferred option and have the relevant information transferred correctly to PayPal.
With ExpressionEngine 2.0 not far from being released and with rumours that it’ll include a more robust ecommerce feature, there may not be the need to use this technique for too much longer, but in the meantime, hopefully it will help some others out who have been in the same situation as me.
























Thank you for a nice tutorial on how to do this. I’ve been giving this some thought but haven’t come up with a good solution yet. So, thanks for saving me some time!
-greg
A big thank you for writing this, I’m doing an ecommerce site soon and doing a bit of research here and there. Nice article!
You’re welcome guys; hopefully it might come in useful for some people.
Hey John, this is an awesome demonstration of how to extend the capabilities of EE to achieve the goals of the project.
A great tutorial!
Thank you.
This is a very helpful overview and tutorial. I would be very interested in seeing the actual site where this was done.
Thanks.
Very nice idea and implementation. I’ll be trying this out soon.
Very useful!
Have you added this to the EE Wiki?
@ Steven, it hadn’t actually occurred to me to do so, but I have now. (Took me a while to get used to Wiki syntax
)
Great instructional! Really helped a lot, but I only need the size not a price per size script/code, and I’m having trouble tweaking it. Do you have any thoughts on how to tweak it for just the size to appear in paypal? Everything else works perfect, I just can’t get the actual size to pull into paypal and not sure what I’m doing wrong. The site is not live so I can’t send a link to it. Any help you can send would be amazing. I’ve been trying to get this for a while and am exhausted trying to get it! It just keeps reading a blank size! Thanks!
John,
Awesome tutorial. Thanks so much for putting this together. Tremendous stuff!
I am having an issue getting the multi-relationships entries to appear. Did you have any trouble using Mark’s extension? I can give you more details on my setup if you are interested, along with the steps I’ve taken. Maybe I can e-mail you so I don’t crowd this comment section? If not, no problem.
Thanks,
Andres
@ Maxine: Make sure that when you copy the code from the post that you pay attention to the quote marks around attributes as some have come out as incorrect entities.
@Andres: I think I did have to implement the fix for the extension outlined in the thread on the EE forum.
re: Maxine comment
when taking out price, do you then use os0 as the value for size?
Excellent article. I keep holding out hope of an “Advanced Commerce” mod from EE, but this will be a big help in the meantime. Well done!
Do you think you could do a similar thing to this using Playa rather than the extension you have used.. im wondering if that will work as well? Im going to give it a go, but maybe it wont work… be interesting if it does.
Yeah, there’s no reason why it wouldn’t work with Playa as well; you just need something to create the relationships.
Thanks for that, do you think its also important to use the SCM or just skip that out.. again its one more thing that the client needs to add in to the CMS i guess..
It will depend on what sort of features are required for the site. If a record of purchases inside EE is required, then you’d use SCM. SCM also makes it easy to bulk edit prices.
As far as i can see as im testing this, the main problem is that when using Playa it is not adding all the options to 1 drop down, rather repeating itself with a drop down and button for each option..
see http://www.mcfarlane.etheya.com/shop/list/category/Portfolio%202008/
Bit hard to say without seeing your code but it looks like you’ve got more than just the code to output an option inside your loop.
This is exactly what I’m looking for working on scm rigth now and I’m trying to figure this out with playa.
need to have 4 different sizes and 2 color varitations.
I have managed to use this great tutorial to create a Merchandise section for the 24HR GYM site (http://www.24hrgym.co.uk).
Some people have been asking how to change the code so that the dropdown menus just have product size or colour options, without including a price element.
I have managed to make products display Size and/or Colour option menus, so that buyers can choose what they want.
The next challenge is to change the Buy Now buttons to Add To Cart buttons, which will mean people can more that one item at the same time. I have I have a solution in mind for this.
Does anyone want to see the code?
Am I able to post the code here?
Oliver Cannell (IC360)
Hi Oliver, that sounds interesting. You’d probably be better posting a thread on the ExpressionEngine forums and include a link back to this article as a reference point as the comments section here isn’t really set up for posting too much code.
I’m getting an error from PayPal when clicking on the Buy Now button, and I can’t for the life of me figure out where I’m going wrong. Here’s the error I’m receiving:
“The link you have used to enter the PayPal system contains an incorrectly formatted item amount.”
I have all of my prices formatted with a period rather than a comma, which I mention because a Google search on that error yields results of people saying that you need to have the separator set as a period.
Can anyone give me some help on this?
Hi James, it’s pretty hard to say without seeing your site or any code.
Got it sorted. Thanks for this tutorial, John!
Glad you worked it out.