Cordova (19.9.3)


Setting up Countly SDK inside your Phonegap, Cordova, Icenium or Meteor application is straightforward. Just follow these steps.

Using SDK

First run the following to create a Countly demo application.

cordova create countly-demo-js com.countly.demo countly-demo-js
cd countly-demo-js

Add Countly core plugin

cordova plugin add
# OR
cordova plugin add countly-sdk-js@19.9.3

Now add platform of your choice

cordova platform add android
cordova platform add ios

It's important that you make sure you build it with Cordova, as Cordova links folders very well.

cordova build android
cordova build ios

Now run the application directly for Android,

cordova run android

Or iOS:

cordova run ios

Alternatively, you can open the source in Xcode, or Eclipse and move on with further development.

Using SDK with Meteor app

Run this command for Meteor:

meteor add countly:countly-sdk-js

Ionic 2.0

npm install -g ionic cordova
ionic start countly-demo-ionic blank
cd countly-demo-ionic
ionic cordova plugin add
ionic serve
# Note to ionic devs: This plugin does not work on a browser.

In your index.html, use the following lines:

<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="Countly.js"></script>

If you looking to try out example code, you may wanna look at the index.html in the countly-sdk-cordova repo in master branch.

Copy and paste into your www/index.html

It has all the required examples you need.


Below you can find necessary code snippets to initialize the SDK for sending data to Countly servers. Where possible, use your server URL instead of in case you have your own server.

// initialize
// use your server name below if required.

//example to start and stop Countly

//example to halt Countly

Enabling logging

If logging is enabled then our sdk will print out debug messages about it's internal state and encountered problems.

When advise doing this while implementing countly features in your application.

// example for setLoggingEnabled


If the data sent to the server is short enough, the sdk will use HTTP GET requests. In case you want an override so that HTTP POST is used in all cases, call the "setHttpPostForced" function after you called "init". You can use the same function to later in the apps life cycle disable the override. This function has to be called every time the app starts.

Countly.setHttpPostForced(true); // default is false

Parameter Tampering Protection

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

// sending data with salt

Setting up custom events

A custom event is any type of action that you can send to a Countly instance, e.g purchase, settings changed, view enabled and so. This way it's possible to get much more information from your application compared to what is sent from Android SDK to Countly instance by default.

Data passed should be in UTF-8

All data passed to Countly server via SDK or API should be in UTF-8.

As an example, we will be recording a purchase event. Here is a quick summary what information each usage will provide us:

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

1. Event key and count

// example for sending basic custom event
var events = {"key":"Basic Event","count":1};

2. Event key, count and sum

// example for event with sum
var events = {"key":"Event With Sum","count":1,"sum":"0.99"};

3. Event key and count with segmentation(s)

// example for event with segment
var events = {"key":"Event With Segment","count":1};
events.segments = {"Country" : "Turkey", "Age" : "28"};

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

// example for event with segment and sum
var events = {"key":"Event With Segment And Sum","count":1,"sum":"0.99"};
events.segments = {"Country" : "Turkey", "Age" : "28"};

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

var events = {
  "key": "Event With Sum And Segment duration",
  "count": 1,
  "Sum": "0.99",
  "duration": "0"
events.segments = {
  "Country": "Turkey",
  "Age": "28"

Those are only a few examples with what you can do with custom events. You can extend those examples and use country, app_version, game_level, time_of_day and any other segmentation that will provide you valuable insights.

Timed events

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

// Time Event
Countly.startEvent("Timed Event");
setTimeout(function() { Countly.endEvent({ "key": "Timed Event"); }, 1000);
// Time Event With Sum Countly.startEvent("Timed Event With Sum"); setTimeout(function() {
countly.endEvent({"key": "Timed Event With Sum", "sum": "0.99"});
}, 1000);

When ending a event you can also provide additional information. But in that case you have to provide segmentation, count and sum. The default values for those are "null", 1 and 0.

// Time Event with segment
Countly.startEvent("Timed Event With Segment");
setTimeout(function() { var events = { "key": "Timed Event With Segment" }; events.segments = { "Country": "Turkey", "Age": "28" }; Countly.endEvent(events); }, 1000)
// Time Event with Segment, sum and count Countly.startEvent("Timed Event With Segment, Sum And Count");
setTimeout(function() { var events = { "key": "timedEvent", "count": 1, "sum": "0.99" }; events.segments = { "Country": "Turkey", "Age": "28" }; Countly.endEvent(events);
}, 1000);

Device ID

When the SDK is initialized for the first time and no device ID is provided, a device ID will be generated by SDK.

For iOS: the device ID generated by SDK is the Identifier For Vendor (IDFV)
For Android:  the device ID generated by SDK is the OpenUDID or Google Advertising ID

You may provide your own custom device ID when initializing the SDK


Changing the Device ID

You may configure/change the device ID anytime using:

Countly.changeDeviceId(DEVICE_ID, ON_SERVER);

You may either allow the device to be counted as a new device or merge existing data on the server. If theonServer bool is 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 onServer bool is set to false, the device will be counted as a new device on the server.

Temporary Device ID

You may use a temporary device ID mode for keeping all requests on hold until the real device ID is set later. 

You can enable temporary device ID when initializing the SDK:

Countly.init(SERVER_URL, APP_KEY, "TemporaryDeviceID")

To enable a temporary device ID after init, you would call:

Countly.changeDeviceId(Countly."TemporaryDeviceID", ON_SERVER);

 Note: When passing TemporaryDeviceID for deviceID parameter, argument for onServerparameter does not matter.

As long as the device ID value is TemporaryDeviceID, the SDK will be in temporary device ID mode and all requests will be on hold, but they will be persistently stored.

When in temporary device ID mode, method calls for presenting feedback widgets and updating remote config will be ignored.

Later, when the real device ID is set using Countly.changeDeviceId(DEVICE_ID, ON_SERVER); method, all requests which have been kept on hold until that point will start with the real device ID

Retrieving the device id and its type

You may wanty to see what device id Countly is assigning for the specific device and what the source of that id is. For that you may use the following calls. The id type is an enum with the possible values of: "DEVELOPER_SUPPLIED", "OPEN_UDID", "ADVERTISING_ID".

// get device id
}, function(getDeviceIDError){

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 apps user base or to send them tailored push notifications based on their coordinates. There are 4 fields that can be provided:

  • country code in the 2 letter iso standard
  • city name (has to be set together with country code)
  • Comma separate latitude and longitude values, for example "56.42345,123.45325"
  • ip address of your user
// send user location
Countly.setLocation("28.006324", "-82.7166183");

When those values are set, they will be sent every time when initiating a session. If they are set after a session was initiated, a separate request will also be sent. 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 null.

Users might want to opt out of location tracking. To do that, call:

It will erase cached location data from the device and the server.

Remote Config

Remote config allows you to modiffy how your app functions or looks by requesting key-value pairs from your Countly server. The returned values can be modiffied based on the user profile. For more details please see Remote Config documentation.

Automatic Remote Config download

There are two ways of acquiring remote config data, by automatic download or manual request. By default, automatic remote config is disabled and therefore without developer intervention no remote config values will be requested.

Automatic value download happens when the SDK is initiated or when the device ID is changed. To enable it, you have to call setRemoteConfigAutomaticDownload before init. As a optional value you can provide a callback to be informed when the request is finished.

Note: call setRemoteConfigAutomaticDownload method before init

// Call this method before init
Countly.setRemoteConfigAutomaticDownload(function(r){ alert(r) }, function(r){ alert(r); });

If the callback returns a non null value, then you can expect that the request failed and no values where updated.

When doing an automatic update, all locally stored values are replaced with the ones received (all locally stored ones are deleted and new ones are associated instead). It is possible that a previously valid key returns no value after an update.

Manual Remote Config download

There are three ways for manually requesting a Remote Config update:

  • Manually updating everything
  • Manually updating specific keys
  • Manually updating everything except specific keys

Each of these requests also has a callback. If that returns a non-null value, that means the request encountered an error and failed.

Functionally, the manual update for everything remoteConfigUpdate is the same as the automatic update - it replaces all stored values with the ones from the server (all locally stored ones are deleted and replaced with new ones instead). The advantage is that you can make the request whenever it is desirable for you. It has a callback to let you know when it has finished.

}, function(r){

You might want to update only specific key values. For that you need to call updateRemoteConfigForKeysOnly with a list of keys you want to be updated. That list is an array with string values of those keys. It has a callback to let you know when the request has finished.

Countly.updateRemoteConfigForKeysOnly(["name"], function(r){
}, function(r){

You might want to update all values except a few defined keys, for that call updateRemoteConfigExceptKeys. The key list is a array with string values of the keys. It has a callback to let you know when the request has finished.

Countly.updateRemoteConfigExceptKeys(["url"], function(r){
}, function(r){

When making requests with a "inclusion" or "exclusion" array, if those arrays ar empty or null, they will function the same as a simple manual request and will update all values. This means that it will also erase all keys not returned by the server.

Getting Remote Config values

To request a stored value, call getRemoteConfigValueForKey with the specified key. If it returns null then no value was found. The SDK has no knowledge of the returned value type and therefore returns an object. The developer needs to cast it to the appropriate type. The returned values can also be a JSONArray, JSONObject or just a simple value like int.

Countly.getRemoteConfigValueForKey("name", function(r){
 }, function(r){

Clearing stored Remote Config values

At some point you might want to erase all values downloaded from the server. To achieve that you need to call one function, depicted below:

}, function(r){

Setting up User Profiles

Available with Enterprise Edition, User Profiles is a tool which helps you identify users, their devices, event timeline and application crash information. User Profiles can contain any information that either you collect, or is collected automatically by Countly SDK.

You can send user related information to Countly and let Countly dashboard show and segment this data. You may also send a notification to a group of users. For more information about User Profiles, see this documentation.

To provide information about the current user, you must call the Countly.userData.setUserData function. You can call it by providing a bundle of only the predefined fields or call it while also providing a second bundle of fields with your custom keys. After you have provided user profile information, you must save it by calling

/ example for setting user data
var options = {}; = "Nicola Tesla";
options.username = "nicola"; = "info@nicola.tesla";
options.organization = "Trust Electric Ltd"; = "+90 822 140 2546";
options.picture = "";
options.picturePath = "";
options.gender = "Male";
options.byear = 1919;

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 organisation 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

Using "" for strings or a negative number for 'byear' will effectively delete that property.

For custom user properties you may use any key values to be stored and displayed on your Countly backend. Note: keys with . or $ symbols will have those symbols removed.

Modifying custom data

Additionally you can do different manipulations on your custom data values, like increment current value on server or store a array of values under the same property.

Below is the list of available methods:

// example for extra user features

Countly.userData.setProperty("setProperty", "My Property");
Countly.userData.incrementBy("incrementBy", 10);
Countly.userData.multiply("multiply", 20);
Countly.userData.saveMax("saveMax", 100);
Countly.userData.saveMin("saveMin", 50);
Countly.userData.setOnce("setOnce", 200);
Countly.userData.pushValue("pushValue", "morning");
Countly.userData.pullValue("pullValue", "morning");

In the end always call to send them to the server.

User Consent management

To be compliant with GDPR, starting from 18.04, Countly provides ways to toggle different Countly features on/off depending on the given consent.

More information about GDPR can be found here.

By default the requirement for consent is disabled. To enable it, you have to call setRequiresConsent with true, before initializing Countly.


By default no consent is given. That means that if no consent is enabled, Countly will not work and no network requests, related to features, will be sent. When consent status of a feature is changed, that change will be sent to the Countly server.

For all features, except push, consent is not persistent and will have to be set every time before countly init. Therefore the storage and persistance of given consent falls on the sdk integrator.

Consent for features can be given and revoked at any time, but if it is given after Countly init, some features might work partially.

If consent is removed, but the appropriate function can't be called before the app closes, it should be done at next app start so that any relevant server side features could be disabled (like reverse geo ip for location)

Feature names in the Android SDK are stored as static fields in the class called CountlyFeatureNames.

The current features are:

  • sessions - tracking when, how often and how long users use your app
  • events - allow sending custom events to server
  • views - allow tracking which views user visits
  • location - allow sending location information
  • crashes - allow tracking crashes, exceptions and errors
  • attribution - allow tracking from which campaign did user come
  • users - allow collecting/providing user information, including custom properties
  • push - allow push notifications
  • starRating - allow to send their rating and feedback
  • apm - allow application performance monitoring

Changing consent

There are 3 ways of changing feature consent:

  • giveConsent/removeConsent - gives or removes consent to a specific feature
Countly.giveConsent(["events", "views", "star-rating", "crashes"]);

// removeConsent
Countly.removeConsent(["events", "views", "star-rating", "crashes"]);
  • giveAllConsent/removeAllConsent - giveAll or removeAll consent to a specific feature


Crash reporting

With this feature, Countly SDK will generate a crash report if your application crashes due to an exception, and send it to Countly server for further inspection.

If a crash report can not be delivered to server (e.g. no internet connection, unavailable server), then SDK stores the crash report locally in order to try again later.

Please add to your html file:

// Using countly crash reports

You can also send a custom crash log to Countly using code below.

// Send a custom crash log
Countly.addCrashLog("My crash log from JavaScript");

// Send Exception to the server
Countly.logException(["My Customized error message"], true, {"_facebook_version": "0.0.1"});
Countly.logException(stackFramesFromStackTraceJS, booleanNonFatal, segments);

// Usage Example

app.addCrashLog = function(){
  Countly.addCrashLog("User Performed Step A");
    Countly.addCrashLog("User Performed Step B");
    Countly.addCrashLog("User Performed Step C");
    console.log("Opps found and error");
    Countly.logException("My Customized error message");


View tracking

You can manually add your own views in your application, and each view will be visible under Analytics > Views. Below you can see two examples of sending a view using Countly.recordview function.

// record a view on your application
Countly.recordView("My Home Page");
Countly.recordView("Profile Page");

Application Performance Monitoring

Minimum Countly SDK Version

This feature is only supported by the minimum SDK version 20.4.0.

Performance Monitoring feature allows you to analyze your application's performance on various aspects. For more details please see Performance Monitoring documentation.

Here is how you can utilize Performance Monitoring feature in your apps:

First, you need to enable Performance Monitoring feature::

Countly.enableApm(); // Enable APM features.

With this, Countly SDK will start measuring some performance traces automatically. Those include app foreground time, app background time. Additionally, custom traces and network traces can be manually recorded.

Custom trace

You may also measure any operation you want and record it using custom traces. First, you need to start a trace by using the startTrace(traceKey) method:


Then you may end it using the endTrace(traceKey, customMetric)method, optionally passing any metrics as key-value pairs:

String traceKey = "Trace Key";
Map<String, int> customMetric = {
"ABC": 1233,
"C44C": 1337
Countly.endTrace(traceKey, customMetric);

The duration of the custom trace will be automatically calculated on ending. Trace names should be non-zero length valid strings. Trying to start a custom trace with the already started name will have no effect. Trying to end a custom trace with already ended (or not yet started) name will have no effect.

You may also cancel any custom trace you started, using cancelTrace(traceKey)method:


Additionally, if you need you may cancel all custom traces you started, using clearAllTraces()method:


Network trace

You may record manual network traces using therecordNetworkTrace(networkTraceKey, responseCode, requestPayloadSize, responsePayloadSize, startTime, endTime) method.

A network trace is a collection of measured information about a network request.
When a network request is completed, a network trace can be recorded manually to be analyzed in the Performance Monitoring feature later with the following parameters: 

- networkTraceKey: A non-zero length valid string
- responseCode: HTTP status code of the received response
- requestPayloadSize: Size of the request's payload in bytes
- responsePayloadSize: Size of the received response's payload in bytes
- startTime: UNIX time stamp in milliseconds for the starting time of the request
- endTime: UNIX time stamp in milliseconds for the ending time of the request

Countly.recordNetworkTrace(networkTraceKey, responseCode, requestPayloadSize, responsePayloadSize, startTime, endTime);

Getting user feedback

There are two ways of getting feedback from your users: Star rating dialog, feedback widget.

Star rating dialog allows users to give feedback as a rating from 1 to 5. The feedback widget allows to get the same 1 to 5 rating and also a text comment.

Feedback widget

Feedback widget shows a server configured widget to your user devices.


It's possible to configure any of the shown text fields and replace with a custom string of your choice.

In addition to a 1 to 5 rating, it is possible for users to leave a text comment and also leave a email in case the user would want some contact from the app developer.

Trying to show the rating widget is a single call, but underneath is a two step process. Before it is shown, the SDK tries to contact the server to get more information about the dialog. Therefore a network connection to it is needed.

You can try to show the widget after you have initialized the SDK. To do that, you first have to get the widget ID from your server:


Using that you can call the function to show the widget popup:

// Feedback Modal
countly.askForFeedback("5e425407975d006a22535fc", "close");

Star rating dialog

Star rating integration provides a dialog for getting user's feedback about the application. It contains a title, simple message explaining what it is for, a 1-to-5 star meter for getting users rating and a dismiss button in case the user does not want to give a rating.

This star-rating has nothing to do with Google Play Store ratings and reviews. It is just for getting a brief feedback from users, to be displayed on the Countly dashboard. If the user dismisses star rating dialog without giving a rating, the event will not be recorded.

Star-rating dialog's title, message and dismiss button text can be customized either through the init function or the SetStarRatingDialogTexts function. If you don't want to override one of those values, set it to "null".

// Star Rating 

Push notifications

Countly uses PhoneGap push notifications plugin. Here is the link to its installation instructions. First, please follow the installation guidelines for installing it in Android and iOS.

Here are the steps to make push notifications work:

  1. Go to
  2. Register / Login to the Firebase console. You should be logged in to
  3. Create and select a project if you haven't done before.
  4. Go to Settings > Project settings.
  5. Create an app for Android and iOS.
  6. Download the google-services.json for Android and GoogleService-Info.plist for iOS.
  7. Place both files under your root project folder. i.e. above www folder.
  8. Put these tags in config.xml file for Android and iOS:
    For Android for iOS
    <platform name="android">
       <resource-file src="google-services.json" target="app/google-services.json" />
  9. Install the push notifications plugin.
    cordova plugin add phonegap-plugin-push
  10. Build your app, and test push notifications.

Limitations of Cordova

Due to limitations of the way push is handled in a Cordova application, it's not possible to report back actions done when a push notification is received.

Push Method Implementation

First, when setting up push for the Cordova SDK, you would first select the push token mode. This would allow you to choose either test or production modes, push token mode should be set before init.

// Important call this method before init method
Countly.pushTokenType(Countly.messagingMode.DEVELOPMENT, "Channel Name", "Channel Description");
// Countly.messagingMode.DEVELOPMENT
// Countly.messagingMode.PRODUCTION
// Countly.messagingMode.ADHOC

When you are finally ready to initialize Countly push, you would call Countly.askForNotificationPermission(), this function should be call after init.

// Call this method any time.
// This method will ask for permission,
// and send push token to countly server.

Cordova code to receive notification data. Call anywhere or event before init.


Rich Push Notification

For Android, there is no special procedure required, you can install the community plugin, and it should work.

For iOS, you will need to follow these instruction:

Removing Plugin

cordova plugin remove countly-sdk-js
cordova platform remove android
cordova platform remove ios


If you get the following error during implementation (for versions before v1.0 SDK):

NSPersistentStoreCoordinator with a nil model

In this case, go to Drag and drop "Countly.xcdatamodeld" folder into your plugins folder, and then build it using Xcode.

Warning about Java

Note: As per the new release v1.0 you will need Java 1.8 to bundle the application. You will need to update the CLASSPATH environment variable of Java and Javac to Java version 1.8

If you would like to set logging, use code snippet below in your code.

// example for setLoggingEnabled

Optional parameters during initialization You can provide optional parameters that will be used during begin_session request. They must be set right after the init function so that they are set before the request is sent to the server. To set them, use the setOptionalParametersForInitialization function. If you want to set those optional parameters, this function has to be called every time the app starts. If you don't to set one off those values, leave that field null.

The optional parameters are:

  • Country code: ISO Country code for the user's country
  • City: Name of the user's city
  • Location: Comma separate latitude and longitude values, for example "56.42345,123.45325"

//setting optional parameters
    city: "Tampa",
    country: "US",
    latitude: "28.006324",
    longitude: "-82.7166183",
    ipAddress: ""

//and then call the below code
Countly.init(this, "https://YOUR_SERVER", "YOUR_APP_KEY", "YOUR_DEVICE_ID")

Looking for help?