session_recorder_flutter 2.0.1
session_recorder_flutter: ^2.0.1 copied to clipboard
A lightweight SDK for capturing user interactions and visible UI layout metadata during a Flutter application session.
Session Recorder Flutter #
Session Recorder Flutter is a lightweight SDK for recording user interactions and the structure of the visible UI.
It captures gestures, scrolling, navigation context, and visible element geometry without recording screenshots, displayed text, or form values.
Session Recorder captures interaction and layout metadata, not screen content.
Installation #
Add the package to your pubspec.yaml:
dependencies:
session_recorder_flutter: ^2.0.1
Import the public API:
import 'package:session_recorder_flutter/session_recorder_flutter.dart';
Compatibility #
- Flutter:
>=3.22.0 - Dart:
>=3.4.0 <4.0.0 - Platforms: Android and iOS
Web and desktop are not currently supported.
Quick Start #
Integration requires only two steps:
- Initialize
SessionRecorder. - Add one
SessionRecorderWidgetaround the application content.
void main() {
WidgetsFlutterBinding.ensureInitialized();
SessionRecorder.init(
const SessionRecorderConfig(
endpoint: 'https://your-subdomain.ux-key.com/endpoint',
),
);
runApp(
MaterialApp(
home: const HomeScreen(),
builder: (context, child) => SessionRecorderWidget(
child: child ?? const SizedBox.shrink(),
),
),
);
}
Call SessionRecorder.init() once during application startup, after:
WidgetsFlutterBinding.ensureInitialized();
and before runApp().
MaterialApp.builder is the recommended integration point.
The same approach can be used with MaterialApp.router.builder.
That's all that is required.
Navigation options can be added when more precise navigation context is needed.
Navigation #
Session Recorder works without a navigation observer.
For standard Flutter navigation, SessionNavigatorObserver is recommended to provide explicit navigation signals and improve capture timing after route changes.
final sessionObserver = SessionNavigatorObserver();
MaterialApp(
navigatorObservers: [
sessionObserver,
],
home: const HomeScreen(),
builder: (context, child) => SessionRecorderWidget(
child: child ?? const SizedBox.shrink(),
),
);
Create the observer once and keep it stable.
If your application uses multiple
Navigatorinstances, such as nested navigation or shell routes, use a separateSessionNavigatorObserver()for each Navigator.
Complex Navigation #
For router-based applications or applications with complex navigation, you can provide the current logical screen name directly:
SessionRecorder.init(
SessionRecorderConfig(
endpoint: 'https://your-subdomain.ux-key.com/endpoint',
screenNameProvider: () => navigationState.currentScreenName,
),
);
navigationState.currentScreenName is only an example. The callback should
return the logical screen name from your application's own navigation system.
For complex navigation, use screenNameProvider when you need more accurate screen context. Without it, recording still works, but navigation context may be less precise.
For example, with GoRouter:
screenNameProvider: () {
final configuration = router.routerDelegate.currentConfiguration;
if (configuration.isEmpty) {
return null;
}
return configuration.last.route.name;
},
Give relevant routes stable names:
GoRoute(
name: 'home',
path: '/home',
builder: (context, state) => const HomeScreen(),
),
GoRoute(
name: 'details',
path: '/details',
pageBuilder: (context, state) => CustomTransitionPage(
key: state.pageKey,
name: state.name,
child: const DetailsScreen(),
transitionsBuilder: ...
),
),
If you use pageBuilder with a custom Page, such as CustomTransitionPage, also preserve the route name on the returned pages.
Screen names are hashed before being stored or sent.
screenNameProvider is optional.
Configuration #
endpoint accepts any non-empty, valid absolute HTTP or HTTPS URI with a host,
including localhost and IP-based endpoints.
SessionRecorderConfig(
endpoint: 'https://your-subdomain.ux-key.com/endpoint',
debugLog: false,
debugShowTree: false,
debugSendSession: false,
screenNameProvider: null,
logger: null,
);
| Option | Purpose |
|---|---|
endpoint |
Endpoint that receives session data. |
debugLog |
Enables SDK diagnostic logs. |
debugShowTree |
Shows captured UI bounds in Debug. |
debugSendSession |
Allows sessions to be sent from Debug and Profile builds. |
screenNameProvider |
Provides a logical screen name for complex navigation. |
logger |
Receives SDK logs and errors through a custom callback. |
Release builds send session data normally.
Data Collection & Privacy #
Session Recorder captures interaction and layout metadata used to understand how users interact with the visible application UI.
Captured #
- Taps, double taps, and long presses.
- Drag and pinch gestures.
- Interaction coordinates.
- Scrolling activity.
- Visible UI structure.
- Positions and sizes of visible UI elements.
- Structural widget/type identifiers.
- Hashed navigation context when available.
- Session and timing metadata required to associate interactions with captures.
Only UI elements that are currently materialized and visible are represented in the captured UI structure.
Not Captured #
Session Recorder does not capture:
- Screenshots or screen pixels.
- Displayed text content.
- Text entered by users.
- Form field values.
- Image or media content.
Session data is grouped into chunks and sent to the configured endpoint.
A separate HTTP request is not sent for every user interaction.
Error Reporting #
Session Recorder is designed so that internal SDK errors do not interrupt your application.
If needed, you can forward SDK errors to your existing monitoring service:
SessionRecorder.init(
SessionRecorderConfig(
endpoint: 'https://your-subdomain.ux-key.com/endpoint',
logger: (level, message, {error, stackTrace}) {
if (level.name == 'error') {
reportRecorderError(
message,
error,
stackTrace,
);
}
},
),
);
The error reporter belongs to your application:
void reportRecorderError(
String message,
Object? error,
StackTrace? stackTrace,
) {
// Send the error to your monitoring provider.
}
Session Recorder does not depend on any error-monitoring provider.
Obfuscated Builds #
Applications built with --obfuscate are supported without additional configuration.
Visible UI geometry, gestures, and scrolling continue working normally.
Some custom or third-party widget type names may appear obfuscated.
Migrating from V1 #
V1 was distributed directly from GitHub.
Version 2.0.0 is the first version distributed through pub.dev.
Dependency #
V1:
dependencies:
session_recorder_flutter:
git: https://github.com/opentech-ux/session-recorder-flutter.git
V2:
dependencies:
session_recorder_flutter: ^2.0.1
Import #
V1:
import 'package:session_recorder_flutter/session_recorder.dart';
V2:
import 'package:session_recorder_flutter/session_recorder_flutter.dart';
Initialization #
V1:
SessionRecorder.instance.init(
SessionRecorderParams(
endpoint: 'https://your-subdomain.ux-key.com/endpoint',
),
);
V2:
SessionRecorder.init(
const SessionRecorderConfig(
endpoint: 'https://your-subdomain.ux-key.com/endpoint',
),
);
Capture Boundary #
V2 requires one SessionRecorderWidget around the application content:
MaterialApp(
home: const HomeScreen(),
builder: (context, child) => SessionRecorderWidget(
child: child ?? const SizedBox.shrink(),
),
);
What Improves in V2? #
V2 introduces a visible-only UI capture model, improved gesture and scroll recording, and substantially reduced runtime and memory overhead compared with V1.
Navigation, lifecycle handling, session reporting, and UI-change capture are also more robust.
Applications that consume Session Recorder payloads directly should review the V2 protocol documentation before upgrading.