Track WebViews

In order to be able to track what is happening in your WebViews, we need to be able to build a bridge between the content of the WebView and our native SDK. This implies two things:

  1. Implementing the Contentsquare Web Tracking Tag on all the web pages that are displayed in your app’s WebViews and that you want to track.

    📚 Web Tracking Tag Documentation

  2. Injecting a JavaScript bridge in your WebViews, which will allow the Tracking Tag you added to the web page in the previous step to communicate with our native SDK.

In order to inject this JavaScript, you will have to call two functions from our bridge:

function injectWebView(webViewTag: number): void;
function removeWebViewInjection(webViewTag: number): void;

The first one will inject your WebView with our JavaScript bridge, and the second remove the injection from it. The webViewTag parameter is the target of your WebView object, which we will explain how to implement thereafter.

Implementing the JavaScript bridge

Section titled Implementing the JavaScript bridge

Here is a simple screen with a react-native-webview WebView component. Let’s detail how we will inject it with the Contentsquare JavaScript WebView interface.

import { WebView } from 'react-native-webview';
const WebviewWithTagScreen = () => {
return (
<>
<WebView
source={{ uri: "https://www.mywebpage.com" }}
/>
</>
);
};
export default WebviewWithTagScreen;

1. Retrieve the native tag to the WebView

Section titled 1. Retrieve the native tag to the WebView

In order to be able to call our bridge injection functions, you need to store the native tag of the WebView component, which acts as an identifier, so you can inject it with Contentsquare bridge later. We do that using the useState hook (1), and setting it to the value of the webview target (2) we get from the onLoadStart callback of the WebView component (3).

import React, { useState } from 'react';
import { WebView } from 'react-native-webview';
import { WebViewNavigationEvent } from 'react-native-webview/lib/WebViewTypes';
const WebviewWithTagScreen = () => {
const [webViewNativeTag, setWebviewNativeTag] = useState<number>(); // (1)
const loadStart = (event: WebViewNavigationEvent) => {
// react-native-webview typing for nativeEvent.target is not correct
// @ts-ignore
const webViewTag = (event.nativeEvent.target as number)
if (webViewTag) {
setWebviewNativeTag(webViewTag); // (2)
}
}
return (
<>
<WebView
source={{ uri: "https://www.mywebpage.com" }}
onLoadStart={loadStart} // (3)
/>
</>
);
};
export default WebviewWithTagScreen;

2. Call the Contentsquare bridge’s injection/removal functions

Section titled 2. Call the Contentsquare bridge’s injection/removal functions

In order for the injection and removal to be successful, you should call the bridge when your WebView is fully loaded, and before it is destroyed. To avoid multiple injections issues, you have to create a new state (1) to set the tag once it is injected (2). You should inject the tag (3) in a function you pass to the onLoadEnd callback of the WebView (4) and remove the injection in the useLayoutEffect (5). Make sure to only inject it once, and pay attention to side effects of useLayoutEffect when states change within your component.

import Contentsquare from '@contentsquare/react-native-bridge';
import React, { useState, useLayoutEffect } from 'react';
import { WebView } from 'react-native-webview';
import { WebViewNavigationEvent } from 'react-native-webview/lib/WebViewTypes';
const WebviewWithTagScreen = () => {
const [webViewNativeTag, setWebviewNativeTag] = useState<number>();
const [injectedWebViewTag, setInjectedWebViewTag] = useState<number>(); // (1)
const loadStart = (event: WebViewNavigationEvent) => {
// react-native-webview typing for nativeEvent.target is not correct
// @ts-ignore
const webViewTag = (event.nativeEvent.target as number)
if (webViewTag) {
setWebviewNativeTag(webViewTag);
}
}
const loadEnd = () => {
if (webViewNativeTag !== undefined && webViewNativeTag !== injectedWebViewTag) {
Contentsquare.injectWebView(webViewNativeTag); // (3)
setInjectedWebViewTag(webViewNativeTag); // (2)
}
}
useLayoutEffect(() => {
return () => {
if (webViewNativeTag !== undefined) {
Contentsquare.removeWebViewInjection(webViewNativeTag); // (5)
}
}
}, [webViewNativeTag])
return (
<>
<WebView
source={{ uri: "https://www.mywebpage.com" }}
onLoadStart={loadStart}
onLoadEnd={loadEnd} // (4)
/>
</>
);
};
export default WebviewWithTagScreen;