Analytics Setup Checklist

As we have seen, analytics allow you to gain powerful insights about user behavior and important business metrics in your apps.

So here’s a handy checklist you can use to add analytics to your apps.

Checklist for adding Analytics to your Flutter app ✅

To add analytics to your app, you need to do three things:

  1. Add the analytics classes to your project, so you can track events and screen views, and identify users
  2. Create a project with a vendor of choice and configure the analytics SDK
  3. Let users opt-out or opt-in to analytics data collection (optional)

Here’s a summary of the steps.

1. Add the analytics classes to your project

If you don’t want to start from scratch, you can use the same setup described in this module:

App Analytics Architecture with Navigator Observer

These classes are all included in the monitoring folder of the Flutter ship project:

Monitoring folder in the Flutter Ship app codebase

To get them, you can clone this repo and switch to the m05-firebase-complete branch:

git clone https://github.com/bizz84/flutter_ship_app
cd flutter_ship_app
git switch m05-firebase-complete
# Open in VSCode
code .

Then, you can create a monitoring folder in your project, and bring over these files:

  • analytics_client.dart
  • analytics_facade.dart
  • logger_analytics_client.dart
  • logger_navigator_observer.dart
  • firebase_analytics_client.dart (if using Firebase Analytics)
  • mixpanel_analytics_client.dart (if using Mixpanel)

Since my code uses Riverpod generator, you’ll need to run dart run build_runner build -d to generate the updated providers.

Note that my AnalyticsClient defines custom events that are only relevant to the Flutter Ship app. You’ll want to replace them with your own events:

abstract class AnalyticsClient {
  // You can keep these methods
  Future<void> setAnalyticsCollectionEnabled(bool enabled);
 
  Future<void> identifyUser(String userId);
  Future<void> resetUser();
 
  Future<void> trackScreenView(String routeName, String action);
 
  // TODO: Replace these events with your own
  Future<void> trackNewAppOnboarding();
  Future<void> trackNewAppHome();
  Future<void> trackAppCreated();
  Future<void> trackAppUpdated();
  Future<void> trackAppDeleted();
  Future<void> trackTaskCompleted(int completedCount);
}

Then, call all the methods as needed in your application code. Example:

unawaited(ref.read(analyticsFacadeProvider).trackOnboardingCompleted());

If you want to track screen views, add the LoggerNavigatorObserver as a navigation observer:

MaterialApp(
  navigatorObservers: [
    SentryNavigatorObserver(),
    LoggerNavigatorObserver(ref.read(analyticsFacadeProvider)),
  ],
)

2. Create projects with a vendor of choice

If you choose Mixpanel, follow the steps in these two lessons:

If you choose Firebase analytics, follow the steps in these two lessons:

If you choose a different analytics vendor:

  • follow the documentation and setup instructions
  • add a new AnalyticsClient subclass and override all the methods
  • register it in the analyticsFacadeProvider

Once the setup is done, run your app and interact with it. Since a LoggerAnalyticsClient is already registered, you should see all the events appear on the console. Example:

[Navigation] trackScreenView(apps, push)
[Event] trackNewAppHome
[Navigation] trackScreenView(createApp, push)
[Event] trackAppCreated
[Navigation] trackScreenView(createApp, pop)
[Navigation] trackScreenView(epics, push)
[Navigation] trackScreenView(tasks, push)
[Event] trackTaskCompleted(completedCount: 19)
[Event] trackTaskCompleted(completedCount: 20)
[Navigation] trackScreenView(tasks, pop)
[Navigation] trackScreenView(epics, pop)

3. Let users opt-out or opt-in to analytics data collection (optional)

If desired, you can add an option to disable data collection to your settings page:

Collect anonymous usage statistics toggle on the settings screen

To do this, follow the instructions in this lesson:

Extra tip: choosing which analytics clients to use

After following the lessons in this module, we ended up with this analyticsFacadeProvider:

@Riverpod(keepAlive: true)
AnalyticsFacade analyticsFacade(Ref ref) {
  final mixpanelAnalyticsClient =
      ref.watch(mixpanelAnalyticsClientProvider).requireValue;
  final firebaseAnalyticsClient = ref.watch(firebaseAnalyticsClientProvider);
  return AnalyticsFacade([
    mixpanelAnalyticsClient,
    firebaseAnalyticsClient,
    if (!kReleaseMode) const LoggerAnalyticsClient(),
  ]);
}

If desired, you can conditionally choose which clients to use based on the build mode, or even the current flavor. For example, here’s the code I’m using in my Flutter Tips app:

@Riverpod(keepAlive: true)
AnalyticsFacade analyticsFacade(Ref ref) {
  return AnalyticsFacade(kReleaseMode
      ? [
          ref.watch(mixpanelClientProvider).requireValue,
          ref.watch(firebaseAnalyticsClientProvider),
          if (getFlavor() == Flavor.prod)
            ref.watch(posthogAnalyticsClientProvider),
        ]
      : [
          LoggerAnalyticsClient(),
        ]);
}

If you want, you can even enable or disable specific vendors dynamically using Firebase Remote Config or by reading some feature flags from your backend API (we will cover these topics in the upcoming modules).

Questions? Let's chat