Flutter数据分析跟踪插件matomo_tracker的使用

发布于 1周前 作者 phonegap100 来自 Flutter

Flutter数据分析跟踪插件matomo_tracker的使用

Matomo Tracker

Matomo Tracker 是一个完全跨平台的Flutter插件,它封装了Matomo Tracking API,可以用于在Flutter应用中集成和使用Matomo进行用户行为分析。以下是关于如何使用该插件的一些关键点。

Summary

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',
);

为了使TraceableClientMixinTraceableWidget正常工作,您需要将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对象用于事件跟踪。
    • 需要在MaterialAppWidgetsApp中添加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

1 回复

更多关于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服务器进行分析。

注意事项

  1. 隐私和合规性:确保你遵守所有适用的隐私法律和规定,特别是关于数据收集和用户同意的法规。
  2. 调试和验证:在生产环境中部署之前,确保在开发环境中测试跟踪功能,并验证数据是否正确发送到你的Matomo服务器。
  3. 文档和更新:参考matomo_tracker插件的官方文档以获取最新功能和API更改。

这样,你就可以在Flutter应用中使用matomo_tracker插件进行数据分析和跟踪了。

回到顶部