A WebView inside your Flutter application is a separate world. The browser agent running in the page and the Flutter agent running around it each record their own sessions, so a user journey that crosses into a WebView appears as two unrelated sessions.
WebView tracking joins them. Events from the page are attributed to the native RUM session, so one session shows the whole journey.
Before you start
You need three things:
- The Atatus Flutter SDK set up in your application. See Flutter Monitoring Setup.
- The Atatus Browser Agent running on the pages you load in the WebView. Without it there are no web events to correlate.
- JavaScript enabled in the WebView. The bridge between the page and the native SDK is JavaScript.
Choose a package
Two packages are available, one for each WebView library:
| WebView library | Package |
|---|---|
webview_flutter |
atatus_webview_tracking |
flutter_inappwebview |
atatus_inappwebview_tracking |
Use the one that matches the WebView library your application already depends on.
Track a webview_flutter WebView
Add the package alongside the core plugin:
dependencies:
atatus_flutter_plugin: ^1.0.4
atatus_webview_tracking: ^1.0.4
webview_flutter: ^4.0.0
Call trackAtatusEvents on your controller, passing the SDK and the hosts you want correlated:
import 'package:atatus_flutter_plugin/atatus_flutter_plugin.dart';
import 'package:atatus_webview_tracking/atatus_webview_tracking.dart';
import 'package:webview_flutter/webview_flutter.dart';
final controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..trackAtatusEvents(
AtatusSdk.instance,
['shop.example.com'],
)
..loadRequest(Uri.parse('https://shop.example.com/cart'));
Set JavaScriptMode.unrestricted before you call trackAtatusEvents. On Android the SDK checks whether JavaScript is enabled, and logs an error and does nothing if it is not. The WebView still works, so the only sign of the problem is that web events never appear in the native session.
Track a flutter_inappwebview WebView
Add the package alongside the core plugin:
dependencies:
atatus_flutter_plugin: ^1.0.4
atatus_inappwebview_tracking: ^1.0.4
flutter_inappwebview: ^6.1.0
This package works in two steps. You inject a user script that sets up the bridge in the page, then you register the handler that receives its messages.
For an InAppWebView, pass the script in initialUserScripts and register the handler in onWebViewCreated:
import 'package:atatus_flutter_plugin/atatus_flutter_plugin.dart';
import 'package:atatus_inappwebview_tracking/atatus_inappwebview_tracking.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
InAppWebView(
initialUserScripts: UnmodifiableListView([
AtatusInAppWebViewUserScript(
atatus: AtatusSdk.instance,
allowedHosts: {'shop.example.com'},
),
]),
onWebViewCreated: (controller) {
controller.trackAtatusEvents(AtatusSdk.instance);
},
)
For an InAppBrowser, subclass it and register the handler in onBrowserCreated:
class ShopBrowser extends InAppBrowser {
@override
void onBrowserCreated() {
webViewController?.trackAtatusEvents(AtatusSdk.instance);
}
}
Pass the same AtatusInAppWebViewUserScript in the browser's initialUserScripts.
Sample the logs from a page
trackAtatusEvents accepts logSampleRate, a percentage from 0.0 to 100.0 that defaults to 100.0. Lower it when a page is chatty and you only want a share of its logs:
controller.trackAtatusEvents(AtatusSdk.instance, logSampleRate: 25.0);
This samples only the logs coming from the page. RUM events from the page are not affected.
InAppBrowser is not tracked on Android 13 (API 33) and above in older versions of flutter_inappwebview. If your browser events are missing on newer devices, move to a version of the package built against flutter_inappwebview 6.2.0 or later. InAppWebView is not affected.
Allowed hosts
Both packages take a list of hosts, and only pages served from those hosts are correlated with the native session. A host matches itself and its subdomains, so example.com also matches shop.example.com.
Wildcards and regular expressions are not supported. Pass bare host names with no scheme and no path:
// Correct
['shop.example.com', 'checkout.example.com']
// Not supported
['*.example.com', 'https://shop.example.com/cart']
A page served from a host you did not list still works normally. Its events are simply recorded as their own browser session rather than joined to the native one.
Verify the setup
Open a WebView in a debug build and load a page that runs the browser agent. In your Atatus dashboard, open the native session and confirm the views from the page appear inside it rather than as a separate session.
If they do not, check these in order:
- JavaScript is enabled in the WebView.
- The page host is in the allowed hosts list, spelled exactly.
- The browser agent is initialized on the page.
Limitations
Two limits are worth knowing before you plan around this feature:
- Session Replay does not capture WebView content. The recorder walks the Flutter widget tree, so a WebView appears as an opaque region in the replay. RUM events from the page are still collected.
- Neither package supports Flutter Web.
Next steps
- Track the requests your application makes with Flutter Network Tracking.
- Set up the browser side with the Atatus Browser Agent.
- Record what your users saw with Flutter Session Replay.
+1-415-800-4104