Native Web Views

In addition to running in a standard web browser environment, the web SDK is also able to be connected or “bridged” to mParticle’s native iOS and Android SDKs.

This allows you to build and instrument your app in a web and Javascript context, while taking advantage of the advanced capabilities of the mParticle native iOS or Android SDKs.

How it works

In bridged mode, the web SDK operates only as an intermediary that passes data to the iOS or Android SDKs. Data collected in a WebView is sent to the mParticle Events API as Android or iOS data.

Configuring Webviews takes two steps. First, add the web SDK. Second, bind the web SDK to the native layer. Instrumentation depends on your use case, as explained below.

Because the web SDK acts as write-only within a WebView, a limited subset of the full web SDK functionality is available. All event logging works as normal, and the event data is simply passed to the native SDK to be sent on to mParticle. However, HTTP API calls will not work within a WebView. Similarly, any callbacks, such as the optional callbacks for IDSync API methods, will not work within a WebView.

1. Add the Web SDK

There are two different approaches for using the web SDK in a WebView:

  • Hybrid - Your website is viewed both via the browser and a mobile app. In this case, the data will be sent to mParticle via the Web input when the code is run in a browser, and via the iOS or Android input when the code is run in a WebView.
  • WebView only - Take this approach if you only need to track activity in a mobile WebView and you want the activity to only ever be attributed to the native app.

Hybrid

If the same JavaScript will potentially be loaded in a web browser and a native app’s WebView, you should instrument the Web SDK as normal. Start by creating a web input in order to get a Web API key. Then initialize the SDK. This setup will cause the SDK to send data via the web input when in a browser, and via the native SDK when in a WebView. At this point, your set up is complete.

Initializing the Web SDK this way only works if your WebView is not instantiated upon app launch. This is generally the case with most native apps. When a user launches your app, the user is brought to a native app and only navigates to a WebView some time after app launch. Alternatively, some native apps use a WebView as their entire app, and in this case, the webview is instantiated at app launch. If this is the case, you will have to also add a config option to the normal Web SDK set up as shown below:.

<script type="text/javascript">
  const mySdkConfig = {
    ...
    requiredWebviewBridgeName: 'myUniqueName',  // this must match the bridge name you set for iOS or Android when binding the SDK in step 2
  };

  window.mParticle = {
    config: mySdkConfig
  };

  // IMPORTANT NOTE! The below snippet is distinct from the WebView only snippet in the next section
  (
  function(e){window.mParticle=window.mParticle||{};window.mParticle.EventType={Unknown:0,Navigation:1,Location:2,Search:3,Transaction:4,UserContent:5,UserPreference:6,Social:7,Other:8};window.mParticle.eCommerce={Cart:{}};window.mParticle.Identity={};window.mParticle.config=window.mParticle.config||{};window.mParticle.config.rq=[];window.mParticle.config.snippetVersion=2.3;window.mParticle.ready=function(e){window.mParticle.config.rq.push(e)};var i=["endSession","logError","logBaseEvent","logEvent","logForm","logLink","logPageView","setSessionAttribute","setAppName","setAppVersion","setOptOut","setPosition","startNewSession","startTrackingLocation","stopTrackingLocation"];var n=["setCurrencyCode","logCheckout"];var t=["identify","login","logout","modify"];i.forEach(function(e){window.mParticle[e]=o(e)});n.forEach(function(e){window.mParticle.eCommerce[e]=o(e,"eCommerce")});t.forEach(function(e){window.mParticle.Identity[e]=o(e,"Identity")});function o(i,n){return function(){if(n){i=n+"."+i}var e=Array.prototype.slice.call(arguments);e.unshift(i);window.mParticle.config.rq.push(e)}}var r,c,a=window.mParticle.config,s=a.isDevelopmentMode?1:0,l="?env="+s,w=window.mParticle.config.dataPlan;if(w){r=w.planId;c=w.planVersion;if(r){if(c&&(c<1||c>1e3)){c=null}l+="&plan_id="+r+(c?"&plan_version="+c:"")}}var d=window.mParticle.config.versions;var m=[];if(d){Object.keys(d).forEach(function(e){m.push(e+"="+d[e])})}var f=document.createElement("script");f.type="text/javascript";f.async=true;f.src=("https:"==document.location.protocol?"https://jssdkcdns":"http://jssdkcdn")+".mparticle.com/js/v2/"+e+"/mparticle.js"+l+"&"+m.join("&");var p=document.getElementsByTagName("script")[0];p.parentNode.insertBefore(f,p)}
  )("REPLACE WITH API KEY");
</script>

WebView only

If your web app will only ever be loaded in your native app’s WebViews, there’s no need to create a web input for your app. You can use the static snippet below to include the web SDK without an API key. For iOS, you should set the mParticle.config.isIOS flag to true when your web app is loaded in a WebView. You will also need to set the bridgename on iOS and Android as detailed below.

<script type="text/javascript">
  const mySdkConfig = {
      ...
      requiredWebviewBridgeName: 'myUniqueName',  // this must match the bridge name you set for iOS or Android
      isIOS: true, // not necessary for Android webviews
  };
  window.mParticle = {
    config: mySdkConfig
  };

  // IMPORTANT NOTE! Use the below snippet if your web app will only ever be loaded in your native app's WebView.  It is unique to this use case and will not work in a hybrid scenario as described earlier.

  (
    function(){window.mParticle=window.mParticle||{EventType:{Unknown:0,Navigation:1,Location:2,Search:3,Transaction:4,UserContent:5,UserPreference:6,Social:7,Other:8}};window.mParticle.eCommerce={Cart:{}};window.mParticle.Identity={};window.mParticle.config=window.mParticle.config||{};window.mParticle.config.rq=[];window.mParticle.ready=function(t){window.mParticle.config.rq.push(t)};function e(e,o){return function(){if(o){e=o+"."+e}var t=Array.prototype.slice.call(arguments);t.unshift(e);window.mParticle.config.rq.push(t)}}var o=["endSession","logError","logEvent","logForm","logLink","logPageView","setSessionAttribute","setAppName","setAppVersion","setOptOut","setPosition","startNewSession","startTrackingLocation","stopTrackingLocation"];var n=["setCurrencyCode","logCheckout"];var i=["identify","login","logout","modify"];o.forEach(function(t){window.mParticle[t]=e(t)});n.forEach(function(t){window.mParticle.eCommerce[t]=e(t,"eCommerce")});i.forEach(function(t){window.mParticle.Identity[t]=e(t,"Identity")});var r=document.createElement("script");r.type="text/javascript";r.async=true;r.src="https://jssdkcdns.mparticle.com/js/v2/mparticle.js";var c=document.getElementsByTagName("script")[0];c.parentNode.insertBefore(r,c);}
  )(); // NO API KEY!
</script>

2. Bind the Web SDK

iOS SDK

On Apple SDK version 7.8.6 or later, the native webview bridge API requires a single initialization per instance of a given WKWebView. If you are using an older version of the Apple SDK, please upgrade to the latest version which you can find here.

Allocate a WKWebView (or otherwise acquire a reference to it), and initialize it with mParticle.

The following will add a WKScriptMessageHandler to your WKWebView that is scoped to your mParticle workspace.

- (void)viewDidLoad {
    [super viewDidLoad];
    WKWebView *myWkWebView = [[WKWebView alloc] init];
    [[MParticle sharedInstance] initializeWKWebView: myWkWebView];
}
override func viewDidLoad() {
    super.viewDidLoad()
    let myWkWebView = WKWebView()
    MParticle.sharedInstance().initializeWKWebView(myWkWebView)
}
How does this work?

The mParticle web SDK will look for this handler by name, forming a bridge to the Apple SDK. By default the handler’s name will be mParticle_<WORKSPACE TOKEN>_<BRIDGE VERSION>.

Where the values are:

  • <WORKSPACE TOKEN> is an alphanumeric value unique to your mParticle workspace
  • <BRIDGE VERSION> represents the version of the mParticle WebView API (currently v2)

Generally, you should let the SDKs use the default bridge names. For advanced use cases, you can customize the bridge name by:

  1. Setting mParticle.config.requiredWebviewBridgeName when initializing the mParticle web SDK
  2. Setting the bridge name from the iOS-side, with the following requirements:

    • The name should be alphanumeric, and no special characters are allowed.
    • The mParticle.config.requiredWebviewBridgeName setting on the web SDK should match the bridge name set on iOS.
[[MParticle sharedInstance] initializeWKWebView:myWkWebView
                                     bridgeName:@"myUniqueName"];
MParticle.sharedInstance().initializeWKWebView(myWkWebView, // reference to your webView variable
                                    bridgeName: "myUniqueName")

Android SDK

The following will add a “javascript interface” inline with this documentation:

WebView myWebView = (web view) findViewById(R.id.web view);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
//note that this *must* be before you load the page
MParticle.getInstance().registerWebView(myWebView);
myWebView.loadUrl("http://www.foo.com");
How does this work?

The mParticle web SDK will look for this interface by name, forming a bridge to the Android SDK. By default the handler’s name will be mParticleAndroid_<WORKSPACE TOKEN>_<BRIDGE VERSION>

Where the values are:

  • <WORKSPACE TOKEN> is an alphanumeric value unique to your mParticle workspace
  • <BRIDGE VERSION> represents the version of the mParticle WebView API (currently v2)

For advanced use cases, you can customize the bridge name by:

  1. Setting mParticle.config.requiredWebviewBridgeName when initializing the mParticle web SDK
  2. Setting the bridge name from the Android-side. Note that the mParticle.config.requiredWebviewBridgeName setting on the web SDK should match the bridge name set on Android.
MParticle.getInstance().registerWebView(myWebview, "myUniqueName");

Was this page helpful?