RSS

Archive for tag: piwik

Piwik: Updated MultiSitesPlugin

by Karl Kopp on Thursday, 30 April 2009

UPDATE - I fixed a bug in the code. My copy and paste skills let me down :)

We use the MultiSitesPluging for Piwik to get a view of all the traffic across a collection of sites. It allows us to see all the basic stats for multiple websites on one page. A few weeks ago, I made a few updates to the plugin to aggregate the data for the all the sites, and since someone else asked about it, thought I would document what I did :)

First was a few updates to MultiSitesPlugin/Controller.php

$total_visits = 0;
$total_actions = 0;
$total_unique = 0;

if(count($my_sites) == 1 )
{
    $my_sites[0]['visits'] = $visits_piwik;
    $my_sites[0]['actions'] = $actions_piwik;
    $my_sites[0]['unique'] = $unique_users;
    $my_sites[0]['sparkline'] = $sparklines_piwik_array[$my_sites[0]['idsite']];
    $my_sites[0]['summary'] = $summary['text'];
    $my_sites[0]['summary_value'] = $summary['value'];
    $total_visits = $visits_piwik;
    $total_actions = $actions_piwik;
    $total_unique = $unique_users;
}
else
{
    $visits_piwik_array = $visits_piwik->getArray();
    $actions_piwik_array = $actions_piwik->getArray();
    $unique_users_piwik_array = $unique_users->getArray();
    foreach($my_sites as &$site)
    {
        $site['visits'] = $visits_piwik_array[$site['idsite']]->getColumn(0);
        $site['actions'] = $actions_piwik_array[$site['idsite']]->getColumn(0);
        $site['unique'] = $unique_users_piwik_array[$site['idsite']]->getColumn(0);
        $site['sparkline'] = $sparklines_piwik_array[$site['idsite']];
        $site['summary'] = $summary[$site['idsite']]['text'];
        $site['summary_value'] = $summary[$site['idsite']]['value'];
        $total_visits = $total_visits + $visits_piwik_array[$site['idsite']]->getColumn(0);
        $total_actions = $total_actions + $actions_piwik_array[$site['idsite']]->getColumn(0);
        $total_unique = $total_unique + $unique_users_piwik_array[$site['idsite']]->getColumn(0);
    }
    usort($my_sites, array("Piwik_MultiSitesPlugin_Controller", "sort_by_".$this->order));
}
$this->count = count($my_sites);

as well as the addition of a few lines here:

$view->page = $this->page;
$view->limit = $this->limit;
$view->count = $this->count;
$view->order_by = $this->order_by;
$view->order = $this->order;
$view->page = $this->page;
$view->total_visits = $total_visits;
$view->total_actions = $total_actions;
$view->total_unique = $total_unique;
$view->total_site_count = count($my_sites);
echo $view->render();

I then created a new template file in the templates directory called total.tpl:

<tr align="center"  style="border-right: 1px solid black;">
<td align="center" class="column">
</td>
<td align="left" class="column" id="siteName">
<b>TOTAL ({$total_site_count})</b>
</td>
<td align="right" class="column" id="visits">
    {$total_visits}&nbsp;</td>
</td>
<td align="right" class="column" id="actions">
    {$total_actions}&nbsp;</td>
</td>
<td align="right" class="column" id="unique">
    {$total_unique}&nbsp;</td>
</td>
<td align="center" class="column" id="sparkline"> </td>
<td class="column"></td>
</tr>

Lastly, I modified the templates/index.tpl file and added the following line (in bold)

foreach from=$my_sites key=i item=site}
{include file='MultiSitesPlugin/templates/row.tpl'}
{/foreach}
{include file='MultiSitesPlugin/templates/total.tpl'}
<tr>

I hope that helps those that are interested :)

Tagged: | Leave comment

Piwik: simplified automatic deployment

by Karl Kopp on Thursday, 30 April 2009

I'm using the excellent Piwik analytics tool on a number of sites hosted on a central CMS platform. The problem I found was that the JavaScript snippet required to track each user has a unique ID in it that identifies the the site. This was going to be a pain, so I modified the code to allow the each visit to use the site ID if it was present, or alternatively, work out the site ID from the URL. 

The code below is replacing the function __construct() in the file piwik/core/Tracker/Visit.php:

function __construct()
{

        $idsite = Piwik_Common::getRequestVar('idsite', 0, 'int', $this->request);

        // No idsite passed in, so try and get from URL
        if($idsite <= 0)
        {
                $host = '';
                // get host name from URL
                $url = Piwik_Common::getRequestVar('url');
                preg_match('@^(?:http://)?([^/]+)@i', $url, $urlmatches);
                $host = "http://" . str_ireplace('www.', '', $urlmatches[1]);
                if ($host != '')
                {      
                        // If no site ID, lets look up URL...
                        $idsiteRow = Piwik_Tracker::getDatabase()->fetch("
                                                SELECT idsite
                                                FROM piwik_site 
                                                WHERE main_url = ?
                                                LIMIT 1",
                                                array($host)
                        );
                        if ($idsiteRow && count($idsiteRow) > 0)
                        {      
                                $idsite = $idsiteRow['idsite'];
                        }
                }
        }

        if($idsite <= 0)
        {      
                throw new Exception("The 'idsite' is invalid");
        }
        $this->idsite = $idsite;

}

Doing some basic performance testing, the code above only adds on extra DB call which in my circumstances is acceptable. But, if you really wanted, you could add some caching as well to improve speed.

Tagged: | Leave comment

Piwik – open source analytics

by Karl Kopp on Thursday, 9 April 2009

I have been working with some PHP sites lately, and considering I'm a .NET kind of guy, have actually (surprisingly?) enjoyed the experience :)

One of the cool new platforms I found was Piwik, the open source analytics platform that is designed to be a competitor to Google Analytics (GA). Now, I am a fan of GA, but in this case, we needed to own the stats data, and do a lot of custom analysis and modelling on the data, so I had to choose something where we could host it, and that's where Piwik came in.

It was really easy to install and I got it up and running in no time. The plug-in framework is awesome; extremely powerful and flexible. Its easy to build and deploy your own plug-ins, and the API to access the data is clean, and so far, very fast.

To deploy on each site, it is as simple as GA - just add a JavaScript tracking code. But I have a case where the client couldn't use assets from 3rd party sites. The JavaScript tracking code effectively generates an IMG (image) tag in HTML, and their legal people wouldn't allow it.

So I created the proxy class below to allow the browser request to be sent to a file hosted on the clients site, and in turn, this proxy will hand off the request and all important information back to the stats server we are running. Not sure if anyone else will need it, but thought I would share anyway :)

<?php

// DEBUGGING - comment out when live
// error_reporting(E_ALL);
// ini_set('display_errors','1');

// Our vars
$url = 'http://statsserver.com/piwik/piwik.php?';
$referer = "";
$ua = "";
$lang = "";
$cookie = "";
$ip = "0.0.0.0";

// Build up URI from query string - need encode the value
foreach($_GET as $key => $value)
{
    $url .= $key . "=" . urlencode($value) . "&";
}

// Now set some headers
if (isset($_SERVER['HTTP_REFERER']))
    $referer = $_SERVER['HTTP_REFERER'];

if (isset($_SERVER['HTTP_USER_AGENT']))
    $ua = $_SERVER['HTTP_USER_AGENT'];

if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
    $lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'];

if (isset($_SERVER['REMOTE_ADDR']))
    $ip = $_SERVER['REMOTE_ADDR'];

$opts = array(
    'http'=>array(
        'method'=>"GET",
        'header'=>"Accept-Language: " . $lang . "\r\n" .
                  "User-Agent: " . $ua . "\r\n" .
                  "Referer: " . $referer . "\r\n" .
                  "X_Forwarded_For: " . $ip . "\r\n"
    )
);

$headers = stream_context_create($opts);
// Send the request
$contents = file_get_contents($url, FILE_BINARY, $headers);
// Find the cookie from the response and pass back to the client
$nlines = count($http_response_header);
for ($i = $nlines-1; $i >= 0; $i--)
{    
    $line = $http_response_header[$i];
    if (substr_compare($line, 'Set-Cookie', 0, 10, true) == 0)
    {
        $cookie = $line;
        break;
    }
}
header('Set-Cookie: ' . $cookie);
header('Content-Type: image/gif');
header('Pragma: no-cache');
header('Cache-Control: private, no-cache, proxy-revalidate');

echo $contents;

?>

Tagged: | 1 comment

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact me so we can take care of it!

Visit my friends!

A few highly recommended friends...

About

Some semi-interesting ramblings from a technology geek (me, Karl Kopp) about some future adventures...