PiwikYesod

Piwik integration for Yesod

Posted on by

Piwik integration for Yesod is pretty simple if you just follow the example for Google Analytics. We will build a version where you can add Piwik tracking based on the stage of deployment (usually you don't want to track your users on test servers or development environments).

First of all we will add a configuration parameter to our config/settings.yml liek this:

#piwikSiteId: {yourPiwikSiteId}

Please replace yourPiwikSiteId with a number (you can find the id of your site tracking in the Piwik administration area). Since we don't wan't to add tracking during development, we comment this parameter out by adding # in front of it and will temporarily remove it for testing after we have implemented the integration.

At this point we need to read this parameter and tell the application if it's set or not. Please open Settings.hs and find the AppSettings data construction. Add the following code:

-- | Runtime settings to configure this application. These settings can be
-- loaded from various sources: defaults, environment variables, config files,
-- theoretically even a database.
data AppSettings = AppSettings
    { appStaticDir              :: String
    -- ^ Directory from which to serve static files.

    -- more settings here which were removed for demonstration 

    , appPiwikTrackingId        :: Maybe Int
    -- ^ Piwik siteId for tracking
    }

We will use appPiwikTrackingId to determine if we need to add tracking code or not. That is why it has to be a Maybe Int. We added the configuration but not the connection to our config/settings.yml. We need to tell Yesod how to fill appPiwikTrackingId. We need to add the following line to instance FromJSON AppSettings where inside the parseJSON function:

appPiwikTrackingId        <- o .:? "piwikTrackingId"

Now we are ready to use our appPiwikTrackingId in the default layout (or any other layout, if you defined different layout. Sidenote: How to define custom Layouts in Yesod

$maybe siteId <- appPiwikTrackingId $ appSettings master
      <script type="text/javascript">
        var _paq = _paq || [];
        _paq.push(["setDomains", ["*.yourpiwik.host"]]);
        _paq.push(['trackPageView']);
        _paq.push(['enableLinkTracking']);
        (function() {
          var u="//piwik.ersocon.net/";
          _paq.push(['setTrackerUrl', u+'piwik.php']);
          _paq.push(['setSiteId', '#{show siteId}']);
          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);
        })();
      <noscript>
        <p>
          <img src="//{youtPiwikHost}/piwik.php?idsite=#{show siteId}" style="border:0;" alt="">

We added the default Piwik code to our layout (written in hamlet) and replaced each occurrence of a specific tracking ID with the parameter siteId. For testing you can now remove the # in config/settings.yml. Start your application an inspect the generated source of the application in your browser.

To distinguish between different staging you just use different configs during your app deployment. But this is only one approach. You can make the decision inside your app which is aware of the stage (as you can see in instance FromJSON AppSettings where).

I hope this small tutorial helps you to integrate Piwik into your application. If you have any comments, suggestions or questions, please feel free to use the section below.