npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@benshi.ai/js-sdk

v1.1.7

Published

Benshi SDK

Downloads

45

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:

  1. content data (static content / items in the app)
  2. 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:

  1. Core

  2. E-commerce

  3. Loyalty

  4. Payments

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

  1. 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.

  2. 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 the identify method, within the BsLog module

  3. At 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, like page or media events. Use this parameter defaultBlock to avoid calling setCurrentBlock 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 is resource.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 recommending
    • type, 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!