mPulse Beacon API (Version 2) Reference

Introduction

The mPulse Beacon API (version 2) is a programmatic interface that you can use to send beacons from any web or mobile application to mPulse.

The API includes a REST interface that can be used by web and mobile applications written in any language and running on any platform.

In addition, there are mPulse Beacon API libraries for Android, iOS, Java, and JavaScript.

What types of data can I send?

The mPulse Beacon API lets you send Custom Metric and Custom Timer beacons to mPulse.

For each beacon, you can set the Page Group (View Group), A/B test, and Custom Dimensions.

Getting Started

Before using this API, the user will need to have a mPulse app and an associated API Key. For information on how to setup the mPulse app and the API Key, go to mPulse setup.

Once your app has been configured in mPulse, you can use any integration method to send beacons.

Choosing An Integration Method

Custom Metrics

Custom Metrics are user-defined counts that refer to a business goal, or to a Key Performance Indicator (KPI) such as revenue, conversion, orders per minute, widgets sold, etc. The value or meaning of a Custom Metric is defined by the App Administrator.

You can programmatically increment a Custom Metric using any of the integration methods.

Custom Metrics must be defined in the App dialog before use.

Custom Timers

A Custom Timer can be based on any measurable user-defined duration.

You can programmatically send the value of a Custom Timer using any of the integration methods.

Custom Timers must be defined in the App dialog before use.

Page Groups and View Groups

A Page Group (or View Group in a native app) allows for measurement across pages (or views) that belong together. Grouping pages and views in this way helps you capture and summarize the performance characteristics across the entire group.

For web apps, the home page may make up one Page Group, while the login page may make up a second, and product pages a third such group. Search results and checkout pages may also have their own groups.

You can programmatically set Page Group using any of the integration methods.

Custom Dimensions

In addition to the out-of-the-box dimensions already provided within mPulse, App Admins can define additional Custom Dimensions for the given app. For example, a Custom Dimension to track Premium Users versus Free Users.

You can programmatically set a Custom Dimension using any of the integration methods.

Custom Dimensions must be defined in the App dialog before use.

REST API

The REST API exposes a simple way to send beacon data from any web, native, hybrid, or server app in any programming language.

If you use Custom Timers, Custom Metrics, or Custom Dimensions, then you must define them first. For more information, see Custom Timers, Custom Metrics, and Custom Dimensions.

The use the REST API, developers will need to create HTTP requests for two different URLs:

  • The Configuration URL returns the configuration response (JSON). This response includes the session ID, session start timestamp, a unique crumb, and so forth.

  • The Beacon URL is where the beacon data is sent to, and is constructed from values found in the Configuration URL response.

Getting Config

The Configuration URL is located at:

https://c.go-mpulse.net/api/config.json

You will need the API Key for your mPulse app, as well as the additional required fields covered below.

Request Parameters

The following parameters should be sent in the query string:

Name Value Description
key API-Key Example: XXXXX-YYYYY-ZZZZZ-XXXXX-YYYYY
bcn URL (Optional) Only used on a Config Refresh. Should be the value of beacon_url from the first Config response.
r (empty) (Optional) Only used on a Config Refresh. Used to get a new Anti-CSRF token.

Example:

https://c.go-mpulse.net/api/config.json?key=XXXXX-YYYYY-ZZZZZ-XXXXX-YYYYY&bcn=%2F%2F36d71138.akstat.io%2F&r=

Response

A JSON object, containing the following values:

Name Description
session_id Session ID for the user. You can use this ID, or you can provide your own session ID (for example, by generating a UUID to use).
h.key The API key you provided.
h.d The app’s domain.
h.t Anti-CSRF timestamp to use when sending beacons. Expires after 10 minutes.
h.cr Anti-CSRF token to use when sending beacons.
beacon_url Where to send beacons to.

Example

{
    "session_id": "6ad5f44a-466f-4373-b3c7-b5cfdd22118d",
    "h.key": "XXXXX-YYYYY-ZZZZZ-XXXXX-YYYYY",
    "h.d": "mobile-beacons.example.com",
    "h.t": 1421874698124,
    "h.cr": "131b1721c986a42bb8f7f8488ad556f12115fa3d",
    "beacon_url": "//xyz.akstat.io/"
}

Refreshing Config

Changes to the app’s configuration within mPulse will be reflected in the config.json response.

In addition, mPulse may change other data returned by config.json periodically, such as the Beacon URL.

Finally, the request crumb values (h.cr and h.t) expire after 10 minutes. For these reasons, you should refresh config.json every 5 minutes using the &r= parameter.

Sending a Beacon

To send a beacon, you will need to first fetch the config.json response. From that response, you can use the beacon_url to send a beacon.

For example, based on the beacon_url of //36d71138.akstat.io/ you would send a Beacon to https://36d71138.akstat.io:

Generic Request Parameters

Parameter Value Sample Required?
api 1 1 Yes
api.v 1 1 Yes
h.key API-key XXXXX-YYYYY-ZZZZZ-XXXXX-YYYYY Yes
h.d h.d from config.json mydomain.com Yes
h.cr h.cr from config.json ad73390de5ba3bdff928806651a4f528dfa98983 Yes
h.t h.t from config.json 1450215931908 Yes
rt.end When the event occurred 1450215932000 Yes
rt.start manual manual Yes
rt.si session_id from config.json (Or your own) c66b9434-965f-47a0-8c41-302dacc1fbcf No
rt.ss Timestamp when the session started 1450215932314 No
rt.sl Session length 3 No
h.pg Page Group / View Group My Page Group No
h.ab A/B test AB Test 1 No
cdim[n] Custom Dimension #n MyDimension No

For a full list of beacon parameters, see the What’s in a Beacon document.

Adding Custom Metrics

To add a Custom Metric, you will need to parse the config.json response for the customMetrics object.

For example, if you have a single Custom Metric:

{ "customMetrics": [{
    "name": "MyMetric",
    "index": 2,
    "type": "Custom",
    "label": "cmet.MyMetric",
    "dataType": "Number"
}]}

Custom Metrics get added to a beacon as the parameter specified by label.

For example, to send a Custom Metric for MyMetric with a value of 1:

cmet.MyMetric=1

Adding Custom Timers

To add a Custom Timer, you will need to parse the config.json response for the customTimers object.

For example, if you have a single Custom Timer: json { "customTimers": [{ "name": "MyTimer", "index":0, "type":"Custom", "label":"custom0" }]}

Custom Timers get added to a beacon as the t_other parameter. t_other is a comma-separated list of Custom Timer labels and values in the following format:

t_other=[label1]|[value1],[label2]|[value2],...

For example, to send a Custom Timer for MyTimer with a value of 10:

t_other=custom0|10

Example

Here’s a full example setting a Page Group, A/B test, and sending a Custom Metric and Timer:

https://<beacon_url>/?
    h.key=XXXXX-YYYYY-ZZZZZ-XXXXX-YYYYY
    &h.d=mydomain.com
    &h.cr=ad73390de5ba3bdff928806651a4f528dfa98983
    &h.t=1450215931908
    &rt.start=manual
    &rt.si=c66b9434-965f-47a0-8c41-302dacc1fbcf
    &rt.ss=1450215932314
    &rt.sl=3
    &h.pg=My%20Page%20Group
    &h.ab=AB1
    &cmet.MyMetric=1
    &t_other=custom0|10

Return Values

The Beacon URL will respond with an empty 204 No Content response.

Android

The mPulse Native Android API can be used in your Android app to send Custom Metrics and Custom Timers to mPulse.

The mPulse Native Android library will also automatically track network requests.

Note that you must define Custom Timers, Custom Metrics, or Custom Dimensions first.

You can use the library with Gradle projects:

Getting the Library (Gradle)

Instrumenting an Android app with Gradle can be done by including the two dependencies to your project’s build.gradle files: one at the project level and one at the application level.

In the project’s build.gradle file, add the following line:

buildscript {
    repositories {
        // ...
    }
    dependencies {
        classpath 'com.soasta.mpulse:mpulse-android-gradle-plugin:<replace with most recent version>'
        // ...
    }
}

At the Android application level, two changes are necessary to make mPulse available in your Android application.

At the top of your application’s build.gradle file, apply the mPulse Gradle plugin:

apply plugin: "com.android.application"
apply plugin: "com.soasta.mpulse.android"

Then add the mPulse library to your compilation dependencies:

dependencies {
    compile 'com.soasta.mpulse:mpulse-android:<replace with most recent version>'
    // ...
}

For <replace with most recent version>, you can find the most recent version on JCenter or Maven.

Configuration

Initialization

To use the mPulse Native Android API, you must first initialize your Android project with your API Key:

import com.soasta.mpulse.android.MPulse;

public static final String MPULSE_API_KEY = "YOUR_API_KEY";

// First, initialize with your API Key in the onCreate Method of your Activity
MPulse.sharedInstance().initializeWithAPIKey(MPULSE_API_KEY, getApplicationContext());

// Later, you can interact with MPulse by getting the shared instance
MPulse mpulse = MPulse.sharedInstance();

After you’ve called initializeWithAPIKey(), you can access the shared instance by calling MPulse.sharedInstance().

In most cases, it makes sense to do this in your main Activity’s onCreate() method.

Note: Do not call initializeWithAPIKey() in Application.onCreate(), as the mPulse Native Android library requires an active Activity to initialize.

ProGuard

If you are using ProGuard with minifyEnabled, you will need to add the following to your proguard-rules.pro file:

-keep class com.soasta.** { *; }
-keepattributes Signature

Permissions

In order to send beacons the following Android permissions are required:

  • android.permission.INTERNET

  • android.permission.ACCESS_NETWORK_STATE

Capturing location data is optional and can be activated by adding one of the following permissions:

  • android.permission.ACCESS_COARSE_LOCATION

Or

  • android.permission.ACCESS_FINE_LOCATION

Example AndroidManifest.xml lines:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Automatic Network Request Instrumentation

Once included in the project, mPulse will automatically instrument all network requests.

Network requests will be instrumented as long as they are sent from one of the following classes (or a library that uses one of these classes):

  • java.net.URLConnection
  • com.squareup.okhttp.OkHttpClient version 1.x
  • okhttp3.OkHttpClient version 3.x (after version 2.2.0)

Network Request Filtering

Network request filtering allows developers to reduce the amount of network request beacons being sent. This means you can concentrate on requests that are relevant to your application while discarding those that are not relevant to the experience of your customers.

You can modify the state of network request monitoring through either the mPulse UI or programmatically at runtime. Network request monitoring can be in one of three modes:

  • ALL (Blacklist mode): All network requests are instrumented and beaconed. You can exclude specific URLs.
  • MATCH (Whitelist mode): Only those requests matching your criteria will be instrumented and beaconed. Your Whitelist will control which URLs are included.
  • NONE: No network requests are sent as beacons.

The mPulse Native Android API allows you to control the state of network request monitoring during runtime using the following API Calls:

Disable network request beacons (ie. set the mode to NONE):

MPulse.sharedInstance().disableNetworkMonitoring();

Enable network request beacons (ie. set the mode to ALL, Blacklist mode):

MPulse.sharedInstance().enableNetworkMonitoring();

Enable Whitelist-based network request filtering (ie. set the mode to MATCH, Whitelist mode):

MPulse.sharedInstance().enableFilteredNetworkMonitoring();

When these APIs are used, they will take precedence over the mPulse UI configuration, for the duration of the runtime of the application.

Programmatically extending the Filters

The mPulse Native Android API maintains a Blacklist and Whitelist (for ALL and MATCH modes respectively), and it will use these lists to filter URLs.

The mPulse UI allows you to control the Blacklist and Whitelist URLs within the app’s configuration dialog.

In addition, you can programmatically add URL filters at runtime. These filters will be amended to the app configuration from the mPulse UI.

Examples of adding URL filters to the Whitelist and Blacklist:

// adds a RegEx pattern to the list of Whitelist filters
MPulse.sharedInstance().addUrlWhiteListFilter("NameOfFilter", ".*pattern.*");

// Optionally if you wish to not add a name to the filter, the name is automatically generated from the pattern
MPulse.sharedInstance().addUrlWhiteListFilter(".*pattern.*");

// adds a RegEx pattern to the list of Blacklist filters
MPulse.sharedInstance().addUrlBlackListFilter("NameOfFilter", ".*pattern.*");

// Just as above, if you wish to not define a name for the Filter, the name is automatically generated from the pattern
MPulse.sharedInstance().addUrlBlackListFilter(".*pattern.*");

// If you wish to only tag a network request with a specific View Group using a pattern
MPulse.sharedInstance().addViewGroupFilter("NameOfFilter", ".*pattern.*", "My View Group");

Here’s an example of using an advanced filter within your application. The MPFilter class is given direct access to the MPBeacon, and should set result.setMatched(true) when matched.

// Imports Section:
import com.soasta.mpulse.core.filter.MPFilter;
import com.soasta.mpulse.core.filter.MPFilterResult;
import com.soasta.mpulse.core.beacons.MPBeacon;
import com.soasta.mpulse.andriod.beacons.MPApiNetworkRequestBeacon;

// In your code:
MPFilter filter = new MPFilter()
{
  @Override
  public MPFilterResult match(MPBeacon beacon)
  {
    MPFilterResult result = new MPFilterResult();

    // Do something here to either drop or include this beacon
    if (beacon != null && beacon instanceof MPApiNetworkRequestBeacon)
    {
      MPApiNetworkRequestBeacon networkBeacon = (MPApiNetworkRequestBeacon) beacon;
      if (networkBeacon.getUrl().matches(".*pattern.*"))
      {
        result.setViewGroup("Example View Group");
        result.setMatched(true);
      }
    }

    return result;
  }
};

For easier interaction with URLs you also have the option to use MPUrlFilter which will pass a String to the match() method:

// Imports Section:
import com.soasta.mpulse.android.filter.MPUrlFilter;
import com.soasta.mpulse.core.filter.MPFilterResult;

// In your code:
MPUrlFilter filter = new MPUrlFilter()
{
  @Override
  public MPFilterResult match(String url)
  {
    MPFilterResult result = new MPFilterResult();

    if (url != null && !url.equals(""))
    {
      if (url.contains("example.com"))
      {
        result.setViewGroup("example");
        result.setMatched(true);
      }
    }

    return result;
  }
};

Now that the filter has been created, you can add it to the Whitelist or Blacklist.

If you wish to include the filter in the Whitelist, setting matched true (MPFilterResult.setMatched(true)) on the MPFilterResult for match(MPBeacon beacon) will tell mPulse to monitor the request, while setting matched to false (MPFilterResult.setMatched(false)) will tell mPulse to ignore the request.

MPulse.sharedInstance().getFilterManager().addWhiteListFilter("NameOfFilter", filter);

Conversely if you wish to include the filter in the Blacklist, a setting matched to false (MPFilterResult.setMatched(false)) on the MPFilterResult for match(MPBeacon beacon) will tell mPulse to monitor the request, while setting the matched to true (MPFilterResult.setMatched(true)) will tell mPulse to ignore the request.

MPulse.sharedInstance().getFilterManager().addBlackListFilter("NameOfFilter", filter);

Should a viewGroup already be configured via the SDK (using MPulse.sharedInstance().setViewGroup(String viewGroup)) the viewGroup set by MPFilterResult via MPFilterResult.setViewGroup("myviewgroup") will override it. A value of null or "" (empty string) will not change the viewGroup on the beacon.

Excluding libraries from instrumentation

Should you wish to not instrument a library that is part of your project you can exclude it by using the following configuration closure in your application’s build.gradle file:

mpulseAndroid {
  exclude ~/.*do-not-instrument.*/
}

Notice that the exclude function inside the mpulseAndroid closure accepts Groovy Patterns using the Pattern operator.

If you wish to exclude the contents of a longer directory path that contains libraries you are using in your project, you should use the ${File.separator} path separator token:

mpulseAndroid {
  exclude ~".*${File.separator}special-libs${File.separator}.*"
}

Send a Custom Timer

The mPulse Android Native API can be used to send a Custom Timer.

You can track the time it took for an action to occur, such as an image upload or an attachment file download, using Custom Timers.

At the start of your action, call startTimer() by giving it a timerName. startTimer() will return a unique Timer ID (String) and will keep track of the start time:

String timerID = MPulse.sharedInstance().startTimer("MyTimer");
// -> "MyTimer-d4d67062-7064-42b5-85ed-4e69d8824ef9"

At the end of your action, call stopTimer() by passing in the Timer ID. mPulse stops the timer and sends a beacon to the server:

MPulse.sharedInstance().stopTimer(timerID);

You may also directly specify a timer name and value using sendTimer():

// value is in milliseconds
MPulse.sharedInstance().sendTimer("MyTimer", 4);

Send a Custom Metric

You may increment a Custom Metric by using sendMetric():

MPulse.sharedInstance().sendMetric("MyMetric", new Integer(23));

Set View Groups

You may get, set, and reset the View Group. Once set, the View Group will be associated with every subsequent beacon.

Set a View Group using setViewGroup():

MPulse.sharedInstance().setViewGroup("MyViewGroup");

Reset the View Group using resetViewGroup():

MPulse.sharedInstance().resetViewGroup();

Get the current View Group using getViewGroup():

String viewGroup = MPulse.sharedInstance().getViewGroup();

In addition, for each network request beacon, you can override the global View Group for that beacon by creating a filter and calling setViewGroup() on the MPFilterResult.

You can call setViewGroup() even if the result is un-matched. For example, in ALL (Blacklist) mode, you can call setMatched(false) so the network request is still monitored, and call setViewGroup() to set that request’s View Group. If multiple filters set the View Group, the result is undefined (the last filter will take precedence).

See the Network Request Filtering section for details.

Set Custom Dimensions

You may get, set, and reset Custom Dimensions. Once set, the Custom Dimension will be associated with every subsequent beacon.

Set or reset a Custom Dimension using setDimension():

MPulse.sharedInstance().setDimension("MyDimension", "new value");

Reset the Custom Dimension using resetDimension():

MPulse.sharedInstance().resetDimension("MyDimension");

Troubleshooting

Build Failure (Gradle)

If you see build failures similar to these:

Error:Uncaught translation error: com.android.dx.cf.code.SimException: local variable type mismatch: attempt to set or access a value of type java.lang.Object using a local variable of type int. This is symptomatic of .class transformation tools that ignore local variable information.

or

com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: java.lang.UnsupportedOperationException

Then your build most likely failed because the mPulse Android Gradle Plugin failed to instrument a JAR in your application. This often happens when one of your JARs is obfuscated.

Finding JAR files that failed to instrument

To find out which of your JARs failed to instrument, run Gradle from the command line with the flags --debug, --info and --full-stacktrace. With these flags set, you will be able to see which of your JARs our plugin attempted to instrument before failing the build:

MPulseAndroidTransform: Weaving file from /some/path/to/a/file.jar
MPulseAndroidTransform: woven class com.example.app.a.b.c
...

Should you see this followed by an exception this may indicate that the file.jar is failing the build. You can exclude it from instrumentation and thus from throwing an error like this in your build.gradle file:

android { /* ... */ }

/* add this to your code to exclude file.jar from being instrumented */
mpulseAndroid {
  exclude ~/.*file.*/;
}

dependencies { /* ... */ }

Notice that the mpulseAndroid closure is invoked at the top-level of your build.gradle file.

Runtime Exceptions after Upgrade 2.x to 2.2.x

Once you have upgraded your version of mPulse native for Android and have run a new successful build you may run into the following exception:

Process: com.example.App, PID: 1234
  java.lang.NoClassDefFoundError: Failed resolution of: Lcom/soasta/mpulse/android/MPLog;
  /* Long stacktrace pointing to code in third party instrumented library such as Volley */

If so, you may have an issue with a cached compiled version of your application where a previously instrumented version of a third party library is still available. In this specific case, com.soasta.mpulse.android.MPLog was moved to com.soasta.mpulse.core.MPLog.

To prevent this error, you will need to run the following:

In your project directory: $> gradle clean ... $> rm -rf build/

This will remove both build artifacts hidden in the .gradle/ and build/ directories of your project.

The same should be done in any subprojects and folders that also contain a build/ or .gradle/ directory, specific to your Android application.

No Beacons Being Sent

If you are not seeing beacons in the mPulse dashboards, please ensure the app has been configured correctly:

  • Ensure Gradle is configured properly:
    • classpath 'com.soasta.mpulse:...' was added to the project’s build.gradle
    • apply plugin: "com.soasta.mpulse.android" was added to the application’s build.gradle after apply plugin: "com.android.application"
    • compile 'com.soasta.mpulse:...' was added to the application’s build.gradle
  • Ensure you are using the correct mPulse API Key in initializeWithAPIKey
  • Ensure initializeWithAPIKey is being called after an Activity has been created (and not in Application.onCreate())
  • If you are using ProGuard, ensure sure you’ve updated proguard-rules.pro per the instructions
    • If you see beacons for Debug builds, but not for Release builds, this is a common cause
  • Ensure you’ve updated your AndroidManifest.xml with the correct permissions
  • Ensure you don’t see a Unable to refresh Config warning in the logs (see below)
  • Ensure you don’t see a Activity context not available warning in the logs (see below)
  • Ensure you see the following lines in the ADB log after the application has started: E/MPulse.MPulseInternal: [main] mPulse Mobile build: n.n.n E/MPulse.MPulseInternal: [main] mPulse initialized. E/MPulse.MPSession: [pool-n-thread-n] mPulse session has started.
  • If you are trying to send a Custom Timer or Custom Metric, ensure they have already been defined in the mPulse app configuration
  • Using a system proxy such as Fiddler or Charles, validate that:
    • There is a Config request to https://c.go-mpulse.net/api/config.json?...
    • There is a beacon being sent to https://*.mpstat.us or https://*.akstat.io

Unable to Refresh Config (log message)

The following message in your ADB log indicates that config.json could not be fetched:

W/MPulse.MPulseInternal: [pool-1-thread-1] Unable to refresh Config.
    java.util.concurrent.TimeoutException
    at java.util.concurrent.FutureTask.get
    at android.os.AsyncTask.get
    at com.soasta.mpulse.android.config.MPConfig.initWithURL
    at com.soasta.mpulse.android.config.MPConfig.refresh
    at com.soasta.mpulse.android.MPulseInternal$1.run
...

If you see this message, it means that mPulse was unable to initialize because it could not fetch the mPulse app configuration. No beacons will be sent.

Please ensure your app can connect to c.go-mpulse.net and that it is not blocked by the application or a firewall.

Activity Context Not Available (log message)

The following message in your ADB log indicates the application may not have been configured properly:

W/MPulse.MPDemographics: Activity context not available...

If you see this message, it means that build.gradle was not configured properly. No beacons will be sent.

Please ensure the apply plugin line is in your project’s build.gradle file:

apply plugin: "com.soasta.mpulse.android"

Debugging Output

To add debugging output, add the following line to the import section:

import com.soasta.mpulse.core.MPLog;

Then add the line below to activate debugging:

MPLog.setDebug(true);

Compilation Errors

If the application is not compiling, please check the following:

  • If the application is being built with Gradle, ensure Gradle is configured properly:
    • classpath 'com.soasta.mpulse:...' was added to the project’s build.gradle
    • apply plugin: "com.soasta.mpulse.android" was added to the application’s build.gradle after apply plugin: "com.android.application"
    • compile 'com.soasta.mpulse:...' was added to the application’s build.gradle

iOS

The mPulse Native iOS API can be used in your iOS app to send Custom Metrics and Custom Timers to mPulse.

The mPulse Native iOS library will also automatically track network requests.

If you use Custom Timers, Custom Metrics, or Custom Dimensions, then you must define them first. For more information, see Custom Timers, Custom Metrics, and Custom Dimensions.

You can either use the library via a Framework package or via CocoaPods.

Getting the Library (Framework)

To use the mPulse Native iOS API, you can install the mPulse Native iOS Framework:

  1. Navigate to the SOASTA/mPulse-iOS Github repository and download the MPulse.framework.zip archive.

  2. Unzip MPulse.framework.

  3. Drag and drop the framework into your Xcode project.

  4. Navigate to the Build Settings section of your target and add the following (if not already present) to the Other Linker Flags setting: -ObjC

  5. Navigate to the Build Phases section of your target and add the following Libraries (if not already present) to the Link Binary With Libraries step:

    • CoreTelephony.framework
    • CoreLocation.framework
    • SystemConfiguration.framework
    • libc++.dylib or libc++.tdb
    • libz.dylib or libz.tdb
  6. If using mPulse from Swift, you must add the following line to the Objective-C bridging header ([project name]-Bridging-Header.h): #import "MPulse/MPulse.h

Getting the Library (CocoaPods)

The mPulse Native iOS library can also be installed via CocoaPods

gem install cocoapods

pod setup
  • Create (or update) a file in your Xcode project called Podfile and add the following line to it:
pod 'mPulse'
  • In the Podfile, use_frameworks! must be set for the desired targets.

  • Run pod install in your Xcode project directory, and then open the Xcode workspace.

pod install

Configuration

To use the mPulse Native iOS API, you must first initialize your iOS project with your API Key.

In most cases, it makes sense to initialize in application:didFinishLaunchingWithOptions:.

Objective-C

#import <MPulse/MPulse.h>

#define MPULSE_API_KEY @"YOUR_API_KEY"

// Initialize the library with your
// mPulse api key, MPULSE_API_KEY
[MPulse initializeWithAPIKey:MPULSE_API_KEY];

// Later, you can get your instance with
MPulse *mpulse = [MPulse sharedInstance];

After you’ve called initializeWithAPIKey:, you can access the mPulse API shared instance by calling [MPulse sharedInstance].

Swift

// If mPulse was installed using Cocoapods then add the following line:
import mPulse

// Initialize the library with your mPulse api key
let apiKey = "YOUR_API_KEY"
MPulse.initializeWithAPIKey(apiKey)

With Swift 3, you may need to use:

MPulse.initialize(withAPIKey: apiKey)

After you’ve called initializeWithAPIKey(), you can access the mPulse API shared instance by calling MPulse.sharedInstance().

Automatic Network Request Instrumentation

Once included in the project, mPulse will automatically instrument all network requests.

Network requests will be instrumented as long as they are sent from one of the following classes (or a library that uses one of these classes):

  • URLConnection
  • URLSession

The following libraries (which use the above classes) will be instrumented:

  • AFNetworking
  • SDWebImage

Network Request Filtering

Network request filtering allows developers to reduce the amount of network request beacons being sent. This means you can concentrate on requests that are relevant to your application while discarding those that are not relevant to the experience of your customers.

You can modify the state of network request monitoring through either the mPulse UI or programmatically at runtime. Network request monitoring can be in one of three modes:

  • ALL (Blacklist mode): All network requests are instrumented and beaconed. You can exclude specific URLs.
  • MATCH (Whitelist mode): Only those requests matching your criteria will be instrumented and beaconed. Your Whitelist will control which URLs are included.
  • NONE: No network requests are sent as beacons.

The mPulse Native iOS API allows you to control the state of network request monitoring during runtime using the following API Calls:

Disable network request beacons (ie. set the mode to NONE):

Objective-C:

[[MPulse sharedInstance] disableNetworkMonitoring];

Swift:

MPulse.sharedInstance().disableNetworkMonitoring()

Enable network request beacons (ie. set the mode to ALL, Blacklist mode):

Objective-C:

[[MPulse sharedInstance] enableNetworkMonitoring];

Swift:

MPulse.sharedInstance().enableNetworkMonitoring()

Enable filtered network request beacons (ie. set the mode to MATCH, Whitelist mode):

Objective-C:

[[MPulse sharedInstance] enableFilteredNetworkMonitoring];

Swift:

MPulse.sharedInstance().enableFilteredNetworkMonitoring()

When these APIs are used, they will take precedence over the mPulse UI configuration, for the duration of the runtime of the application.

Programmatically extending the Filters

The mPulse Native iOS API maintains a Blacklist and Whitelist (for ALL and MATCH modes respectively), and it will use these lists to filter URLs.

The mPulse UI allows you to control the Blacklist and Whitelist URLs within the app’s configuration dialog.

In addition, you can programmatically add URL filters at runtime. These filters will be amended to the app configuration from the mPulse UI.

If you wish to add to the Blacklist for ALL mode, you can use the example below. Returning a MPFilterResult with setMatched:YES will result in the network request not being monitored.

Objective-C:

[[MPulse sharedInstance] addURLBlackListFilter:@"Example.com Filter" filter:^MPFilterResult *(NSString *url) {
  // By default MPFilterResults are set to not matched.
  MPFilterResult *result = [[MPFilterResult alloc] init];

  if ([url isEqual:@"http://example.com"])
  {
    [result setMatched:YES];
  }

  return result;
}];

Swift:

MPulse.sharedInstance().addURLBlackListFilter("MyFilter") { (url) -> MPFilterResult? in
  // By default MPFilterResults are set to not matched.
  let result = MPFilterResult.init();

  if (url != nil)
  {
    if (url!.contains("example.com"))
    {
      result.matched = true;
    }
  }
  return result;
};

If you wish to add to the Whitelist for MATCH mode, you can use the example below. Returning a MPFilterResult with setMatched:YES will result in the network request being monitored.

[[MPulse sharedInstance] addURLWhiteListFilter:@"Example.com Filter" filter:^MPFilterResult *(NSString *url) {
  // By default Filter results are set to not matched.
  MPFilterResult *result = [[MPFilterResult alloc] init];

  if ([url containsString:@"example.com"])
  {
    [result setMatched:YES];
    [result setViewGroup:@"My View Group"];
  }

  return result;
}];

Swift:

MPulse.sharedInstance().addURLWhiteListFilter("MyFilter") { (url) -> MPFilterResult? in
  // By default MPFilterResults are set to not matched.
  let result = MPFilterResult.init();

  if (url != nil)
  {
    if (url!.contains("example.com"))
    {
      result.matched = true;
      result.viewGroup = "My View Group";
    }
  }
  return result;
};

Send a Custom Timer

The mPulse iOS Native API can be used to send a Custom Timer.

You can track the time it took for an action to occur, such as an image upload or an attachment file download, using Custom Timers.

At the start of your action, call startTimer() by giving it a timerName. startTimer() will return a unique Timer ID (NSString) and will keep track of the start time:

Objective-C:

NSString *timerID = [[MPulse sharedInstance] startTimer:@"TimerName"];

Swift:

let timerID = MPulse.sharedInstance().startTimer("TimerName")

At the “end” of your action, call stopTimer: by passing in the timerID. mPulse stops the timer and sends a beacon to the server:

Objective-C:

[[MPulse sharedInstance] stopTimer:timerID];

Swift:

 MPulse.sharedInstance().stopTimer(timerID)

You may also directly specify a timer name and value (in seconds) using sendTimer::

Objective-C:

// value is NSTimeInterval
[[MPulse sharedInstance] sendTimer:@"TimerName" value:4];

Swift:

MPulse.sharedInstance().sendTimer("TimerName", value: 4)

Send a Custom Metric

You may increment a Custom Metric by using sendMetric::

Objective-C:

[[MPulse sharedInstance] sendMetric:@"MyMetric" value:[NSNumber numberWithInt:23]];

Swift:

MPulse.sharedInstance().sendMetric("MyMetric", value: 23)

Set View Groups

You may get, set, and reset the View Group. Once set, the View Group will be associated with every subsequent beacon.

View Group names are limited to 100 characters, and can include any of the following: 0-9, a-z, A-Z, “ ” (space), _ (underbar) and - (dash)

Set a View Group using setViewGroup::

Objective-C:

[[MPulse sharedInstance] setViewGroup:@"MyViewGroup"];

Swift:

MPulse.sharedInstance().setViewGroup("MyViewGroup")

Reset the View Group using resetViewGroup::

Objective-C:

[[MPulse sharedInstance] resetViewGroup];

Swift:

MPulse.sharedInstance().resetViewGroup()

Get the current View Group using getViewGroup::

Objective-C:

NSString* viewGroup = [[MPulse sharedInstance] getViewGroup];

Swift:

let viewGroup = MPulse.sharedInstance().getViewGroup()

In addition, for each network request beacon, you can override the global View Group for that beacon by creating a filter and calling setViewGroup: on the MPFilterResult.

You can call setViewGroup: even if the result is un-matched. For example, in ALL (Blacklist) mode, you can call setMatched:NO so the network request is still monitored, and call setViewGroup: to set that request’s View Group. If multiple filters set the View Group, the result is undefined (the last filter will take precedence).

See the Network Request Filtering section for details.

Set Custom Dimensions

You may get, set, and reset Custom Dimensions. Once set, the Custom Dimension will be associated with every subsequent beacon.

Set or reset a Custom Dimension using setDimension::

Objective-C:

[[MPulse sharedInstance] setDimension:@"My Dimension" value:@"new value"];

Swift:

MPulse.sharedInstance().setDimension("My Dimension", value: "new value")

Reset the Custom Dimension using resetDimension::

Objective-C:

[[MPulse sharedInstance] resetDimension:@"My Dimension"];

Swift:

MPulse.sharedInstance().resetDimension("My Dimension")

Troubleshooting

No Beacons Being Sent

If you are not seeing beacons in the mPulse dashboards, please ensure the app has been configured correctly:

  • Ensure you are using the correct mPulse API Key in initializeWithAPIKey:
  • Ensure you see the following lines in the debug log after the application has started: mPulse Mobile build: n.n.n mPulse initialized. mPulse session has started.
  • If you are trying to send a Custom Timer or Custom Metric, ensure they have already been defined in the mPulse app configuration
  • Using a system proxy such as Fiddler or Charles, validate that:
    • There is a Config request to https://c.go-mpulse.net/api/config.json?...
    • There is a beacon being sent to https://*.mpstat.us or https://*.akstat.io

FAQ

  1. I see the following error in my build logs:
Ignoring file libMPulse[Sim].a, missing required architecture [arch] in file libMPulse.a ([n] slices)

Answer: This is just a warning, and is expected. The mPulse libraries are split into two files (libMPulse.a and libMPulseSim.a) because of GitHub file size limits (100 MB), where the CocoaPod libraries are hosted. libMPulseSim.a is for simulators and libMPulse.a is for devices, and only one will be used at a time.

Java

The mPulse Java API can be used in your Java app to send Custom Metrics and Custom Timers to mPulse.

Note that you must define Custom Timers, Custom Metrics, or Custom Dimension first.

Getting the Library (Gradle)

Instrumenting a Java app with Gradle can be done by including a dependency to the build.gradle file of your project.

Add the following mPulse Java library to your compilation dependencies:

dependencies {
    compile 'com.soasta.mpulse:mpulse-java:<replace with most recent version>'
    // ...
}

For <replace with most recent version>, you can find the most recent version at JCenter or Maven.

Configuration

Initialization

To use the mPulse Java API, you must first initialize your Java project with your API Key:

import com.soasta.mpulse.core.MPulse;

public static final String MPULSE_API_KEY = "YOUR_API_KEY";

// First, initialize with your API Key
MPulse.sharedInstance().initializeWithAPIKey(MPULSE_API_KEY);

// Later, you can interact with MPulse by getting the shared instance
MPulse mpulse = MPulse.sharedInstance();

After you have called initializeWithAPIKey(), you can access the shared instance by calling MPulse.sharedInstance().

In most cases, it makes sense to do this in your main method or in other app initialization code.

Shutdown

To stop using the Java API, you may call shutdown():

MPulse.sharedInstance().shutdown();

shutdown() may block in order to flush queued beacons. If this behavior is not desired, shutdown() accepts a timeout parameter in seconds. Setting the timeout to 0 will shutdown immediately.

MPulse.sharedInstance().shutdown(0);

The mPulse Java API should not be used after calling shutdown().

Send a Custom Timer

The mPulse Java API can be used to send a Custom Timer.

You can track the time it took for an action to occur, such as an file transfer or database request, using Custom Timers.

At the start of your action, call startTimer() by giving it a timerName. startTimer() will return a unique Timer ID (String) and will keep track of the start time:

String timerID = MPulse.sharedInstance().startTimer("MyTimer");
// -> "MyTimer-d4d67062-7064-42b5-85ed-4e69d8824ef9"

At the end of your action, call stopTimer() by passing in the Timer ID. mPulse stops the timer and sends a beacon to the server:

MPulse.sharedInstance().stopTimer(timerID);

You may also directly specify a timer name and value using sendTimer():

// value is in milliseconds
MPulse.sharedInstance().sendTimer("MyTimer", 4);

Send a Custom Metric

You may increment a Custom Metric by using sendMetric():

MPulse.sharedInstance().sendMetric("MyMetric", new Integer(23));

Set View Groups

You may get, set, and reset the View Group. Once set, the View Group will be associated with every subsequent beacon.

View Group names are limited to 100 characters, and can include any of the following: 0-9, a-z, A-Z, “ ” (space), _ (underbar) and - (dash)

Set a View Group using setViewGroup():

MPulse.sharedInstance().setViewGroup("MyViewGroup");

Reset the View Group using resetViewGroup():

MPulse.sharedInstance().resetViewGroup();

Get the current View Group using getViewGroup():

String viewGroup = MPulse.sharedInstance().getViewGroup();

Set Custom Dimensions

You may get, set, and reset Custom Dimensions. Once set, the Custom Dimension will be associated with every subsequent beacon.

Set or reset a Custom Dimension using setDimension():

MPulse.sharedInstance().setDimension("MyDimension", "new value");

Reset the Custom Dimension using resetDimension():

MPulse.sharedInstance().resetDimension("MyDimension");

JavaScript (mpulse.js)

The mPulse JavaScript API (mpulse.js) allows you to send beacons from JavaScript.

If you use Custom Timers, Custom Metrics, or Custom Dimensions, then you must define them first. For more information, see Custom Timers, Custom Metrics, and Custom Dimension.

Documentation is available at docs.soasta.com/mpulse.js.