Contentsquare Cordova Integration

Last updated on

Introduction

Cordova support is currently only accessible to customers participating in the Beta program. For more information reach out to your Contentsquare contact.

Get Started

Add Contentsquare to your app

This guide walks you through the process of adding the Contentsquare SDKs to your Cordova application. The Contentsquare Plugin for Cordova is a plugin between the Contentsquare SDKs for iOS and Android, and your Cordova JavaScript code. It allows for the use of our solution both in native and JavaScript parts of your app. The Contentsquare functionality is provided through a simple NPM package including only the plugin and dependencies to specific versions of the SDKs. Check the compatibility section for more information about these dependencies, and the minimum Cordova version compatible for each version of the Plugin.

How to include it

Open up a terminal window and navigate to the folder where your application is stored. First, find the latest version of the plugin compatible with your version of Cordova using our compatibility table. Then, install the plugin as follows, specifying the exact version you want to install if needed:

cordova plugin add @contentsquare/cordova-plugin

If your app is written in TypeScript, you can also install the types definitions package.

npm install -D @contentsquare/cordova-plugin-types

How to use the plugin in your JavaScript code

The plugin defines an object ContentsquarePlugin. Although the object is in the global scope, features provided by this plugin are not available until after the deviceready event.

document.addEventListener("deviceready", onDeviceReady, false);
 
function onDeviceReady() {
  // ContentsquarePlugin is now available
}

Start the SDK

You do not need to do anything to start the SDK. Now that the SDK is a dependency of your app, it will autostart itself when your application starts.

Validate SDK integration

Look at the native SDK docs for validation on each platform.

In-app features

Alongside its tracking capabilities, the SDKs embed some features aimed at Contentsquare users such as SDK Logs.

Implement in-app features

1. Install the Cordova plugin to handle URL schemes

In order for your application to open when you scan the QR code or enter the URL we provide in a web browser, you have to install a Cordova plugin which will handle the URL scheme.

cordova plugin add cordova-plugin-customurlscheme --variable URL_SCHEME=cs-{package-id}
// Example:
// my package id is 'com.mycompany.myapp'
// cordova plugin add cordova-plugin-customurlscheme --variable URL_SCHEME=cs-com.mycompany.myapp

2. Call the SDK when your app is opened with the custom URL

Then, you will need to link your app with our SDK. When your application is started via a deeplink, a specific global JavaScript function, handleOpenURL(), is automatically called in your App. You will have to define this function in the 'window' global scope and you will need to call a function of our API via the Contentsquare Cordova Plugin.

window.handleOpenURL = function (url) {
    console.log("received url: " + url);
    ContentsquarePlugin.handleURL(url);
}

Enable in-app features

In-app features can be enabled in different ways:

Scan the QR Code

If you have access to the Contentsquare platform, you can open the in-app features modal from the menu and scan the QR code displayed with your phone.

Take a look at the native documentation for further information.

Alternative methods

We provide alternative methods to enable in-app features especially for iOS Simulator and Android Emulator.

[tab] Android

Follow the Native Android SDK documentation for Enable in-app features

[tab] iOS

Follow the Native iOS SDK documentation for Enable in-app features

Debugging and Logging

Contentsquare provides Logging capabilities that allow you to see the raw event data logged by your app. This is very useful for validation purposes during the instrumentation phase of development and can help you discover errors and mistakes in your analytics implementation and confirm that all events are being logged correctly.

[tab] Android

Follow the Native Android SDK documentation for Debugging and Logging

[tab] iOS

Follow the Native iOS SDK documentation for Debugging and Logging

Track Screens

Contentsquare aggregates user behavior and engagement at the screen level. To do so, it is required to track screen transitions by calling a dedicated API. When the API is called, the SDK logs a screenview event that identifies the new screen with the screen name provided.

import { ContentsquareCDVPlugin } from '@contentsquare/cordova-plugin-types';
 
declare var ContentsquarePlugin: ContentsquareCDVPlugin;
 
ContentsquarePlugin.sendScreenName("ScreenName", (result)=>{
    // Success
}, (err)=>{
    // Handle error
});

Screen name handling

The screen name length is not limited on the SDK side. However, the limit is 2083 characters on the server side.

Screenview after app in background

The SDK triggers a screenview automatically after the app is put in background and foreground, as long as a screenview with a screen name has been triggered previously. It will use the last screen name set.

Implementation recommendations

From a functional standpoint, we expect a screenview to be sent:

  • When the screen appears
  • When a modal/pop-up is closed and the user is back on the screen
  • When the app is put in the foreground (after an app hide)

How to name screens

As a general rule, keep distinct screen names under 100. As they are used to map your app in Contentsquare, you will want something comprehensive.

Separate words with space, dash or underscore characters

If you want to generate screen names including more than one word, it is best to separate them and to do so using space, dash or underscore characters. Contentsquare handles automatically the formatting for them.

Example: For a sub-category list of a retail app, use Home & Living - Home Furnishings instead of homeLivingHomeFurnishings.

Use screen template/layout names

As a general recommendation, use names referring to the screen template/layout rather than referring to the specific content (data). This will help:

  • To keep the number of distinct screen names low and therefore make Contentsquare easier to use
  • Remove the risk of sending Personal Data to Contentsquare

List of screen types falling into that category: Product detail, Event detail, Conversation/Chat, User profile...

Multiple layouts/states for one screen

In some cases, there will be screen that can have different layouts/states depending on the user context. In this situation, it would be interesting to append the layout/state value to the screen name. Examples:

  • Home screen of a travel app adapting its layout on the user context:
    StateScreen name
    No trip plannedHome - no trip
    Trip plannedHome - trip planned
    Trip about to startHome - upcoming trip
    Trip in progressHome - trip in progress
  • Product detail screen of an e-commerce app with different layouts depending on the type of product:
    StateScreen name
    Default templateProduct detail
    Template with suggested productsProduct detail - Suggestions
    Template with bundled productsProduct detail - Bundle

Track Transactions

To associate a user's session with their potential purchases (and corresponding revenue), you must send the transaction via a dedicated API. For each transaction, we send:

  • Price (number, mandatory)
  • Currency (CurrencyCode or string, mandatory)
  • Transaction ID (string, optional)

The plugin defines a TransactionItem type to prevent potential typing errors.

import { ContentsquareCDVPlugin, CurrencyCode, TransactionItem } from '@contentsquare/cordova-plugin-types';
 
declare var ContentsquarePlugin: ContentsquareCDVPlugin;
 
const myTransaction: TransactionItem = {
      transactionValue: 10,
      transactionCurrency: CurrencyCode.USD,
      transactionId: 'my_transaction_id',
};
 
ContentsquarePlugin.sendTransaction(myTransaction, (result) => {
  // Success
}, (err) => {
    // Handle Error
});

Currency

The currency is conforming to the ISO 4217 standard. Although the currency can be passed as "alphanumeric code", you should always prefer using the plugin's CurrencyCode object values. If you have to pass the ISO code as a string, note that capitalization is not a factor ("USD", "Usd" or "usd" will all be treated as the US Dollar).

If the currency passed doesn't match our supported currencies, the SDK will send a currency value of "-1". It will be processed as the default currency of the project.

Track Dynamic Variables

General principles

Usage

Dynamic variables are additional information on the session that can be used to segment sessions.

For example, they can include information on the A/B Test variations displayed to the current user.

Limits

On the server side
  • It is possible to save up to 40 distinct dynamic variable keys per screen view. If more are received, only the first 40 keys will be kept.
  • If you are using the same key twice, the last value associated with the key will be collected.
On the SDK side
  • Every dynamic variable is composed of a pair of key (max. 512 characters) and value (max. 255 characters string or a whole number between 0 and 232 - 1 ). The SDK will trim the exceeding characters.
  • If key or value is empty, the SDK will send the string "cs-empty".

Defining dynamic variables

To define and send a dynamic variable, use the API below. For each dynamic variable, we send:

  • Key (string, mandatory)
  • Value (string or integer, mandatory)

Note that if you send an integer as a value, it has indeed to be an integer. A null or a float will not be accepted as a valid parameter, and will result in an error.

import { ContentsquareCDVPlugin, DynamicVarItem } from '@contentsquare/cordova-plugin-types';
 
declare var ContentsquarePlugin: ContentsquareCDVPlugin;
 
const myDynamicVar: DynamicVarItem = {
    dynVarKey: 'myKey',
    dynVarValue: 32,
}
 
ContentsquarePlugin.sendDynamicVar(myDynamicVar, (result) => {
    // Success
}, (err) => {
    // Handle Error
});

Sending a dynamic variable for each session

You may want to send a dynamic variable for each session (like the user's country or store). While triggering the dynamic variable at app launch will cover most cases, it will not be enough. A session can start when the app is put in foreground, after staying in background for more than 30 minutes. See Session definition for more information.

That is why we also recommend sending such dynamic variable every time the app enters foreground.

You can use the onResume event triggered by Cordova to detect foreground and trigger a dynamic variable.

Privacy

The Contentsquare Cordova Plugin and SDKs are compliant with the Play Store and App Store Privacy guidelines as well as with the EU General Data Protection Regulation (GDPR).

Consult our Privacy Center and Privacy Policy.

Even though Contentsquare only collects usage data on your app, we will consider every new user to be opted-out. To start tracking, the Opt-in API must be called.

Opt-in

Use the Opt-in API to get user consent. Calling this API will generate a user ID and initiate tracking.

import { ContentsquareCDVPlugin } from '@contentsquare/cordova-plugin-types';
 
declare var ContentsquarePlugin: ContentsquareCDVPlugin;
 
ContentsquarePlugin.optIn((result)=>{
    // Success
}, (err)=>{
    // Handle error
});

Opt-Out

Permanently breaking the link and stopping all data collection.

When this API is called, tracking stops immediately, all settings are reset (session number, page number, user ID...) and all files related to Contentsquare tracking are deleted. Contentsquare will never track and collect any data from the user's phone unless the Opt-in API is called again.

import { ContentsquareCDVPlugin } from '@contentsquare/cordova-plugin-types';
 
declare var ContentsquarePlugin: ContentsquareCDVPlugin;
 
ContentsquarePlugin.optOut((result)=>{
    // Success
}, (err)=>{
    // Handle error
});

How the SDK works

Initialization

The way our SDK works is by auto-starting with the application launch and attaching to the current process in order to intercept the events and gestures we are interested in.

Configuration

Once started, our SDK fetches it config from our servers, and then depending on the segmentation size (defined by our team when you sign a contract) it will start collecting data from system and user events it detects from the runtime.

Tracking

The SDK monitors the application lifecycle events and the view hierarchy, and generates analytics data from the behavior of the app, the content of the screen and the interaction of the user. These events are then locally stored, and eventually sent to our servers in batches. We then aggregate that data to create usable visual information into our Web Application, which you use to gather insights.

Sending data

[tab] Android

Checkout the Native Android SDK documentation for Sending data

[tab] iOS

Checkout the Native iOS SDK documentation for Sending data

Session definition

A session represents a single period of user interaction in the app. In Contentsquare, a session ends when the user has spent a certain amount of time outside the app. The SDK checks this when an app start or app show event is detected. This time spent outside the app, ending a session is set to 30 minutes by default. But it can be changed if it is requested.

If the app is put in the background or killed (intentionally by the user or by the OS) but the user comes back within 30 minutes, it will not end the session. These events are considered to be part of a session.

Collected data points

  • The events are in JSON format, which lists the properties and their description in comment.
  • Events are sent to the server in batches.
  • A batch is a subset of events originating from one session. A session can send events in more than one batch.
  • The batch size is defined in a run configuration file specific to each app (50 events by default).

Requests meta data

Each batch has a common header, a set of device specific, and repeatable information and an array of events, which is immutable. The header is composed at the moment of sending, so it has to be constant info ONLY. The array in the payload is data stored at the moment of collection.

The structure of the batches of events will have the following format:

{
  pid:8, // int - ProjectId - represented in the mobile config format
  uid:"ac1529a7-59f6-49d9-b254-6f0a22f57284", // String - uuid Unique user ID
  dt:4, // int - device type (loosely enforced enum - [SDK-phone : 4, SDK-tablet :5])
  dma:"Samsung", // String - device manufacturer. This property is optional and if by any chance the device model cannot be determined it will be dropped from the Json object.
  dmo:"SG", // String - device model. This property is optional and if by any chance the device model cannot be determined it will be dropped from the Json object.
  os:"7.0", // String - os version (Android version name 6.0, 7.0, 8.0)
  l:"en_US", // String - Language in iso-639 format https://www.ibabbleon.com/iOS-Language-Codes-ISO-639.html
  tz:"Europe/Paris", // String - timezone https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
  now:1522159618000, // long - timestamp when the batch was sent
  to:{ // object - type origin of the event
    an:"appname" // String - application name
    st:"SDK-android", // String - type of SDK
    sf:"release", // string - SDK flavor/variant [release/debug/god]
  },
  r:{ // Device - resolution.
    w:1080, // int - width
    h:1920 // int - height
    d: 1.5 // The device density as float. Its values can vary between (0.75 and 10)
  },
  pl:[] // JSon array payload - list of event objects, see below
}

Events

Events meta data

All events have a common first part (don't confuse it with the header explained above). This common section is data which is common for all events by type but is gathered at the moment the event occurred. This common section is a part of the actual event payload.

{
  upt:1522, // long - system update in milliseconds
  euid:"euid", // String - event UUID
  url:"app-and://identifier/mainPath/secondaryPath?title=screeName", // String - screenName is passed in the title query Parameter
  scn:4, // int - the number of screens already shown in the session
  c:3, // int - connectivity type [-1 - offline, 0 - error, 1 - wifi, 2 - 2g, 3 - 3g, 4 - 4g]
  ci:"verizon", // String - carrier_id when user is on mobile network
  o:1, // int - orientation [0 = portrait, 1 = landscape]
  vo:{ // object - version origin of the event
    sv:"2.1", // string version of the SDK
    sb:4, // int - SDK build number
    av:"appVersion", // String - application version
    af:"appFlavor" // String - application string - [release/debug/god]
    ab:1 // int - application build number
  },
  sn:1, // int - session id (positive int)
  t:12894726459435 // long - timestamp of the event (in milliseconds)
}

All event specific properties are appended to this JSON object.

App Start

This event describes the absolute start of the app.

The trigger for this event is the absolute start of the app.

This is the first event sent when the SDK is invoked.

ea:0 // int - event action - defined above

App Show

This event is sent when the user brings the app in the foreground (switching from another app, exiting lock screen, etc.). This event means the app is focused.

ea:1 // int - event action - defined above

App Hide

This event is sent when the user exit (minimizes) the app, or switches to something else . This event means the app is not focused and the session might end, but we have not completely ended the session yet, as the user might return.

ea:2 // int - event action - defined above

Screenview

Everything starts with a View event. This is an event which describes the equivalent of a "page view" in the web. This event is sent when the Track Screen API is called.

ea:4 // int - event action - defined above
st:"title", // String - screen title
sl:34543 // int - (load time) screen load time (diff between last action and this event)

Transaction

To track transactions, we provide a public API which can send a transaction object (see section Track Transactions). This object must contain the following parameters:

ea: 16, // int - event action - defined above
tr: { // a json object with different properties defining the transaction made
    vl: 20.0, // mandatory - float - the value of the transaction
    cu: 978, // mandatory - int - the ISO 4217 code of the currency of the transaction
    id: "32akjkljklJ575775" // optional - string - an id for the transaction
}

Dynamic variables

To track dynamic variables we provide a public API which can send a custom event object (see section Dynamic variables).

// Dynamic variable event with a string value
ea:18, // int - event action - defined above
k:"key", // String - Custom key assigned by client.
v:"value" // String - Custom value assigned by client.
// Dynamic variable event with a number value
ea:19, // int - event action - defined above
k:"key", // String - Custom key assigned by client.
v: 2344 // Integer - Custom value assigned by client.

Tap

Single Finger gesture event, when the user is interacting with a loaded screen. This is an event which describes the equivalent of a "click" in the web. This event is defined by the following sequence of touch events:

  • Touch Down -> N x Touch Move -> Touch Up
ea:6 // int - event action - defined above
tvp:"[root]>view#id>view2>", // String - target view path
tvid:"btn_ok", // String - target view id
ur: true, // boolean - was this a "responsive" touch event (the target view had a handler)

Long press

Single Finger gesture event, when the user is interacting with a loaded screen.

This event is defined by the following sequence of touch events:

  • Touch Down → N x Touch Move → Touch Up
  • Duration: > 500ms
  • Distance: < 24 dp
ea:8 // int - event action - defined above
tvp:"[root]>view#id>view2>", // String - target view path
tvid:"btn_ok", // String - target view id

Drag (Slow Swipe)

Single Finger gesture event, when the user is interacting with a loaded screen.

This event is defined by the following sequence of touch events:

  • Touch Down → N x Touch Move → Touch Up
  • Distance: > 48 dp
  • Finger Velocity < 100 dp/s
ea:9 // int - event action - defined above
tvp:"[root]>view#id>view2>", // String - target view path
tvid:"btn_ok", // String - target view id
fd: 3, // int - finger direction - [1,2,3,4,5] -> [up, down, left, right, complex_pattern]
tvd:100, // int - target view distance dragged
tvv:100 // int - target view velocity while dragging dp/s

Flick (Fast Swipe)

Single Finger gesture event, when the user is interacting with a loaded screen.

This event is defined by the following sequence of touch events:

  • Touch Down → N x Touch Move → Touch Up
  • Distance: > 48 dp
  • Finger Velocity > 100 dp/s
ea:10 // int - event action - defined above
tvp:"[root]>view#id>view2>", // String - target view graph path
tvid:"btn_ok", // String - target view id
fd: 3, // int - finger direction - [1,2,3,4,5] -> [up, down, left, right, complex_pattern]
tvd:100, // int - target view distance scrolled
tvv:100 // int - target view velocity while scrolling dp/s

Security

Transmission and hosting

Our server side uses HTTPS to makes sure that data is encrypted in transport.

Our hosting solution is a PCI DSS Level 1 Service Provider.

What is not collected

  • Passwords from password fields
  • Geo location information
  • Information from contacts, emails, or any other user identifiable information.
  • Text from labels, buttons, and any other widget which contains text
  • Accessibility information from any widget which the user interacts with
  • Labels printed on the screen of any kind.

Compatibility

Each version of the Contentsquare plugin will be linked to specific, fixed versions of each native SDK. In order to make that clear, here is a compatibility table to consider when choosing your version of the plugin (refer to the Cordova Plugin Changelog to know what the changes are for each version.

Plugin VersioniOS SDK VersionAndroid SDK VersionMin Cordova VersionMax Cordova Version
0.3.04.20.04.15.011.0.011.0.x
0.2.04.18.04.15.011.0.011.0.x
0.1.04.15.14.11.011.0.011.0.x

Impact on performances

We always strive to be non-intrusive, and transparent to the developers of the client app.

We apply this rule on the performance as well.

[tab] Android

[tab] iOS

Changelog

📚 Cordova Plugin Changelog

📚 Mobile SDK Homepage

📚 iOS SDK Documentation

📚 Android SDK Documentation