analytics_hub 0.4.0
analytics_hub: ^0.4.0 copied to clipboard
A unified analytics abstraction for Dart/Flutter. Send events to multiple backends (Firebase, Mixpanel, etc.) through one API with a single LogEvent model and session support.
Analytics Hub #
This documentation is also available in Ukrainian.
analytics_hub is a small aggregation layer on top of analytics SDKs
such as Firebase, Mixpanel, and custom providers.
Features #
- Single event model based on
LogEvent. - One routing entry point via
AnalyticsHub. - Provider targeting through
EventProvider. - Centralized session propagation through
HubSessionDelegate. - Global and provider-level event interceptors.
- Typed event metadata context (
EventContext/ContextEntry).
When you might want it #
- You send the same logical event to multiple analytics SDKs.
- You want to decouple domain/UI code from concrete analytics dependencies.
- You need centralized session and configuration management for analytics.
- You want to be able to toggle providers on/off per environment or product.
Current providers (each has its own README with integration steps):
- Firebase: analytics_hub_firebase — log events
- Mixpanel: analytics_hub_mixpanel — log events
- Appsflyer:
analytics_hub_appsflyer— log events viaAppsflyerSdk.logEvent
Installation #
In your app pubspec.yaml:
dependencies:
analytics_hub: ^0.4.0
# and then any concrete providers you need, e.g.:
# analytics_hub_firebase: ^0.4.0
# analytics_hub_mixpanel: ^0.4.0
# analytics_hub_appsflyer: ^0.4.0
Core concepts #
AnalyticsHub– the facade you use to send events.Event– base class for events sent by the hub.LogEvent– simplename + propertiesevent.AnalytycsProvider– abstraction of an analytics provider.EventResolver– provider event handling contract.ProviderIdentifier– identifies a provider; events list targets viaEventProvider.Session/HubSessionDelegate– session model plus a delegate that supplies the current session and a stream of session changes.EventInterceptor– middleware that can transform or drop event dispatches.EventDispatchContext– runtime context available inside interceptors and resolvers.
Event model #
Only LogEvent is supported by core.
namedefines the event key.propertiescontains optional payload (Map<String, Object?>?).providersdefines which registered providers should receive the event.contextcontains typed metadata available during interception and resolving.
Defining events #
class ScreenViewEvent extends LogEvent {
const ScreenViewEvent({
required this.screenName,
required this.screenClass,
}) : super(
'screen_view',
context: const EventContext().withEntry(
const FeatureContextEntry('navigation'),
),
);
final String screenName;
final Type screenClass;
@override
Map<String, Object?> get properties => {
'screen_name': screenName,
'screen_class': screenClass.toString(),
};
@override
List<EventProvider> get providers => [
const EventProvider(BackendAnalyticsProviderIdentifier()),
];
}
final class FeatureContextEntry extends ContextEntry {
const FeatureContextEntry(this.feature);
final String feature;
}
Implementing your own provider (step‑by‑step) #
A custom provider (e.g. sending events to your backend) consists of:
- Provider identifier (
ProviderIdentifier). - Event resolver (
EventResolver). - Provider class (
AnalytycsProvider) registered inAnalyticsHub.
1. Provider identifier (ProviderIdentifier) #
import 'package:analytics_hub/analytics_hub.dart';
class BackendAnalyticsProviderIdentifier
extends ProviderIdentifier {
const BackendAnalyticsProviderIdentifier({super.name});
}
2. Event resolver (EventResolver) #
import 'package:analytics_hub/analytics_hub.dart';
class BackendEventResolver
implements EventResolver {
const BackendEventResolver();
@override
Future<void> resolve(
ResolvedEvent event, {
required EventDispatchContext context,
}) async {
// e.g. POST event.name + event.properties to your backend.
// context has event metadata and correlationId for tracing.
}
}
3. Provider class (AnalytycsProvider) #
import 'package:analytics_hub/analytics_hub.dart';
class BackendAnalyticsProvider
extends AnalytycsProvider {
BackendAnalyticsProvider({String? name})
: super(
identifier: BackendAnalyticsProviderIdentifier(name: name),
interceptors: const [],
);
@override
BackendEventResolver get resolver => const BackendEventResolver();
@override
Future<void> initialize() async {
// e.g. create HTTP client, auth headers
}
@override
Future<void> setSession(Session? session) async {
// e.g. send session.id to backend for user association
}
@override
Future<void> dispose() async {
// close HTTP client, etc.
}
}
Important details:
identifiermust uniquely identify this provider instance (type + name).resolvercan be cached or created on demand.setSessionis called whenever the session changes (HubSessionDelegate.sessionStream).initialize/flush/disposehelp you manage provider lifecycle.
4. Registering the provider in AnalyticsHub #
final hub = AnalyticsHub(
sessionDelegate: yourSessionDelegate,
providers: [
BackendAnalyticsProvider(),
],
);
await hub.initialize();
await hub.sendEvent(
ScreenViewEvent(
screenName: 'settings',
screenClass: SettingsScreen,
),
);
await hub.flush();
Any event that includes BackendAnalyticsProviderIdentifier in providers
will be routed to your provider.
When to create your own provider #
- You have an in‑house analytics system (logging service, data pipeline, etc.).
- You need to support another 3rd‑party SDK that doesn’t have a ready‑made package.
- You want to wrap a complex SDK behind a simple resolver, so the rest of the app never talks to that SDK directly.
Interceptors #
Use interceptors for cross-cutting behavior (renaming events, redaction, sampling).
final class PrefixInterceptor implements EventInterceptor {
const PrefixInterceptor(this.prefix);
final String prefix;
@override
FutureOr<InterceptorResult> intercept({
required ResolvedEvent event,
required EventDispatchContext context,
required NextEventInterceptor next,
}) {
return next(
event.copyWith(name: '${prefix}_${event.name}'),
context,
);
}
}
final hub = AnalyticsHub(
sessionDelegate: yourSessionDelegate,
providers: [BackendAnalyticsProvider()],
interceptors: [const PrefixInterceptor('prod')],
);
More information #
- Core example:
example/main.dart. - Firebase and Mixpanel providers are in sibling packages in this repository.
Suggestions and improvements #
Have an idea to improve Analytics Hub or one of the providers? We’d love to hear it. Please open an issue in the repository with your suggestion or feedback.