In this post, I am going to briefly walk through the process of creating a very simple and basic ecommerce setup using MODx Evolution and PayPal. There are several MODx shopping carts that are at different stages of development and that have different features, however I haven’t extensively tested or used any of them, but I hope to eventually do some writeups on them if I get the opportunity to play with them. I would recommend that you definitely explore them too, as well as other third party services that integrate with MODx, such as Ecwid and Foxycart. For this tutorial we’re going to do something very simple, basic, and direct with PayPal being the only payment gateway offered. This tutorial is by no means exhaustive or comprehensive, but it should give a good starting point for thinking about how to integrate PayPal with your MODx website for simple sales.
The steps we will go through are:
1. Set up the template variables for the products
2. Set up the templates for the product pages
3. Add code to create Add to Cart buttons on the fly
I am working with the latest version of MODx Evolution – 1.0.4. You can extend the ideas here to Revolution but remember that the tag syntax for Revo is different than that for Evo.
In the interest of saving time and avoiding redundancy, I will not describe in detail the more general MODx things, such as installing MODx, setting up a template, how to create template variables, etc. If you need help with these or any other basic MODx topics be sure to visit the beginner tutorials section.
That said, let’s get started!
The Template Variables
The first step is to set up the template variables that we will use for our products. Our fictional store is going to sell simple products that have just a name, image, description, and price. And of course each product will need an Add to Cart button.
So I start by creating these four TVs: product_name, product_price, product_image, product_desc, and product_addToCart.
Remember to assign these to the template that is to be used for the individual product entries.
The Product page template
Now that we have our TVs, we can go ahead and set up the TV tags in the template that will display our individual products. In my case, I create a chunk and call it singleProductTpl and place this code in it:
<strong>[*product_name*]</strong> <p>[*product_image*]<p> <p>[*product_desc*]</p> <p><strong>Price: $ [*product_price*]</strong></p> <center><p>[*product_addtocart*]</p></center>
I then call this chunk into my single product page template. So now when I go to create a new product, using this template, I have these five fields to fill out. I choose to use these fields only and use the ManagerManager plugin to hide the other default fields (click on the image for a clearer view).
So now I am able to create products and display them, but I don’t have the code for the add to cart button yet.
Create Add to Cart buttons on the fly
There are two ways to add buttons to your online store – one is to go to the PayPal site and generate a button each and every time I want to add a new product, and the second is to create the buttons programmatically each time a new product is added. This second option is much easier and less taxing than the first, so we will use that.
The instructions for creating buttons programmatically are actually right in the PayPal documentation and what I’ve done is simply copied the sample code there and then modified it to suit my needs by adding the TV tags in the relevant places. The resulting code looks like this:
<form target="paypal" action="https://www.paypal.com/cgi-bin/webscr" method="post"> <!-- Identify your business so that you can collect the payments. --> <input type="hidden" name="business" value="your_paypal@email_here"> <!-- Specify a PayPal Shopping Cart Add to Cart button. --> <input type="hidden" name="cmd" value="_cart"> <input type="hidden" name="add" value="1"> <!-- Specify details about the item that buyers will purchase. --> <input type="hidden" name="item_name" value="[*product_name*]"> <input type="hidden" name="amount" value="[*product_price*]"> <input type="hidden" name="currency_code" value="USD"> <!-- Continue shopping on the main shop page --> <input type="hidden" name="shopping_url" value="[(site_url)][~2~]"> <!-- Display the payment button. --> <input type="image" name="submit" border="0" src="https://www.paypal.com/en_US/i/btn/btn_cart_LG.gif" alt="PayPal - The safer, easier way to pay online"> <img alt="" border="0" width="1" height="1" src="https://www.paypal.com/en_US/i/scr/pixel.gif" > </form>
Basically what this code does is generate the Add to Cart button and insert the specific values for the product from the TVs, allowing you to generate the buttons on the fly.
Save this code in a chunk, I call mine paypal_addtoCart. You can then bind this as the default value to the AddtoCart TV. So if we go back to our template variables, open the product_addtoCart TV for editing, and in the default value put in:
@CHUNK paypal_addtocart
You can also do what I’ve done and add something like “Don’t Modify this” in the description value so that if someone else is adding products they will know to not edit this field.
NOTE: As Greg just reminded me in the comments, I could also just hide this Add To Cart field using ManagerManager like I did with the others. Thanks Greg!! 🙂
If you now go to create a resource using the single product template, you will notice the Add to Cart field is prepopulated with instruction to not modify it.
So if we now create a new product and add the relevant values, the final product display will show the Add to Cart button from PayPal.
One strategy I use is to create an empty container (unpublished) that uses the shop template and then create my product pages within that container. That way the child pages will all use the same template without me having to select it each time
You can now use Ditto to aggregate your products on a single shop page or several category pages, and add tagging and such for more views. From this point there are many other things you can do to set things up like you want, and if time permits I will write some follow ups to this tutorial to explore further ways you could refine your store.
Some notes:
– If you want to play with this using the PayPal developer sandbox, which is how I recommend you do it, then for the form action simply replace https://www.paypal.com/cgi-bin/webscr with https://www.sandbox.paypal.com/cgi-bin/webscr and replace your actual paypal email address with a business address that you have generated in the sandbox.
– The input type=”hidden” name=”shopping_url” value=”[(site_url)][~2~]” line sets what url the customer should be returned to if they choose to Continue Shopping. In my case 2 is my main shop page ID.
– The other fields and values are pretty self explanatory, and you can add more and create more complex options by adding more inputs and HTML variables in the PayPal button code. You can find more documentation with sample code and examples for more complex options and such at the PayPal website. For Buy Now and Add to Cart buttons and the sample code I used here, take a look at this link (shortened) – http://bit.ly/aSTffs
One thing I should mention is that because these buttons are not encrypted, they’re not completely secure, therefore you will need to secure your buttons or else validate each transaction to make sure the price paid matches the product price and that there are no fraudulent transactions. There are several options and you can read more about them at https://cms.paypal.com/us/cgi-bin/?&cmd=_render-content&content_ID=developer/e_howto_html_encryptedwebpayments
As I mentioned if time permits I may do some follow ups on refining the store, adding more product options and fields, making a more sophisticated cart, creating a module to simplify the process of adding products, using the PayPal IPN, etc. But I hope that this tutorial has given you some idea of how to get started with exploiting the flexibility of MODx and creating a simple store using MODx Template Variables and the PayPal HTML variables.
More Reading:
1. Paypal Documentation on integrating using HTML – https://cms.paypal.com/us/cgi-bin/?&cmd=_render-content&content_ID=developer/howto_html_landing
2. MODx Template Variables – http://svn.modxcms.com/docs/display/Evo1/Template+Variables
Great post. This will be really useful. It occurred to me that you could probably use ManagerManager to hide the product_addtoCart TV to remove the possibility of having it altered by you site user.
Greg,
Yes!! Not sure why that escaped my mind, I think it’s because I set all the ManagerManager stuff before I did the code for the Add To Cart field… lol. But yes, that would definitely be the way to do it to ensure that that field doesn’t get messed with!
thanks
mary
Nice job Mary! MODx is such a great tool + PayPal. No question about it for those “quick” shopping carts solutions. How’s your experience with FoxyCart? I’m not partial to hosted solutions, any insight?
Thanks Sal, I’ve worked a bit with FoxyCart and think it’s a good solution. But like you I’m not too crazy about hosted carts and solutions. While I understand and appreciate the merits of outsourcing that part of the transaction, there’s always the question of reliability in the long run, potential down times, etc. Plus some clients don’t really like to pay the monthly fee plus their merchant fees, which is what I ran into with this client. I also like Ecwid, and the fact that it does have a free package is really nice. However, having to manage products on a different interface is not always optimal. So it’s trade off, and I really would go by the client’s preference, budget, tech-savvyness, and flexibility.
What I haven’t really had the time to delve into it is the various MODx carts like gcart, shopkeeper, and treasurechest, but my interest has been stirred. For the simple ecommerce site I’m building this seems like a much simpler solution since the client is sure that PayPal is all she wants to use and it fits her budget perfectly 🙂
mary
Nice! This is just what I needed. I’m starting the design process for a non-profit website, and they just need something simple like this. Good timing…
Thanks!
Thanks for the post, Mary. Suggestion — why not use the InheritPageTemplate plug-in for your product page? By setting the TV value to the product page template on the parent page, you achieve the same thing as keeping an empty container. This approach might be simpler for the client. At any rate, I’m using this method on a site currently in development that has a nested directory with two separate child page templates in use — works very well.
Oh, i didn’t heart of this system before. But it sounds, that ModX in combination with PayPal could be an low-cost-purchase for companies without big budget. Nice!!
Thanks for posting the paypal source code! 🙂
Hi,
For what it’s worth, I used the code found here
https://www.x.com/thread/30664
to set up an IPN listener for Paypal on an Evo install. By setting the notify URL in the Paypal store to the location of the listener and passing a product ID, I was able to validate the order coming from Paypal and then send out an email to the buyer of a digital download. That leg of work was based on material found here :
http://www.ngcoders.com/php/selling-digital-goods-with-paypal-ipn-and-php
The email contained a link with an encrypted parameter, which also did some database, time interval, etc. checking, after which it served up the file from an inaccessible location. This created a viable alternative to iTunes for a small-volume musician.
What would be helpful at this point would be to alter the code to deal with a shopping cart and handle Paypal’s “cart” mode. (The above work uses Paypal’s online cart or buy-it-now modes).
Also, the code could be better integrated with MODx, since as written it is meant to be standalone.
Hope this is helpful.
Matt,
Thank you for this, it’s definitely helpful. My approach was a simple one based on the online cart and buy-it-now modes. I haven’t really dug enough into PayPal’s API to create a standalone MODx cart but that would be an interesting task. I have, for a simple project I was working on, created a simple IPN listener to capture the data from the transaction and then I would manually compare that with what PayPal sends me before authorizing the product to be shipped out. Would be interesting to see what your listener looks like if you don’t mind sharing it? You can shoot me an email through the contact form.
Have you attempted the integration? Any success?
thanks for the input
mary
Thanks for posting, Mary. This is indeed a great solution to avoid monthly costs for clients. I used this method for a client for my first “real” MODx site. I wanted to also mention that the View Cart/Checkout code is static as well and can be included in a global area or (as I’ve done on a page like-a-so: http://sunnydaymn.com/shop/led-lighting/10-watt-par-38-4-way-dimmable-bulb.html). Here’s what it looks like. Hopefully this is helpful to people utilizing this great post for their current project.
Goes without saying but, Mary, your blog rules and super helpful to the MODx community. Thank you and kudos.
Thanks Brian! Appreciate the feedback and the tip on the View Cart code!!
cheers
mary
Nice tutorial.
I think I did everything but I am not getting any button?
I created a sandbox account. I get all the filled out TV’s on my page but no Buy it Now button? ANy ideas? Thanks…
Max
Did you get the code for creating the button from the PayPal website or from the tutorial and add it to the relevant TV?
mary
Hi,
I am having the same problem. I used the code from the tutorial and changed the email to the email linked to my Paypal account. Any ideas?
Thanks
Bren,
What are you getting when you paste the code in? Also, are you working locally on WAMP/XAMPP, etc or on a hosted server?
mary
I am using modx 1.0.2 and its on a hosted server. Everything seems to be the same in TV and chunks; though no image/link to paypal?
What do you see when you view source for your page? Do you have a link I can look at? If you don’t want to post it here just DM me on Twitter and I’ll take a look at it.
mary
Bren
OK, I think this is solved now. What happened is that you had a mismatch in your TV names. You named your TV with a capital C but in the template you called it with a small c. Easy mistake to make but one that can have you scratching your head for hours 🙂
mary
Mary, I got it from the tutorial but added a real email link. I am working locally using MAMP.
This is my first dip into the e-commerce pool. I am doing this site for an old friend who is selling a line of supplements. He has an awful looking site now. My plan is building a new MODx site so he can create blog posts AND sell his product from one site. Right now I have three test systems running on the development site: the Paypal system, Ecwid and FoxyCart. So far I am really digging the FoxyCart option. I think its worth the $19 a month. But this decision is up the to client.
To be honest I stopped playing with the Paypal option and began testing Ecwid and Foxycart. I would like to figure out the Paypal thing though. Its sort of confusing mixing my real account login with the Paypal sandbox account. From a user standpoint I much prefer the Foxycart procedure than the Paypal system. But Paypal is a cheaper option.
Mary, do you have any plans for a Part II for this tutorial?
One more question:
With this section of the code:
Are we supposed to change “business” to something more specific from our Paypal account?
Max,
Somehow I missed this comment 🙁 You may have solved this by now but it looks like something in your comment got cut off
mary
Sorry, but its been a while since I was playing with this. I am in the middle of working on two e-commerce sites right now. One will be with Foxycart and the other with a private community hosted solution. I am using Ditto and a whole series of custom TV’s to present titles, paragraphs, images and Buy it Now links etc. So far so good.
Max
Cool, sorry again. I just never saw your comment for some reason. Foxycart is pretty cool if the client is willing to pay the monthly fee. Good luck with the projects!! 🙂
mary
Is it possible to add quantity field here? If yes, how?
use shopkeeper, modular as modx is :). in evolution is the best,.. quite fun to get it running with paypal, but still possible 😉
This is great by the way, was just wondering if you know of a way to do this with stock levels?
Hi
Does any one know whow is it possible to get the pack downloadable products for TC mentioned here:http://forums.modx.com/thread/35962/snippet-downloadable-products-for-treasure-chest-dp4tc
Thanks
Not sure, all the links for treasurechest free downloads and docs seem to be broken or the domains expired. Your best bet may be to contact the folks at http://www.altipoint.ch/index.php?id=237 which seems to be the official home of the commercial arm of treasurechest.
mary
Thanks,
the original developer’s website contact form and the page’s at altpoint contact form seem die on send request ))
Mary, I wonder if you can advise me on a slightly different PayPal integration than what you’ve described in this post. I’m still figuring out how to implement my approach, which uses a multi-option cart form (and the mini-cart). You can see this in action currently here.
My challenge is that print dimensions and options vary by photograph. What I’d like to do is establish a way to create “price sets” that define a set of dimensions and options. Then, for example, if 50 of my 100 photos have the same dimensions/options, I could simply associate the appropriate price set when creating an ‘image page’ (the template used by the example provided above) rather than repeating this laborious process for every image I upload.
I can do this easily enough for myself using a chunk, but an added hitch is that I want to make this end-user friendly, meaning that a photographer with no knowledge of ModX/HTML etc. makes this association between an image and price set on the ‘image page’ rather than building out chunks. Hope this makes sense!
I should also add that although I’ve built this site from scratch using ModX, I’m not a programmer. I know a little HTML/CSS, but do not have the ability to create custom PHP (which would probably solve my challenge easily).
Any ideas (and thanks in advance for any thoughts you provide)?
Thanks,
Wesley