Using Google Analytics to Monitor Qt Applications - Part 2

Jeff Tranter

Jeff Tranter


Jeff Tranter is a Qt Consulting Manager at ICS. Jeff oversees the architectural and high-level design of software systems for clients. Jeff’s leadership organizes global teams of developers on desktop and embedded applications.

By Jeff Tranter | Wednesday, January 28, 2015

A previous blog post (1) described how we've been using Google Analytics at ICS to collect usage information for a Kiosk application. In this second blog post, I'll present more technical information about how to use Google Analytics from C++ code and how Qt makes this very easy to implement.

Administration of Google Analytics (2) is done through a web browser. Once you've signed up, you need to create a project. You will be given a unique tracking code to use when recording events so that you and others can see the data from the web interface.

The Google Analytics Measurement Protocol defines the application programming interface that allows applications to send HTTP requests corresponding to user interaction data to the Google Analytics servers. The protocol (3) and parameters (4) are well documented. Briefly, you will need to map important events in your application to specific Google Analytics parameters. Some parameters are required while others are optional. Which parameters you send will depend on your application and how you want to map important events in your application to Google Analytics parameters.

The required parameters are the protocol version, tracking identifier, anonymous client identifier and hit type. Each hit type has it's own set of required fields. For example, to send a page view event for the /home page, you could use the following network request:

v=1&tid=UA-XXXX-Y&cid=555&t=pageview&dp=%2Fhome

Qt makes this easy to do using the QNetworkAccessManager and related classes such as QNetworkRequest. Network requests can be sent and received asynchronously so that the application does not block.

When I was initially evaluating Google Analytics, I wrote a small Qt application that allows me to send some different events and fields. Here is the relevant code that builds up a network request:

void MainWindow::post()
{
    // Get hostname so we can set it as a parameter.
    QString hostname = QHostInfo::localHostName() + "." + QHostInfo::localDomainName();

    // Generate a unique ID to use as the Client ID.
    QUuid uuid = QUuid::createUuid();

    // Create an http network request.
    QNetworkRequest req(QUrl("http://www.google-analytics.com/collect"));
    req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");

    // Build up the query parameters.
    QUrlQuery query;
    query.addQueryItem("v", "1"); // Version
    query.addQueryItem("tid", "UA-XXXXXXXX-1"); // Tracking ID - use value assigned to you by Google Analytics
    query.addQueryItem("cid", uuid.toString()); // Client ID

    if (ui->hitTypeComboBox->currentText() == "pageview") {
        query.addQueryItem("t", "pageview"); // Page view hit type
        query.addQueryItem("dh", hostname); // Document hostname
        query.addQueryItem("dp", ui->pageViewPageLineEdit->text()); // Page
        query.addQueryItem("dt", ui->pageViewTitleLineEdit->text()); // Title
    }

    if (ui->hitTypeComboBox->currentText() == "event") {
        query.addQueryItem("t", "event"); // Event hit type
        query.addQueryItem("ec", ui->eventCategoryLinedit->text()); // Event category
        query.addQueryItem("ea", ui->eventActionLineEdit->text()); // Event action
        query.addQueryItem("el", ui->eventLabelLineEdit->text()); // Event label
        query.addQueryItem("ev", ui->eventValueLineEdit->text()); // Event value
    }

    QByteArray data;
    data.append(query.query());
    qDebug() << data; // Output for debug purposes.
    nam->post(req, data);
}

As you can see, the QNetWorkRequest class makes it easy to create an http network request. The QUrlQuery class can create the query based on different items or parameters. You then just need to post the query to the network request and you are done.

Sample query strings for page view and event hit types look like this:

v=1&tid=UA-XXXXXXXX-1&cid=%7B092a31b6-50e7-479e-a0bf-78381a4d85a5%7D&t=pageview&dh=mycomputer.ics.com&dp=/home&dt=home
v=1&tid=UA-XXXXXXXX-1&cid=%7B024e984c-a017-4c87-bc32-6d069d354c8a%7D&t=event&ec=video&ea=start&el=foo.mov&ev=300

As you can see, the QNetWorkRequest class makes it easy to create an http network request. The QUrlQuery class can create the query based on different items or parameters. You then just need to post the query to the network request and you are done.

Sample query strings for page view and event hit types look like this:

v=1&tid=UA-XXXXXXXX-1&cid=%7B092a31b6-50e7-479e-a0bf-78381a4d85a5%7D&t=pageview&dh=mycomputer.ics.com&dp=/home&dt=home v=1&tid=UA-XXXXXXXX-1&cid=%7B024e984c-a017-4c87-bc32-6d069d354c8a%7D&t=event&ec=video&ea=start&el=foo.mov&ev=300

I needed a unique identifier to use as the client identifier parameter. The QUuid class created exactly what was required.

It is good practice to handle the finished() signal from the QNetworkReply and check for any errors; the example program does this.

Here is a screen shot of the program executing:

If the program is executing and some events have been sent, you should see the events show up in the Google Analytics web interface. The two screen shots below provide examples.

The full source code (5) for the example program is available for download. While it was written for Qt 5.4.0, it should compile with any version of Qt 5, or Qt 4 with some minor changes.

One word of advice: if any parameters are invalid or required parameters are missing, Google Analytics might indicate this within the web interface, but it is more likely that the data will simply be discarded and you won't see any events reported. I recommend you start with a small example program, get it working and then incrementally add to it so that if code changes cause Google Analytics to break, you can revert back to a working version to determine what you did wrong.

In a real-world application, you would want to wrap all of the analytics code into one or more C++ classes with methods that can be called to log various interesting events in your application. In addition to wrapping all of the analytics, in the ViewPoint kiosk software we also exposed the analytics functions to QML, as much of the ViewPoint application is written in that language. We also made some parameters configurable via a configuration file, including enabling and disabling the analytics feature and specifying the tracking identifier to use.

Google Analytics is powerful, but its web interface is complex and can be confusing. If you have no prior experience with Google Analytics you may want to enlist the help of someone in your organization within the marketing or web development group to help you understand its use and translate the usage reports.

Summary

There are commercial solutions for application analytics and they tend to be expensive. In the case of ViewPoint we wanted to ultimately support all the major platforms for desktop (Linux, Windows, Mac) and mobile (Android, iOS, Windows phone). Most of the commercial tools only supported a subset of these platforms, while Google Analytics supports them all.

In my opinion, there are several major advantages of Google Analytics. First, it is free, and has servers that are global and scalable for large applications. Access to reports can be done from a web browser and it uses a simple, low overhead protocol that is easily implemented in C++ with Qt.

One limitation is that Google requires an active Internet connection. Google Analytics does not support caching of events to be sent at a later time. You could implement such a scheme yourself within your application, but you would face some challenges getting it to work. For example, Google Analytics throws away events that it considers too old, so you would need to find some way to work around this.

Google Analytics also requires mapping your application events into the event definitions that analytics provides, which is geared more toward web page access. The reporting tools are basic and and you may need some third-party tools or retrieve the raw data and analyze it yourself.

While the events are quite small, extensive reporting could potentially slow down your application or generate a lot of network bandwidth. You may need to be selective about what is logged. One approach is to make the level of logging configurable, defaulting to a minimal level of logging and increasing the level when needed.

In summary, we are pleased with our decision to use Google Analytics for the ViewPoint kiosk. The system is still in the early stages of deployment to customers, so we expect to do more tuning and tweaking based on the initial results to continually improve the entire process.

References

  1. Using Google Analytics to Monitor Qt Applications, ICS blog post, accessed 13 Jan 2015, https://www.ics.com/blog/using-google-analytics-monitor-qt-applications
  2. Google Analytics web site, accessed 13 Jan 2015, https://www.google.com/analytics/
  3. Google Analytics Measurement Protocol Developer Guide, accessed 13 Jan 2015, https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide
  4. Google Analytics Measurement Protocol Parameter Reference, accessed 13 Jan 2015, https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
  5. Google Analytics example source code, uploaded 19 Jan 2015, ftp://ftp.ics.com/pub/pickup/googleanalytics.zip


Have a question or add to the conversation: Log in Register