Recently I have been working on a Magento extension for a 3rd party customer analytics and targeting web service, think Google Analytics alternative. One of the eCommerce tracking features that needed to be implemented was the “add product to cart” action. Since these kind of tracking services use JavaScript to trigger their tracking code, it’s up to us to see where and when will be embed certain tracking JavaScript in Magento. What’s interesting about “add product to cart” action is that it’s not your usual web page on which you land and are then in possibility to execute certain JavaScript.
In Magento, when you click any “Add to Cart” page, you usually end up on a URL like http://magentoce1800.loc/index.php/checkout/cart/add/uenc/aHR0…0bWw,/product/16/form_key/oTSbNJ4ZIUC46W0R/. Where checkout/cart/add part is the interesting one, as it points to Mage_Checkout module, its CartController and then addAction() within the CartController class. Second interesting part is the product/16 part of the URL which actually tells Magento that product with id 16 is being added to cart. Additionally, there is a lot more going on within the addAction() action method itself. What is important to know is that once the Magento code within the addAction() method adds the product to cart, it redirect you to the cart page itself. Meaning that the actual checkout/cart/add page is never rendered to the browser, so you cannot execute any JavaScript within it.
So, where am I going with all of this? Well, one of the cooler features of Magento is definetly its Event/Observer system. If you think about it, each controller action supports generic controller_action_predispatch event defined within the app/code/core/Mage/Core/Controller/Varien/Action.php around line 527 as follows Mage::dispatchEvent(‘controller_action_predispatch’, array(‘controller_action’ => $this));. Then there are more specific one event that matches its module forntend name, controller and action, which in this case, resolves to frontend event controller_action_predispatch_checkout_cart_add.
With this in mind, here is a simple idea for tracking “add product to cart” actions via JavaScript:
1. define an event observer method for controller_action_predispatch_checkout_cart_add event
2. within the event observer method, make a “record” of the product that was just added to the cart, for example something like Mage::getModel(‘core/session’)->setProductToShoppingCart(…) will do.
3. make a layout update for checkout_cart_index handle, that loads a custom .phtml template file, you can use core/template or your own block class for block type definition
4. within the custom .phtml template file generate your “add product to cart” tracking point by using the Mage::getModel(‘core/session’)->getProductToShoppingCart() to fetch the info for the product just added to cart, then when you are done, simply unset the session by doing something like Mage::getModel(‘core/session’)->unsProductToShoppingCart()
Below is a code example for just described workflow.
As described in step #1 above: app/code/community/Inchoo/Test/etc/config.xml
<?xml version="1.0"?>
<config>
<modules>
<Inchoo_Test>
<version>1.0.0.0</version>
</Inchoo_Test>
</modules>
<global>
<models>
<inchoo_test>
<class>Inchoo_Test_Model</class>
</inchoo_test>
</models>
</global>
<frontend>
<layout>
<updates>
<inchoo_test>
<file>inchoo_test.xml</file>
</inchoo_test>
</updates>
</layout>
<events>
<controller_action_predispatch_checkout_cart_add>
<observers>
<inchoo_test_log_cart_add>
<class>inchoo_test/observer</class>
<method>logCartAdd</method>
</inchoo_test_log_cart_add>
</observers>
</controller_action_predispatch_checkout_cart_add>
</events>
</frontend>
</config>
As described in step #2 above: app/code/community/Inchoo/Test/Model/Observer.php
<?php
class Inchoo_Test_Model_Observer
{
public function logCartAdd() {
$product = Mage::getModel('catalog/product')
->load(Mage::app()->getRequest()->getParam('product', 0));
if (!$product->getId()) {
return;
}
$categories = $product->getCategoryIds();
Mage::getModel('core/session')->setProductToShoppingCart(
new Varien_Object(array(
'id' => $product->getId(),
'qty' => Mage::app()->getRequest()->getParam('qty', 1),
'name' => $product->getName(),
'price' => $product->getPrice(),
'category_name' => Mage::getModel('catalog/category')->load($categories[0])->getName(),
))
);
}
}
Obviously the code above is very basic. It does not cover various Magento product type combinations as it pulls the price directly from product model. So in cases where you have configurable, bundle or grouped products you would need a little extra to get to it. You could however start from product id, then do a look-up on the quote items table in order to find child products, etc.
As described in step #3 above: app/design/frontend/default/default/layout/inchoo_test.xml
<?xml version="1.0"?>
<layout version="0.1.0">
<checkout_cart_index>
<reference name="before_body_end">
<block type="inchoo_test/event_checkout_cart_index" name="inchoo_test_event_checkout_cart_index" template="inchoo/test/event/checkout/cart/index.phtml" />
</reference>
</checkout_cart_index>
</layout>
As described in step #4 above: app/design/frontend/default/default/ template/inchoo/test/event/checkout/cart/index.phtml
<?php $_product = Mage::getModel('core/session')->getProductToShoppingCart() ?>
<?php if ($_product && $_product->getId()): ?>
<script type="text/javascript">
//Some 3rd party JS tracking code
</script>
<?php Mage::getModel('core/session')->unsProductToShoppingCart(); ?>
<?php endif; ?>
That’s about it, one simple way to track “add product to cart” action for your analytics service.
The good thing about it is that you do not have to edit any existing .phtml template files adding JS onclick events or something like that.
Hope this helps someone.