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
andsendEvent
. Both are just calling the native implementation that we will implement later. We also define a mother class for the native implementationPlatformGoogleAnalytics
. 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 toandroid_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
, inandroid_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 theinclude
directory in it - Create a
libs
directory and copylibAdIdAccess.a
andlibGoogleAnalyticsServices.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 convenienttoNSString()
method forQString
.
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.