Webview Tagging
This guide covers the steps to implement screen name tagging in webviews using UXCam for both Android and iOS platforms. Screen name tagging enhances the clarity of user journey visualisation within your app's webviews.
For tagging webviews, it is necessary to add some JS injection, here are some simplified examples you can check to accomplish this:
Android Example:
Step 1: Create a Java WebAppInterface
To expose a method to JavaScript, create a Java class that acts as a bridge between the webview and the Android native code.
public class WebAppInterface {
@JavascriptInterface
public void tagScreenName(String screenName) {
UXCam.tagScreenName(screenName);
}
}Step 2: Attach the Interface Class to the Webview
Attach the interface class to the webview, allowing JavaScript to call native methods.
WebView webView = (WebView) findViewById(R.id.webview);
webView.addJavascriptInterface(new WebAppInterface(), "UXCamBridge");Step 3: Call the Java Method Through the Bridge
In your HTML code, call the Java method through the bridge you attached.
<input type="button" value="Tag Screen" onClick="tagScreenName('screenName')" />
<script type="text/javascript">
function tagScreenName(screenName) {
UXCamBridge.tagScreenName(screenName);
}
</script>
iOS Example:
On iOS, we don't have easy solution for webview tagging as Android but there are some ways to do that. For this, first on ios, we need to observe the uxcam values using contentController.
Step 1: Observe UXCam Values using WKUserContentController
In your iOS project, use WKUserContentController to observe the messages from web content. Create a WKWebViewConfiguration and attach it to the WKWebView.
let contentController = WKUserContentController()
contentController.add(self, name: "uxcam")
let config = WKWebViewConfiguration()
config.userContentController = contentController
self.webView = WKWebView(frame: .zero, configuration: config)
Step 2: Pass Method Name and Parameters from JS to Native
Then on JS side, we need to pass method name and parameters that we need to use on native side and post that to native one using postMessage eg.
<script type="text/javascript">
function tagScreenName(screenName) {
const method = {
name: "tagScreenName", // Method name
param: "screenName" // Parameters for that method
}
window.webkit.messageHandlers["uxcam"].postMessage(method);
}
</script>Step 3: Observe UXCam Values on the Webview Controller
And observe the uxcam values on the webview controller:
extension WebViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
guard message.name == "uxcam" else { return }
guard let methodInfo = message.body as? [String: String] else { return }
if let methodName = methodInfo["name"], methodName == "tagScreenName" {
guard let screenName = methodInfo["param"] else { return }
UXCam.tagScreenName(screenName)
}
}
}
React Native Example:
There are two approaches to tag screens within a WebView:
Option 1: Using URL path (recommended)
Automatically tag screens based on the URL path when navigation changes:
import React from 'react';
import { WebView } from 'react-native-webview';
import RNUxcam from 'react-native-ux-cam';
const MyWebView = () => {
const handleNavigationChange = (navState) => {
if (navState.url) {
const url = new URL(navState.url);
const screenName = url.pathname || '/home';
RNUxcam.tagScreenName(`WebView${screenName}`);
}
};
return (
<WebView
source={{ uri: 'https://example.com/' }}
onNavigationStateChange={handleNavigationChange}
/>
);
};Option 2: Using page title
Tag screens based on the HTML document title:
import React, { useRef } from 'react';
import { WebView } from 'react-native-webview';
import RNUxcam from 'react-native-ux-cam';
const MyWebView = () => {
const webviewRef = useRef(null);
const handleMessage = (event) => {
const title = event.nativeEvent.data;
RNUxcam.tagScreenName(title);
};
const handleNavigationChange = (navState) => {
if (!navState.loading) {
webviewRef.current?.injectJavaScript(`
ReactNativeWebView.postMessage(document.title);
true;
`);
}
};
return (
<WebView
ref={webviewRef}
source={{ uri: 'https://example.com/' }}
onNavigationStateChange={handleNavigationChange}
onMessage={handleMessage}
/>
);
};Flutter Example:
Webview has a delegate which gets called whenever the URL changes, which can be tracked to tag the screen name:
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:uxcam_flutter/uxcam.dart';
class WebViewScreen extends StatefulWidget {
@override
_WebViewScreenState createState() => _WebViewScreenState();
}
class _WebViewScreenState extends State<WebViewScreen> {
late WebViewController _controller;
@override
void initState() {
super.initState();
UXCam.startWithConfiguration(configuration);
// Initialize WebView
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onPageStarted: (String url) {
// Log the web page as a screen in UXCam
UXCam.tagScreenName("WebView: $url");
print("Navigated to: $url");
},
),
)
..loadRequest(Uri.parse("https://your-webpage.com"));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("WebView Example")),
body: WebViewWidget(controller: _controller),
);
}
This approach can be extended to other methods such as sending events and occluding sensitive views within the webview.
Updated 21 days ago
