Flutter数据分析跟踪插件matomo_tracker的使用
Flutter数据分析跟踪插件matomo_tracker的使用
Matomo Tracker
Matomo Tracker 是一个完全跨平台的Flutter插件,它封装了Matomo Tracking API,可以用于在Flutter应用中集成和使用Matomo进行用户行为分析。以下是关于如何使用该插件的一些关键点。
Summary
- Supported Matomo Versions
- Getting Started
- Using userId
- Opting Out
- Using Dimensions
- Cookieless Tracking
- Dispatching
Documentation
Supported Matomo Versions
此包 (matomo_tracker v5.0.0) 目前支持Matomo 4.X至Matomo 5.X版本。
Getting Started
在应用程序中尽可能早地配置Matomo Tracker以通过传递您的实例URL端点和站点ID来初始化:
await MatomoTracker.instance.initialize(
siteId: siteId,
url: 'https://example.com/matomo.php',
);
如果您需要使用自己的访客ID,可以在初始化MatomoTracker时传递:
await MatomoTracker.instance.initialize(
siteId: siteId,
url: 'https://example.com/matomo.php',
visitorId: '2589631479517535',
);
为了使TraceableClientMixin
和TraceableWidget
正常工作,您需要将matomoObserver
添加到navigatorObservers
中:
MaterialApp(
// ...
navigatorObservers: [
matomoObserver,
],
);
要跟踪视图,只需在State
上添加TraceableClientMixin
:
class MyHomePageState extends State<MyHomePage> with TraceableClientMixin {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Text('Hello World!'),
),
);
}
@override
String get actionName => 'Created HomePage'; // optional
@override
String get path => '/home'; // optional
}
对于无状态小部件,您可以使用TraceableWidget
小部件:
class MyHomePage extends StatelessWidget {
const MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return TraceableWidget(
actionName: 'Created HomePage', // optional
path: '/home', // optional
child: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Text('Hello World!'),
),
),
);
}
}
Using userId
如果您的应用程序使用身份验证,并且希望将访问者特定的身份信息包含到Matomo中,可以使用Visitor属性userId与来自后端的任何唯一标识符一起使用,通过调用setVisitorUserId()
方法实现。以下是如何使用Firebase的一个示例:
String userId = auth.currentUser?.email ?? auth.currentUser!.uid;
MatomoTracker.instance.setVisitorUserId(userId);
Opting Out
如果想为用户提供退出分析的方式,可以使用setOptOut()
方法:
MatomoTracker.instance.setOptOut(optout: true);
Using Dimensions
如果想要跟踪访问或操作维度,可以使用trackDimensions
(如果是访问级别维度)或在trackEvent
的可选参数dimensions
中提供数据(如果是操作级别维度):
MatomoTracker.instance.trackDimensions({
'dimension1': '0.0.1'
});
MatomoTracker.instance.trackEvent(
eventInfo: EventInfo(
category: "eventCategory",
action: "eventAction",
name: "eventName",
value: 18,
),
dimensions: {'dimension2':'guest-user'}
);
MatomoTracker.instance.trackPageViewWithName(
actionName: "Settings",
path: "/settings",
dimensions: {'dimension1': '0.0.1'}
);
Cookieless Tracking
如果想使用无cookie跟踪,可以在initialize
方法中使用cookieless
属性:
await MatomoTracker.instance.initialize(
siteId: siteId,
url: 'https://example.com/matomo.php',
cookieless: true,
);
当使用无cookie跟踪时,user_id不会被发送或保存在本地。
Dispatching
已记录的操作不会立即发送给Matomo,而是会在可配置的时间段内(默认为10秒)排队,然后批量发送。用户可能在仍有未分发操作的情况下终止应用程序,默认情况下这些操作将会丢失。队列可以配置为持久化,这样这些操作将在下次启动应用程序时发送。有关更多配置选项,请参阅DispatchSettings类。
await MatomoTracker.instance.initialize(
siteId: siteId,
url: 'https://example.com/matomo.php',
dispatchSettings: const DispatchSettings.persistent(),
);
Migration Guide
-
v5.0.0
Session
类及其相关属性已被移除。LocalStorage
方法已被移除。siteId
现在是String
类型而不是int
类型。
-
v4.0.0
- 多个方法名更改,如
trackScreen
改名为trackPageView
等。 - 引入了
EventInfo
对象用于事件跟踪。 - 需要在
MaterialApp
或WidgetsApp
中添加matomoObserver
。
- 多个方法名更改,如
-
v3.0.0
initialize()
方法现在接受LocalStorage? localStorage
而不是SharedPreferences? prefs
作为参数。
Contributors
感谢所有贡献者的努力,他们帮助改进和完善了这个插件。
示例代码
下面是一个完整的示例demo,演示了如何在Flutter项目中使用matomo_tracker
插件。
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:matomo_tracker/matomo_tracker.dart';
import 'package:url_launcher/url_launcher.dart';
// 测试Matomo实例运行的常量
const _matomoEndpoint = 'http://localhost:8765/matomo.php';
const _sideId = "1";
const _testUserId = 'Nelson Pandela';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await MatomoTracker.instance.initialize(
siteId: _sideId,
url: _matomoEndpoint,
verbosityLevel: Level.all,
);
MatomoTracker.instance.setVisitorUserId(_testUserId);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Matomo Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Matomo Example'),
navigatorObservers: [matomoObserver],
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
MyHomePageState createState() => MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> with TraceableClientMixin {
int _counter = 0;
void _incrementCounter() {
MatomoTracker.instance.trackEvent(
eventInfo: EventInfo(
category: 'Main',
action: 'Click',
name: 'IncrementCounter',
),
);
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const ContentWidget(),
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 20.0),
child: ElevatedButton(
onPressed: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const OtherPage(),
),
);
},
child: const Text('Go to OtherPage'),
),
),
const Outlink(),
const SearchWidget(),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
@override
String get actionName => widget.title;
@override
String? get path => '/homepage';
}
class OtherPage extends StatefulWidget {
const OtherPage({super.key});
@override
State<OtherPage> createState() => _OtherPageState();
}
class _OtherPageState extends State<OtherPage> {
late bool _loading;
late Duration? _workTime;
@override
void initState() {
super.initState();
_loading = true;
final workStart = DateTime.now();
Future.delayed(Duration(seconds: Random().nextInt(4) + 3))
.then((_) => setState(() {
_loading = false;
_workTime = DateTime.now().difference(workStart);
}));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Other Page'),
),
body: Center(
child: _loading
? const CircularProgressIndicator()
: TraceableWidget(
path: '/otherpage',
actionName: 'Other Page',
performanceInfo: PerformanceInfo(
serverTime: _workTime,
),
child: const Text(
'Welcome to the other page!',
),
),
),
);
}
}
class Outlink extends StatelessWidget {
static const _outlink = 'https://github.com/Floating-Dartists/matomo-tracker';
const Outlink({super.key});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 15.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('Outlink tracking test:'),
ElevatedButton(
onPressed: _onPressed,
child: const Text('View on GitHub'),
),
],
),
);
}
void _onPressed() {
MatomoTracker.instance.trackOutlink(
link: _outlink,
);
launchUrl(Uri.parse(_outlink));
}
}
class SearchWidget extends StatefulWidget {
const SearchWidget({super.key});
@override
State<SearchWidget> createState() => _SearchWidgetState();
}
class _SearchWidgetState extends State<SearchWidget> {
final _searchController = TextEditingController(text: 'Enter Search Text...');
bool _canSearch = true;
String? _lastSearch;
@override
void initState() {
super.initState();
_searchController.addListener(_textChange);
}
@override
void dispose() {
super.dispose();
_searchController.removeListener(_textChange);
}
void _textChange() {
final canSearch = _searchController.text.trim().isNotEmpty;
if (_canSearch != canSearch) {
setState(() {
_canSearch = canSearch;
});
}
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 15.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
width: 300.0,
child: TextField(controller: _searchController),
),
IconButton(
onPressed: _canSearch ? _search : null,
icon: const Icon(Icons.search),
),
],
),
_lastSearch == null
? const Text('No search yet!')
: Text('Last search: $_lastSearch'),
],
),
);
}
void _search() {
MatomoTracker.instance.trackSearch(
searchKeyword: _searchController.text,
);
setState(() {
_lastSearch = _searchController.text;
});
}
}
class ContentWidget extends StatefulWidget {
const ContentWidget({
super.key,
});
@override
State<ContentWidget> createState() => _ContentWidgetState();
}
class _ContentWidgetState extends State<ContentWidget> {
late bool _closed;
final Content _exampleContent = Content(
name: 'Matomo is great',
piece: 'banner',
);
@override
void initState() {
super.initState();
_closed = false;
MatomoTracker.instance.trackContentImpression(
content: _exampleContent,
);
}
@override
Widget build(BuildContext context) {
return Visibility(
visible: !_closed,
child: Card(
color: Colors.blue,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
IconButton(
onPressed: _close,
icon: const Icon(
Icons.close,
),
),
const SizedBox(
width: 200,
height: 150,
child: Center(
child: Text(
'Matomo is great!',
),
),
)
],
)));
}
void _close() {
setState(() {
_closed = true;
});
MatomoTracker.instance.trackContentInteraction(
interaction: 'close',
content: _exampleContent,
);
}
}
以上代码展示了如何在Flutter应用程序中使用matomo_tracker
插件进行页面视图、事件、搜索、内容印象和交互的跟踪。
更多关于Flutter数据分析跟踪插件matomo_tracker的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter数据分析跟踪插件matomo_tracker的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用matomo_tracker
插件进行数据分析跟踪的详细代码示例。matomo_tracker
是一个用于与Matomo(也称为Piwik Pro或Piwik)分析平台集成的Flutter插件。
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加matomo_tracker
依赖:
dependencies:
flutter:
sdk: flutter
matomo_tracker: ^x.y.z # 替换为最新版本号
然后运行flutter pub get
来安装依赖。
2. 配置Matomo
在你的main.dart
文件中,配置并初始化Matomo跟踪器。你需要提供Matomo服务器的URL和站点ID。
import 'package:flutter/material.dart';
import 'package:matomo_tracker/matomo_tracker.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
// 初始化Matomo
MatomoTracker.instance().init(
url: "https://your-matomo-server.com/", // 替换为你的Matomo服务器URL
siteId: "12345", // 替换为你的站点ID
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Matomo Tracker Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Matomo Tracker Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'跟踪页面视图',
),
ElevatedButton(
onPressed: () {
// 跟踪页面视图
MatomoTracker.instance().trackPageView(
pageName: 'HomePage',
customTitle: 'Home Page with Custom Title',
customVariables: [
{'index': 1, 'name': 'example_variable', 'value': 'example_value'},
],
);
},
child: Text('跟踪页面视图'),
),
SizedBox(height: 20),
Text(
'跟踪事件',
),
ElevatedButton(
onPressed: () {
// 跟踪事件
MatomoTracker.instance().trackEvent(
category: 'Button',
action: 'Click',
name: 'Submit Button',
value: 1, // 可选,事件的数值(如购买金额)
customVariables: [
{'index': 1, 'name': 'example_variable', 'value': 'example_value'},
],
);
},
child: Text('跟踪事件'),
),
],
),
),
);
}
}
3. 运行应用
现在你可以运行你的Flutter应用,点击按钮来触发页面视图和事件的跟踪。这些数据将会发送到你的Matomo服务器进行分析。
注意事项
- 隐私和合规性:确保你遵守所有适用的隐私法律和规定,特别是关于数据收集和用户同意的法规。
- 调试和验证:在生产环境中部署之前,确保在开发环境中测试跟踪功能,并验证数据是否正确发送到你的Matomo服务器。
- 文档和更新:参考
matomo_tracker
插件的官方文档以获取最新功能和API更改。
这样,你就可以在Flutter应用中使用matomo_tracker
插件进行数据分析和跟踪了。