@benshi.ai/js-sdk
v1.1.7
Published
Benshi SDK
Downloads
77
Readme
benshi.ai Analytics js SDK
This documentation covers the steps to integrating SDK in your js apps. We’ll also discuss a few fundamentals of how the dashboard works in tandem with your app usage to view your users and engage them with contextually personalized messages.
There are two types of data we collect from the partner's side:
- content data (static content / items in the app)
- event data (event names, event details)
Content data are static data of certain content (e.g. video, audio, a product, etc.). Event data is time-series data generated by the user.
Getting Started
In order to create ease for partners, we have divided the SDK into multiple modules. Each module represents a specific app niche that partners can use based on their app category.
A list of these modules are:
In order to use the SDK, Core is mandatory to include as it contains the elements regarding the basic app navigation and workflow including nudges. Moreover, all the modules require the core to be integrated in order to successfully log the events.
As NPM dependency
npm i @benshi.ai/js-sdk
# or
yarn @benshi.ai/js-sdk
for latest release please head to npm package.
SDK overview
Benshi's SDK
provides a mechanism to inject logs to the data analytics server. The overall functionality may be described as follows: whenever an event is logged, it is not inmediately delivered. Instead, it is queued internally and sent to the server in batches, to save network bandwidth. If the network is down, the SDK
is also able to store the events until it is back, or even store them in a permanent storage, like localStorage
to manage the case where the user closes the application before the events are correctly delivered.
Benshi SDK automatically starts tracking user data (e.g., Upload/download speed, OS version, device IDs) and engagement with the basic setup above. This data can be stored on the device and uploaded in batches to reduce network and power usage, and to increase the likelihood of successful uploads while you can also upload the events as soon as they happen.
Each event can further be understood in the context of its attributes which includes details like time, upload/download speed, device details, locale, online/offline usage, screen time, interactions, and so on. This enables you to gain in-depth insights into user interactions across your app. You can also leverage this data to segment users, personalize messages and configure campaign targeting.
Let’s take a look at the general structure of the attributes sent using that SDK:
| Property Name | Reported on Portal | Description | | :------------: | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | User Id | u_id | User Id assigned in your Database, if you don’t have any signup/login process SDK defaults that to deviceID.| | Device Id | d_id | User’s Device ID to uniquely recognize.| | OS | os | The current OS they are using. It is specified in {os.Name (os.Version)} e.g. android (30) Having the device OS and version help us to deliver content better presentable on their device.| | SDK Version | sdk | Current SDK version you are using.| | Content Block | block | Current content block name the log is being called.| | Online Status | ol | Tracks if the device was online or not when the event was recorded.| | Timestamp | ts | Track the timestamp of the event in RFC 3339 format.| | Upload Speed | up | Track the upload speed of the device when the event was recorded.| | Download Speed | down | Track the download speed of the device when the event was recorded.| | Event Type | type | Type of event being tracked, use EventType class predefined events.| | Properties | props | Properties of the event being tracked. SDK provides predefined property models for you to integrate with ease. You can also track custom events too.|
For example, if a user needs to click on a product to view its details, then it is advisable to track this action as the event, product viewed as it brings them a step closer to making a purchase.
Workflow
First step to use the library is to create an instance of
BsLog
which is the module responsible for the communication with Benshi's platform and also for tracking some events autonomously.Once the user is identified, let the
SDK
know about that. This way, the events tracked from that moment will be associated to that user, improving the analytics performance. Regardless the user were already logged or if she/he has performed the login process in this session, call theidentify
method, within theBsLog
moduleAt any moment, track user events by calling the corresponding function in the
SDK
Next section describes how to perform these steps:
Get the SDK instance
In your App.js,
import {
BsLog,
IdentifyAction
} from '@benshi-ai/js-sdk'
const bslog = new BsLog('<your-analitycs-key>')
In order to customize the internal behaviour of the SDK
, an options object may be provided which can help with the enabling or disabling of nudges for multiplatform apps.
const option = {
activateNudgeMechanism: true
}
const bslog = new BsLog('<your-analitycs-key>', options)
// OR
const bslog = new BsLog('<your-analitycs-key>', {activateNudgeMechanism: true, defaultBlock: ContentBlock.ECommerce})
where:
- activateNudgeMechanism, indicates whether the SDK must receive and show nudges or not. When the SDK is embedded into a WebView and the native application already uses the Benshi SDK, it is not needed to receive nudge also in the WebView, since they are already been received in the main application. Default true
- defaultBlock, the SDK Provides the function
setCurrentBlock
to set the block name of those events that does not belong to a specific module, likepage
ormedia
events. Use this parameterdefaultBlock
to avoid callingsetCurrentBlock
in your different views if all of them belong to the same block.
Identification
Identification is a key step in the overall process. Once the user is identified, its user_id
will be included in the information sent to server within all events.
bslog.identify(IdentifyAction, <user-id>, user_properties)
where IdentifyAction
is defined as follows:
export enum IdentifyAction {
Login = "login",
Logout = "logout",
Register = "register"
}
where UserProperties
is defined as follows:
export interface UserProperties {
name?: string
organization?: string,
experience?: string,
region_state?: string,
city?: string,
workplace?: string,
profession?: string,
zipcode?: string,
/**
* country which the user is, represented as
* two characters in ISO 3166
*/
country?: Country, // Enum provided by SDK
/**
* iSO 639-1
*/
language?: Language, // Enum provided by SDK
education_level?: EducationLevel // Enum provided by SDK
}
Page Events
By default, SDK auto listens for page changes in the app along with session timings that implicates how to log a user spends on an activity, but you can also set the content block name for the page as well to specify the block the page is linked to, it can be core which represents basic app navigation, e-commerce if it is a page from your in app marketplace, e-learning if it related to learning section inside the app.
To provide this information, the application must call the method setCurrentBlock
which is available in the Navigation
module:
Navigation.setCurrentBlock(contentBlockName) //SDK provides enum/constants ContentBlock for specifying content block name.
If the none of the available section provided in the enum ContentBlock
fits fine for the new URL, use ContentBlock.Core
By default, SDK will get the class name of the page to use as the page title.
Search Events
You can use search events to track how search returns results based on user queries and what items users are searching for. It supports all the modules available by benshi i.e. general, e-learning, e-commerce, etc. You also need to log the Ids in the form of a string list to log what results are returned by the search and in case of no result found, you can log with an empty list. Search also supports filters if any applied to the search by the user which is supported in the app. You can provide these filters in the form of hashMap formatted as <String, String>
const searchId = Navigation.logSearchEvent(searchProperties, isNewSearch)
where searchProperties
is defined as below:
const searchProperties = {
contentBlock: 'e-commerce', // ContentBlock.ECommerce
page: 1, // int
query, // string
results_ids, // string array of ids
filter: filterOptions // hash of <string, string>
}
and isNewSearch
is the boolean to help you with the search consisting of mulple pages. set this true if it is a new search and false if the action performed on the search is just traversing between search pages.
E Commerce - Logging Events
We have several predefined actions that users can perform while interacting with your app. These actions are referred to as System Events that help in tracking elements on your app with user interaction.
Here's a list of System Events that can be tracked using e-commerce module:
| Event Name | Description | | ---------- | ---------------------------------------------------------------- | | Item | Track user interactions with items of marketplace.| | Cart | Track user interactions with the cart. | | Checkout | Track user interactions with checkout event happening inside the app. | | Delivery | Track events related with delivery of the order. |
Next table summarizes the available events managed by the SDK. Note how each module exposes several ones and how each of them may have several subtypes
and associated actions
.
Tracking Item Events
It can be called when a user taps on an item to view it in full screen and also when a user taps on the description of the item to view more details or item gets an impression. This event refers to the item view log that reflects the user has seen a specific item or viewed its details.
where type-of-event
is defined within each module, and properties
is an object whose contents depends on the type-of-event
An example of this mechanism is the logItemEvent
that belongs to ECommerce
module:
logItemEvent(properties: ItemProperties)
In the SDK API docs
describes the ItemProperties
as follows:
export interface ItemProperties {
action: ItemAction,
item: ItemDetail,
search_id?: string
meta?:any
}
export interface ItemDetail {
id: string,
quantity: number,
price: number,
currency: CurrencyCode,
type: ItemType,
stock_status: StockStatus,
promo_id: string
}
export enum ItemAction {
View = "view",
Detail = "detail",
Impression = "impression", // generated automatically
AddFavorite = "add_favorite",
RemoveFavorite = "remove_favorite",
AddReminder = "add_reminder",
RemoveReminder = "remove_reminder",
RemoveReminderAuto = "remove_reminder_auto"
}
export enum ItemType {
Drug = "drug",
Electronics = "electronics",
Clothing = "clothing",
Book = "book",
Misc = "misc"
}
export enum StockStatus {
InStock = 'in_stock',
LowStock = 'low_stock',
OutOfStock = 'out_of_stock'
}
so, just call the function like this:
ECommerce.logItemEvent(ItemProperties)
In the case of itemAction being view, you also need to pass the catalog events as well which contains the the details about the product being viewed.
export interface DrugProperties {
market_id?: string,
name?: string,
description?: string,
supplier: string, // required
producer?: string,
packaging?: string,
active_ingredients?: string,
drug_form?: string,
drug_strength?: string,
atc_anatomical_group?: string,
otc_or_ethical?: string
}
ECommerce.logItemEvent(ItemProperties, DrugProperties )
Tracking impressions
For the e-commerce
section, it is required to track the viewable impressions
, that is, those items that have been visible in the screen for, at least, a specific time. The SDK performs this tracking semi-automatically, so requires some developer intervention. There are some functions in the API for that:
startTrackingImpressions(containerClassname: string, itemClassname: string, searchId: string)
stopTrackingImpressions(containerClassname: string)
restartTrackingImpressions(containerClassname: string, searchId: string)
Whenever the user goes to a page that shows a list of e-commerce items
, call startTrackingImpressions
, indicating the className
of the container where the items are listed. All the items must also share a common className, itemClassname
, to allow the SDK to track them. searchId
is an identifier returned by logSearchEvent
, in case the user have performed a search in that section.
When the user performs a search in the same page, call restartTrackingImpressions
indicating the new searchId
In addition, each item must contain some data, as shown in the next example:
<div
data-log-id="{item_id}"
data-log-quantity="{item_quantity}"
data-log-price="{item_price}"
data-log-currency="{item_currency_code}" // SDK provides enum/constants CurrencyCode
data-log-type="{item_type}" // SDK provides enum/constants ItemType
data-log-stock-status="{item_id}" // SDK provides enum/constants StockStatus
data-log-promo-id="{item_id}" // string
data-log-drug-catalog-object={JSON.stringify(drugProperties)} // SDK provides object DrugProperties
class="{item_id}" // id/class name/container name for the card layout in your code
>
All the fields, id
, quantity
, price
, currency
(see CurrencyCode
definition), type
(see ItemType
definition) are mandatory.
Tracking Cart Events
Is used to log the events related to the cart. You can use this event to log when an item was added or removed from the cart.
export interface ItemDetail {
id: string,
type: ItemType,
quantity: number,
price: number,
currency: CurrencyCode,
stock_status: StockStatus, // OPTIONAL
promo_id: string // OPTIONAL
}
export enum CartAction {
AddItem = "add_item",
RemoveItem = "remove_item"
}
export enum ItemType {
Drugs = "drugs",
Electronics = "electronics",
Clothing = "clothing",
Books = "books",
Misc = "misc"
}
export interface CartProperties {
id: string;
action: CartAction,
item: ItemDetail,
cart_price: number,
currency: CurrencyCode,
meta?: any
}
BsECommerce.logCartEvent(CartProperties)
Tracking Checkout Events
Is required to log checkout events for orders. You can trigger this event when the order has been placed or is unable to place. you need to provide orderId in both cases. If you don't have the orderId in case of not being successful then you can pass cartId for that order.
const items = [
{
id: '123',
type: 'drugs',
quantity: 2,
price: 23,
currency: CurrencyCode.EUR,
stock_status: StockStatus.InStock,
promo_id: ''
},{
id: '456',
type: 'drugs',
quantity: 1,
price: 10,
currency: CurrencyCode.EUR,
stock_status: StockStatus.InStock,
promo_id: ''
}
]
export interface CheckoutProperties {
id: string //order_id
is_successful: boolean // if checkout was successful or not.
cart_price: number,
currency: CurrencyCode,
items: Array<ItemDetail>,
cart_id: string
meta?: any
}
const checkoutEvent = {
id: '<order id>',
is_successful: true,
cart_price: 56,
currency: CurrencyCode.EUR,
items: items,
cart_id: '<cart id>'
}
BsECommerce.logCheckoutEvent(checkoutEvent)
Tracking Delivery Events
Is used to log the status of the delivery. It can be used to log the delivered status of the order or partial order. Details about the items in the specified delivery should be provided in the catalog.
export interface DeliveryProperties {
id: string, // delivery_id
action: DeliveryAction,
order_id: string,
meta?: any
}
export enum DeliveryAction {
Delivered = "delivered"
}
const deliveredEvent = {
id: 'delivery-id',
action: DeliveryAction.Delivered,
order_id: 'order-id'
}
BsECommerce.logDeliveryEvent(deliveredEvent)
Loyalty - Logging Events
Benshi SDK Loyalty module consists of events for rewarding platforms. You need to implement this module if your app offers users some rewards, points on completing certain actions or achieving a certain milestone by using your app. To use the payments module you need to include the following dependency in your app-level build
| Event Name | Description | | ---------- |---------------------------------------------------------------- | | Promo | Track user interaction with a promo button (a button that automatically adds items to the current cart) |
Promo
export enum PromoAction {
Apply = "apply",
View = "view"
}
export enum PromoType {
AddToCart = "add_to_cart",
Coupon = "coupon"
}
export enum PromoItemType {
Blood = "blood",
Book = "book",
Clothing = "clothing",
Drug = "drug",
Electronics = "electronics",
Misc = "misc",
Oxygen = "oxygen"
}
export interface PromoItem {
id: string,
type: PromoItemType
}
export interface PromoProperties {
id: string,
action: PromoAction,
items: PromoItem[],
title: string,
type: PromoType
}
Payments - Logging Events
Here's a list of System Events that can be tracked using the payment module:
| Event Name | Description | | ---------- |---------------------------------------------------------------- | | Deferred Payment | Track user payment status when they undergo processing or processed. |
Usage for the above-mentioned event is given below:
Deferred Payment Event
Whenever the application is aware of the payment, this method must be called
export interface DeferredPaymentProperties {
id: string, // payment_id
order_id: string, // the same ID used in Checkout and Delivery events
action: DeferredPaymentType,
account_balance: number,
payment_amount: number,
currency: CurrencyCode,
is_successful: boolean, // is payment processed successfully
meta?: any
}
export enum DeferredPaymentType {
PaymentProcessed = "payment_processed"
}
const deferredPaymentEvent = {
id: 'payment-id',
order_id: 'order-id-1234',
action: DeferredPaymentType.PaymentProcessed,
account_balance: 100,
payment_amount: 56,
currency: CurrencyCode.EUR,
is_successful: true,
}
logDeferredPaymentEvent(deferredPaymentEvent)
Updating in-app messages styles
in-app
messages are notifications showed directly by the SDK. They can be styled accoording to application needs just by overwriting the corresponding CSS classes. First of all, notification are enclosed into a container, whose class is benshi-notification-container
. Then, each message is represented as a direct child div
element.
Example: show notifications in the bottom:
.benshi-notification-container {
bottom: 0px;
top: unset;
}
Example: change notification background color
.benshi-notification-container > div > div {
background-color: 'red'
}
Receiving nudges
SDK will automatically receive nudges from Benshi Analytics platform and they will be shown as system notification according to its timestamp. However, not all major browsers works in the same way. Firefox, for instance, requires the user to interact with the application to call the requestPermission
API. If the user does not interact with the application in some way, the SDK won't be able to requests permissions and the notifications will never be shown. SDK captures
automatically click events to enable notification in the corresponding callback.
There are also some key constraints that the application must satisfy to use the Notification
API.
- use HTTPS
- cross-origin not allowed, that is the application can not be embedded within an
<iframe>
When the user taps on the nudge notification, the main application may receive an event to act accordingly. The event is specified in the type
parameter, and the resource
include some additional information that may be required to complete the action.
- Type, string of type
BsLogEventType
BsLogEventType.Redirect
, the app must redirect to the product page, whose id isresource.id
BsLogEventType.AddToCart
, the app must include the indicated product in the current cart.
- Resource, an object with two attributes:
id
, the ID of the product this nudge is recommendingtype
, it represents the family a product belongs to (drug, media,etc)
bslog.on(BsLogEvents.NudgeAction, (type, resource) => {
if (type === BsLogEventType.Redirect) {
// code to navigate to the product whose Id is resource.id
} else if (type === BsLogEventType.AddToCart) {
// code to add the product to the cart
}
})
Development
Find some development notes in DEV.md
Guidelines
Anything you include in the
meta
will be sent to the backend and be visible in the log monitoring section, but it will not be processed.Custom Event Attributes
can be of these data types: String, Number, Boolean, Date, List, Map.Make sure to include your SDK key while initialization or else it would through an exception.
By default, SDK logs the events after evert 10 seconds. You can decide for each event if it needs to be updated immediately, or it can wait until the end of the app session. To send an event immediately, you can use:
ECommerce.logItemEvent(props, sendNow) // set sendNow to true to log immediately
Please ensure consistent usage of the names of Custom Events in meta and their Custom Attributes across all your apps (Android, iOS, Web) and website.
Please use the same name conventions as provided by the enums if you choose to pass strings as values or else an erorr will be thrown.
Nudges may not be delivered to apps which were put into background restriction by the user (such as via: Setting -> Apps and Notification -> [app-name] -> Battery). Once your app is removed from background restriction, new messages to the app will be delivered as before. In order to prevent lost messages and other background restriction impacts, make sure to avoid bad behaviors listed by the Android vitals effort. These behaviors could lead to the Android device recommending to the user that your app be background restricted. Your app can check if it is background restricted using: isBackgroundRestricted().
In situations where your web app is used inside a webview in android, do update the DOM-Storage of the webview to allow local storage. To do that you can use:
webView.settings.domStorageEnabled = true
In cases where the user restricted the app to show push notifications for the whole app or blocked the benshi notification channel, the SDK will log
block
event for that nudge.
Please feel free to drop in a few lines at [email protected] in case you have any further queries. We're always just an email away!