Event Listener lets your app observe every event the Insider SDK records on the device. You can forward these events to your own analytics tool, such as Google Analytics 4 (Firebase), Mixpanel, or Amplitude.
The listener receives custom events, default events, and campaign events (e.g., push_session and inapp_seen). Each event arrives with its parameters and the time it was recorded.
This method is available on Flutter SDK 5.3.0 or higher. For release details, see Flutter Changelogs.
Before you start
Check the following before you add a listener:
The Insider SDK is initialized, and you add the listener after initialization.
Events tagged before a session starts are delivered when the session starts.
The user has not opted out of data collection. Nothing is delivered while the user has opted out. For details, see Set GDPR consent.
Add an event listener
Call FlutterInsider.Instance.events.addObserver with a callback. The callback is called once for every event the SDK records and receives an InsiderRecordedEvent. The method returns an InsiderEventSubscription that you use to stop receiving events.
The following table shows the properties of InsiderRecordedEvent.
Property | Data Type | Description |
|---|---|---|
name | String | The event name, e.g., product_detail_page_view. |
parameters | Map<String, dynamic> | The event parameters. The map is read-only and empty when the event has no parameters. |
timestamp | int | The time the event was recorded, in whole seconds since 1970. It is the same value the SDK sends to Insider One for this event. |
recordedAt | DateTime | The timestamp converted to a DateTime. |
Method signature
FlutterInsiderEvents get events
// FlutterInsiderEvents
Future<InsiderEventSubscription> addObserver(void Function(InsiderRecordedEvent event) callback)Method example
Register the listener after you initialize the SDK.
import 'package:flutter_insider/flutter_insider.dart';
Future<void> startForwardingInsiderEvents() async {
final subscription = await FlutterInsider.Instance.events.addObserver((event) {
// Forward the event to your analytics tool.
print('${event.name} ${event.parameters} ${event.recordedAt}');
});
}Remove an event listener
Call cancel() on the subscription to stop receiving events. Calling it more than once is safe. You can check whether a subscription is cancelled with isCancelled.
Method signature
// InsiderEventSubscription
Future<void> cancel()
bool get isCancelledMethod example
Cancel the subscription when its owner goes away, e.g., in State.dispose().
class _AnalyticsBridgeState extends State<AnalyticsBridge> {
InsiderEventSubscription? _subscription;
@override
void initState() {
super.initState();
FlutterInsider.Instance.events
.addObserver(_forwardToAnalytics)
.then((subscription) => _subscription = subscription);
}
@override
void dispose() {
_subscription?.cancel();
super.dispose();
}
void _forwardToAnalytics(InsiderRecordedEvent event) {
// Forward the event to your analytics tool.
}
}Event details
Which events are delivered
The listener receives every event the SDK records. The following events are delivered:
Custom events and default events.
Campaign events, such as inapp_seen and push_session.
session_start.
Events you create by calling the tag event methods from inside the callback. This is safe and does not cause recursion.
The following events are not delivered:
Events recorded while the SDK is disabled or the user has opted out of data collection.
Events dropped by the per-session event limit.
flush_event, the SDK heartbeat event.
Event names that Insider One excludes from listener delivery for your app.
Event timestamps
timestamp is in seconds, while Dart's DateTime uses milliseconds. Use event.recordedAt, or multiply timestamp by 1000. DateTime.fromMillisecondsSinceEpoch(event.timestamp) gives a date in January 1970.
Parameter values and dates
Parameter values are String, int, double, bool, List, or nested Map. Date parameters arrive as formatted date strings, not as DateTime objects.
Ordering and error handling
You can add several listeners. The plugin registers a single native listener, delivers each event to all of your callbacks, and removes the native listener when the last subscription is canceled.
Callbacks run on the Dart isolate, in the order the SDK recorded the events. Keep the callback light; queue or batch network calls instead of making them for every event.
Do not throw from the callback. An error thrown from the callback stops delivery for that subscription.
Forward events to your analytics tool
The following example forwards selected events, keeps only flat parameter values that most analytics tools accept, and converts the timestamp to milliseconds.
const forwardedEvents = {'purchase', 'item_added_to_cart', 'product_detail_page_view'};
void _forwardToAnalytics(InsiderRecordedEvent event) {
if (!forwardedEvents.contains(event.name)) return;
final recordedAtMillis = event.timestamp * 1000;
final properties = <String, Object>{
for (final entry in event.parameters.entries)
if (entry.value is String || entry.value is num || entry.value is bool)
entry.key: entry.value as Object,
};
// Send event.name, properties, and recordedAtMillis to your analytics tool.
}Forward only the event names you need. GA4 allows up to 500 distinct event names per user, so forwarding every Insider event can push your own events over that limit.
Event parameters may contain user data. You are responsible for what you send to third-party tools. Forward an allow-list of events and parameters, as in the example above.
Limits
Events dropped by the per-session event limit are never delivered, so the stream you forward matches what Insider One records.
Priority events such as inapp_seen, push_session, and confirmation_page_view bypass the limit and are always delivered.
Events you create from inside the callback are delivered to every listener, and they count toward the per-session event limit.
Insider One can exclude specific event names from listener delivery for your app. flush_event is never delivered.
In an add-to-app setup with more than one FlutterEngine, only the most recently attached engine receives events. Add your listeners again after an engine is detached.