Piwik C# Tracking API

This is an extension of the unofficial C# implementation of the Piwik Tracking API. You find my code on GitHub.


Three Visual Studio Solutions are provided : 

How to contribute

The Piwik C# Tracking API is a translation of the official PHP Tracking API in C#.

Translating the project is currently a manual process.

Manually translating the project is tedious because it requires

  • identifying features that have already been translated
  • merging code

We would ideally like to automate this process, we welcome contributions aimed towards this goal.

To ease the process in the mean time, the following rules are applied to any new code contributions :

  • a commit in the PHP project implies a commit in the C# project with the same message and content
  • one-to-one tag mapping between the PHP and C# projects
  • the C# code should mirror as close as possible the PHP code

As long as we do not have an automated process, we welcome suggestions in improving the manual process.

Code style

To mirror as close as possible the PHP code, we copy-paste the PHP code in the C# class and alter it so it compiles.

This can lead in a loss of C# best practices. We consider the time savings an acceptable trade-off.

Publishing the project to NuGet


  1. The process detailed in this section must be executed right before adding a release tag to git.
  2. Publishing the project to NuGet must be done by a member of the Piwik team, holder of the private NuGet Key.

Track events for Google Analytics and Piwik

After my post of yesterday, I've worked for creating a script to integrate Google Analytics (new version with analytics.js) and Piwik (Piwik is the leading open-source analytics platform similar to Google Analytics. You can download it from its site or directly in your IIS with WebMatrix).

With this code you have only one function to call in every part of your page. Automatically the function detects download, email, phone number, external links and tracks them. You can insert in an anchor a code like:

<a href="http://www.puresourcecode.com/" 
   onclick="TrackEvent('Link to my site', 'PSC', 
            'Click from the user', 'Url or something else');">
   Visit PureSourceCode

You find the code for that here:

// Piwik
var _paq = _paq || [];
_paq.push(["setDocumentTitle", document.domain + "/" + document.title]);
_paq.push(["setCookieDomain", "*"]);
_paq.push(["setDomains", ["*"]]);
(function () {
    var u = "//a.esia.info/";
    _paq.push(['setTrackerUrl', u + 'piwik.php']);
    _paq.push(['setSiteId', 28]);
    var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
    g.type = 'text/javascript'; g.async = true; g.defer = true; g.src = u + 'piwik.js'; s.parentNode.insertBefore(g, s);

// Google analytics
(function (i, s, o, g, r, a, m) {
    i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
        (i[r].q = i[r].q || []).push(arguments)
    }, i[r].l = 1 * new Date(); a = s.createElement(o),
    m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m)
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');

ga('create', 'UA-XXXXXXXX-1', 'auto');
ga('send', 'pageview');

if (typeof jQuery != 'undefined') {
    jQuery(document).ready(function ($) {
        var filetypes = /\.(zip|exe|dmg|pdf|doc.*|xls.*|ppt.*|mp3|txt|rar|wma|mov|avi|wmv|flv|wav)$/i;
        var baseHref = '';
        if (jQuery('base').attr('href') != undefined) baseHref = jQuery('base').attr('href');

        jQuery('a').on('click', function (event) {
            var el = jQuery(this);
            var track = true;
            var href = (typeof (el.attr('href')) != 'undefined') ? el.attr('href') : "";
            var isThisDomain = href.match(document.domain.split('.').reverse()[1] + '.' + document.domain.split('.').reverse()[0]);
            if (!href.match(/^javascript:/i)) {
                var elEv = []; elEv.value = 0, elEv.non_i = false;
                if (href.match(/^mailto\:/i)) {
                    elEv.category = "email";
                    elEv.action = "click";
                    elEv.label = href.replace(/^mailto\:/i, '');
                    elEv.loc = href;
                else if (href.match(filetypes)) {
                    var extension = (/[.]/.exec(href)) ? /[^.]+$/.exec(href) : undefined;
                    elEv.category = "download";
                    elEv.action = "click-" + extension[0];
                    elEv.label = href.replace(/ /g, "-");
                    elEv.loc = baseHref + href;
                else if (href.match(/^https?\:/i) && !isThisDomain) {
                    elEv.category = "external";
                    elEv.action = "click";
                    elEv.label = href.replace(/^https?\:\/\//i, '');
                    elEv.non_i = true;
                    elEv.loc = href;
                else if (href.match(/^tel\:/i)) {
                    elEv.category = "telephone";
                    elEv.action = "click";
                    elEv.label = href.replace(/^tel\:/i, '');
                    elEv.loc = href;
                else if (href.match(/^call\:/i)) {
                    elEv.category = "telephone";
                    elEv.action = "click";
                    elEv.label = href.replace(/^call\:/i, '');
                    elEv.loc = href;
                else track = false;

                if (track) {
                    TrackEvent(elEv.category.toLowerCase(), elEv.action.toLowerCase(), elEv.label.toLowerCase(), elEv.value);
                    if (el.attr('target') == undefined || el.attr('target').toLowerCase() != '_blank') {
                        setTimeout(function () { location.href = elEv.loc; }, 400);
                        return false;

/* Tracking events */
function TrackEvent(category, action, label, value) {
    // add to Google Analytics
    ga('send', 'event', category, action, label, value);
    // add to Westhill Analtics
    _paq.push(['trackEvent', category, action, label, value]);

In attach the code trackingGenerator.js (4KB)



Planet Xamarin

Planet Xamarin