如何在 Firebase 分析中跟踪 Flutter 屏幕?
Posted
技术标签:
【中文标题】如何在 Firebase 分析中跟踪 Flutter 屏幕?【英文标题】:How do I track Flutter screens in Firebase analytics? 【发布时间】:2019-09-13 18:45:40 【问题描述】:我有一个 Flutter 应用,我正在 Flutter 上测试 Google Analytics for Firebase。
我想看看我们的用户(好吧,现在是我)正在访问的路线。我按照firebase_analytics
中的设置步骤进行操作,也检查了他们的示例应用程序。如Debug View docs
不幸的是,我在分析调试视图中收到的仅有两种屏幕视图 (firebase_screen_class
) 是 Flutter
和 MainActivity
。
我希望在某个地方看到/example-1
、/example-2
和/welcome
,但我没有。
这是我在 Flutter 中运行的应用程序
class App extends StatelessWidget
final FirebaseAnalytics analytics = FirebaseAnalytics();
@override
Widget build(BuildContext context)
return MaterialApp(
routes: <String, WidgetBuilder>
'/example-1': (_) => Example1(),
'/example-2': (_) => Example2(),
'/welcome': (_) => Welcome(),
,
home: Welcome(),
navigatorObservers: [FirebaseAnalyticsObserver(analytics: analytics)],
);
【问题讨论】:
为什么你不把事件放在每个单独的屏幕上而不是做漏斗? 在你的 Screen Constructor 中添加 firebase 事件。? 【参考方案1】:这个确切的用例在 Track Screenviews 部分下的 Firebase Analytics 文档中。
如果您的应用不为您可能希望跟踪的每个屏幕(例如在游戏中)使用单独的 UIViewController 或 Activity,则手动跟踪屏幕很有用。
这正是 Flutter 的情况,因为 Flutter 负责屏幕更新:大多数简单的 Flutter 应用程序运行一个 FlutterActivity
/FlutterAppDelegate
,它负责自己渲染不同的屏幕,因此让 Firebase Analytics 自动跟踪屏幕不会带来预期的效果。
就我过去的经验而言,FirebaseAnalyticsObserver
并不是很有帮助,但是,我也向您推荐check their docs again,它们确实暗示事情应该“正常工作”。我最好的猜测是它对我来说效果不佳,因为我没有在我的任何路线上使用RouteSettings
*
。
如果FirebaseAnalyticsObserver
无法工作或无法申请您的应用,那么在过去几个月的开发过程中,下一个方法对我来说效果很好。
您可以在任何时候使用FirebaseAnalytics
设置当前屏幕,如果您使用屏幕名称调用setCurrentScreen
方法:
import 'package:firebase_analytics/firebase_analytics.dart';
// Somewhere in your widgets...
FirebaseAnalytics().setCurrentScreen(screenName: 'Example1');
作为第一次尝试,我在小部件构造函数中这样做了,但这不会很好地工作并且错误地计算了事件:如果你弹出或推送路由,堆栈中的所有小部件构造函数都将被调用,即使实际上只有顶部路由符合“当前屏幕”的条件。
为了解决这个问题,我们需要使用RouteAware
类,并且只设置当前屏幕以防它是顶部路由:要么我们的路由被添加到堆栈中,要么之前的顶部路由被弹出并且我们到达了路由.
RouteAware
带有样板代码,我们不想在所有屏幕上重复该样板代码。即使对于小型应用程序,您也有几十个不同的屏幕,所以我创建了RouteAwareAnalytics
mixin:
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:flutter/widgets.dart';
// A Navigator observer that notifies RouteAwares of changes to state of their Route
final routeObserver = RouteObserver<PageRoute>();
mixin RouteAwareAnalytics<T extends StatefulWidget> on State<T>
implements RouteAware
AnalyticsRoute get route;
@override
void didChangeDependencies()
routeObserver.subscribe(this, ModalRoute.of(context));
super.didChangeDependencies();
@override
void dispose()
routeObserver.unsubscribe(this);
super.dispose();
@override
void didPop()
@override
void didPopNext()
// Called when the top route has been popped off,
// and the current route shows up.
_setCurrentScreen(route);
@override
void didPush()
// Called when the current route has been pushed.
_setCurrentScreen(route);
@override
void didPushNext()
Future<void> _setCurrentScreen(AnalyticsRoute analyticsRoute)
print('Setting current screen to $analyticsRoute');
return FirebaseAnalytics().setCurrentScreen(
screenName: screenName(analyticsRoute),
screenClassOverride: screenClass(analyticsRoute),
);
我创建了一个enum
来跟踪屏幕(以及将枚举转换为屏幕名称的函数)。我使用枚举能够轻松跟踪所有路由,重构路由名称。使用这些枚举和函数,我可以对所有可能的值进行单元测试并强制执行一致的命名:没有意外空格或特殊字符,没有不一致的大小写。可能还有其他更好的方法来确定屏幕类值,但我采用了这种方法。
enum AnalyticsRoute example
String screenClass(AnalyticsRoute route)
switch (route)
case AnalyticsRoute.example:
return 'ExampleRoute';
throw ArgumentError.notNull('route');
String screenName(AnalyticsRoute route)
switch (route)
case AnalyticsRoute.example:
return '/example';
throw ArgumentError.notNull('route');
初始设置的下一步是将routeObserver
注册为navigatorObserver
的navigatorObserver
:
MaterialApp(
// ...
navigatorObservers: [
routeObserver,
// FirebaseAnalyticsObserver(analytics: FirebaseAnalytics()),
],
);
最后,我们可以添加我们第一个跟踪的示例路线。将with RouteAwareAnalytics
添加到您的状态并覆盖get route
。
class ExampleRoute extends StatefulWidget
@override
_ExampleRouteState createState() => _ExampleRouteState();
class _ExampleRouteState extends State<ExampleRoute> with RouteAwareAnalytics
@override
Widget build(BuildContext context) => Text('Example');
@override
AnalyticsRoute get route => AnalyticsRoute.example;
每次添加新路由时,您都可以毫不费力地完成:首先,添加一个新的枚举值,然后 Dart 编译器会指导您接下来添加什么:添加屏幕名称和类覆盖它们各自switch-case
中的值。然后,找到正在构建路由的州,添加 with RouteAwareAnalytics
,并添加 route
getter。
*
我不使用RouteSettings
的原因是我更喜欢带有类型参数的Simon Lightfoot's approach,而不是设置提供的Object
参数:
class ExampleRoute extends StatefulWidget
const ExampleRoute._(@required this.integer, Key key) : super(key: key);
// All types of members are supported, but I used int as example
final int integer;
static Route<void> route(@required int integer) =>
MaterialPageRoute(
// I could add the settings here, though, it wouldn't enforce good types
builder: (_) => ExampleRoute._(integer: integer),
);
// ...
【讨论】:
DRY 的优点:我意识到我不能只使用screen_view
事件来构建漏斗,所以我刚刚用额外的 analytics.logEvent(name: 'screen_view-$screenName');
更新了我的抽象类的 setCurrentScreen
您真的可以在 Firebase 控制台中看到您的真实屏幕名称吗?我只是将“screen_name”视为事件,无论我如何使用 setCurrentScreen("whatever"); 命名事件
为什么不让 AnalyticsScreen 覆盖 StatefulWidget?这样,您可以在 AnalyticsScreen 构造函数中调用 setCurrentScreen(),从而防止您忘记对屏幕的此调用。
是否有任何已知的方法来实现 ModalRoutes 的日志记录?我的应用程序中有很多底部工作表是无状态小部件(这就是为什么我不想使用 RouteAware,因为它需要有状态小部件)并且标准 FirebaseAnalyticsObserver 不起作用,因为它只观察 PageRoutes
知道如何在无状态小部件上使用 mixin【参考方案2】:
你可以添加一个firebase分析navigation observer:
要使用它,请将其添加到 Navigator 的 navigatorObservers 中,例如如果 您正在使用 MaterialApp:
class MyApp extends StatelessWidget
FirebaseAnalytics analytics = FirebaseAnalytics();
...
MaterialApp(
home: MyAppHome(),
navigatorObservers: [
FirebaseAnalyticsObserver(analytics: analytics),
],
);
注意!
如果这是您第一次在应用中集成分析,则您的分析需要大约一天才能显示在仪表板中。
立即查看结果
为了立即查看调试结果,请在终端上运行上述命令并在 firebase analytic debugView 上检查您的分析(如上图所示):
adb shell setprop debug.firebase.analytics.app [your_app_package_name]
享受吧!
【讨论】:
我没有看到实际的屏幕名称,只是屏幕截图中的 screen_name? 如果您按下其中一个 screen_view 分析,您将获得更多信息,例如时间戳、令牌和屏幕名称【参考方案3】:我遇到这个问题有一段时间了,只是能够让它工作
我的问题是我没有正确传递 MaterialPageRoute 中的设置
return MaterialPageRoute(
settings: RouteSettings(
name: routeName,
),
builder: (_) => viewToShow);
我按照FilledStack 上的教程进行操作,并且在看到示例代码后能够找出我的问题
【讨论】:
【参考方案4】:如果您在 screen_view
的 firebase_screen_class
参数中看到“Flutter”
事件,这意味着你已经正确配置了它。
您应该在firebase_screen
参数而不是firebase_screen_class
中找到您期望的值。
还值得检查firebase_previous_screen
参数以查看在此之前打开的屏幕是什么。
【讨论】:
以上是关于如何在 Firebase 分析中跟踪 Flutter 屏幕?的主要内容,如果未能解决你的问题,请参考以下文章
Google Analytics for Firebase:如何分析事件 [关闭]