Using Zen Cart as a cart only system

UPDATE – 12/26/2012 - This Post is WAAY outdated, please see my new post regarding this method.

I’ve seen this question has been asked many times before on the Zen-Cart forums with the same answer given each time: “it is not meant to be used like that, just make your whole site in Zen-Cart.”

Well, if you have ever used a CMS like Typolight, you know that by comparison, the “CMS” capabilities of Zen-Cart cannot compare by any stretch of the imagination. However as an e-commerce platform, Zen-Cart is fantastic. It’s light, stable, and easy to modify. It just doesn’t stand up to the challenges that a web developer faces for managing a large site. Some of the suggestions for pseudo integration involve sharing the header and footer HTML to try and get the Zen-Cart pages to look like your existing site. Doing it this way it has the appearance that it’s at least somewhat integrated. The problem is, it isn’t and you still need to design pages in Zen-Cart.

Well, I quickly found out that creating an “Add to Cart” button that can be added practically to any external page  made in any sort of CMS was very possible. In addition, it can be expanded even further using jQuery to create some amazing AJAX effects that rival what is seen in systems like Magento and Freeway.

On with the show…

For my site, I started by installing to a sub-directory (domain.com/cart/) and stripping Zen-Cart down to basic functionality by turning off all side boxes and links to categories, etc. Essentially, the only pages that will be served from Zen-Cart are the cart and checkout pages. By editing the tpl_shopping_cart_default.php file, you can get a good feel for the cart structure and layout. For the fancy stuff, you will need to make changes to this file later.

I also setup my products but leaving out any kind of description since all that is handled on my other CMS. Each product is given an ID. This is what we will use to create the add to cart form buttons.

On the external page you wish to place your button, just past the following code:

<form enctype="multipart/form-data" method="post" action="/cart/index.php?action=add_product">
    <input type="text" name="cart_quantity" value="1" />
    <input type="hidden" name="products_id" value="#" />
    <input type="submit" alt="Add to Cart" value="Add to Cart" title="Add to Cart" />
</form>

Just replace the value=“#” with the number of the product.

When you click the add to cart button, it will then take you to the cart page where the product will be shown in the cart. This form can also be further modified using a select list where you can have a dropdown to choose different products, hide the quantity box, etc. It follows the same styling rules as any kind of form so it can be styled however you wish.

For basic level “Add to cart” button functionality, that is it. You don’t need to do anything further.

Getting fancy…

Now you can then get even fancier by using an invisible iframe and doing your submit to it so that the add to cart is actually handled in the “background” eliminating the page jump.

Just add the following to your page footer:

<iframe id="cart_frame" src="/cart/index.php?main_page=shopping_cart"
        name="zenframe" width="0" height="0" style="visibility:hidden">
</iframe>

Then change your form to the following:

<form enctype="multipart/form-data" method="post" action="/cart/index.php?action=add_product" target="zenframe">
    <input type="hidden" name="cart_quantity" value="1" />
    <input type="hidden" name="products_id" value="#" />
    <input type="submit" alt="Add to Cart" value="Add to Cart" title="Add to Cart" />
</form>

When you click add to cart, it will silently submit it to the iframe. You will want to add a link somewhere to open the cart page to see the results. As a bonus of having the iframe load in your footer, the session stays active as your customer browses the site so you don’t lose the cart contents. You can also just add the iframe and use it to keep the session active if you don’t want to do a silent submit.

Now, beyond this, you can use jQuery to have messages appear such as “Item added to Cart” when you submit the form. This gives a nice ajaxy feel. This can be done by creating a trigger tied to the form submit.

$("form").submit(function () {
    // Your code to fade in a div and fade out
});

By using the load() function, you can create a fully functional modal box that appears after you click add to cart that shows the cart contents and allows you edit it right there. To accomplish this, you will want to create a hidden section on the Zen-Cart “Edit Cart” page that is customized for your modal pop-up.  I created a whole hidden cart section on the zencart side that the load() function pulls from.

Here is the code I added in my cart template. It is a modified duplicate of the default cart display code that strips out a number of things I didn’t need and adds some div ids so I could grab various sections using jQuery.

<!--START HIDDEN MAIN CART THIS IS USED FOR THE POPUP CART IN EXTERNAL SITES -->
<div id="maincartwrapperh" style="display: none;">
  <div id="cartInstructionsDisplay"><?php echo TEXT_INFORMATION; ?></div>
  <?php if (!empty($totalsDisplay)) { ?>
  <div><?php echo $totalsDisplay; ?></div>
  <?php } ?>
  <table  border="0" width="100%" cellspacing="0" cellpadding="0" id="cartContentsDisplay">
  <tr>
    <th scope="col" id="scProductsHeading"><?php echo TABLE_HEADING_PRODUCTS; ?></th>
    <th scope="col" id="scUnitHeading"><?php echo TABLE_HEADING_PRICE; ?></th>
    <th scope="col" id="scQuantityHeading"><?php echo TABLE_HEADING_QUANTITY; ?></th>
    <th scope="col" id="scTotalHeading"><?php echo TABLE_HEADING_TOTAL; ?></th>
    <th scope="col" id="scRemoveHeading">&amp;nbsp;</th>
  </tr>
  <!-- Loop through all products /-->
  <?php foreach ($productArray as $product) { ?>
  <tr>
    <td><span id="cartProdTitle"><?php echo $product['productsName'] . '<span>' . $product['flagStockCheck'] . '</span>'; ?></span></td>
    <td><?php echo $product['productsPriceEach']; ?></td>
    <td>
      <form id="securecart" enctype="multipart/form-data" method="post" action="/cart/index.php?action=update_product" target="hole">
        <div><?php echo $product['quantityField']?></div>
        <div><input type="image" title="Update Quantity" alt="Update Quantity" src="/buttons/english/button_update_cart.gif"/></div>
        <input type="hidden" value="<?php echo $product['id']; ?>" name="products_id[]"/>
      </form>
    </td>
    <td><?php echo $product['productsPrice']; ?></td>
    <td>
      <form id="securecart" enctype="multipart/form-data" method="post" action="/cart/index.php?action=update_product" target="hole">
        <input type="hidden" name="cart_quantity" value="0" />
        <input type="hidden" value="<?php echo $product['id']; ?>" name="products_id[]"/>
        <input type="image" title="Remove item from cart" alt="Remove item from cart" src="/cart/includes/templates/images/icons/small_delete.gif"/>
      </form>
    </td>
  </tr>
  <?php } // end foreach ($productArray as $product) ?>
  <!-- Finished loop through all products /-->
  </table>
  <div id="cartSubTotal"><?php echo SUB_TITLE_SUB_TOTAL; ?> <?php echo $cartShowTotal; ?></div>
  <!--bof shopping cart buttons-->
  <div><a target="_blank" href="<?php echo zen_href_link(FILENAME_CHECKOUT_SHIPPING, '', 'SSL')  ?>"><img src="/cart/includes/templates/buttons/english/button_checkout.gif" title="Checkout now" /></a></div>
  <!--eof shopping cart buttons-->
</div>
<!--END HIDDEN MAIN Cart Area-->

This gives us a custom area to pull data from that will be formatted on our external page. The display: none keeps it from showing up when going to that page directly.

Because our iframe loads the cart page, we can use it to load up sections and display them.

I have this code in my header. It automatically is triggered after the iframe has loaded.

$("#cart_frame").load(function () {
  var contents = $('#cart_frame').contents();
  var cartXitemsInCart = contents.find('div#cart').html();
  var cartTotalDollarAmt = contents.find('td.cartTotalDisplay').html();
  var cartFullCartDisplay = contents.find('div#shoppingCartDefault').html();
  var cartPopupDisplay = contents.find('div#maincartwrapperh').html();
  var cartEmptyMessage = contents.find('h2#cartEmptyText').html();
  $('#cartbox').html('<h3>Your Stuff ' + cartXitemsInCart + '</h3>');
  $('#cart_box_content').html(cartPopupDisplay);
  $('#cart_message').html(cartEmptyMessage);
});

#cart_frame is the ID of the invisible iframe and so by specifying it above, we are using it as our source for pulling HTML from the page and loading it into variables that I can then display wherever I choose. For example, by placing the var “cartPopupDisplay” into a div I can make it appear on submit to show the cart contents and allow the customer to edit the contents or simply close the box and continue shopping. Also provided is a link to checkout that will load the secure checkout screen in a new window.

I know this little tutorial isn’t the most complete and perhaps barely comprehensible, but hopefully contains enough information to help someone out. Zen Cart CAN be used as a cart-only system, it just takes a little work.