Client implementation for Google Analaytics Measurement API v1. Built for interactive multiuser installations with long run times. Deployed to and optimized for highly trafficked installations at public spaces with 5,000+ tracked real world interactions per hour.
Tested in production on Windows 7, but also runs on MacOS and iOS. See Google's dev guide for more API implementation info.
- Track events and screen views
- Extendable to support more hit types
- Multi-threaded HTTP requests using Cinder-Asio and Protocol
- Offline support with automatic retries at increasing intervals
- Configured to stay within Google Analytics quota limits
- Automatic session renewal
- Automatic hit batching
- Automatic cache busting
Cinder-Asio is a required dependency that needs to be installed in Cinder/blocks. Protocol is included in this repo since it's not set up as a Cinder block.
string clientId = "00000000-0000-0000-0000-000000000000"; // required
string gaId = "UA-00000000-0"; // required
string appName = "My App"; // required
AnalyticsClient::getInstance()->setup(clientId, gaId, appName);
AnalyticsClient::getInstance()->trackScreenView("Test Screen");
AnalyticsClient::getInstance()->trackEvent("Test Category", "Test Action");
The client ID is used to identify unique clients and measures as unique users in Google Analytics. The client ID is a UUID according to RFC 4122 spec, which can be pre-generated and hard coded into your app (e.g. using online tools) or randomly generated at run time (e.g. using boost).
Example UUID generation using boost:
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
//...
string clientId = boost::uuids::to_string(boost::uuids::random_generator()());
If your app only tracks as a single user, you can just use the shared instance with your GA ID and client ID. All hits sent to GA will track under the same unique user.
AnalyticsClient::getInstance()->setup(clientId, gaId, appName, appVersion);
AnalyticsClient::getInstance()->trackEvent("Test Category", "Test Action");
AnalyticsClient::getInstance()->trackEvent("Test Category", "Test Action");
AnalyticsClient::getInstance()->trackEvent("Test Category", "Test Action");
This will create three event hits in total, each by the same user.
See the AnalyticsSample project for more details.
If your app should track multiple users individually, you can create one client per user, each with their own unique client ID:
mClientA = AnalyticsClientRef(new AnalyticsClient());
mClientB = AnalyticsClientRef(new AnalyticsClient());
mClientC = AnalyticsClientRef(new AnalyticsClient());
mClientA->setup(clientIdA, gaId, appName, appVersion);
mClientB->setup(clientIdB, gaId, appName, appVersion);
mClientC->setup(clientIdC, gaId, appName, appVersion);
mClientA->trackEvent("Test Category", "Test Action");
mClientB->trackEvent("Test Category", "Test Action");
mClientC->trackEvent("Test Category", "Test Action");
This will create three event hits in total, each by individual users.
See the MultiUserSample project for more details.
The Google Analytics API does not return any form of errors when reporting hits via HTTP. In fact, it returns 200 OK
for every request, regardless of its data and format, so make sure that your GA ID and client ID are correctly formatted.
You can test if events and screen views are coming in correctly by looking at the Real Time view in your GA dashboard.
See Google's hit validation notes for more info.
Google Analytics has a few limitations that make tracking of high amounts of hits on multi-user apps difficult. For example, each session is limited to 500 hits. This Cinder block automatically renews sessions once 400 hits have been reached to stay under this limit, but that means that session data in GA is not really meaningful.
This automatic renewal can be disabled using setAutoSessionsEnabled(false)
.
The following features are nice to have and would cover relatively rare edge cases (e.g. payload size with reasonable events/screen views should never reach the limits below).
- Check for batch size limit of 16K bytes (reference)
- Check for hit size limit of 8K bytes (reference)
- Send remaining batches before app quits (currently all remaining batches will be discarded)
- Version 1.0.0
- Tested with Cinder
0.9.1dev
commit 0b24d643e3