Tracking User Behaviour
Track Custom Events
Create a RetenoCustomEvent and pass it to the Reteno instance:
import 'package:reteno_plugin/reteno.dart';
final event = RetenoCustomEvent(
eventTypeKey: 'product_added_to_favorites',
dateOccurred: DateTime.now(),
parameters: [
RetenoCustomEventParameter('product_id', 'PRODUCT_ID'),
RetenoCustomEventParameter('source', 'product_page'),
],
forcePush: false,
);
await Reteno().logEvent(event: event);The event fields are:
| Field | Type | Description |
|---|---|---|
eventTypeKey | String | Required. Event type key agreed with the marketing team |
dateOccurred | DateTime | Required. Event time, serialized as UTC ISO 8601 |
parameters | List<RetenoCustomEventParameter> | Required. Pass an empty list when the event has no parameters |
forcePush | bool | Optional, defaults to false. Sends the event immediately on iOS instead of waiting for the next batch; ignored on Android |
RetenoCustomEventParameter takes two positional arguments: String name and String? value. Use non-null values: Android drops a null value, iOS sends it as an empty string.
The returned Future<bool> resolves after the native call is dispatched, not after the backend ingests the event.
Log Parameters from a Map
For string-valued parameters, logEventJson() provides a shorter equivalent:
await Reteno().logEventJson(
eventTypeKey: 'product_added_to_favorites',
jsonParameters: {
'product_id': 'PRODUCT_ID',
'source': 'product_page',
},
dateOccurred: DateTime.now(),
forcePush: false,
);eventTypeKey and jsonParameters are required; map values cannot be null. dateOccurred defaults to DateTime.now() and forcePush defaults to false.
iOS timestamp limitation
The iOS bridge does not accept timestamps with fractional seconds, which DateTime.now() produces, and silently substitutes the current native time. Android preserves dateOccurred. Do not rely on a historical custom-event timestamp on iOS.
