This document explains how to install Countly SDK for Windows desktop applications. It applies to version 20.11.0.
Minimum Windows version
The Countly Windows SDK supports the following operating systems and .NET versions:
- Windows 8.1
- Windows 10
- Windows 10 Mobile
- .NET 3.5
- .NET 4.0 Client Profile
- .NET 4.5 and above
- .NET Standard 2.0
Older documentation
To access the documentation for version 20.05 click here.
In order to set up Countly SDK in your Windows app, follow these steps:
- In Solution Explorer open context menu on References - Manage NuGet Packages.
- Select nuget.org in Package source.
- Type Countly in search box.
- Select Countly Analytics from results list and click Install button.
The usage of the SDK requires a connection to the server. This connection usually is access to the internet.
SDK sample app
The Countly github page for this SDK contains also sample projects. You should be able to download them to test the basic functionality of this SDK and make sure you are using it correct in case you encounter any problems in your application
The project page can be found here
SDK Integration
Minimal Setup
Before you can use any Countly functionality, you need to call Countly.Instance.Init
to initiate the SDK.
To that Init
call, you need to pass a CountlyConfig
object where you set up your relevant configuration.
//create the Countly init object
CountlyConfig cc = new CountlyConfig();
cc.serverUrl = "http://YOUR_SERVER";
cc.appKey = "YOUR_APP_KEY";
cc.appVersion = "1.2.3";
//initiate the SDK with your preferences
Countly.Instance.Init(cc);
appKey - (Mandatory) The “App Key” for the app that you created on the Countly server. Example: 124qw3er5u678qwef88d6123456789qwertyui123.
serverUrl - (Mandatory) The URL of the Countly server where you are going to post your requests. Example: https://try.count.ly/
Note:The SDK targets multiple profiles. Therefore for some of them, there are feature differences. Either with additional function calls or with additional fields in the CountlyConfig object.
Providing the application key
Also called "appKey" as shorthand. The application key is used to identify for which application this information is tracked. You receive this value by creating a new application in your Countly dashboard and accessing it in its application management screen.
Note: Ensure you are using the App Key (found under Management -> Applications) and not the API Key. Entering the API Key will not work.
Providing the server URL
If you are using Countly Enterprise trial servers, use https://try.count.ly
, https://us-try.count.ly
or https://asia-try.count.ly
It is basically the domain from which you are accessing your trial dashboard.
If you use both Countly Lite and Countly Enterprise, use your own domain name or IP address, such as https://example.com or https://IP (if SSL has been set up).
SDK logging / debug mode
In order to make sure that requests to Countly are sent correctly, you need to enable logging using the following:
Countly.IsLoggingEnabled = true;
You can turn it on and off in any place of your code. This will print debug messages and give better insight into the inner workings of the SDK.
SDK data storage
Cached requests and other SDK relevant information is stored in files in a named folder. All platform targets except .net40 call that folder "countly", .net40 calls that folder "countly_data".
All platform targets except .net35 will use IsolatedStorage for that. .net35 will store that named folder in the same folder as the executable by default.
If there are permission limitations for your app targeting .net35, then there is a call where you can change the path for the named storage folder. You can change that by using this:
Countly.SetCustomDataPath("C:\path\to\new\folder\");
SDK notes
Additional info for Windows Store project setup
Windows Store build has been removed
The following section of documentation will be removed soon
As the Countly SDK requires Internet (Client & Server) to be enabled. Open Package.appxmanifest, click on Capabilities section and make it enabled
Add using CountlySDK;
in the App.xaml.cs usings section
You need to call Countly.Instance.SessionBegin();
each time when app is activated and await Countly.EndSession();
when app is deactivated.
That would mean adding SessionBegin
calls to OnLaunched
, OnActivated
and OnResuming
events and SessionEnd
calls to OnLaunched
event which is already prepared for you by Visual Studio in App.xaml.cs
file. Add initialization code before page navigation happens.
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
...
//create the Countly init object
CountlyConfig cc = new CountlyConfig();
cc.serverUrl = "http://YOUR_SERVER";
cc.appKey = "YOUR_APP_KEY";
cc.appVersion = "1.2.3";
cc.application = this
//initiate the SDK with your preferences
await Countly.Instance.Init(cc)
if (rootFrame.Content == null)
{
// Removes the turnstile navigation for startup.
if (rootFrame.ContentTransitions != null)
{
this.transitions = new TransitionCollection();
foreach (var c in rootFrame.ContentTransitions)
{
this.transitions.Add(c);
}
}
...
}
Add override
method called OnActivated
to App.xaml.cs
file and call Countly.Instance.SessionBegin();
inside
protected override void OnActivated(IActivatedEventArgs args)
{
await Countly.Instance.SessionBegin();
}
Subscribe to application Resuming
method in App
constructor.
public App()
{
this.InitializeComponent();
this.Resuming += this.OnResuming;
this.Suspending += this.OnSuspending;
}
private void OnResuming(object sender, object e)
{
await Countly.Instance.SessionBegin();
}
Update OnSuspending
method created by Visual Studio in App.xaml.cs
file to handle Countly deactivation logic. Make sure you use async/await statements, so app will not be closed before Countly receives end session
event
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
await Countly.Instance.SessionEnd();
deferral.Complete();
}
Additional info for UWP project setup
It's possible to register a unhandled crash handler during SDK initialization. To do that, you need to provide a link to your application.
var cc = new CountlyConfig
{
serverUrl = "SERVER_URL",
appKey = "APP_KEY",
appKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX
appVersion = "1.2.3",
application = referenceToApplication //provide link to your application
};
await Countly.Instance.Init(cc);
Crash reporting
Automatic crash handling
Countly SDK has an ability to automatically collect crash reports which you can examine and resolve later on the server. This applies for Windows Store apps, on other platforms you should subscribe to unhandled exceptions handler manually. Exception details and device properties will be sent on next app launch.
Handled exceptions
To log handled exceptions, which are not fatal, use Countly.RecordException;
the method. You can provide custom properties for crash providing key/value object to store for this crash report and server will segment values for you for the same crash.
Dictionary<string, string> customInfo = new Dictionary<string, string>
{
{ "customData", "importantStuff" }
};
Countly.RecordException(ex.Message, ex.StackTrace, customInfo);
Crash breadcrumbs
Throughout your app, you can leave crash breadcrumbs Mandatory that would describe previous steps that were taken in your app before the crash. After a crash happens, they will be sent together with the crash report.
The following command adds a crash breadcrumb:
Countly.AddBreadCrumb("breadcrumb");
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.
Recording events
Here is a quick way to record an event:
Countly.RecordEvent("event-key");
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 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.
First, add using CountlySDK;
in the usings section
1. Event key and count
Countly.RecordEvent("purchase", 3);
2. Event key, count and sum
Countly.RecordEvent("purchase", 3, 0.99);
3. Event key and count with segmentation(s)
Segmentation segmentation = new Segmentation();
segmentation.Add("country", "Germany");
segmentation.Add("app_version", "1.0");
Countly.RecordEvent("purchase", 3, segmentation);
Countly.RecordEvent("purchase", 1, 0.99);
4. Event key, count and sum with segmentation(s)
Segmentation segmentation = new Segmentation();
segmentation.Add("country", "Germany");
segmentation.Add("app_version", "1.0");
Countly.RecordEvent("purchase", 3, 2.97, segmentation);
5. Event key, count, sum, duration with segmentation(s)
Segmentation segmentation = new Segmentation();
segmentation.Add("country", "Germany");
segmentation.Add("app_version", "1.0");
Countly.RecordEvent("purchase", 3, 2.97, 122.45, segmentation);
Sessions
Manual sessions
After you have initiated the SDK, call Countly.Instance.SessionBegin()
when you want to start tracking the user session. Usually, that is called in the entry point of the app.
Call Countly.Instance.SessionEnd()
before the app is closed to mark the end of the apps session.
The SDK will send an update request every 60 seconds, to track how long the session is.
That time is tracked using an internal timer. Some usage scenarios (like using the SDK in a console application) can prevent the timer from working. In those circumstances, you can manually call Countly.Instance.SessionUpdate(elapsedTime)
to track the passage of time. You should still call it about every minute.
//start the user session
Countly.Instance.SessionBegin();
//end the user session
Countly.Instance.SessionEnd();
//update the session manually
int elapsedTime = 60;//elapsed time in seconds
Countly.Instance.SessionUpdate(elapsedTime);
View tracking
Manual view recording
The SDK provides a call to record views in your application. More information about how to use them can be found here. You only need to provide the name for the view.
Countly.Instance.RecordView("Some View");
Device ID management
To link events, sessions, crashes, etc to a user, a deviceId is used. It is usually generated by the SDK. It is then saved locally and then reused on every init unless the developer supplies its own device Id.
Ideally, the same device Id would be generated on the same device when using the same generation method. This way it would be possible to track users on reinstalls.
Device ID generation
The SDK supports multiple ways for generating that ID, each with its pro's and cons and some limited to a specific compilation target:
- cpuId - [net35, net40] (we recommend against using this) uses the OS-provided CPU id info to generate a hash that is used as an id. It should be possible to generate the same id on a reinstall if the CPU stays the same. On virtual machines and Windows 10 devices are not guaranteed to be unique and generate the same id and therefore device id conflicts
- multipleWindowsFields - [net35, net40] uses multiple OS-provided fields (CPU id, disk serial number, windows serial number, windows username, mac address) to generate a hash that would be used as the device Id. This method should regenerate the same id on a reinstall, provided those source fields do not change
- windowsGUID - [all platforms] generates a random GUID that will be used as a device id. Very high chance of being unique. Will generate a new id on a reinstall.
- winHardwareToken - [windows 8 store apps] uses the hardware identification token provided by the OS to generate a hash that will be used as an id. Should be the same on a reinstall. Very high chance of being unique
- developerSupplied - The device Id was provided by the developer. Used in cases where developers want to use an id tied to their internal systems/servers.
Device id and generation method can be provided during SDK init. Those values can also bet not set, then the default method for that target will be used.
//create the Countly init object
CountlyConfig cc = new CountlyConfig();
cc.serverUrl = "http://YOUR_SERVER";
cc.appKey = "YOUR_APP_KEY";
cc.appVersion = "1.2.3";
cc.developerProvidedDeviceId = "use@email.com";
//initiate the SDK with your preferences
Countly.Instance.Init(cc);
Changing device ID
It is possible to change the device Id after the app is initiated. It can be done with a server-side merge and without one. In both cases, the new id will be used on further app launches.
If it is done without a server-side merge, then the previous session will end and a new session will be started with the new id.
With a server-side merge, the events, session information and etc will be assigned to the new device id.
//changing without a server side merge
Countly.Instance.ChangeDeviceId("newId", false);
Countly.Instance.ChangeDeviceId("newIdAgain");
//changing with a server side merge
Countly.Instance.ChangeDeviceId("ThisIsUnique", true);
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
After SDK initialization, you can set location info.
//set user location
String gpsLocation = "63.445821, 10.898868";
String ipAddress = "13.56.33.12";
String country_code = null;
String city = null;
Countly.Instance.SetLocation(gpsLocation, ipAddress, country_code, city);
If there are fields you don't want to set, set them to null. If you want to reset a field, set it to an empty string.
If no location is provided, it will be approximated by using GeoIP.
Disabling location
Users might want to opt-out of location tracking. To do so call:
//disable location tracking
Countly.Instance.DisableLocation();
This will also erase all location info server side.
User Profiles
This feature is available with Countly Enterprise subscription. For information about User Profiles, review this documentation.
Setting predefined values
The SDK allows you to upload specific data related to a user to the Countly server. You may set the following predefined data for a particular user:
- Name: Full name of the user.
- Username: Username of the user.
- Email: Email address of the user.
- Organization: Organization the user is working in.
- Phone: Phone number.
- Picture: Web-based Url for the user’s profile.
- Gender: Gender of the user (use only single char like ‘M’ for Male and ‘F’ for Female).
- BirthYear: Birth year of the user.
You can save info about user tracking data is related to. Countly provides Countly.UserDetails
an object that exposes user-related properties
Each time you change a property value, Countly syncs it with a server. If you set value as null
, you will delete the property.
Example:
Countly.UserDetails.Name = "John";
// set name to JohnCountly.UserDetails.Name = "null";
// remove name
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.
You can provide custom properties for user using Custom
object
Countly.UserDetails.Custom.Add("city", "london");
Setting User picture
Additionally, you can upload a picture of the user to the server. Accepted picture formats are .png, .gif and .jpeg and picture will be resized to maximal 150x150 dimensions.
Countly.UserDetails.UploadUserPicture(picture_stream);
Note: dots (.) and dollar signs ($) in key names will be stripped out.
User consent
If you want to comply with GDPR or similar privacy requirements, there is functionality to manage user consent to features.
More information about GDPR can be found here.
Setup during init
By default the requirement for consent is disabled. To enable it, you have to do it with the CountlyConfig object by setting consentRequired
to true
.
//create the Countly init object
CountlyConfig cc = new CountlyConfig();
cc.serverUrl = "http://YOUR_SERVER";
cc.appKey = "YOUR_APP_KEY";
//enable consent
cc.consentRequired = true;
//initiate the SDK with your preferences
Countly.Instance.Init(cc);
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 the consent status of a feature is changed, that change will be sent to the Countly server.
Consent for features is not persistent and will have to be set every time while initializing countly. Therefore the storage and persistence of given consent fall on the SDK integrator.
Feature names in this SDK are stored as an enum called ConsentFeatures
.
Features currently supported by this SDK are:
- sessions - tracking when, how often and how long users use your app
- events - allow sending events to the server
- location - allow sending location information
- crashes - allow tracking crashes, exceptions, and errors
- users - allow collecting/providing user information, including custom properties
In case consent is required, you may give consent to features before the SDK Init call. These features consents are not persistent and must be given on every restart.
//create the Countly init object
CountlyConfig cc = new CountlyConfig();
cc.serverUrl = "http://YOUR_SERVER";
cc.appKey = "YOUR_APP_KEY";
//enable consent
cc.consentRequired = true;
//set consent features
Dictionary<ConsentFeatures, bool> consent = new Dictionary<ConsentFeatures, bool>();
consent.Add(ConsentFeatures.Crashes, true);
consent.Add(ConsentFeatures.Events, false);
consent.Add(ConsentFeatures.Location, true);
consent.Add(ConsentFeatures.Sessions, false);
consent.Add(ConsentFeatures.Users, false);
cc.givenConsent = consent;
//initiate the SDK with your preferences
Countly.Instance.Init(cc);
Changing consent
Consent can also be changed at any other moment in the app after init:
//preparing consent features
Dictionary<ConsentFeatures, bool> consent = new Dictionary<ConsentFeatures, bool>();
consent.Add(ConsentFeatures.Crashes, true);
consent.Add(ConsentFeatures.Events, false);
consent.Add(ConsentFeatures.Location, true);
//changing consent
Countly.Instance.SetConsent(consent);
Other features
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
- Current hour
- Current day of week
- Current timezone
- SDK version
- SDK name
* If sessions are used then it would record the session start time, end time, and duration
* If sessions are used then also device metrics are collected which contains:
- Screen resolution
- Screen density
- OS name
- OS version
- App version
- Locale identifier
* When events are recorded, the following information collected:
- Time of event
- Current hour
- Current day of week
* If crash tracking is enabled, it will collect the following information at the time of the crash:
- OS name
- OS version
- Device resolution
- App version
- Time of the crash
- Crash stack trace
- Error description
- Total RAM
- If there is a network connection
Any other information like data in events, location, user profile information, or other manual requests depends on what the developer decides to provide and is not collected by the SDK itself.
Comments
Please sign in to leave a comment.