Overview
leancode_analytics_firebase provides a Firebase Analytics backend for the LeanCode analytics system. It implements the LeanAnalytics interface from leancode_analytics_base and includes automatic screen view tracking through NavigatorObserver.
This package requires Firebase to be initialized in your app before use. Make sure to set up Firebase in your project first.
Features
Firebase Analytics integration using the official firebase_analytics package
Automatic screen view tracking via FirebaseAnalyticsNavigationObserver
Support for custom analytics events
Type-safe event tracking with built-in events (Tap, Login)
Tracks navigation actions (push, pop, replace)
Installation
Add dependencies
Add the package to your pubspec.yaml: dependencies :
leancode_analytics_firebase : 0.1.0+1
firebase_core : ^3.13.0
Install packages
Run the Flutter package manager:
Configuration
Basic Setup
Initialize Firebase and create a FirebaseLeanAnalytics instance:
import 'package:firebase_core/firebase_core.dart' ;
import 'package:leancode_analytics_firebase/leancode_analytics_firebase.dart' ;
import 'firebase_options.dart' ; // Generated by FlutterFire CLI
void main () async {
WidgetsFlutterBinding . ensureInitialized ();
// Initialize Firebase
await Firebase . initializeApp (
options : DefaultFirebaseOptions .currentPlatform,
);
// Create analytics instance
final analytics = FirebaseLeanAnalytics ();
runApp ( MyApp (analytics : analytics));
}
Integrate with MaterialApp
Add the navigator observers to enable automatic screen tracking:
class MyApp extends StatelessWidget {
const MyApp ({ required this .analytics, super .key});
final FirebaseLeanAnalytics analytics;
@override
Widget build ( BuildContext context) {
return MaterialApp (
title : 'My App' ,
navigatorObservers : analytics.navigatorObservers,
home : const HomeScreen (),
);
}
}
Using with GoRouter
final router = GoRouter (
observers : analytics.navigatorObservers,
routes : [
GoRoute (
path : '/' ,
builder : (context, state) => const HomeScreen (),
),
],
);
class MyApp extends StatelessWidget {
@override
Widget build ( BuildContext context) {
return MaterialApp . router (
routerConfig : router,
);
}
}
Tracking Events
Using Built-in Events
Tap Events
Login Events
Custom Events
import 'package:leancode_analytics_firebase/leancode_analytics_firebase.dart' ;
// Track button taps
analytics. register (
TapAnalyticsEvent (
key : 'submit_button' ,
label : 'Submit Form' ,
),
);
// With additional parameters
analytics. register (
TapAnalyticsEvent (
key : 'product_card' ,
label : 'iPhone 15' ,
params : {
'product_id' : 'prod_123' ,
'category' : 'electronics' ,
},
),
);
Creating Custom Events
Extend AnalyticsEvent for domain-specific events:
class AddToCartEvent extends AnalyticsEvent {
AddToCartEvent ({
required String productId,
required String productName,
required double price,
int quantity = 1 ,
}) : super (
name : 'add_to_cart' ,
params : {
'product_id' : productId,
'product_name' : productName,
'price' : price,
'quantity' : quantity,
},
);
}
// Usage
analytics. register (
AddToCartEvent (
productId : 'prod_123' ,
productName : 'Wireless Headphones' ,
price : 79.99 ,
quantity : 2 ,
),
);
Automatic Screen Tracking
The FirebaseAnalyticsNavigationObserver automatically tracks screen views for routes implementing LeanAnalyticsRoute.
Implementing LeanAnalyticsRoute
With GoRouter
With Custom Route
class ProductDetailsRoute extends GoRoute implements LeanAnalyticsRoute {
ProductDetailsRoute ()
: super (
path : '/product/:id' ,
builder : (context, state) {
final productId = state.pathParameters[ 'id' ] ! ;
return ProductDetailsScreen (productId : productId);
},
);
@override
String get id => 'product_details_screen' ;
@override
Map < String , dynamic > ? get analyticsParams => null ;
}
Screen View Types
The observer tracks different navigation actions:
lib/src/firebase_analytics_observer.dart
enum ScreenViewType {
/// A new route was pushed onto the navigator.
push,
/// A route was popped from the navigator.
pop,
}
Each screen view event includes an action_type parameter indicating how the user navigated to the screen.
Implementation Details
FirebaseLeanAnalytics Class
The main implementation class:
lib/src/firebase_analytics.dart
class FirebaseLeanAnalytics implements LeanAnalytics {
static final FirebaseAnalytics _instance = FirebaseAnalytics .instance;
@override
Future < void > register ( AnalyticsEvent event) async {
await _instance. logEvent (
name : event.name,
parameters : event.params,
);
}
@override
List < NavigatorObserver > get navigatorObservers =>
[ FirebaseAnalyticsNavigationObserver ()];
}
Navigation Observer
Tracks screen views on navigation events:
lib/src/firebase_analytics_observer.dart
class FirebaseAnalyticsNavigationObserver extends NavigatorObserver {
@override
void didPush ( Route < dynamic > route, Route < dynamic > ? previousRoute) {
if (route case final LeanAnalyticsRoute route) {
_instance. logScreenView (
screenName : route.id,
parameters : {
'action_type' : ScreenViewType .push.name,
},
);
}
}
@override
void didPop ( Route < dynamic > route, Route < dynamic > ? previousRoute) {
if (previousRoute case final LeanAnalyticsRoute previousRoute ? ) {
_instance. logScreenView (
screenName : previousRoute.id,
parameters : {
'action_type' : ScreenViewType .pop.name,
},
);
}
}
// Also implements didRemove and didReplace...
}
When a route is popped, we track the previousRoute because that’s the screen the user is now viewing. This ensures accurate screen view tracking when users navigate backwards.
Advanced Usage
Multiple Analytics Instances
class CompositeAnalytics implements LeanAnalytics {
CompositeAnalytics ( this ._backends);
final List < LeanAnalytics > _backends;
@override
void register ( AnalyticsEvent event) {
for ( final backend in _backends) {
backend. register (event);
}
}
@override
List < NavigatorObserver > get navigatorObservers =>
_backends. expand ((b) => b.navigatorObservers). toList ();
}
// Use multiple backends
final analytics = CompositeAnalytics ([
FirebaseLeanAnalytics (),
PostHogLeanAnalytics (),
]);
Conditional Tracking
class ConditionalAnalytics implements LeanAnalytics {
ConditionalAnalytics ( this ._delegate, this ._shouldTrack);
final LeanAnalytics _delegate;
final bool Function () _shouldTrack;
@override
void register ( AnalyticsEvent event) {
if ( _shouldTrack ()) {
_delegate. register (event);
}
}
@override
List < NavigatorObserver > get navigatorObservers =>
_delegate.navigatorObservers;
}
// Disable analytics in debug mode
final analytics = ConditionalAnalytics (
FirebaseLeanAnalytics (),
() => kReleaseMode,
);
Testing
Mocking Analytics
class MockAnalytics implements LeanAnalytics {
final events = < AnalyticsEvent > [];
@override
void register ( AnalyticsEvent event) {
events. add (event);
}
@override
List < NavigatorObserver > get navigatorObservers => [];
}
// In tests
void main () {
test ( 'tracks login event' , () {
final analytics = MockAnalytics ();
final service = AuthService (analytics);
service. login ( 'user_123' );
expect (analytics.events, hasLength ( 1 ));
expect (analytics.events.first.name, 'login' );
expect (analytics.events.first.params[ 'user_id' ], 'user_123' );
});
}
Version: 0.1.0+1
Minimum Dart SDK: 3.5.0
Minimum Flutter: 3.24.0
Dependencies:
firebase_analytics: ^11.4.5
firebase_core: ^3.13.0
leancode_analytics_base: 0.1.0
Repository: flutter_corelibrary
leancode_analytics_base Core analytics abstractions and interfaces
leancode_analytics_posthog PostHog analytics backend implementation