Overview
leancode_analytics_posthog provides a PostHog Analytics backend for the LeanCode analytics system. It implements the LeanAnalytics interface from leancode_analytics_base and leverages the posthog_flutter package for comprehensive product analytics including events, screen views, and session replay.
This package requires PostHog to be configured in your app before use. You’ll need a PostHog API key and host URL.
Features
PostHog Analytics integration using the official posthog_flutter package
Automatic screen view tracking via LeanAnalyticsPostHogObserver
Support for custom analytics events
Type-safe event tracking with built-in events (Tap, Login)
Session replay capabilities (from PostHog)
Feature flags and A/B testing support (from PostHog)
Self-hosted or cloud options
Installation
Add dependencies
Add the package to your pubspec.yaml: dependencies :
leancode_analytics_posthog : 0.1.0+1
posthog_flutter : ^5.6.0
Install packages
Run the Flutter package manager:
Get PostHog credentials
Sign up at PostHog or set up a self-hosted instance to get your API key and host URL
Configuration
Basic Setup
Initialize PostHog and create a PostHogLeanAnalytics instance:
import 'package:leancode_analytics_posthog/leancode_analytics_posthog.dart' ;
void main () async {
WidgetsFlutterBinding . ensureInitialized ();
// Initialize PostHog
await Posthog (). setup (
apiKey : 'phc_YOUR_API_KEY' ,
host : 'https://app.posthog.com' , // or your self-hosted URL
);
// Create analytics instance
final analytics = PostHogLeanAnalytics ();
runApp ( MyApp (analytics : analytics));
}
Advanced Configuration
Configure PostHog with additional options:
await Posthog (). setup (
apiKey : 'phc_YOUR_API_KEY' ,
host : 'https://app.posthog.com' ,
// Enable session replay
captureScreenViews : true ,
// Auto-capture touch events
captureApplicationLifecycleEvents : true ,
// Enable debug mode
debug : kDebugMode,
// Custom flush interval
flushIntervalSeconds : 30 ,
);
Never commit your PostHog API key to version control. Use environment variables or Flutter’s --dart-define flag for secure configuration.
Integrate with MaterialApp
Add the navigator observers to enable automatic screen tracking:
class MyApp extends StatelessWidget {
const MyApp ({ required this .analytics, super .key});
final PostHogLeanAnalytics 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_posthog/leancode_analytics_posthog.dart' ;
// Track button taps
analytics. register (
TapAnalyticsEvent (
key : 'checkout_button' ,
label : 'Proceed to Checkout' ,
),
);
// With additional parameters
analytics. register (
TapAnalyticsEvent (
key : 'product_card' ,
label : 'MacBook Pro' ,
params : {
'product_id' : 'prod_456' ,
'price' : 2399.00 ,
'category' : 'laptops' ,
},
),
);
Creating Custom Events
Extend AnalyticsEvent for domain-specific events:
class SubscriptionPurchasedEvent extends AnalyticsEvent {
SubscriptionPurchasedEvent ({
required String planId,
required String planName,
required double price,
required String interval,
}) : super (
name : 'subscription_purchased' ,
params : {
'plan_id' : planId,
'plan_name' : planName,
'price' : price,
'interval' : interval,
'currency' : 'USD' ,
},
);
}
// Usage
analytics. register (
SubscriptionPurchasedEvent (
planId : 'plan_premium' ,
planName : 'Premium Monthly' ,
price : 9.99 ,
interval : 'monthly' ,
),
);
Automatic Screen Tracking
The LeanAnalyticsPostHogObserver extends PostHog’s PosthogObserver to track screen views for routes implementing LeanAnalyticsRoute.
Implementing LeanAnalyticsRoute
With GoRouter
With Named Routes
class CheckoutRoute extends GoRoute implements LeanAnalyticsRoute {
CheckoutRoute ()
: super (
path : '/checkout' ,
builder : (context, state) => const CheckoutScreen (),
);
@override
String get id => 'checkout_screen' ;
@override
Map < String , dynamic > ? get analyticsParams => {
'step' : 'payment' ,
'cart_value' : 149.99 ,
};
}
Screen View with Parameters
The observer automatically includes analyticsParams in screen view events:
class SearchResultsRoute extends GoRoute implements LeanAnalyticsRoute {
SearchResultsRoute ( this .query, this .resultsCount)
: super (
path : '/search' ,
builder : (context, state) => SearchResultsScreen (query : query),
);
final String query;
final int resultsCount;
@override
String get id => 'search_results_screen' ;
@override
Map < String , dynamic > ? get analyticsParams => {
'query' : query,
'results_count' : resultsCount,
'search_type' : 'instant' ,
};
}
Implementation Details
PostHogLeanAnalytics Class
The main implementation class:
lib/src/posthog_analytics.dart
class PostHogLeanAnalytics implements LeanAnalytics {
@override
Future < void > register ( AnalyticsEvent event) async {
await Posthog (). capture (
eventName : event.name,
properties : event.params,
);
}
@override
List < NavigatorObserver > get navigatorObservers => [
LeanAnalyticsPostHogObserver (),
];
}
Navigation Observer
Extends PostHog’s observer to track LeanAnalyticsRoute implementations:
lib/src/posthog_analytics_observer.dart
class LeanAnalyticsPostHogObserver extends PosthogObserver {
@override
void didPush ( Route < dynamic > route, Route < dynamic > ? previousRoute) {
if (route is LeanAnalyticsRoute ) {
_sendLeanAnalyticsScreen (route as LeanAnalyticsRoute );
}
super . didPush (route, previousRoute);
}
void _sendLeanAnalyticsScreen ( LeanAnalyticsRoute route) {
final params = route.analyticsParams;
final properties = params ? . map (
(key, value) => MapEntry < String , Object >(key, value as Object ),
);
Posthog (). screen (
screenName : route.id,
properties : properties,
);
}
// Also implements didPop, didReplace, didRemove...
}
Why extend PosthogObserver?
By extending PosthogObserver, we get all the built-in PostHog tracking features (like automatic screen capture) while adding support for LeanAnalyticsRoute. This gives you the best of both worlds: LeanCode’s clean API and PostHog’s powerful features.
Advanced Features
User Identification
Identify users for better analytics:
// Identify user after login
await Posthog (). identify (
userId : 'user_123' ,
userProperties : {
'email' : '[email protected] ' ,
'name' : 'John Doe' ,
'plan' : 'premium' ,
},
);
// Track login event
analytics. register (
LoginAnalyticsEvent (userId : 'user_123' ),
);
Feature Flags
Use PostHog’s feature flags:
// Check if feature is enabled
final isNewUIEnabled = await Posthog (). isFeatureEnabled ( 'new_ui' );
if (isNewUIEnabled) {
// Show new UI
} else {
// Show old UI
}
// Get feature flag with payload
final payload = await Posthog (). getFeatureFlagPayload ( 'ab_test_variant' );
Session Replay
PostHog supports session replay to see exactly how users interact with your app:
// Start recording (usually automatic if enabled in setup)
await Posthog (). startRecording ();
// Stop recording
await Posthog (). stopRecording ();
Multiple Analytics Backends
Combine PostHog with other analytics providers:
class MultiBackendAnalytics implements LeanAnalytics {
MultiBackendAnalytics ( 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 both PostHog and Firebase
final analytics = MultiBackendAnalytics ([
PostHogLeanAnalytics (),
FirebaseLeanAnalytics (),
]);
Privacy & GDPR Compliance
PostHog provides tools for privacy compliance:
// Opt user out of tracking
await Posthog (). optOut ();
// Opt user back in
await Posthog (). optIn ();
// Reset user data (e.g., on logout)
await Posthog (). reset ();
Testing
Mocking Analytics
class MockPostHogAnalytics implements LeanAnalytics {
final events = < AnalyticsEvent > [];
final screenViews = < String > [];
@override
void register ( AnalyticsEvent event) {
events. add (event);
}
@override
List < NavigatorObserver > get navigatorObservers => [];
}
// In tests
void main () {
test ( 'tracks subscription purchase' , () {
final analytics = MockPostHogAnalytics ();
final service = SubscriptionService (analytics);
service. purchaseSubscription ( 'premium' );
expect (analytics.events, hasLength ( 1 ));
expect (analytics.events.first.name, 'subscription_purchased' );
expect (analytics.events.first.params[ 'plan_id' ], 'premium' );
});
}
Disable in Development
final analytics = kDebugMode
? MockPostHogAnalytics ()
: PostHogLeanAnalytics ();
Troubleshooting
Events not appearing in PostHog
Verify your API key and host URL are correct
Check that PostHog is initialized before calling register()
Events are batched and flushed periodically - wait a few minutes or call Posthog().flush()
Enable debug mode in PostHog setup to see logs
Ensure your routes implement LeanAnalyticsRoute
Verify navigatorObservers is added to your MaterialApp or router
Check that the route’s id property returns a non-empty string
Version: 0.1.0+1
Minimum Dart SDK: 3.5.0
Minimum Flutter: 3.24.0
Dependencies:
posthog_flutter: ^5.6.0
leancode_analytics_base: 0.1.0
Repository: flutter_corelibrary
leancode_analytics_base Core analytics abstractions and interfaces
leancode_analytics_firebase Firebase analytics backend implementation
Resources