mostly_good_metrics_flutter 0.3.0
mostly_good_metrics_flutter: ^0.3.0 copied to clipboard
Official Flutter SDK for MostlyGoodMetrics - Simple, privacy-focused analytics for your applications.
MostlyGoodMetrics Flutter SDK #
A lightweight Flutter SDK for tracking analytics events with MostlyGoodMetrics.
Table of Contents #
- Requirements
- Platform Support
- Installation
- Quick Start
- Configuration Options
- User Identification
- Tracking Events
- Event Naming
- Properties
- Automatic Events
- Automatic Context
- Automatic Behavior
- A/B Testing (Experiments)
- Manual Flush
- Session Management
- Debug Logging
- Error Handling
- Framework Integration
- Running the Example
- Testing
- License
Requirements #
- Flutter 3.10+
- Dart 3.0+
Platform Support #
| Platform | Supported |
|---|---|
| iOS | Yes |
| Android | Yes |
| Web | Yes |
| macOS | Yes |
| Windows | Yes |
| Linux | Yes |
Installation #
Add the package to your pubspec.yaml:
dependencies:
mostly_good_metrics_flutter: ^0.1.0
Then install dependencies:
flutter pub get
Or install directly via command line:
flutter pub add mostly_good_metrics_flutter
Quick Start #
Initialize once at app startup (typically in main.dart):
import 'package:flutter/material.dart';
import 'package:mostly_good_metrics_flutter/mostly_good_metrics_flutter.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await MostlyGoodMetrics.configure(
MGMConfiguration(apiKey: 'mgm_proj_your_api_key'),
);
runApp(const MyApp());
}
Then track events anywhere in your app:
MostlyGoodMetrics.track('button_clicked');
That's it! Events are automatically batched and sent.
Configuration Options #
For more control, pass additional configuration:
await MostlyGoodMetrics.configure(
MGMConfiguration(
apiKey: 'mgm_proj_your_api_key',
baseUrl: 'https://mostlygoodmetrics.com',
environment: 'production',
appVersion: '1.0.0', // Required for install/update tracking
maxBatchSize: 100,
flushInterval: 30,
maxStoredEvents: 10000,
enableDebugLogging: kDebugMode,
trackAppLifecycleEvents: true,
),
);
| Option | Default | Description |
|---|---|---|
apiKey |
Required | Your MostlyGoodMetrics API key |
baseUrl |
https://mostlygoodmetrics.com |
API endpoint |
environment |
"production" |
Environment name |
appVersion |
- | App version string (required for install/update tracking) |
maxBatchSize |
100 |
Events per batch (1-1000) |
flushInterval |
30 |
Auto-flush interval in seconds |
maxStoredEvents |
10000 |
Max cached events |
enableDebugLogging |
false |
Enable debug output |
trackAppLifecycleEvents |
true |
Auto-track lifecycle events |
User Identification #
By default, the SDK tracks events with an anonymous user ID. You can identify users to associate events with a specific user:
// Set user identity
await MostlyGoodMetrics.identify('user_123');
Once identified, all future events will be associated with this user ID. The user ID persists across app launches.
To reset the identity (e.g., on logout):
// Reset identity (generates new anonymous ID)
await MostlyGoodMetrics.resetIdentity();
Note: After calling
resetIdentity(), the SDK generates a new anonymous ID and starts a new session.
Tracking Events #
Track events anywhere in your app:
// Simple event
MostlyGoodMetrics.track('button_clicked');
// Event with properties
MostlyGoodMetrics.track('purchase_completed', properties: {
'product_id': 'SKU123',
'price': 29.99,
'currency': 'USD',
});
Events are automatically queued and sent in batches for optimal network usage.
Event Naming #
Event names must:
- Start with a letter (or
$for system events) - Contain only alphanumeric characters, underscores, and spaces
- Be 255 characters or less
Reserved
$prefix: Event names starting with$are reserved for SDK system events (e.g.,$app_opened,$app_installed). Do not use the$prefix for your own events.
// Valid
MostlyGoodMetrics.track('button_clicked');
MostlyGoodMetrics.track('PurchaseCompleted');
MostlyGoodMetrics.track('step_1_completed');
MostlyGoodMetrics.track('user signed up'); // spaces allowed
// Invalid (will throw MGMError)
MostlyGoodMetrics.track('123_event'); // starts with number
MostlyGoodMetrics.track('event-name'); // contains hyphen
MostlyGoodMetrics.track('$custom_event'); // $ prefix is reserved
Properties #
Events support various property types:
MostlyGoodMetrics.track('checkout', properties: {
'string_prop': 'value',
'int_prop': 42,
'double_prop': 3.14,
'bool_prop': true,
'list_prop': ['a', 'b', 'c'],
'nested': {
'key': 'value',
},
});
Limits:
- String values: max 1000 characters
- Nesting depth: max 3 levels
- Total event payload: max 10KB
Automatic Events #
When trackAppLifecycleEvents is enabled (default), the SDK automatically tracks:
| Event | When | Properties |
|---|---|---|
$app_installed |
First launch after install | - |
$app_updated |
First launch after version change | previous_version, current_version |
$app_opened |
App became active | - |
$app_backgrounded |
App went to background | - |
Automatic Context #
Every event automatically includes contextual information to provide rich analytics capabilities. You don't need to manually add these fields.
Identity & Session #
| Field | Description | Example | Persistence |
|---|---|---|---|
user_id |
Identified user ID (set via identify()) or anonymous ID |
user_123 or $anon_abc123def456 |
Persisted in local storage (survives app restarts) |
session_id |
UUID generated per app launch | a1b2c3d4-e5f6-7890-abcd-ef1234567890 |
Regenerated on each app launch |
Device & Platform #
| Field | Description | Example | Source |
|---|---|---|---|
platform |
Platform identifier | ios, android, web, macos, windows, linux |
Platform.operatingSystem |
os_version |
Operating system version | iOS 17.4, Android 14, macOS 14.3, Version 10.0 (Build 19045) |
Platform.operatingSystemVersion |
device_manufacturer |
Device manufacturer | Apple |
iOS/macOS only; null on other platforms |
locale |
User's locale from device settings | en_US, fr_FR |
Device locale settings |
timezone |
User's timezone offset name | EST, PST, UTC+5 |
System timezone settings |
App & Environment #
| Field | Description | Example | Source |
|---|---|---|---|
app_version |
App version (if configured) | 1.2.3 |
Configuration option (appVersion) |
environment |
Environment name | production, staging, development |
Configuration option (default: production) |
Event Metadata #
| Field | Description | Example | Purpose |
|---|---|---|---|
client_event_id |
Unique UUID for each event | 550e8400-e29b-41d4-a716-446655440000 |
Deduplication (prevents processing the same event twice) |
timestamp |
ISO 8601 timestamp when event was tracked | 2024-01-15T10:30:00.000Z |
Event ordering and time-based analysis |
Note: All fields are automatically included with every event—no additional code required.
Automatic Behavior #
The SDK automatically handles common tasks so you can focus on tracking what matters:
- Anonymous user ID generation - UUID automatically generated and persisted for anonymous tracking
- User ID persistence - Identity set via
identify()persists across app launches; falls back to anonymous ID when reset - Event persistence - Events are saved to local storage and survive app restarts
- Batch processing - Events are grouped for efficient network usage
- Periodic flush - Events are sent every 30 seconds (configurable via
flushInterval) - Background flush - Events are sent when the app goes to background
- Retry on failure - Failed requests are retried; events are preserved until successfully sent
- Session management - New session ID generated on each app launch
- Deduplication - Events include unique IDs (
client_event_id) to prevent duplicate processing
A/B Testing (Experiments) #
Variants are assigned by the MostlyGoodMetrics server — the SDK never buckets users locally. Assignments are fetched in the background at configure (never blocking), cached per user in shared_preferences with no expiry, and refreshed at most about once per hour (stale-while-revalidate).
Read a variant:
// Synchronous, never throws, never blocks.
// Returns the fallback (default null) when the experiment is unknown
// or assignments haven't loaded yet.
final variant = MostlyGoodMetrics.getVariant(
'checkout-flow',
fallback: 'control',
);
if (variant == 'treatment') {
// Show treatment UI
}
Wait for assignments to load (optional):
// Completes when the initial load attempt finishes (success or failure),
// or when the timeout elapses - whichever comes first. Never hangs.
final loaded = await MostlyGoodMetrics.ready(
timeout: Duration(seconds: 2),
);
Behavior:
- Reading a variant sets the super property
$experiment_{snake_case(name)}so the variant is attached to all subsequent events - Reading a variant tracks a
$experiment_exposureevent ($experiment_name,$variant) once per user/experiment/variant — the dedup is persisted and survives app restarts - After
identify()with a new user ID, the SDK keeps serving the current variants and refetches assignments for the new user (linking the stored anonymous ID); the new assignments are swapped in atomically when the response arrives
Manual Flush #
Events are automatically flushed periodically and when the app backgrounds. You can also trigger a manual flush:
await MostlyGoodMetrics.flush();
To check pending events:
final count = await MostlyGoodMetrics.getPendingEventCount();
print('$count events pending');
To clear pending events:
await MostlyGoodMetrics.clearPendingEvents();
Session Management #
The SDK automatically generates a new session ID when:
- The SDK is configured
resetIdentity()is calledstartNewSession()is called
// Start a new session manually
await MostlyGoodMetrics.startNewSession();
// Access current session ID
final sessionId = MostlyGoodMetrics.sessionId;
Debug Logging #
Enable debug logging to see SDK activity:
await MostlyGoodMetrics.configure(
MGMConfiguration(
apiKey: 'mgm_proj_your_api_key',
enableDebugLogging: true,
),
);
Output example:
[MostlyGoodMetrics] Configuring MostlyGoodMetrics SDK
[MostlyGoodMetrics] Tracked event: button_clicked
[MostlyGoodMetrics] Flushing 5 events
[MostlyGoodMetrics] Successfully sent 5 events
Error Handling #
The SDK throws MGMError for validation errors:
try {
MostlyGoodMetrics.track('invalid-event-name');
} on MGMError catch (e) {
print('Error type: ${e.type}');
print('Message: ${e.message}');
}
Error types:
MGMErrorType.notConfigured- SDK not configuredMGMErrorType.invalidEventName- Invalid event nameMGMErrorType.invalidProperties- Invalid properties (too deeply nested)MGMErrorType.networkError- Network failureMGMErrorType.storageError- Storage failureMGMErrorType.rateLimited- API rate limited
Framework Integration #
MaterialApp #
For a complete Flutter app setup with MostlyGoodMetrics:
import 'package:flutter/foundation.dart' show kDebugMode;
import 'package:flutter/material.dart';
import 'package:mostly_good_metrics_flutter/mostly_good_metrics_flutter.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await MostlyGoodMetrics.configure(
MGMConfiguration(
apiKey: 'mgm_proj_your_api_key',
appVersion: '1.0.0',
enableDebugLogging: kDebugMode,
),
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Home')),
body: Center(
child: ElevatedButton(
onPressed: () {
MostlyGoodMetrics.track('button_clicked', properties: {
'screen': 'home',
});
},
child: const Text('Track Event'),
),
),
);
}
}
Running the Example #
cd example
flutter pub get
flutter run
Testing #
To run the tests:
flutter test
License #
MIT