Integration

Kumulos provides an SDK in the form of a NuGet package to ease the integration of the Kumulos Analytics, Push Notification, Crash Reporting and Build features into your Xamarin apps. This guide provides an overview of setting up the SDK for your project and sample usage.

Integrate SDK components and dependencies

The Kumulos SDK is an open source project hosted on Github. You can find a link to the project in your agency console and here: https://github.com/Kumulos/KumulosSdkXamarin. It is distributed via a NuGet package for referencing in your apps.

You must then add extra configuration for your Android project, in [MyProjectName].Android.csproj

<AndroidDexTool>d8</AndroidDexTool>

It is possible to add the Com.Kumulos NuGet package only to your Xamarin Forms project, it will then be available via the abstraction layer to your iOS and Android projects, however for the Android project it is advisable to add the package again so that it can manage its dependencies for Firebase Messaging automatically.

Initialization

To configure the SDK for use you need to initialize it with your app's API credentials, and configure it for the features you wish to use.

using Com.Kumulos;
using Com.Kumulos.Abstractions;

...

Kumulos.CurrentConfig.AddKeys("YOUR_API_KEY", "YOUR_SECRET_KEY")
    .EnableInAppMessaging(InAppConsentStrategy.AutoEnroll);

Kumulos.Current.Initialize(Kumulos.CurrentConfig);

Your API Key and Secret Key can be obtained from the App Dashboard in your agency console.

You don't need to initialize the Kumulos SDK every time you wish to make an API call. It only needs to be initialized once, after which it will remember the API key and secret key you've given it the first time.

iOS

The initialization should be performed early in your FinishedLaunching method in AppDelegate.cs

Android

Initialization should be performed by overriding the MainApplication class and adding extra initialization after the framework OnCreate method has completed.

using System;
using Android.App;
using Com.Kumulos;
using Com.Kumulos.Abstractions;

namespace TestApp.Droid
{
    [Application]
    public class MainApplication : Application
    {
        public MainApplication(IntPtr javaReference, Android.Runtime.JniHandleOwnership transfer) : base(javaReference, transfer)
        {
        }

        public override void OnCreate()
        {
            base.OnCreate();

            Kumulos.CurrentConfig.AddKeys("YOUR_API_KEY", "YOUR_SECRET_KEY")
                .EnableInAppMessaging(InAppConsentStrategy.AutoEnroll);

            Kumulos.Current.Initialize(Kumulos.CurrentConfig);
        }
    }
}

Checking installs of your App

When you run your app on a simulator or install your app on a device, you can check that the SDK has been initialized correctly by selecting the app and clicking the Installs tab to see the ten most recent installs of your app. Click on any install to see more information.

Recent installs

If you experience any difficulties integrating an SDK or initializing the Kumulos client, please don't hesitate to contact support who are standing by to help!

Installation ID

When initialized for the first time, the Kumulos SDK will create a unique identifier for the current installation. This identifier can be used to target push notifications to a specific device via KScript or the Push Notifications API.

In order to retrieve this identifier, simply access the property from the SDK:

string id = Kumulos.Current.InstallId

Once you have the installation ID, you can send it to your app's backend to be used later for push targeting. For more information about push targeting, please see the KScript Documentation or push notification documentation as appropriate.

Analytics

So long as you initialize the SDK at some point in your app's lifecycle, Kumulos will automatically record analytics data such as the device model, operating system version and more, available in Analytics & Reporting for your app.

Session Analytics

Kumulos records sessions based on application foreground and background events. When an app enters the background, Kumulos will wait for a configurable idle period. If there are no more foreground events during that idle period, the current session will be closed.

Session analytics

You can configure the idle period to suit your app's use-case. By default the idle period is 40 seconds of inactivity. The idle period does not count towards session duration calculations.

To adjust the idle period, you can configure the SDK as follows:

Kumulos.CurrentConfig.AddKeys("YOUR_API_KEY", "YOUR_SECRET_KEY")
    .SetSessionIdleTimeout(120);

Kumulos.Current.Initialize(Kumulos.CurrentConfig);

Note that due to background task limits, in practise the idle timeout can only reasonably be up to a few minutes

Event Tracking

Kumulos allows you to track custom analytics events that can be used as a trigger to fire automation rules (e.g. to trigger a push notification) or as steps in a funnel to track conversion through key user journeys in your app.

Track conversion

To track a custom analytics event, use Kumulos.Current.TrackEvent as follows:

var props = new Dictionary<string, object>
{
   { "productId", 404 }
};
Kumulos.Current.TrackEvent("product.purchased", props);

Event tracking is available offline as all events are persisted locally before being synced to the server in batches in the background.

A similar method TrackEventImmediately will immediately start an event sync rather than waiting for the next time the app is backgrounded.

Checking events from your App

When you run your app on a simulator or install your app on a device, you can check that the SDK is recording events correctly by selecting the app and clicking the Installs tab to see the ten most recent installs of your app. Click on any install and then click on the Events tab.

Install events

Alternatively, to see counts of all analytics events, including system events such as opened a push notification, recorded by installs of the app in the last 30 days, expand 'Analytics' and click 'Explore' in the left menu. For comparison, the total number of sessions in the same period is shown.

Analytics Explorer

User Association

Kumulos allows associating a user identifier with the current installation ID. This user identifier is useful for performing analytics aggregations & analyses at the user level, for example, funnels completed by users across multiple devices. You can also optionally associate a collection of attributes with the user.

To associate the current app installation with a user, you can use the helper method as shown below:

Kumulos.Current.AssociateUserWithInstall("unique-user-identifier");

User association is time-aware, so in the case of two different users sharing a device to log in to the app, their user IDs will be associated with the same install for the time between subsequent calls to the helper method. For example:

Kumulos.Current.AssociateUserWithInstall("Bob")

// This event will belong to Bob
var firstProps = new Dictionary<string, object>
{
   { "productId", 404 }
};
Kumulos.Current.TrackEvent("product.purchased", firstProps);
Kumulos.Current.AssociateUserWithInstall("Alice")

// This event will belong to Alice
var secondProps = new Dictionary<string, object>
{
   { "productId", 405 }
};
Kumulos.Current.TrackEvent("product.purchased", secondProps);

User Identifier

When initialized for the first time, the Kumulos SDK will create an unauthenticated user for the current device based on the installation Id. This can be updated at any time by associating your own user identifier as seen above, in order to retrieve this identifier, simply access the property from the SDK:

string identifier = Kumulos.Current.UserIdentifier;

Clearing association

If your app supports signing out or you wish to clear the current user association from the device then you can call the helper method, any subsequent events occurring on the device will be attributed to an anonymous user until the next association occurs.

Kumulos.Current.ClearUserAssociation();

Messaging

Kumulos provides powerful multi-channel messaging services to reach your users. By initializing the SDK you can quickly and easily receive both push notifications to re-engage your users as well as feature-rich In-App messages.

Configuration & Setup

To integrate into your Xamarin project, you have to complete the following steps:

  1. Integrate and Initialize the Kumulos SDK
  2. Set up FCM and APNS
  3. Configure Push in the Kumulos Agency Console
  4. Integrate SDK components with your Xamarin project
  5. Register to receive push and in-app messages from your app

In order to send push notifications to iOS devices with Kumulos, you'll need to create certificates in the Apple Developer Member Center. The steps to complete this are shown in the video guide.

Configuring APNS for iOS with Kumulos

In order to enable push notifications for Android with Kumulos, you'll need to set up an FCM project and configure push for your app. These steps are shown in the following video guide.

Enabling Push Notifications for Android

The next step is to add the google-services.json file to the root directory of your android project:

  1. Copy google-services.json to the project folder.
  2. Add google-services.json to the app project (click Show All Files in the Solution Explorer, right click google-services.json, then select Include in Project).
  3. Select google-services.json in the Solution Explorer window.
  4. In the Properties pane, set the Build Action to GoogleServicesJson.

This process will automatically update your AndroidManifest.xml file as part of your project build.

In order for pushes to be handled by your registered receiver you must add a reference to your android manifest, inside the Application section.

<application android:label="MyApp.Android">
...
<service android:name="com.kumulos.android.FirebaseMessagingService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>
...
</application>

Next, you must create an instance of PushBroadcastReceiver, with the appropriate attributes for Xamarin to link it at build time.

using Android.App;
using Android.Content;
using Com.Kumulos.Android;

namespace FormsApp.Droid
{
    [BroadcastReceiver(Enabled = true, Exported = false)]
    [IntentFilter(new[] { ActionPushReceived, ActionPushOpened })]
    public class MyPushReciever : PushBroadcastReceiver
    {
    }
}

Finally configure your SDK for In-App and opt-in the device for Push notifications, on iOS this will prompt the user to accept, on Android the permission has been given as part of the app installation.

Kumulos.CurrentConfig.AddKeys("YOUR_API_KEY", "YOUR_SECRET_KEY")
    .EnableInAppMessaging(InAppConsentStrategy.AutoEnroll);

Kumulos.Current.Initialize(Kumulos.CurrentConfig);
Kumulos.Current.RegisterForRemoteNotifications();

Advanced

Checking integration status

When you run your app on a simulator or install your app on a device, you can check that the install has successfully registered for push notifications by selecting the app and clicking the Installs tab to see the ten most recent installs of your app. Click on any install and then click on Push tab.

Install push details

If you would like your users to opt-in to receive In-App messages you can configure the SDK during initialization to make opt-in explicit by setting the strategy, then calling the SDK helper to manage their consent.

using Com.Kumulos;
using Com.Kumulos.Abstractions;

...

Kumulos.CurrentConfig.AddKeys("YOUR_API_KEY", "YOUR_SECRET_KEY")
    .EnableInAppMessaging(InAppConsentStrategy.ExplicitByUser);
Kumulos.Current.Initialize(Kumulos.CurrentConfig);

Kumulos.Current.UpdateInAppConsentForUser(true);

Deep-linking for In-App

In-App messages allow you to hand-off to your own code via deep-linking action buttons. When tapped, these buttons pass control to the defined deep-link handler, including their defined data payload (configured in the In-App message composer for the action button).

If you want to handle deep-links with custom data payloads as part of an In-App message you can create a class that implements the IInAppDeepLinkHandler interface.

using System;
using Com.Kumulos.Abstractions;
using Newtonsoft.Json.Linq;

namespace TestApp
{
    public class DeepLinkHandler : IInAppDeepLinkHandler
    {
        public void Handle(JObject data)
        {
            // Custom code
        }
    }
}

and add it to your configuration options during SDK initialization.

 var deepLinkHandler = new IInAppDeepLinkHandlerImplementation();

Kumulos.CurrentConfig.AddKeys("YOUR_API_KEY", "YOUR_SECRET_KEY")
    .EnableInAppMessaging(InAppConsentStrategy.AutoEnroll)
    .SetInAppDeepLinkHandler(myDeepLinkHandler);

Inbox for In-App Messages

When configured to save in the users inbox messages can be retrieved for future display by the helper methods.

InAppInboxItem[] items = Kumulos.Current.InboxItems;
Kumulos.Current.PresentInboxMessage(items[0]);

Customizing iOS Push Behavior

If you would like to perform additional work when the app is opened via a push notification or when a notification is received while the app is foregrounded you can access and set the additional helper methods by casting the config in your iOS project and set the handler blocks accordingly.

var config = (KSConfigImplementation)Kumulos.CurrentConfig;
config.SetPushOpenedHandler((Com.Kumulos.iOS.KSPushNotification notification) =>
{
    //Custom Code
});

Customizing Android Push Behavior

The push broadcast receiver class that was implemented during the setup process has several methods which can be overridden to provide more control over the notification presentation and handling and insert custom code before or after the base implementation.

using Android.App;
using Android.Content;
using Com.Kumulos.Android;

namespace TestApp.Droid
{
    [BroadcastReceiver(Enabled = true, Exported = false)]
    [IntentFilter(new[] { ActionPushReceived, ActionPushOpened })]
    public class MyPushReciever : PushBroadcastReceiver
    {
        protected override Intent GetPushOpenActivityIntent(Context context, PushMessage pushMessage)
        {
            return base.GetPushOpenActivityIntent(context, pushMessage);
        }

        protected override Notification BuildNotification(Context context, PushMessage pushMessage)
        {
            return base.BuildNotification(context, pushMessage);
        }

        protected override Intent GetBackgroundPushServiceIntent(Context context, PushMessage pushMessage)
        {
            return base.GetBackgroundPushServiceIntent(context, pushMessage);
        }
    }
}

Remove device tokens from Kumulos

To remove the token from Kumulos, call this method.

Kumulos.Current.UnregisterDeviceToken();

Channels

You can create and manage subscriptions to push notification Channels via the SDK. Channels allow your users to define preferences for the type of content they would like to receive via notifications.

You can manage all channel interactions via the Kumulos.Current.PushChannels class.

Kumulos.Current.PushChannels.ListChannels().ContinueWith(r =>
{
    Console.WriteLine(r.Result);
});

Helper methods are then available for creating, listing and managing subscriptions to channels. Each helper is async and can be awaited or given a continue block.

public Task<object> ClearSubscriptions ();
public Task<object> CreateChannel (string uuid, bool subscribe, string name, bool showInPortal, Dictionary<string, object> meta);
public Task<object> ListChannels ();
public Task<object> SetSubscriptions (string[] uuids);
public Task<object> Subscribe (string[] uuids);
public Task<object> Unsubscribe (string[] uuids);

Channel visibility and meta data can be controlled when they are created.

Location Tracking

You can send Kumulos location updates and use this to trigger automations such as sending push notifications when an install enters a GeoFence.

iOS

Once you have created a CLLocationManagerDelegate you can use the helper method in the SDK to send location updates to Kumulos, a reference implementation of a LocationManager has been provided.

CLLocation location;
Kumulos.Current.SendLocationUpdate(location.Coordinate.Latitude, location.Coordinate.Longitude);

How you configure the Core Location services for iOS depends on the specific use case of your app. You should consider both accuracy and battery life when making this decision. Refer to the Apple documentation for details of how to configure location services.

To use the reference implementation simply construct a LocationManager and maintain a reference to it for the lifetime of your app.

using Com.Kumulos;
...
public class AppDelegate : UIApplicationDelegate
{
...
    public static LocationManager Manager { get; set; }
...
    Manager = new LocationManager();
    Manager.StartLocationUpdates();
...
}

Android

A helper method is supplied in the SDK to send a location update to Kumulos.

Kumulos.Current.SendLocationUpdate(double lat, double lng);

iBeacon Detection

You can send Kumulos beacon proximity updates and use these to trigger automations such as sending a push notification when an install is in proximity to a beacon.

How you configure the Core Location services for iOS depends on the use case for your app and you should consider throttling how regularly these events are transmitted for both battery life and network traffic.

The Kumulos SDK provides a helper method to notify our services of proximity to a detected beacon.

Kumulos.Current.TrackiBeaconProximity(CLBeacon beacon);

The SDK includes a reference implementation of setting up and tracking beacons, although this does not feature any throttling and is designed to provide a quick start for development.

Eddystone Beacon Detection

You can send Kumulos eddystone proximity updates via the provided helper method in the SDK.

Kumulos.Current.TrackEddystoneBeaconProximity(string namespaceHex, string instanceHex, double distanceMetres);

Build

You can call API methods defined in the Kumulos Build service using the Kumulos.Current.Build.CallAPI method.

Parameters are provided as a list of key value pairs. Simply add a pair for each parameter that your API method expects and provide it as the second parameter to the CallAPI method.

var parameters = new List<KeyValuePair<string, string>>
{
    new KeyValuePair<string, string>("param1", "foo"),
    new KeyValuePair<string, string>("param2", "bar")
};

Kumulos.Current.Build.CallAPI("myAPIMethod", parameters).ContinueWith(t =>
{
    ApiResponse response = t.Result;
});

A threading task will be returned, which your code can continue with once the network operation has completed. The Result of the task will be an ApiResponse object. This object can then be inspected for the payload of the API method, its response code and message.

For an insert operation the response object will be a simple integer which can be cast.

For select operations the return type is a Newtonsoft JSON array, an example of reading this into a specific type could be.

public class OptionType
{
    public string title { get; set; }
    public int displayOrder { get; set; }
}

Kumulos.Current.Build.CallAPI("getOptionTypesWithOptions", parameters).ContinueWith(t =>
{
   ApiResponse response = t.Result;
   var array = (Newtonsoft.Json.Linq.JArray)response.payload;
   foreach(var item in array) {
       var type = item.ToObject(typeof(OptionType));
   }
});

Handling data fields

Kumulos stores data fields as base64 encoded data, so if you receive data from Kumulos, you will have to base64 decode it to access the original data. Similarly, when you send data to Kumulos, you should base64 encode it before transport.

Crash

Crash reporting allows you to track unhandled exceptions in your app, and optionally log any caught exceptions for further investigation. Crash reporting is not enabled by default, and can be optionally enabled at both the native OS level and as a global exception handler for your managed code.

Note that crash reporting is not available whilst connected to a debugger, but it does work with debug builds.

Native layer crash reporting

To enable the OS level crash reporting in iOS simply enable it as part of the configuration for the SDK.

var config = Kumulos.CurrentConfig.AddKeys("YOUR_API_KEY", "YOUR_SECRET_KEY").EnableCrashReporting();
Kumulos.Current.Initialize(config);

Native crash reporting will catch all exceptions, including unhandled exceptions raised from the Mono application, although these will include references to managed code and can be harder to parse.

Managed code crash reporting

You can also add a global exception handler to your C# code layer to record those exceptions with more complete detail from the .NET exception object.

iOS

...
public class AppDelegate : UIApplicationDelegate
{
...
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
   AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
   {
      Kumulos.Current.LogUncaughtException((Exception)args.ExceptionObject);
   };
   ...
}

Android

...
[Activity(Label = "MyAndroidTestApp", MainLauncher = true, Icon = "@mipmap/icon")]
public class MainActivity : Activity
{
...
     protected override void OnCreate(Bundle savedInstanceState)
     {
         AndroidEnvironment.UnhandledExceptionRaiser += (sender, EventArgs) =>
         {
             Kumulos.Current.LogUncaughtException(EventArgs.Exception);
         };
         ...
      }
      ...
}

Unhandled exceptions that lead to crashes will now be recorded automatically and shown in your App Delivery Console.

Manual tracking of exceptions

If you wish to log any caught exceptions, you can also record them with the relevant helper method.

Kumulos.Current.LogException(Exception e)
Kumulos.Current.LogUncaughtException(Exception e)

Ensure that crash reporting is enabled when attempting to log exceptions.

Changelog

2.0

  • Add In-App Messaging support

1.0 (Com.Kumulos)

  • Refactor of interfaces to cut down on platform specific code / implementation details.

  • Add Crash Reporting, Custom Analytics Events, User Attributes, iBeacon/Eddystone support and background caching and sync of all events.

Legacy packages

KumulosXamarinShared / KumulosXamarinDroid / KumulosXamariniOS

1.1.0

  • Add geolocation update helper method

1.0.0

  • Initial release with Build, Push and Analytics support.