C++ (22.02.X)

Follow

This document will guide you through the process of SDK installation and it applies to version 22.02.0.

To access the documentation for version 21.11 and older, click here.

It is an open-source SDK, you can take a look at our SDK code in the Github repo

Supported Platforms: Windows, GNU/Linux, and Mac OS X.

Adding the SDK to the project

Countly C++ SDK has been designed to work with very few dependencies in order to be available on most platforms. In order to build this SDK, you need:

  • a C++ compiler with C++11 support
  • libcurl (with openssl) and its headers if you are on *nix
  • cmake >= 3.13

First, clone the repository with its submodules:

git clone --recursive https://github.com/Countly/countly-sdk-cpp

If you want to use SQLite to store session data persistently, build sqlite:

# assuming we are on project root
cd vendor/sqlite
cmake -D BUILD_SHARED_LIBS=1 -B build . # out of source build, we don't like clutter :)
# we define `BUILD_SHARED_LIBS` because sqlite's cmake file compiles statically by default for some reason
cd build
make # you might want to add something like -j8 to parallelize the build process

The cmake build flow is pretty straightforward:

# assuming we are on project root again
cmake -B build . # this will launch a TUI, configure the build as you see fit
cd build
make

Build with the optionCOUNTLY_BUILD_TESTS and COUNTLY_BUILD_SAMPLEON to build executables to run the tests and sample app.

cmake -DCOUNTLY_BUILD_SAMPLE=1 -DCOUNTLY_BUILD_TESTS=1 -B build . # or do it interactively with cmake
cd build
make ./countly-tests   # run unit test
make ./countly-sample # run sample app

SDK Integration

Minimal Setup

Before you can use any functionality, you have to initiate the SDK. 

The shortest way to initiate the SDK is with this code snippet:

Countly& countly = Countly::getInstance();
countly.setDeviceID("test-device-id");
countly.start("YOUR_APP_KEY", "https://try.count.ly", 443, true);

It is there that you provide your appKey, and your Countly server URL. For more information on how to acquire you application key (appKey) and server URL, check here.

The third parameter with typeint is a virtual port number and it is an optional parameter with a default value of -1.
The last boolparameter is also optional with a default value false. When you set this trueSDK automatically extends the session after every 60 seconds. 

If you are in doubt about the correctness of your Countly SDK integration you can learn about methods to verify it from here.

SDK logging mode

The first thing you should do while integrating our SDK is enable logging. If logging is enabled, then our SDK will print out debug messages about its internal state and encounter problems. 

Set setLogger(logger_function) on the Counlty object to enable logging:

void printLog(Countly::LogLevel level, const string& msg) {...}
...

void (*logger_function)(Countly::LogLevel level, const std::string& message);
logger_function = printLog;
Countly::getInstance().setLogger(logger_function);

Device ID

All tracked information is tied to a "device ID". A device ID is a unique identifier for your users.

You have to specify the device ID by yourself (it has to be unique for each of your users). It may be an email or some other internal ID used by your other systems.

Countly::getInstance().setDeviceID("UNIQUE_DEVICE_ID");

SDK notes

To access the Countly Global Instance use the following code snippet:

Countly::getInstance().

Events

An event is any type of action that you can send to a Countly instance, e.g. purchases, changed settings, view enabled, and so on, letting you get valuable information about your application.

There are a couple of values that can be set when recording an event. The main one is the key property which would be the identifier/name for that event.  For example, in case a user purchased an item in a game, you could create an event with the key 'purchase'.

Optionally there are also other properties that you might want to set:

  • count -  a whole numerical value that marks how many times this event has happened. The default value for that is 1.
  • sum - This value would be summed across all events in the dashboard. For example, in-app purchase events sum of purchased items. Its default value is 0.
  • duration - Used to record and track the duration of events. The default value is 0.
  • segments - A value where you can provide custom segmentation for your events to track additional information. It is a key and value map. The accepted data type for the value isstd::string.

Recording events

Based on the example below of an event recording a purchase, here is a quick summary of the information for each usage:

  • Usage 1: how many times the purchase event occurred.
  • Usage 2: how many times the purchase event occurred + the total amount of those purchases.
  • Usage 3: how many times the purchase event occurred + from which countries and application versions those purchases were made.
  • Usage 4: how many times the purchase event occurred + the total amount, both of which are also available, segmented into countries and application versions.
  • Usage 5: how many times the purchase event occurred + the total amount, both of which are also available, segmented by countries and application versions + the total duration of those events.

1. Event key and count

Countly::getInstance().RecordEvent("purchase", 1);

2. Event key, count, and sum

Countly::getInstance().RecordEvent("purchase", 1, 0.99);

3. Event key and count with segmentation(s)

std::map<std::string, std::string> segmentation;
segmentation["country"] = "Germany";

Countly::getInstance().RecordEvent("purchase", segmentation, 1);

4. Event key, count, and sum with segmentation(s)

std::map<std::string, std::string> segmentation;
segmentation["country"] = "Germany";

Countly::getInstance().RecordEvent("purchase", segmentation, 1, 0.99);

5. Event key, count, sum, and duration with segmentation(s)

std::map<std::string, std::string> segmentation;
segmentation["country"] = "Germany";

Countly::getInstance().RecordEvent("purchase", segmentation, 1, 0.99, 60.0);

These are only a few examples of what you can do with Events. You may go beyond those examples and use country, app_version, game_level, time_of_day, and any other segmentation of your choice that will provide you with valuable insights.

Timed events

It's possible to create timed events by defining a start and a stop moment.

Event event("Some event", 1);

//start some event

event.startTimer();
//wait some time

//end the timer and record event
event.stopTimer();
Countly.getInstance().addEvent(event);

You may also provide additional information e.g segmentation, count, and sum.

//event with count and sum
Event event("Some event", 1, 0.99);
//add segmentation to event
event.addSegmentation("country", "Germany");
...

Countly.getInstance().addEvent(event);

Sessions

Automatic session tracking 

The SDK handles the session automatically. After calling the start(...) method, the SDK starts the session automatically and extends the session after every 60 seconds. This value is configurable during and after initialization. 
Example:

Countly::getInstance().setAutomaticSessionUpdateInterval(10);

The SDK ends the current session whenever the user quits the app.

Device ID management

A device ID is a unique identifier for your users. You have to specify the device ID yourself. When providing one yourself, keep in mind that it has to be unique for all users. Some potential sources for such an id may be the user's username, email, or some other internal ID used by your other systems.

In the C++ SDK the device ID is not persistant and has to be provided every time you start the SDK.

Changing device ID

In case your application authenticates users, you might want to change the ID to the one in your backend after he has logged in. This helps you identify a specific user with a specific ID on a device he logs in, and the same scenario can also be used in cases this user logs in using a different way (e.g another tablet, another mobile phone, or web). In this case, any data stored in your Countly server database associated with the current device ID will be transferred (merged) into the user profile with the device id you specified in the following method call:

Countly::getInstance().setDeviceID("new-device-id", true);

You might want to track information about another separate user that starts using your app (changing apps account), or your app enters a state where you no longer can verify the identity of the current user (user logs out). In that case, you can change the current device ID to a new one without merging their data. You would call:

Countly::getInstance().setDeviceID("new-device-id", false);

Doing it this way, will not merge the previously acquired data with the new id.

If the second parametersame_useris set to true, the old device ID on the server will be replaced with the new one, and data associated with the old device ID will be merged automatically.

Otherwise, if same_user bool is set to false, the device will be counted as a new device on the server.

View Tracking

Manual View Recording

The Countly C++ SDK supports manual view (screen) tracking, with which, you can report which views a user has visited with the duration of that visit. To report a screen from your app to the Countly server, you can use the following method:

std::string& viewID = Countly::getInstance().views()("Home Scene");

While tracking views manually, you may add your custom segmentation to those views like this:

std::map<std::string, std::string> segmentation = {
{"cats", "123"},
{"moons", "9.98"},
{"Moose", "deer"},
};

std::string& viewID = Countly::getInstance().views().openView("Home Scene", segmentation);

When the screen closes you can report it to the server by using one of the following methods:

1. Ending a view with a view ID:

When you start recording a view by calling the openView method, it returns a view ID of type std::string. You can use this ID to close a view.

For example:

std::string& viewID = Countly::getInstance().views().openView("Home Scene");
...
Countly::getInstance().views().closeViewWithID(viewId);

2. Ending a view with a view name:
You may close a view by its name using the following method:

Countly::getInstance().views().closeViewWithName("Home Scene");

To review the resulting view data, go to the Analytics > Views section in your Countly server. For more information on how to utilize view tracking data to its fullest potential, click here.

User location

While integrating this SDK into your application, you might want to track your user location. You could use this information to better know your app’s user base. There are 4 fields that can be provided:

  • Country code (two-letter ISO standard).
  • City name (must be set together with the country code).
  • Latitude and longitude values, separated by a comma e.g. "56.42345,123.45325".
  • Your user’s IP address.

Setting location

During init, you may set location, and after SDK initialization, this location info will be sent to the server at the start of the user session.

Example:

string countryCode = "us";
string city =
"Houston";
string latitude =
"29.634933";
string longitude =
"-95.220255";
string ipAddress = "192.168.0.1"
; 

Countly::getInstance().setLocation(countryCode, city, latitude + "," + longitude, ipAddress);

Note that the IP address will only be updated if set through the init process.

When those values are set after SDK initialization, a separate request will be created to send them. Except for IP address, because Countly server processes IP address only when starting a session.

If you don't want to set specific fields, set them to empty.

Remote config

Available in the Enterprise Edition, Remote Config allows you to modify how your app functions or looks by requesting key-value pairs from your Countly server. The returned values may be modified based on the user profile. For more details, please see the Remote Config documentation.

Manual remote config

To download Remote Config, call updateRemoteConfig()

Countly.getInstance().updateRemoteConfig();

Accessing remote config values

To access the stored config,  call Countly.getInstance().getRemoteConfigValue(const std::string& key). It will return null if there isn't any config stored.

Countly.getInstance().getRemoteConfigValue("Key");

It returns a value of the type json

User profiles

For information about User Profiles, review this documentation.

Setting predefined values

The Countly C++ SDK allows you to upload specific data related to a user to the Countly server. You may set the data against predefined keys for a particular user.

The keys for predefined user data fields are as follows:

Key Type Description
name string User's full name
username string User's nickname
email string User's email address
organization string User's organization name
phone string User's phone number
picture string URL to avatar or profile picture of the user
gender string User's gender as M for male and F for female
byear string User's year of birth as integer

The SDK allows you to upload user details using the methods listed below.

Example:

std::map<std::string, std::string> userdetail = { 
{"name", "Full name"},
{"username", "username123"},
{"email", "useremail@email.com"},
{"phone", "222-222-222"},
{"picture", "http://webresizer.com/images2/bird1_after.jpg"},
{"gender", "M"},
{"byear", "1991"},
{"organization", "Organization"},
};
Countly.getInstance().setUserDetails(userdetail);

Setting custom values

The SDK gives you the flexibility to send only the custom data to Countly servers, even when you don’t want to send other user-related data.

Example:

std::map<std::string, std::string> userdetail = { 
{"Height", "5.8"},
{"Mole", "Lower Left Cheek"}
};

Countly.getInstance().setCustomUserDetails(userdetail);

Setting User picture

The SDK allows you to set the user's picture URL along with other details using the methods listed below.

Example:

std::map<std::string, std::string> userdetail = { 
{"name", "Full name"},
{"picture", "http://webresizer.com/images2/bird1_after.jpg"},
};

Counlty.getInstance().setUserDetails(userdetail);

Security and privacy

Parameter tamper protection

You may set the optional salt to be used for calculating the checksum of requested data which will be sent with each request, using the &checksum field. You will need to set exactly the same salt on the Countly server. If the salt on the Countly server is set, all requests would be checked for the validity of the &checksum the field before being processed.

Countly.getInstance().setSalt("salt");

Other features

Setting event queue threshold

After SDK init, you may limit the number of events that can be recorded internally by the system before they can all be sent together in one request. 
Example:

Counlty.getInstance().SetMaxEventsPerMessage(10);

Once the threshold limit is reached, the system groups all recorded events and sends them to the server.

Setting custom SHA-256

C++ SDK allows users to set a custom SHA-256 method for calculating the checksum of request data.

To use the custom SHA-256 feature follow the following steps:

1. Build the Countly C++ SDK executable with the COUNTLY_USE_CUSTOM_SHA256 option.

cmake -DCOUNTLY_USE_SQLITE=1 -DCOUNTLY_USE_CUSTOM_SHA256=1 -B build

2. Set custom SHA-256 method setSha256

For example:

std::string customChecksumCalculator(const std::string& data) {
...
return result;
}


Countly& countly = Countly.getInstance();
countly.setSalt("salt");
countly.setSha256(customChecksumCalculator);

FAQ

What information is collected by the SDK

The following description mentions data that is collected by SDK to perform their functions and implement the required features. Before any of it is sent to the server, it is stored locally.

* When sending any network requests to the server, the following things are sent in addition to the main data:
- Timestamp of when the request is created
- SDK version
- SDK name

Comments

0 comments

Please sign in to leave a comment.