
Analytics event tracking with filtering, buffering, and multi-sink export
Add to your pubspec.yaml:
dependencies:
philiprehberger_event_tracker: ^0.2.0
Then run:
dart pub get
import 'package:philiprehberger_event_tracker/event_tracker.dart';
final tracker = EventTracker();
tracker.addSink(const ConsoleSink());
await tracker.track('page_view', properties: {'page': '/home'});
import 'package:philiprehberger_event_tracker/event_tracker.dart';
final memorySink = MemorySink();
final buffered = BufferedSink(memorySink, batchSize: 10);
final tracker = EventTracker();
tracker.addSink(buffered);
await tracker.track('click', properties: {'button': 'ok'});
await tracker.flush(); // Force flush pending events
import 'package:philiprehberger_event_tracker/event_tracker.dart';
final tracker = EventTracker();
tracker.addSink(const ConsoleSink());
// Only track page_view and purchase events
tracker.addFilter(EventFilter.byName({'page_view', 'purchase'}));
// Sample 50% of events
tracker.addFilter(EventFilter.bySample(0.5));
// Custom filter
tracker.addFilter(EventFilter.custom((e) => e.properties.containsKey('userId')));
import 'package:philiprehberger_event_tracker/event_tracker.dart';
final tracker = EventTracker();
tracker.addSink(const ConsoleSink());
// Suppress duplicate events within a 1-second window
tracker.deduplicate(const Duration(seconds: 1));
await tracker.track('click', properties: {'button': 'ok'});
await tracker.track('click', properties: {'button': 'ok'}); // suppressed
import 'package:philiprehberger_event_tracker/event_tracker.dart';
final tracker = EventTracker();
tracker.addSink(const ConsoleSink());
// Add session ID to every event
tracker.addEnricher((event) => TrackedEvent(
event.name,
properties: {...event.properties, 'session': 'abc-123'},
));
await tracker.track('page_view', properties: {'page': '/home'});
// Event will include both 'page' and 'session' properties
import 'package:philiprehberger_event_tracker/event_tracker.dart';
final tracker = EventTracker();
await tracker.track('page_view', properties: {'page': '/home'});
await tracker.track('click', properties: {'button': 'signup'});
final views = tracker.store.eventsNamed('page_view');
final summary = tracker.store.summary(); // {'page_view': 1, 'click': 1}
final results = tracker.store.search('signup');
final exported = tracker.store.export();
import 'package:philiprehberger_event_tracker/event_tracker.dart';
final store = EventStore();
// ... add events ...
// Query with predicate, limit, and offset
final page = store.query(
where: (e) => e.name == 'click',
limit: 10,
offset: 20,
);
// Get all distinct event names
final names = store.distinctNames(); // ['click', 'page_view', ...]
import 'package:philiprehberger_event_tracker/event_tracker.dart';
final tracker = EventTracker();
tracker.addSink(const ConsoleSink());
tracker.addSink(MemorySink());
tracker.addSink(BufferedSink(MemorySink(), batchSize: 50));
await tracker.track('event'); // Sent to all three sinks
| Method / Property |
Description |
TrackedEvent(name, {properties, timestamp, id}) |
Create a tracked event |
name |
Event name |
properties |
Key-value string map |
timestamp |
When the event occurred |
id |
Unique event identifier |
| Method |
Description |
send(events) |
Send a batch of events to the sink |
| Method |
Description |
send(events) |
Print events to stdout |
| Method / Property |
Description |
send(events) |
Store events in memory |
events |
List of all received events |
| Method / Property |
Description |
BufferedSink(inner, {batchSize}) |
Create a buffered sink wrapping another sink |
send(events) |
Buffer events, auto-flush when batch size reached |
flush() |
Manually flush all pending events |
pending |
Number of buffered events |
| Method |
Description |
EventFilter.byName(names) |
Pass events whose name is in the set |
EventFilter.bySample(rate) |
Pass events at the given sample rate (0.0-1.0) |
EventFilter.custom(predicate) |
Pass events matching a custom function |
| Method / Property |
Description |
add(event) |
Add an event to the store |
all() |
Return all stored events |
eventsNamed(name) |
Return events with the given name |
eventsBetween(start, end) |
Return events in a date range |
search(query) |
Search events by name or property values |
summary() |
Return map of event name to count |
clear() |
Remove all events |
count |
Number of stored events |
query({where, limit, offset}) |
Query events with optional predicate, limit, and offset |
distinctNames() |
Get all distinct event names, sorted |
export() |
Export all events as a formatted string |
| Method / Property |
Description |
track(name, {properties}) |
Track a new event |
addSink(sink) |
Add an event sink |
removeSink(sink) |
Remove an event sink |
addFilter(filter) |
Add a filter (all filters must pass) |
deduplicate(window) |
Enable event deduplication within a time window |
addEnricher(enricher) |
Add an enricher that transforms events before sinking |
flush() |
Force all buffered sinks to flush |
store |
Access the internal EventStore |
dart pub get
dart analyze --fatal-infos
dart test
If you find this project useful:
⭐ Star the repo
🐛 Report issues
💡 Suggest features
❤️ Sponsor development
🌐 All Open Source Projects
💻 GitHub Profile
🔗 LinkedIn Profile
MIT