NodeJS

Follow

This documentation shows how to use Countly NodeJS SDK to track your nodejs running device or server, like tracking your API. It applies to the SDK version 22.06.0.

Click here, to access the documentation for older SDK versions.

Countly NodeJS runs with the following node versions, and up:

Node Versions
^18 ^17 ^16 ^14.15 ^12.22

If you want to get the Countly NodeJS SDK codebase locally you can go to the GitHub repo here and download it inside your project folder by executing the lines:

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

Adding the SDK to the project

You can reach Countly NodeJS SDK npm package here. To add it to your project, you would use a command similar to these with your preferred package manager:

npm yarn
npm install countly-sdk-nodejs

After this, you can import and use Countly as you wish inside your project as described below.

SDK Integration

Minimal Setup

Wherever you want to integrate Countly NodeJS SDK, you should import 'countly-sdk-nodejs' and initialize Countly. Here, you would also need to provide your application key and server URL. Please check here for more information on how to acquire your application key (APP_KEY) and server URL.

Example basic setup would look like this:

var Countly = require('countly-sdk-nodejs');

Countly.init({
    app_key: "YOUR-APP-KEY",
    url: "https://your_server_url/"
});

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

SDK Logging

If you encounter a problem or want to see if everything is working smoothly just turning on the logs during the initialization is all you really need. You can do so by setting the debug flag as true, during the init. This way you can see the inner workings of the Countly from your console.

var Countly = require('countly-sdk-nodejs');

Countly.init({
    app_key: "YOUR-APP-KEY",
    url: "https://your_server_url/",
    debug: true
});

But sometimes you might want to see the logs only for a small time frame or some particular operation. In those situations, you can simply use setLoggingEnabled function to turn the logs on or off as you wish, just like this:

//to turn on the logs
Countly.setLoggingEnabled(true);

//some code in between
//<...>

//to turn off the logs
Countly.setLoggingEnabled(false);

SDK Data Storage

Countly stores information like requests, events and device ID locally as JSON objects before using it to ensure data consistency. Default location of this stored data is at the base of your project under a folder called Data. You can change the location or file name during the initialization by using the storage_path flag:

var Countly = require('countly-sdk-nodejs');

Countly.init({
    app_key: "YOUR-APP-KEY",
    url: "https://your_server_url/",
    // by default it is "../data/"
    storage_path: "../your_storage/path" 
});

Crash reporting

Countly also provides a way to track NodeJS errors on your server.

To automatically capture and report Javascript errors on your server, call the following function:

Countly.track_errors()

You can additionally, add more segments or properties/values to track with error reports, by providing an object with key/values to add to error reports.

Countly.track_errors({
  "facebook_sdk": "2.3",
  "jquery": "1.8"
})

Apart from reporting unhandled errors automatically, you can also report handled exceptions to server too, so you can figure out how and even if you need to handle them later on. And optionally you can again provide custom segments to be used in the report (or use the ones provided with track_error method as default ones).

Countly.log_error(error, segments);

try{
  //do something here
}
catch(ex){
  //report error to Countly
  Countly.log_error(ex);
}

To better understand what happened prior to getting an error, you can leave out breadcrumbs through out the code, on different actions. This breadcrumb will be then combined in single log and reported to server too.

Countly.add_log("user clicked button a");

Events

Adding an event

An event is a way to track any custom actions or other data you want to track from your website. You can also provide segments to be able to view breakdown of action by provided segment values.

An event consists of Javascript object with keys: * key - the name of the event (mandatory) * count - number of events (default: 1) * sum - sum to report with event (optional) * dur - duration to report with event (optional) * segmentation - an object with key/value pairs to report with event as segments

Here is an example of adding an event with all possible properties:

Countly.add_event({
  "key": "click",
  "count": 1,
  "sum": 1.5,
  "dur": 30,
  "segmentation": {
    "key1": "value1",
    "key2": "value2"
  }
});
Data passed should be in UTF-8

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

Timed Events

You can report time or duration with every event by providing dur property of the events object. But if you want, you can also let Web SDK to track duration of some specific event for you, you can use start_event and end_event methods.

First, you can start tracking event time by providing name of the event (which later on will be used as key for event object)

Countly.start_event("timedEvent")

Countly will internally mark the start of event and will wait until you end event with end_event method, setting up dur property based on how much time has passed since start_event for same event name was called.

//end event
Countly.end_event("timedEvent")

//or end event with additional data
Countly.end_event({
  "key": "timedEvent",
  "count": 1,
  "sum": 1.5,
  "segmentation": {
    "key1": "value1",
    "key2": "value2"
  }
});

Session

Beginning a session

This method would allow you to control sessions manually. Use it only, if you don't call track_sessions method.

If noHeartBeat is true, then Countly SDK won't extend session automatically, and you will need to do that manually.

Countly.begin_session(noHeartBeat);

Extending a session

By default (if noHeartBeat was not provided in begin_session) Countly SDK will extend session itself, but if you chose not to, then you can extend is using this method and provide seconds since last call begin_session or session_duration call, whatever was the last one.

Countly.session_duration(sec)

Ending a session

When visitor is leaving your app or website, you should end his session with this method, optionally providing amount of seconds since last begin session or session_duration calls, whatever was the last one.

Countly.end_session(sec)

View tracking

This method allows you to track different parts of your application, called views. You can track how much time is spent on each part of the application.

Countly.track_view("viewname");

And optionally, as the third parameter, you can provide view segments (key/value pairs) to track together with the view. There is a list of reserved segment keys that should not be used:

  • start
  • visit
  • bounce
  • end
  • name
  • domain
  • view
  • segment
  • platform
//Provide view segments
Countly.track_view("viewname", {theme:"red", mode:"fullscreen"});

Device ID management

In some cases you may want to change the ID of the user/device that you provided or Countly generated automatically, for example, when user was changed.

Countly.change_id("myNewId");

If device ID is changed without merging and consent was enabled, all previously given consent will be removed. This means that all features will cease to function until new consent has been given again for that new device ID.

In some cases, you may also need to change user's device ID in a way, that server will merge data of both user IDs (existing and new ID you provided) on the server, for e.g., when user used website without authenticating and have recorded some data, and then authenticated and you want to change ID to your internal id of this user, to keep tracking it across multiple devices.

This call will merge any data recorded for current ID and save it as user with new provided ID.

Countly.change_id("myNewId", true);

Remote Config

Remote Config feature enables you to fetch data that you have created in your server. Depending on the conditions you have set, you can fetch data from your server for the specific users that fits those conditions and process the Remote Config data in anyway you want. Whether to change the background color of your site to showing a certain message, the possibilities are virtually endless. For more information on Remote Config please check here.

Automatic Remote Config

Automatic Remote Config functionality is disabled by default and needs to be explicitly enabled. When automatic Remote Config is enabled, the SDK will try to fetch it upon some specific triggers. For example, after SDK initialization, changing device ID.

You may enable this feature by providing to the remote_config flag a callback function or by setting it to true while initializing the SDK.

If you provide a callback, the callback will be called when the Remote Config is initially loaded and when it is reloaded if you change the device_id. This callback should have two parameters, first is for error, and second is for the Remote Config object.

// in your Countly init script
Countly.init({
  app_key:"YOUR_APP_KEY",
  url: "https://try.count.ly",
debug: true, remote_config: true });

// OR // provide a callback to be notified when configs are loaded Countly.init({ app_key:"YOUR_APP_KEY", url: "https://try.count.ly",
debug: true, remote_config: function(err, remoteConfigs){ if (!err) { //we have our remoteConfigs here console.log(remoteConfigs); } } });

Manual Remote Config

If you want, you can manually fetch the Remote Config in order to receive the latest value anytime after the initialization. To do so you have to use the fetch_remote_config call. This method is also used for reloading the values for updating them according to the latest changes you made on your server.

By using this method, you can simply load the entire object or load some specific keys or omit some specific keys in order to decrease the amount of data transfer needed, assuming the values for some of the keys are large. This call will automatically save the fetched keys internally.

Fetch All Keys

Here you so not need to provide any parameters to the call but providing a callback is the recommended practice. This callback should have two parameters, first is for error, and second is for the Remote Config object.

// load the whole configuration object with a callback
Countly.fetch_remote_config(function(err, remoteConfigs){
  if (!err) {
    console.log(remoteConfigs);
// or do something else here if you want with remoteConfigs object }
});

// or whole configuration object with no params Countly.fetch_remote_config();

Fetch Specific Keys

Here the keys should be provided as string values in an array, as the first parameter in fetch_remote_config call. You can provide a callback function as a second parameter. This callback should have two parameters, first is for error, and second is for the Remote Config object.

// load specific keys only, as `key1` and `key2`
Countly.fetch_remote_config(["key1","key2"], function(err, remoteConfigs){
  if (!err) {
    console.log(remoteConfigs);
// or do something else here if you want with remoteConfigs object } });

Fetch All Except Specific Keys

Here the first parameter should be set to 'null' or 'undefined' and the keys that you want to omit must be provided as the second parameter as an array of keys as string. As a third parameter you can provide a callback function. This callback should have two parameters, first is for error, and second is for the Remote Config object.

// load all key values except specific keys, as `key1` and `key2'
Countly.fetch_remote_config(null, ["key1","key2"], function(err, remoteConfigs){
  if (!err) {
    console.log(remoteConfigs);
// or do something else here if you want with remoteConfigs object } });

Accessing Remote Config Values

You may call get_remote_config each time you would like to receive the Remote Config object of a value for a specific key or all keys from your local storage.

This method should be called once the Remote Config have been successfully loaded, or it will simply return an empty object or undefined values.

//get whole Remote Config object
var remoteConfig = Countly.get_remote_config();

//or get value for specific key like 'test'
var test = Countly.get_remote_config("test");

A/B Testing

While fetching Remote Config, the SDK will automatically enroll the user to A/B testing. For more information on A/B testing please check here.

Consent

If consents are enabled, to fetch the Remote Config data you have to provide the 'remote-config' consent for this feature to work.

User feedback

If there is any way you can get some user feedback, there is not a simple method to report collected data to Countly.

//user feedback
Countly.report_feedback({
    widget_id:"1234567890",
    contactMe: true,
    rating: 5,
    email: "user@domain.com",
    comment: "Very good"
});

 

User profiles

User details

If you have any details about the user/visitor, you can provide Countly with that information. This will allow you track each and specific user on "User Profiles" tab, which is available with Countly Enterprise Edition.

The list of possible parameters you can pass is:

Countly.user_details({
    "name": "Arturs Sosins",
    "username": "ar2rsawseen",
    "email": "test@test.com",
    "organization": "Countly",
    "phone": "+37112345678",
    //Web URL pointing to user picture
    "picture": "https://pbs.twimg.com/profile_images/1442562237/012_n_400x400.jpg", 
    "gender": "M",
    "byear": 1987, //birth year
    "custom":{
      "key1":"value1",
      "key2":"value2",
      ...
    }
 });

Modifying custom data

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

Below is the list of available methods:

Countly.userData.set(key, value) //set custom property
Countly.userData.set_once(key, value) //set custom property only if property does not exist
Countly.userData.increment(key) //increment value in key by one
Countly.userData.increment_by(key, value) //increment value in key by provided value
Countly.userData.multiply(key, value) //multiply value in key by provided value
Countly.userData.max(key, value) //save max value between current and provided
Countly.userData.min(key, value) //save min value between current and provided
Countly.userData.push(key, value) //add value to key as array element
Countly.userData.push_unique(key, value) //add value to key as array element, but only store unique values in array
Countly.userData.pull(key, value) //remove value from array under property with key as name
Countly.userData.save() //send userData to server

Application Performance Monitoring

You can report a trace using report_trace method. Contents of it depend on which trace you report.

Here is an example of how to report network trace:

//report network trace
Countly.report_trace({
    type: "network", //device or network
    name: "/some/endpoint", //use name to identify trace and group them by
    stz: 1234567890123, //start timestamp in miliseconds
    etz: 1234567890123, //end timestamp in miliseconds
    app_metrics: {
        response_time: 1000,
        response_code: 200,
        response_payload_size: 12345,
        request_payload_size: 5432
    }
});

 And here is an example of device trace:

//user built in method to report app start time
Countly.report_app_start();

//or report device trace manually
Countly.report_trace({
    type: "device", //device or network
    name: "My App", //use name to identify trace and group them by
    stz: 1234567890123, //start timestamp in miliseconds
    etz: 1234567890123, //end timestamp in miliseconds
    app_metrics: {
        duration: 1000,
    }
});

Or you can report any custom traces to provide duration:

//or report device trace manually
Countly.report_trace({
    type: "device", //device or network
    name: "Some process we launched", //use name to identify trace and group them by
    stz: 1234567890123, //start timestamp in miliseconds
    etz: 1234567890123, //end timestamp in miliseconds
    app_metrics: {
        duration: 1000,
    }
});

Other features and notes

SDK Config Parameters Explained

Here are the properties you can setup on Countly initialization

  • app_key - mandatory, App key for your app created in Countly.
  • device_id - To identify a visitor, will be auto generated if not provided.
  • url - Your Countly server url (default: "https://cloud.count.ly"), you must use your own server URL here.
  • app_version - (optional) The version of your app or website.
  • country_code - (optional) Country code for your visitor.
  • city - (optional) Name of the city of your visitor.
  • ip_address - (optional) IP address of your visitor.
  • debug - output debug info into console (default: false).
  • interval - set an interval how often to check if there is any data to report and report it (default: 500 ms).
  • fail_timeout - set time in seconds to wait after failed connection to server (default: 60 seconds).
  • session_update - how often in seconds should session be extended (default: 60 seconds).
  • max_events - maximum amount of events to send in one batch (default: 10).
  • force_post - force using post method for all requests (default: false)
  • storage_path - where SDK would store data, including id, queues, etc (default: "../data/").
  • require_consent - pass true if you are implementing GDPR compatible consent management. It would prevent running any functionality without proper consent (default: false).
  • remote_config - Enable automatic remote config fetching, provide callback function to be notified when fetching done (default: false).
  • http_options - function to get http options by reference and overwrite them, before running each request.
  • max_logs - maximum amount of breadcrumbs to store for crash logs (default: 100)
  • metrics - provide metrics override or custom metrics for this user. For more information on the specific metric keys used by Countly, check here.

Setting up properties in Countly NodeJS SDK is as follows (if you have your own server, use it instead of try.count.ly):

Countly.init({
    debug:false,
    app_key:"YOUR_APP_KEY",
    device_id:"1234-1234-1234-1234",
    url: "https://try.count.ly",
    app_version: "1.2",
    country_code: "LV",
    city: "Riga",
    ip_address: "83.140.15.1",
    http_options: function(options){
        options.headers["user-agent"] = "Test";
    },
    metrics:{
        _os: "Ubuntu",
        _os_version: "16.04",
        _device: "aws-server"
    }
});

SDK Internal Limits

Countly is highly customizable and let's you take a huge part at the control of the system in multiple ways. From customizing segmentation values to changing event keys. Great liberty comes with the cost of great responsibility. As a sanity check measure Countly relies on internal limits to get a hold of the free flow of values, keys, character and more. These internal limits are again customizable at initialization and current limits and their default values are as follows:

  • maxKeyLength - 128 chars. Keys that exceed this limit will be truncated.
    • This is used for setting the maximum size of all string keys including:
    • - event names
    • - view names
    • - custom trace key name (APM)
    • - custom metric key (apm)
    • - segmentation key (for all features)
    • - custom user property
    • - custom user property keys that are used for property modifiers (mul, push, pull, set, increment, etc)
  • maxValueSize - 256 chars. Values that exceed this limit will be truncated.
    • This is used for setting the maximum size of all values in key-value pairs including:
    • - segmentation value in case of strings (for all features)
    • - custom user property string value
    • - user profile named key (username, email, etc) string values. Except "picture" field, that has a limit of 4096 chars
    • - custom user property modifier string values. For example, for modifiers like "push", "pull", "setOnce", etc.
    • - breadcrumb text
    • - manual feedback widget reporting fields (reported as event)
    • - rating widget response (reported as event)
  • maxSegmentationValues - 30 dev entries. Entries that exceed this limit will be removed.
    To set the maximum amount of custom segmentation that can be recorded in one event.
  • maxBreadcrumbCount - 100 entries. If the limit is exceeded, the oldest entry will be removed.
    To limit the amount of breadcrumbs that can be recorded before the oldest one is deleted from the logs.
  • maxStackTraceLinesPerThread - 30 lines. Lines that exceed this entry will be removed.
    Sets the maximum number of stack trace lines that can be recorded per thread.
  • maxStackTraceLineLength - 200 chars. Lines that exceed this limit will be truncated.
    This can set the maximum number of characters that is allowed per stack trace line. This also limits the crash message length.

To change these default values, all you have to do is to set the properties during the initialization:

Countly.init({
    app_key:"YOUR_APP_KEY",
    url: "https://try.count.ly",
    max_key_length: 500,
    max_value_size: 12,
    max_segmentation_values: 23,
    max_breadcrumb_count: 80,
    max_stack_trace_lines_per_thread: 50,
    max_stack_trace_line_length: 300
});

Setting Maximum Request Queue Size

When you initialize Countly, you can specify a value for the queueSize flag. This flag limits the number of requests that can be stored in the request queue when the Countly server is unavailable or experiencing connection problems.

If the server is down, requests sent to it will be queued on the device. If the number of queued requests becomes excessive, it can cause problems with delivering the requests to the server, and can also take up valuable storage space on the device. To prevent this from happening, the queueSize flag limits the number of requests that can be stored in the queue.

If the number of requests in the queue reaches the queueSize limit, the oldest requests in the queue will be dropped, and the newest requests will take their place. This ensures that the queue doesn't become too large, and that the most recent requests are prioritized for delivery.

If you do not specify a value for the queueSize flag, the default setting of 1,000 will be used.

Countly.init({
    app_key:"YOUR_APP_KEY",
    url: "https://try.count.ly",
    queueSize: 5000
});

Attribution

When using Countly attribution analytics, you can also report conversion to Countly server, for e.g., when visitor purchased something or registered.

Note: that conversion for each user may be reported only once, all other conversions will be ignored for this same user

//or provide campaign id yourself
Countly.report_conversion("MyCampaignID");

Make raw request

If you are switching between users a lot, or changing some other data, which is hard to handle over multiple processes, etc. You can simply make a raw request with all possible SDK parameters described in API reference

Countly.request({
  app_key:"somekey", 
  devide_id:"someid", 
  events:"[{'key':'val','count':1}]", 
  metrics:"{'_os':'Linux'}",
  begin_session:1
});

 

Looking for help?