Skip to main content

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

1

Add dependencies

Add the package to your pubspec.yaml:
pubspec.yaml
dependencies:
  leancode_analytics_posthog: 0.1.0+1
  posthog_flutter: ^5.6.0
2

Install packages

Run the Flutter package manager:
flutter pub get
3

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:
main.dart
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

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

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(),
  ];
}
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...
}
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

  • 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
  • PostHog batches events automatically to minimize network calls
  • Adjust flushIntervalSeconds in setup if needed
  • Consider implementing conditional tracking to disable in debug mode

Package Information

  • 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

Build docs developers (and LLMs) love