Tracking in Android WebViews: JavaScript Bridge

JavaScript bridge is useful if you are using WebViews in your Android app.

WebEngage provides a JavaScript bridge which enables you to handle WebEngage Website SDK calls from your Android WebViews. When you use this bridge, all WebEngage JavaScript API calls (such as track, user.setAttribute, screen) made from web pages inside WebViews will be redirected to WebEngage Android native APIs. This will ensure that tracked data is attributed to the right devices, even if Website SDK APIs are called from within your Android app WebViews.

Follow the steps below to create a bridge between WebEngage Website SDK and Android SDK. These steps assume that you have already integrated the Website SDK and are using it to track users, events and other information on your website.

Step 1: Replace your existing WebEngage Website SDK integration code with the one below at the end of the <head> section of each page you are tracking.

<script id="_webengage_script_tag" type="text/javascript">
  var webengage;
  ! function(w, e, b, n, g) {
    function o(e, t) {
      e[t[t.length - 1]] = function() {
        r.__queue.push([t.join("."), arguments])
      }
    }
    var i, s, r = w[b],
      z = " ",
      l = "init options track screen onReady".split(z),
      a = "feedback survey notification".split(z),
      c = "options render clear abort".split(z),
      p = "Open Close Submit Complete View Click".split(z),
      u = "identify login logout setAttribute".split(z);
    if (!r || !r.__v) {
      for (w[b] = r = {
          __queue: [],
          __v: "6.0",
          user: {}
        }, i = 0; i < l.length; i++) o(r, [l[i]]);
      for (i = 0; i < a.length; i++) {
        for (r[a[i]] = {}, s = 0; s < c.length; s++) o(r[a[i]], [a[i], c[s]]);
        for (s = 0; s < p.length; s++) o(r[a[i]], [a[i], "on" + p[s]])
      }
      for (i = 0; i < u.length; i++) o(r.user, ["user", u[i]])
    }
  }(window, document, "webengage");


  if (window.__WEBENGAGE_MOBILE_BRIDGE__) {

    (function(bridge) {

      var type = Object.prototype.toString;

      webengage.user.login = webengage.user.identify = function(id) {
        bridge.login(id)
      };
      webengage.user.logout = function() {
        bridge.logout()
      };

      webengage.user.setAttribute = function(name, value) {
        var attr = null;

        if (type.call(name) === '[object Object]') {
          attr = name;
        } else {
          attr = {};
          attr[name] = value;
        }

        if (type.call(attr) === '[object Object]') {
          bridge.setAttribute(JSON.stringify(attr));
        }
      };

      webengage.screen = function(name, data) {
        if (arguments.length === 1 && type.call(name) === '[object Object]') {
          data = name;
          name = null;
        }

        bridge.screen(name || null, type.call(data) === '[object Object]' ? JSON.stringify(data) : null);
      };

      webengage.track = function(name, data) {
        bridge.track(name, type.call(data) === '[object Object]' ? JSON.stringify(data) : null);
      };

    })(window.__WEBENGAGE_MOBILE_BRIDGE__);

  } else {

    setTimeout(function() {
      var f = document.createElement("script"),
        d = document.getElementById("_webengage_script_tag");
      f.type = "text/javascript",
        f.async = !0,
        f.src = ("https:" == window.location.protocol ? "https://ssl.widgets.webengage.com" : "http://cdn.widgets.webengage.com") + "/js/webengage-min-v-6.0.js",
        d.parentNode.insertBefore(f, d)
    });

  }

  webengage.init("__LICENSE_CODE__");
</script>

🚧

Make sure you replace YOUR_WEBENGAGE_LICENSE_CODE with your WebEngage license code.

Step 2: Inject WebEngage Mobile Bridge into your Android WebView as shown below.

import com.webengage.sdk.android.bridge.WebEngageMobileBridge;
  ...
  ...
myWebView.addJavascriptInterface(new WebEngageMobileBridge(this), WebEngageMobileBridge.BRIDGE_NAME);
import com.webengage.sdk.android.bridge.WebEngageMobileBridge;
 ...
 ...
myWebView.addJavascriptInterface( WebEngageMobileBridge(this), WebEngageMobileBridge.BRIDGE_NAME)

Here myWebView is the WebView for which you are adding this bridge.

Event Reporting Strategy

WebEngage stores every datapoint in local database and sends them periodically to server in a background thread when a certain criteria is met. The criteria is based on the number of events in local database and last synced time.

WebEngage allows you to change the event reporting behaviour during SDK initialization , so that you can make events sync faster to WebEngage if available connectivity is good.

WebEngageConfig webEngageConfig = new WebEngageConfig.Builder()
  	.setEventReportingStrategy(ReportingStrategy.FORCE_SYNC) //During initialization
  	.build();
WebEngage.engage(this.getApplicationContext(), webEngageConfig);
val webEngageConfig = WebEngageConfig.Builder()
            .setEventReportingStrategy(ReportingStrategy.FORCE_SYNC) //During initialization
            .build()
        WebEngage.engage(this.applicationContext, webEngageConfig)

Alternatively you can also change this behaviour anytime during application lifecycle using below API.

WebEngage.get().setEventReportingStrategy(ReportingStrategy.BUFFER);
WebEngage.get().setEventReportingStrategy(ReportingStrategy.BUFFER);

🚧

setEventReportingStrategy is to be called only once in a session. The SDK remembers this setting unless your app is restarted.

By default, the reporting strategy is set to ReportingStrategy.BUFFER. See ReportingStrategy for details.

Fetch WebEngage Configuration

Returns WebEngage configuration. See WebEngageConfig for details.

WebEngageConfig weConfig = WebEngage.get().getWebEngageConfig();
val weConfig = WebEngage.get().webEngageConfig

Logging

You can enable/disable logs from WebEngage SDK during SDK initialization as shown below.

WebEngageConfig webEngageConfig = new WebEngageConfig.Builder()
  	.setDebugMode(true)
  	.build();
WebEngage.engage(this.getApplicationContext(), webEngageConfig);
val webEngageConfig = WebEngageConfig.Builder()
            .setDebugMode(true)
            .build()
        WebEngage.engage(this.applicationContext, webEngageConfig)

Alternatively, you can change log level anytime using below API.

WebEngage.get().setLogLevel(Logger.SILENT);
WebEngage.get().setLogLevel(Logger.SILENT);

🚧

This is to be used only in development mode.

Location Tracking

WebEngage Android SDK allows you to define location tracking accuracy, or to disable location tracking, which enables you to optimize for resources - device battery and data usage. Follow the steps below to set location tracking accuracy:

Step 1: Add Google Play location dependency in your app's build.gradle.

dependencies {
  implementation 'com.google.android.gms:play-services-location:15.0.1'
}

Step 2: Add the below location permission in your AndroidManifest.xml file.

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

Step 3: Use setLocationTrackingStrategy to define location tracking accuracy. Note that this method is to be called after WebEngage SDK initialization.

Method 1: Setting Location Tracking Strategy in WebEngageConfig

import com.webengage.sdk.android.WebEngageConfig;
import com.webengage.sdk.android.LocationTrackingStrategy;

...

WebEngageConfig config = new WebEngageConfig.Builder()
	...
	.setLocationTrackingStrategy(LocationTrackingStrategy.ACCURACY_CITY)
	.build();
import com.webengage.sdk.android.WebEngageConfig;
import com.webengage.sdk.android.LocationTrackingStrategy;

...

val config = WebEngageConfig.Builder()
...

.setLocationTrackingStrategy(LocationTrackingStrategy.ACCURACY_CITY)
.build();

Method 2: Setting Location Tracking Strategy Dynamically

import com.webengage.sdk.android.WebEngage;
import com.webengage.sdk.android.LocationTrackingStrategy;
        
...
  WebEngage.get().setLocationTrackingStrategy(LocationTrackingStrategy.ACCURACY_BEST);
import com.webengage.sdk.android.WebEngage;
import com.webengage.sdk.android.LocationTrackingStrategy;
        
...
  WebEngage.get().setLocationTrackingStrategy(LocationTrackingStrategy.ACCURACY_BEST);

Following are the options that you can use to define location tracking accuracy.

Location accuracy levelDescription
ACCURACY_BESTUses the highest level of accuracy. Recommended for using geofencing; consumes more device power.
Interval between location updates: 15 minutes
Fastest interval between location updates: 5 mins
Smallest displacement that can be measured: 1 km
ACCURACY_CITYRecommended for city-level location tracking; consumes less device power.
Interval between location updates: 3 hours
Fastest interval between location updates: 1 hour
Smallest displacement that can be measured: 20 km
ACCURACY_COUNTRYRecommended for country-level location tracking; consumes less power.
Interval between location updates: 12 hours
Fastest interval between location updates: 12 hours
Smallest displacement that can be measured: 100 km
DISABLEDDisables location tracking by WebEngage SDK. With this value, WebEngage will neither track any user location nor update it on your WebEngage dashboard.

If you are using this configuration, you can manage location updates by using setLocation to manually set the location.

🚧

Note that WebEngage.get().setLocationTracking(true) is deprecated.

Apps targeting Android Marshmallow and above would need to request location permission from user and set location tracking to true or false from permission request callback depending on whether location permission is granted or not.

Alternative Initialization

Use this approach if you are targeting devices below Android API level 14.

Step 1: Initialize WebEngage SDK from the onCreate of your Application class.

import com.webengage.sdk.android.WebEngageConfig;

public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    WebEngageConfig webEngageConfig = new WebEngageConfig.Builder()
            .setWebEngageKey(YOUR_WEBENGAGE_LICENSE_CODE)
            .setDebugMode(true) // only in development mode
            .build();
    WebEngage.engage(this, webEngageConfig);
  }
}
val webEngageConfig = WebEngageConfig.Builder()
            .setWebEngageKey(YOUR_WEBENGAGE_LICENSE_CODE)
            .setDebugMode(true) // only in development mode
            .build()
WebEngage.engage(this, webEngageConfig)

Step 2: Manually call WebEngage's session tracking API from onStart and onStop of each of your activities.

import com.webengage.sdk.android.WebEngage;

...
...

@Override
public void onStart(){
  super.onStart();
  WebEngage.get().analytics().start(this);
}

@Override
public void onStop(){
  super.onStop();
  WebEngage.get().analytics().stop(this);
}
import com.webengage.sdk.android.WebEngage;

...
...
 
   override fun onStart() {
        super.onStart()
        WebEngage.get().analytics().start(this)
    }

    override fun onStop() {
        super.onStop()
        WebEngage.get().analytics().stop(this)
    }

You are now ready to continue with the setup process here.

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!