openpanel 0.1.1
openpanel: ^0.1.1 copied to clipboard
OpenPanel analytics for Flutter with native Android and iOS clients, persistent offline event queue and batching.
openpanel #
OpenPanel analytics for Flutter with native Android (Kotlin) and iOS (Swift) clients, a persistent offline event queue and batching.
OpenPanel does not ship an official Flutter SDK — this package fills the gap
with hand-written native clients that speak the documented
/track REST API directly, mirroring
the API of the official mobile SDKs.
Features #
- Native clients, zero native dependencies: Kotlin (
HttpURLConnection) and Swift (URLSession) implementations, no OpenPanel SDK dependencies, no third-party libraries. - Full API:
track,identify,increment,decrement,setGlobalProperties,clear,flush— everything the official mobile SDKs expose. - Persistent offline queue: events survive app restarts (capped at 500, oldest dropped first).
- Batching: the queue is flushed when it reaches 10 events, 5 seconds
after the first queued event, when the app goes to the background, or on
an explicit
flush(). Failures retry with exponential backoff (0.5s up to 60s); events rejected with a 4xx are dropped instead of blocking the queue. - Lifecycle tracking: automatic
app_opened/app_closedevents (opt-out viaautomaticTracking: false). - Device metadata on every event: OS name/version, device model/manufacturer, screen size, app version/build, locale, SDK version.
- Self-hosted support via
apiUrl. - Analytics never crashes the app: platform errors are swallowed (logged in debug), release builds drop events sent before initialization.
Platform support #
| Android | iOS |
|---|---|
| API 24+ | 15.0+ |
Android release builds need the
INTERNETpermission in the main manifest (the Flutter debug template adds it only for debug builds). Networked apps already have it.
Usage #
Initialize #
import 'package:openpanel/openpanel.dart';
await Openpanel.instance.initialize(
OpenpanelOptions(clientId: 'YOUR_CLIENT_ID'),
);
For a self-hosted instance:
await Openpanel.instance.initialize(
OpenpanelOptions(
clientId: 'YOUR_CLIENT_ID',
apiUrl: 'https://openpanel.example.com',
),
);
Events tracked before initialization completes are held back and delivered
afterwards. In debug builds tracking before initialize throws a
StateError to surface mis-wiring early; in release builds such events are
dropped silently.
Track events #
Openpanel.instance.track('button_clicked', properties: {
'button': 'signup',
});
Property values must be JSON-compatible primitives (num, String, bool,
null, lists and nested maps of those).
Identify users #
Openpanel.instance.identify(
'user-42',
firstName: 'John',
email: 'john@example.com',
properties: {'plan': 'pro'},
);
After identify, every subsequent track event carries the profileId.
The binding persists across app restarts until clear() is called.
Profile counters #
Openpanel.instance.increment('user-42', 'login_count', value: 1);
Openpanel.instance.decrement('user-42', 'credits_remaining', value: 5);
Global properties #
Openpanel.instance.setGlobalProperties({'environment': 'production'});
Merged into every future track event (event properties win on conflicts);
persists across app restarts until clear().
Screen views (optional) #
MaterialApp(
navigatorObservers: [OpenpanelNavigatorObserver()],
// ...
);
Reports screen_view events with { 'name': <route name> } for routes that
have a non-empty name.
API #
| Method | Description |
|---|---|
initialize(options) |
Configure and start the SDK (once). |
track(name, {properties}) |
Send a named event. |
identify(profileId, {firstName, lastName, email, avatar, properties}) |
Bind events to a user profile. |
increment(profileId, property, {value}) |
Increment a numeric profile property. |
decrement(profileId, property, {value}) |
Decrement a numeric profile property. |
setGlobalProperties(properties) |
Merge properties attached to every event. |
flush() |
Send everything queued immediately. |
clear() |
Clear profile binding, global properties and the queue. |
Options #
| Option | Default | Description |
|---|---|---|
clientId |
— | Client ID of your OpenPanel project (required). |
clientSecret |
null |
Optional; the track endpoint works without it. A secret embedded in a mobile app is public anyway. |
apiUrl |
https://api.openpanel.dev |
Base API URL; point to your self-hosted instance. |
automaticTracking |
true |
Track app_opened / app_closed automatically. |
disabled |
false |
Drop all events, send nothing. |
verbose |
false |
Log every queued/sent event natively. |
Example #
See the example app. Run it with your credentials:
cd example && flutter run \
--dart-define=OPENPANEL_CLIENT_ID=... \
--dart-define=OPENPANEL_API_URL=https://your-openpanel.example.com
Comparison with openpanel_flutter #
The existing community package is an unofficial thin client. Differences:
identify/increment/decrement(profile attributes and counters) — this package supports them.- Persistent offline queue — events survive restarts; both official SDKs and the community package keep at most an in-memory buffer.
- Actively built on the documented REST protocol (
{type, payload}envelopes) instead of the unpublished Kotlin SDK.
License #
MIT — see LICENSE.