How to use Google Analytics in a Qt Quick app for Android/iOS

Even if there are other mobile analytics services such as Flurry, Google Analytics (GA) is a popular (and free) way to get insights about marketing campaigns or app usage. In this article I will explain how to implement a simple tracking of displayed screens and events in a multiplatform Qt Quick app.

tl;dr : A sample app is available on GitHub: GATutorial-QML.

Choose your way

When integrating with third party services in a Qt Quick app, there are often two ways.

  • The API way
  • The native SDK way

For GA, there is a low level API called Measurement Protocol. When a low level API, the developer is required to write more code. Here, we would need to cache data when the user is offline, get device ID ourself etc... The advantage of using the low level API is that it's easy to make a cross platform app. Measurement protocol relies only on HTTP.

GA also provides SDKs for Android and iOS. Both SDKs most likely implements the Measurement Protocol but they also provide several other features such as automatic screen views tracking (but a Qt Quick app cannot use it...), caching of hits when the device is offline, getting device ID for better tracking... To sum it up, The SDKs are doing all the heavy lifting for us. Google also provide an SDK for Unity but no Qt Quick SDK. It's a curse any Qt developer will encounter a lot... (Hopefully not for long!)

If you are reading this, and know about a Google Analytics Qt project, even not from Google, let me know, I'd love to be wrong.

Our app is currently only available on iOS and Android. So, I chose the SDK way with a future fallback to Measurement Protocol if necessary.

Creating the app and a simple API

  • Obviously a new property and tracking ID is necessary. You can get one on Google Analytics website.

  • Create a C++ class we can call from QML. The class has two Q_INVOKABLE functions sendHit and sendEvent. Both are just calling the native implementation that we will implement later. We also define a mother class for the native implementation PlatformGoogleAnalytics. Next paragraphs will describe the Android and iOS implementation. A default implementation using Measurement Protocol could be written too.

  • Expose the class to QML. In main.cpp, add

GoogleAnalytics ganalytics;  
ganalytics.initTracker();  
engine.rootContext()->setContextProperty("gAnalytics", &ganalytics);  
  • in QML, to register an new screen view, just call
gAnalytics.sendHit("myView")  

Android glue

We have now a C++ class that we can call from QML. This class will now need to call Java and the Google Analytics SDK for Android.

Setup the Google Analytics SDK for Android
  • Create a directory in your project named android_data.

  • Add the following to your pro file

ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android_data  

Qt Creator will merge the android_data directory with the one provided by Qt when building.

  • Install the Google Analytics SDK for Android. You can find it in the maintenance tool of the SDK, in the extra section. Once installed, copy the sdk/extras/google/google_play_services directory to android_data

  • create a project.properties file in android_data and add this line

android.library.reference.1=google-play-services_lib  
  • copy android-support-v4.jar from the android SDK to "android_data/libs"

*Copy the AndroidManifest.xml file from Qt ( android_armv7/src/android/java/AndroidManifest.xml) to the android_data directory in the project

  • Add the following the AndroidManifest.xml In <activity>
<!-- Analytics -->  
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/>  
<meta-data android:name="com.google.android.gms.analytics.globalConfigResource" android:resource="@xml/analytics_global_config"/>  
<!-- Analytics -->  

in <application>

<!-- Used for Google Play Store Campaign Measurement-->;  
<service android:name="com.google.android.gms.analytics.CampaignTrackingService"/>  
<receiver android:name="com.google.android.gms.analytics.CampaignTrackingReceiver" android:exported="true">  
     <intent-filter>
            <action android:name="com.android.vending.INSTALL_REFERRER"/>
     </intent-filter>
</receiver>  

This second part is not useful for tracking hits and events. It's used to track installation referrer. Read more about Campaign Measurement

  • Add analytics configuration files, as described in AndroidManifest.xml, in android_data/res/xml. I created one for the tracker and one with global parameters. The tracker one contains the tracker ID and it needs to be change to your own value.
Java side

I wrote a short Java class, named QGoogleAnalytics in order to call two of the function provided by the SDK. The class is very simple and has two static public functions sendHit and sendEvent. Let's see how we can call them from C++ via JNI.

C++ JNI

Qt provides a very useful androidextras package to ease the writing of JNI.

  • add the following to your pro file
android {  
  QT += androidextras
}
  • The code to call a static method is easy enough. The C++ class inherits from PlatformGoogleAnalytics.
void AndroidGoogleAnalytics::sendHit(const QString &screenName)  
{
  QAndroidJniObject jsScreenName = QAndroidJniObject::fromString(screenName);
  QAndroidJniObject::callStaticMethod<void>("com/lasconic/QGoogleAnalytics", "sendHit", "(Ljava/lang/String;)V", jsScreenName.object<jstring>());
}

iOS glue

setup the Google Analytics SDK for iOS

  • Download the Google Analytics SDK for iOS v3
  • Unzip it
  • Create an ios directory in your project and copy the include directory in it
  • Create a libs directory and copy libAdIdAccess.a and libGoogleAnalyticsServices.a in it
  • Modify the pro file to link these libraries and add framework dependencies.
ios {  
  QMAKE_LFLAGS += -framework CoreData -framework AdSupport -ObjC
  LIBS += -L$$PWD/ios/libs -lGoogleAnalyticsServices -lAdIdAccess -lsqlite3.0
}

Objective-C glue

Objective-C can be mixed with C++ more easily than Java.

  • To add an Objective-C class, modify the pro files
OBJECTIVE_SOURCES += ios/iosanalytics.mm  
  • also add a header file iosanalytics.h
  • This class inherits PlatformGoogleAnalytics and call the SDK directly. You need to change the GA tracking ID in this class. Qt provides a convenient toNSString() method for QString.
void IosGoogleAnalytics::sendHit(const QString &screenName) {  
    id<GAITracker> tracker = [[GAI sharedInstance] defaultTracker];
    // Send a screen view
    [tracker send:[[[GAIDictionaryBuilder createAppView] set:screenName.toNSString() forKey:kGAIScreenName] build]];
}

Conclusion

This is a working and simple solution to integrate an iOS/Android Qt Quick app with Google Analytics. The code is available on GitHub: GATutorial-QML.
The approach would be similar for any service which provide more value in native SDKs than in its crossplatform API, or even doesn't provide a crossplatform API.

Of course, it's a crude example. We could expose more Google Analytics features to QML such as e-commerce tracking. Also, if we would want to support more platforms such as desktop ones or Windows Mobile, we would need to complete the fallback to Measurement Protocol.

Any comment? Find me on twitter.