Logging user/customer actions in Magento

Recently I wrote a Magento extension called ActionLogger, inspired (thematically) by the “Logging of Administrator Actions” feature available in Magento Enterprise. ActionLogger is pretty simple extension, working on pretty simple but powerful concept of Magento controllers predispatch action.

All you need to do is to create event observer/observers for “controller_action_predispatch” event. This event is fired on every controller action call.

For example, if your store is located on url http://magento-1501.net url, and you go to url like http://magento-1501.net/electronics/cell-phones this will call action “view” from controller “category” from module “Mage_Catalog“. Simple logic/tracing would point this to be appcodecoreMageCatalogcontrollersCategoryController.php file and its viewAction().

Adding an event observer like the one shown below will trigger your code upon calling such url.

<frontend>
<events>
<controller_action_predispatch>
<observers>
<activecodeline_actionlogger_controller_action_predispatch>
<class>activecodeline_actionlogger/observer</class>
<method>hookToFrontendControllerActionPredispatch</method>
</activecodeline_actionlogger_controller_action_predispatch>
</observers>
</controller_action_predispatch>
</events>
</frontend>

Same goes for the admin section, for example if you open a link like http://magento-1501.net/index.php/admin/sales_order/index/key/9c13e78eecdc3d5805f6426be9f56254/. This one would call action “index” from controller “sales_order” from module “Mage_Adminhtml“. Simple logic/tracing would point this to be appcodecoreMageAdminhtmlcontrollersSalesOrderController.php file and its indexAction().

Adding an event observer like the one shown below will trigger your code upon calling such url.

<adminhtml>
<events>
<controller_action_predispatch>
<observers>
<activecodeline_actionlogger_controller_action_predispatch>
<class>activecodeline_actionlogger/observer</class>
<method>hookToAdminhtmlControllerActionPredispatch</method>
</activecodeline_actionlogger_controller_action_predispatch>
</observers>
</controller_action_predispatch>
</events>
</adminhtml>

All this is fine & etc., but what’s the point? We already know this, you might say.

The point is, the concept is very simple but enables you to add powerful logging mechanism on top of it. All you need to do is to add few lines of code that would record given action, controller, current user/customer, possibly entire parameters passed to controller, etc.

Then you can store it either in database or in some file.

For example, in ActionLogger extension I created a special models, called Admin and Frontend that handle writing logged values to database from observer.

public function hookToFrontendControllerActionPredispatch($observer = null)
{
if (!Mage::helper('activecodeline_actionlogger')->_canLogFrontendActions()) {
return;
}
 
$log = Mage::getModel('activecodeline_actionlogger/frontend');
 
$log->setActionName(Mage::app()->getRequest()->getActionName());
$log->setControllerName(Mage::app()->getRequest()->getControllerName());
 
if (Mage::helper('activecodeline_actionlogger')->_canLogRequestParams()) {
if($params = Mage::app()->getRequest()->getParams()) {
$log->setParams(Mage::helper('core')->encrypt(serialize($params)));
}
}
 
$log->setClientIp(Mage::app()->getRequest()->getClientIp());
$log->setControllerModule(Mage::app()->getRequest()->getControllerModule());
 
if ($customer = Mage::getSingleton('customer/session')->getCustomer()) {
$log->setCustomerId($customer->getId());
} else {
$log->setCustomerId(0);
}
 
try {
$log->save();
} catch (Exception $e) {
Mage::log('file: '.__FILE__.', line: '.__LINE__, 'msg: '.$e->getMessage());
}
}

On top of that you can create a nice grid in Magento for listing these. Combine this with built in Magento roles, and you can have your grid shown only to certain role.

Concept like this can be used for development/debugging purposes and possibly for some user/customer behaviour profiling. Although “profiling” can mostly be done via Google Analytics these days, there are still admin part of sites that are not suppose to get analyzed by Google.

Thinking further down the road, one can build truly dynamic user specific menus based on the logged data statistics, etc.

Hope I got you thinking.

P.S. Unlike my usual way of packing up the code into the zip archive, this time I decided to actually submit extension to Magento connect. This was done yesterday and is waiting to be approved :). Once approved, I’ll post a link to extension for those who are interested. Extension is now live at Magento Connect here.

Cheers.