A newer version of this documentation is available. Switch to the
latest version
docs.
Note
To enable WebView tracking, a JavaScript bridge between the WebView content and
the Contentsquare SDK needs to be built. This involves implementing the Contentsquare
WebView JavaScript Tracking Tag in the web pages loaded within your app’s WebViews.
📚 WebView JavaScript Tracking Tag Documentation
We provide a plugin to simplify this integration.
Once the WebView Tracking Tag is implemented in the web pages, you need to wrap
any tracked WebView in the ContentsquareWebViewTrackerBuilder
Widget.
You can omit using our plugin and implement tracking your webviews manually
(for example if you use a custom webView package).
In that case you need to use the ContentsquareWebViewTrackerBuilder
widget constructor.
The builder provides a tracker with three methods, that need to be called in the following order:
tracker.registerWebViewController
: registers the ContentsquareWebViewController
with the tracker.
tracker.javascriptChannels
: a set of (JavaScript) channels that you must register for the communication between Contentsquare and the WebView
tracker.startPageTracking
: this method must be called every time a new page has finished loading.
Warning
You also need JavaScript injection to be allowed in your WebView.
See the following section for implementation examples featuring the most popular webview packages.
Note
If you need help implementing webview tracking for a package not mentioned here, contact us.
If you are using the flutter_inappwebview ↗ ,
use the following code can be used to track a webview:
ContentsquareWebViewTrackerBuilder (
builder : (context , tracker) {
initialUrlRequest : URLRequest (
url : Uri . parse ( 'https://your_tracked_webview.com' ) ,
onWebViewCreated : (controller) {
tracker . registerWebViewController (
ContentsquareWebViewController (
evaluateJavascript : (source) async {
return ' ${ await controller . evaluateJavascript ( source : source )} ' ;
currentUrl : () async => ' ${ await controller . getUrl ()} ' ,
javascriptChannelCall : (channelName , data) {
return 'window.flutter_inappwebview.callHandler(" $ channelName ", $ data )' ;
for ( final javascriptChannel in tracker . javascriptChannels) {
controller . addJavaScriptHandler (
handlerName : javascriptChannel . name ,
return javascriptChannel . onMessageReceived (args . first) ;
onLoadStop : (controller , uri) async {
// This MUST be called AFTER the controller is registered and the JavaScript
// channels are available
await tracker . startPageTracking () ;
Note
JavaScript injection is enabled by default, therefore there is no mention of it in the code above.
If you are using the webview_flutter ↗ ,
use the following code can be used to track a webview:
Start by defining a WebViewTrackerInitializer
widget:
class WebViewTrackerInitializer extends StatefulWidget {
const WebViewTrackerInitializer ({
required this . initialUrl ,
required this . webviewController ,
final ContentsquareWebViewTracker tracker ;
final WebViewController webviewController ;
State < WebViewTrackerInitializer > createState () =>
_WebViewTrackerInitializerState () ;
class _WebViewTrackerInitializerState extends State < WebViewTrackerInitializer > {
Future < void > _initTracking () async {
final tracker = widget . tracker ;
final controller = widget . webviewController ;
await controller . setJavaScriptMode ( JavaScriptMode . unrestricted) ;
tracker . registerWebViewController (
ContentsquareWebViewController (
evaluateJavascript : (source) async {
return ' ${ await controller . runJavaScriptReturningResult ( source )} ' ;
currentUrl : controller . currentUrl ,
javascriptChannelCall : (channelName , data) {
return 'window. $ channelName .postMessage( $ data )' ;
for ( final javascriptChannel in tracker . javascriptChannels) {
await controller . addJavaScriptChannel (
onMessageReceived : (javascriptMessage) {
javascriptChannel . onMessageReceived (javascriptMessage . message) ;
await controller . setNavigationDelegate (
onPageFinished : (_) async {
// This will be called AFTER the controller is registered and the
// JavaScript channels are available since we register the controller
// and the JavaScript channels BEFORE loading the initial url.
await tracker . startPageTracking () ;
await controller . loadRequest ( Uri . parse (widget . initialUrl)) ;
Widget build ( BuildContext context) => widget . child ;
Which you can then use to track your webview:
ContentsquareWebViewTrackerBuilder (
builder : (context , tracker) {
return WebViewTrackerInitializer (
initialUrl : 'https://your_tracked_webview.com' ,
webviewController : webviewController ,
child : WebViewWidget (controller : webviewController) ,
Note
JavaScript injection is enabled by default, therefore there is no mention of it in the code above.
If you are using the webview_flutter ↗ v2 or v3,
use the following code can be used to track a webview:
ContentsquareWebViewTrackerBuilder (
builder : (context , tracker) {
initialUrl : 'https://your_tracked_webview.com' ,
javascriptMode : JavascriptMode . unrestricted ,
onWebViewCreated : (controller) {
tracker . registerWebViewController (
ContentsquareWebViewController (
evaluateJavascript : controller . runJavascriptReturningResult ,
javascriptChannelCall : (channelName , data) {
return 'window. $ channelName .postMessage( $ data )' ;
for ( final channel in tracker . javascriptChannels)
onMessageReceived : (message) => channel . onMessageReceived (
onPageFinished : (_) async {
await tracker . startPageTracking () ;
Note
JavaScript injection is enabled by default, therefore there is no mention of it in the code above.
To validate that the WebView tracking is working correctly, check the logs in your Flutter console.
Opening a screen with tracked WebView will result in the following log:
┌───────────────────────────────────────────────────────────────────────────────
│ ℹ️ INFO ℹ️ (CSLIB) [ Tracked WebView ]
├───────────────────────────────────────────────────────────────────────────────
│ WebView tracking enabled on WebView with initialUrl:
│ https://your.tracked.website
└───────────────────────────────────────────────────────────────────────────────