CleanInsights for Android is a privacy-preserving analytics tool that enables measurement of digital interactions in a safe, secure, and sustainable way. With Clean Insights, developers, data scientists, and others can extract value from data while discarding the toxic by-products typically generated by commercial analytics platforms.
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

Clean Insights Android SDK

This document describes how to get started using the Clean Insights SDK for Android. CleanInsights gives developers a safe, sustainable, and secure way to gather insights about their users using cutting edge techniques like differential privacy, onion routing, certificate pinning and more.

This SDK is based on the Android SDK, and is fully compatible with a Piwik backend server instance. We recommend hosting your own instance of Piwik, securing it with TLS (letsencrypt!), and setting up a Tor Onion Service (".onion") site for it. This ensures you have direct control of your data, that the transport is encrypted in a secure way, and that users can reach your site safely without being surveilled.

Our Focus on Privacy and Security

As stated, the Clean Insights system is based on and fully compatible with the software and service. We have focused on implementing a number of privacy and security enhancing features and defaults. In addition, our focus is on "measuring" the use of applications to gain "insights", as opposed to "tracking" users for "data". This is a subtle shift in language and perspective, but an important one.

Here are the primary changes in the Clean Insights SDK:

Usage Privacy

  • No unique permanent user identifiers are generated or set by default. Static identifiers or session-length random identifiers are used.
  • No notification of download or first use timestamps are stored, set or sent to the server.
  • No count of number of uses of the app is stored or sent to the server.

Advanced Privacy

  • Built-in implementation of Google's RAPPOR Privacy Preserving Reporting:
  • Support for threshold-based measurement triggers to reduce the amount of data gathered
  • Long lifecycle for dispatch of measurements to server (i.e. send only once per day, week or month)

Network Security

  • HTTPS/TLS or a Tor Onion Service (.onion) is required for the backend Piwik instance.
  • Certificate pinning is supported and encouraged by default.
  • Support for domain-fronting via common cloud services is included/planned, to destination of traffic.
  • Support for sending data proxyied over Orbot (Tor for Android) is built-in if the user has it installed and activated.

Dataflow diagram v1

Getting started

Integrating Clean Insights with Piwik into your Android app

  1. Install Piwik
  2. Create a new website in the Piwik web interface. Copy the Website ID from "Settings > Websites".
  3. Include the library
  4. Initialize Insights.
  5. Safely measures import values, exceptions, goals and more.
  6. Advanced measurement usage

Include library

j Add this to your apps build.gradle file:

allprojects {
	repositories {
		maven { url '' }

dependencies {
        compile 'com.github.cleaninsights:cleaninsights-android-sdk:-SNAPSHOT'

Initialize Tracker


You can simply extend your application with a CleanInsightsApplication class. This approach is used in our demo app.


Developers could manage the measurement lifecycle by themselves. To ensure that the metrics are not over-counted, it is highly recommended that the Measurer instance be created and managed in the Application class.


public class YourApplication extends Application {
    private Measurer mMeasurer;

    public synchronized Measurer getMeasurer() {
        if (mMeasurer != null) {
            return mMeasurer;

        try {
            mMeasurer = CleanInsights.getInstance(this).newMeasurer("http://your-piwik-domain.tld/piwik.php", 1);
        } catch (MalformedURLException e) {
            Log.w(Tracker.LOGGER_TAG, "url is malformed", e);
            return null;

        return mMeasurer;

Don't forget to add application name to your AndroidManifest.xml file.

    <application android:name=".YourApplication">
        <!-- activities goes here -->

Insights Usage

Measure screen views

To send a screen view set the screen path and titles on the measurer. Measurement of every screen opened and when could leak certain usages of the app, and should used carefully. That said, Clean Insights will detect if you have already tracked that this screen was opened once, and not report it multiple times per session. This is an appropriate level of usage tracking, as opposed to every time a user opens a screen.

public class YourActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        Measurer measurer = ((CleanInsightsApplication) getApplication()).getMeasurer();

Measure events

To gain insights about user's interaction with interactive components of your app, like button presses or the use of a particular item in a game use [measureEvent](, java.lang.String, java.lang.String, java.lang.Integer)) method.

MeasureHelper.measure().event("category", "action").name("label").value(1000f).with(measurer);

Measure goals

If you want to trigger a conversion manually or measure some user interaction simply call the method measureGoal. Read more about what is a Goal in Piwik.


Measure custom vars

To measure a custom name-value pair assigned to your users or screen views use [setVisitCustomVariable](, java.lang.String, java.lang.String)) and [setScreenCustomVariable](, java.lang.String, java.lang.String)) methods. Those methods have to be called before a call to trackScreenView. More about custom variables on

Measurer measurer = ((CleanInsightsApplication) getApplication()).getMeasurer();
measurer.setVisitCustomVariable(2, "Age", "99");
MeasurerHelper.measure().screen("/path").variable(2, "Price", "0.99").with(measurer);

Measure application downloads

To measure the number of app downloads you may call the method measureAppDownload This method uses SharedPreferences to ensures that tracking application downloading will be fired only once.


Custom Dimensions

To measure Custom Dimensions in scope Action or Visit consider following example:

Measure measurer = ((YourApplication) getApplication()).getMeasurer();
    new CustomDimensions()
        .set(1, "foo")
        .set(2, "bar")


The measurer by default will dispatch any pending events every once per day. We user a longer interval of dispatching in order to reduce network surveillance of traffic and app usage.

If a negative value is used the dispatch timer will never run, a manual dispatch must be used:

    Measurer measure = ((YourApplication) getApplication()).getMeasurer();
    // Measure exception
    try {
        revenue = getRevenue();
    } catch (Exception e) {
        tracker.trackException(e, e.getMessage(), false);
        revenue = 0;

User ID

The default behavior of Pwiki is to provide the tracker with a user ID lets you connect data collected from multiple devices and multiple browsers for the same user. A user ID is typically a non empty string such as username, email address or UUID that uniquely identifies the user. The User ID must be the same for a given user across all her devices and browsers.

With Clean Insights, we use a static user-id across all clients by default. The user can choose to override this to provide unique per client id's, but we think our default is the most optimal for preservation of privacy.

        ((YourApplication) getApplication()).getMeasurer()
                .setUserId("ffffffffffffff"); //this is our static hexadecimal userid

If user ID is used, it must be persisted locally by the app and set directly on the tracker each time the app is started.

Modifying default parameters

The Tracker has a method getDefaultTrackMe modifying the object returned by it will change the default values used on each query. Note though that the Tracker will not overwrite any values you set on your own TrackMe object.

Detailed API documentation

Here is the design document written to give a brief overview of the SDK project:

CleanInsights SDK should work fine with Android API Version >= 10 (Android 2.3.3+)

Optional autoBindActivities method is available on API level >= 14.

Check out the full API documentation.


CleanInsights uses Timber. If you don't use Timber in your own app call Timber.plant(new Timber.DebugTree());, if you do use Timber in your app then Piwik should automatically participate in your logging efforts. For more information see Timbers GitHub

Check SDK

Following command will clean, build, test, generate documentation, do coverage reports and then create a jar.

$ ./gradlew :piwik-sdk:clean :piwik-sdk:assemble :piwik-sdk:test :piwik-sdk:jacocoTestReport :piwik-sdk:generateReleaseJavadoc :piwik-sdk:coveralls --info :piwik-sdk:makeJar
  • Coverage output ./piwik-sdk/build/reports/jacoco/jacocoTestReport/html/index.html
  • Tests report ./piwik-sdk/build/test-report/debug/index.html
  • Javadoc ./piwik-sdk/build/docs/javadoc/index.html

Demo application

Browse the code or build an .apk by running following command:

./gradlew :exampleapp:clean :exampleapp:build

Generated .apk would be placed in ``./exampleapp/build/apk/`


  • Fork the project
  • Create a feature branch based on the 'dev' branch
  • Drink coffee and develop an awesome new feature
  • Add tests for your new feature
  • Make sure that everything still works by running "./gradlew clean assemble test".
  • Commit & push the changes to your repo
  • Create a pull request from your feature branch against the dev branch of the original repo
  • Explain your changes, we can see what changed, but tell us why.
  • If your PR passes the travis-ci build and has no merge conflicts, just wait, otherwise fix the code first.


CleanInsights Android SDK for Piwik is released under the BSD-3 Clause license, see LICENSE.