Piwik Plugin
A drop-in plugin to add a Piwik tracker to your presentation layer. To use this plugin, you'll
need to have a Piwik server installed and running.
Installation
Install the plugin
$ symfony plugin:install sfPiwikPlugin
Enable sfPiwikPlugin (if not automatically enabled) @ config/ProjectConfiguration.class.php
public function setup()
{
$this->enablePlugins( array('sfPiwikPlugin'));
}
Add the sfPiwikFilter to your filter chain in appconfig filters.yml
[...]
# insert your own filters here
sf_piwik_plugin:
class: sfPiwikFilter
[...]
Configure your appconfig app.yml
all:
sf_piwik_plugin:
enabled: on
tracker_url: example.com/piwik/
site_id: 1
tracker_url is where the Piwik server is located. Do not inlcude the protocol prefix (http://), nor the script suffix (piwik.php).
site_id is the ID of your site in the Piwik installation
Advanced Configuration
Module/Action-level Configuration
There are various Piwik attributes that can be set at the module or action level by configuring the module.yml file.
all:
sf_piwik_plugin:
params:
# any of the optional params in app.yml can go here
# this configures the entire module
action_name:
sf_piwik_plugin:
params:
# any of the optional params in app.yml can go here
# this configures a specific action within a module
Configurable Parameters
All the supported parameters are listed at the config/app.yml file (located in the plugin directory) for reference.
The parameters are categorised into those defined by the sfPiwikTracker and those defined by the Piwik javascript object. For the latter, the sfPiwikTracker methods act as proxy setters.
Read the Javascript docs on the Piwik website for further details on these parameters.
Dynamically configuring the Tracker
The sfPiwikTracker can by dynamically configured via it's getter methods. Dynamic configuration has priority over static configuration. The correct places where dynamic configuration can take place, are :
1) In Actions (see next section "Accessing the Tracker")
2) In piwik_filter.configure event handler (see next section "Tracker Events")
The list of methods that are available for the dynamic configuring can be seen at the sfPiwikTracker class definition. Please note that most of them have a configuration param equivalent.
Here is the list of configuration methods that are only configured dynamically:
trackGoal( $id, $revenue = null)
trackLink( $url, $linkType = 'link')
setCustomVariable( $index, $name, $value, $scope = 'visit')
deleteCustomVariable( $index, $scope, $skip_js = false )
getVisitorId()
Please refer to the piwik documentation for explanations.
Accessing the Tracker from Actions
At some point, you might want to be able to access the tracker instance from your action code to perform dynamic configuration. Here's how you'd do that:
class myActions extends sfActions
{
public function executeIndex($request)
{
// get the tracker instance from the context
$tracker = $this->getContext()->get(sfPiwikTracker::NS);
// you can get or set any of the optional parameters
$tracker->setDocumentTitle("My Title");
}
}
Tracker Events
Tracker fires two events.
piwik_filter.configure event is fired just before any tracker handling is done. This is the prefered way to dynamically configure the sfPiwikTracker object. In addition the event object provides the $event['context'] variable, with the active sfContext object, giving access to utility functions for the tracker configuration.
piwik_filter.inserting event is fired just before the tracker writes the Javascript to the response body. This is kept for backward compatibility with previous versions of the sfPiwikPlugin and it's usage should be avoided for configuration purposes. This is the last chance to modify tracker parameters. Note that, some configuration variables (force, enabled, skip) could not be dynamically configured with this event.
Read the Events section from the Symfony guide to understand how events work, and how to setup an event handler.
Case study:: Defining custom variables
Piwik supports custom variables, bits of information to help the segmentation of visits, based on custom criteria like: language (for multilang sites), isAuthenticated (whether the visitor is authenticated or a guest) and many more.
Two basic types of custom variables exits, visit, for those targeting the hole visit and page, for those targeting specific pages. See Piwik documentions on custom variables for more information.
One caveat in the usage of custom variables is, that each of them should be assigned a distinct index. That index is to be used only for that naned variable. E.g. "language" cvar should be always stored to slot 2. Thus, it is very convinient to keep all cvars definitions in a centralized place. While this is straightforward for visit scope cvars, things are less obvious for the page scope cvars.
The following bits of code use the dynamic configuration capability of sfPiwikTracker to define custom variables for the visit as well as for the page scope. To assist in the page scope cvars management, an array of all the supported page cvars is defined, where each page scope cvar is assigned an internal indentifier. To set a page scope cvar from an action, a new dynamic property (sfAction->trackerCustomVarsPage) is defined.
Lets support the following cvars
scope visit: 1. Language (culture of the visit), 2: isAuth (is authenticated ?)
scope page: 1. Category (the article category)
First we define the event handler in app/config/frontendApplicationConfiguration.class.php (assuming that you are working on the forntendApplication). Then we implement the logic in the listenToPiwikFilterConfigure event listener :
class frontendConfiguration extends sfApplicationConfiguration
{
public function configure()
{
// dynamic configure piwik tracker
$this->dispatcher->connect( 'piwik_filter.configure', array($this, 'listenToPiwikFilterConfigure')) ;
}
public function listenToPiwikFilterConfigure( sfEvent $event )
{
$tracker = $event->getSubject();
$context = $event['context'];
$user = $context->getUser();
// add custom variables for visit, 1: Language, 3: Username
$tracker->setCustomVariable(1, "Language", $user->getCulture()) ;
$tracker->setCustomVariable(3, "IsAuth", ($user->isAuthenticated()? 'Yes': 'No')) ;
// Add custom variables for page
// supported page vars, define them in a cetralized place (here) and set the tracker_cvars_page array from actions
$cvarsPage = array(
'category' => array('index'=>1, 'name'=>'Category'),
);
$controller = $context->getController() ;
$actionEntry = $controller->getActionStack()->getLastEntry();
$actionInstance = $actionEntry->getActionInstance();
$cvars_action = (isset($actionInstance->trackerCustomVarsPage) ? $actionInstance->trackerCustomVarsPage : array() );
foreach ($cvars_action as $cvar_name => $cvar_value) {
if ( null !== ($cvar = @$cvarsPage[$cvar_name])) {
$tracker->setCustomVariable( $cvar['index'], $cvar['name'], $cvar_value, 'page' );
}
}
}
}
Note that the visit scope cvars are set using a general object (sfUser), that exists in every page.
To modify the page scope cvars, in particular to the "category" page scope cvar, we can write inside an action:
public function executeShow(sfWebRequest $request)
{
[...]
$this->trackerCustomVarsPage = array('category'=>$article->getCategory());
}
Unit testing sfPiwikTracker
sfPiwikTracker comes with a set of unit tests.
Requirements:
- symfony dir lives in lib/vendor
To enable testing at config/ProjectConfiguration.class.php
public function setupPlugins()
{
$this->pluginConfigurations['sfPiwikPlugin']->connectTests();
}
Then test like usual
$ symfony test:unit
or to only test the sfPiwikTracker:
$ symfony test:unit sfPiwikTracker