Showing
5 changed files
with
53 additions
and
33 deletions
1 | # Auto_Track_Plugin | 1 | # Auto_Track_Plugin |
2 | 2 | ||
3 | -> Flutter 自动埋点插件,支持 Android 和 iOS | 3 | +> Flutter全埋点插件,支持 Android 和 iOS |
4 | 4 | ||
5 | 低侵入全局自动埋点,自动记录页面进入、退出,点击、滑动等事件,并支持自定义事件。 | 5 | 低侵入全局自动埋点,自动记录页面进入、退出,点击、滑动等事件,并支持自定义事件。 |
6 | 6 | ||
7 | 7 | ||
8 | ## Getting Started 使用指南 | 8 | ## Getting Started 使用指南 |
9 | 9 | ||
10 | +只需在入口配置`AutoTrack().config()`即可启用全局埋点 | ||
11 | + | ||
10 | 目前仅在移动端验证通过,其他平台暂无验证。 | 12 | 目前仅在移动端验证通过,其他平台暂无验证。 |
11 | 13 | ||
12 | ### Installation 安装 | 14 | ### Installation 安装 |
@@ -39,8 +41,10 @@ class _MyAppState extends State<MyApp> { | @@ -39,8 +41,10 @@ class _MyAppState extends State<MyApp> { | ||
39 | AutoTrack() | 41 | AutoTrack() |
40 | .config(AutoTrackConfig( // 其余配置可查看AutoTrackConfig类 | 42 | .config(AutoTrackConfig( // 其余配置可查看AutoTrackConfig类 |
41 | host: 'http://localhost:3000/api/track', | 43 | host: 'http://localhost:3000/api/track', |
42 | - appKey: 'xxxx', | ||
43 | - appSecret: 'xxxx', | 44 | + eventHandler: (model) => { |
45 | + // 事件触发会调用此方法,可自行处理 | ||
46 | + print('event handler ${model.type}') | ||
47 | + }, | ||
44 | pageConfigs: [ | 48 | pageConfigs: [ |
45 | AutoTrackPageConfig<PageA>( | 49 | AutoTrackPageConfig<PageA>( |
46 | pageID: 'page_a', // 配置页面ID,统计时可基于此ID进行统计 | 50 | pageID: 'page_a', // 配置页面ID,统计时可基于此ID进行统计 |
@@ -124,9 +128,10 @@ class PageA extends StatelessWidget { | @@ -124,9 +128,10 @@ class PageA extends StatelessWidget { | ||
124 | ``` | 128 | ``` |
125 | 129 | ||
126 | ### Data upload 数据上报 | 130 | ### Data upload 数据上报 |
127 | -数据上报需配合服务端使用,参考 [AutoTrack Server(开发中)](https://github.com/epoll-j/auto_track_server),可自行实现服务端。 | ||
128 | 131 | ||
129 | -数据上报的格式 | 132 | +#### 配置host并启用数据上报后会定时上报数据 |
133 | + | ||
134 | +##### 数据上报的格式 | ||
130 | ``` | 135 | ``` |
131 | { | 136 | { |
132 | 'app_key': config.appKey ?? '', | 137 | 'app_key': config.appKey ?? '', |
@@ -3,7 +3,6 @@ import 'package:auto_track_example/home.dart'; | @@ -3,7 +3,6 @@ import 'package:auto_track_example/home.dart'; | ||
3 | import 'package:auto_track_example/page_a.dart'; | 3 | import 'package:auto_track_example/page_a.dart'; |
4 | import 'package:flutter/material.dart'; | 4 | import 'package:flutter/material.dart'; |
5 | 5 | ||
6 | - | ||
7 | void main() { | 6 | void main() { |
8 | runApp(const MyApp()); | 7 | runApp(const MyApp()); |
9 | } | 8 | } |
@@ -20,11 +19,14 @@ class _MyAppState extends State<MyApp> { | @@ -20,11 +19,14 @@ class _MyAppState extends State<MyApp> { | ||
20 | void initState() { | 19 | void initState() { |
21 | AutoTrack() | 20 | AutoTrack() |
22 | .config(AutoTrackConfig( | 21 | .config(AutoTrackConfig( |
23 | - pageConfigs: [ | ||
24 | - AutoTrackPageConfig<PageA>( | ||
25 | - pageID: 'page_a', | ||
26 | - ), | ||
27 | - ])) | 22 | + eventHandler: (model) => { |
23 | + print('event handler ${model.type}') | ||
24 | + }, | ||
25 | + pageConfigs: [ | ||
26 | + AutoTrackPageConfig<PageA>( | ||
27 | + pageID: 'page_a', | ||
28 | + ), | ||
29 | + ])) | ||
28 | .enable() | 30 | .enable() |
29 | .enablePageLeave() | 31 | .enablePageLeave() |
30 | .enablePageView() | 32 | .enablePageView() |
1 | import 'dart:convert'; | 1 | import 'dart:convert'; |
2 | 2 | ||
3 | +import 'package:auto_track/auto_track/utils/track_model.dart'; | ||
3 | import 'package:crypto/crypto.dart'; | 4 | import 'package:crypto/crypto.dart'; |
4 | import 'package:flutter/widgets.dart'; | 5 | import 'package:flutter/widgets.dart'; |
5 | import 'package:uuid/uuid.dart'; | 6 | import 'package:uuid/uuid.dart'; |
6 | 7 | ||
8 | +typedef EventHandlerFunc = void Function(TrackModel); | ||
9 | + | ||
7 | class AutoTrackConfig { | 10 | class AutoTrackConfig { |
8 | AutoTrackConfig({ | 11 | AutoTrackConfig({ |
9 | - this.host, | ||
10 | - this.appKey = '', | 12 | + this.host, // 数据上报地址 |
13 | + this.uploadInterval, // 数据上报间隔 | ||
14 | + this.appKey = '', // 数据上报时根据key和secret生成签名 | ||
11 | this.appSecret = '', | 15 | this.appSecret = '', |
12 | - this.trackId, | ||
13 | - this.userId, | ||
14 | - this.signature, | 16 | + this.signature, // 签名生成方法,默认使用sha256对key、时间戳和secret进行签名 |
17 | + this.enableUpload = false, // 开启数据上报 | ||
18 | + this.trackId, // 埋点ID,默认使用UUID,每次启动时会变化 | ||
19 | + this.userId, // 用户ID | ||
15 | this.uniqueId, | 20 | this.uniqueId, |
21 | + this.eventHandler, // 事件处理 | ||
16 | this.pageConfigs = const [], | 22 | this.pageConfigs = const [], |
17 | - this.useCustomRoute = false, | ||
18 | - this.ignoreElementKeys = const [], | 23 | + this.useCustomRoute = false, // 使用自定义路由 |
24 | + this.ignoreElementKeys = const [], // 忽略key列表 | ||
19 | this.ignoreElementStringKeys = const [], | 25 | this.ignoreElementStringKeys = const [], |
20 | - this.enablePageView = true, | ||
21 | - this.enablePageLeave = false, | ||
22 | - this.enableClick = true, | ||
23 | - this.enableUpload = false, | ||
24 | - this.enableDrag = false, | ||
25 | - this.enableIgnoreNullKey = false, | ||
26 | - this.uploadInterval | 26 | + this.enablePageView = true, // 监听页面进入事件 |
27 | + this.enablePageLeave = false, // 监听页面离开事件 | ||
28 | + this.enableClick = true, // 监听点击事件 | ||
29 | + this.enableDrag = false, // 监听拖拽事件 | ||
30 | + this.enableIgnoreNullKey = false, // 忽略空key事件 | ||
27 | }) { | 31 | }) { |
28 | trackId ??= const Uuid().v4().replaceAll('-', ''); | 32 | trackId ??= const Uuid().v4().replaceAll('-', ''); |
29 | signature ??= (t) => sha256.convert(utf8.encode('$appKey$t$appSecret')).toString(); | 33 | signature ??= (t) => sha256.convert(utf8.encode('$appKey$t$appSecret')).toString(); |
@@ -39,6 +43,7 @@ class AutoTrackConfig { | @@ -39,6 +43,7 @@ class AutoTrackConfig { | ||
39 | int? uploadInterval; | 43 | int? uploadInterval; |
40 | 44 | ||
41 | Function? signature; | 45 | Function? signature; |
46 | + EventHandlerFunc? eventHandler; | ||
42 | 47 | ||
43 | List<AutoTrackPageConfig> pageConfigs; | 48 | List<AutoTrackPageConfig> pageConfigs; |
44 | 49 | ||
@@ -87,6 +92,4 @@ class AutoTrackPageConfig<T extends Widget> { | @@ -87,6 +92,4 @@ class AutoTrackPageConfig<T extends Widget> { | ||
87 | bool ignore; | 92 | bool ignore; |
88 | String? pageTitle; | 93 | String? pageTitle; |
89 | PageWidgetFunc? isPageWidget; | 94 | PageWidgetFunc? isPageWidget; |
90 | - | ||
91 | -// bool isPageWidget(Widget pageWidget) => pageWidget is T; | ||
92 | } | 95 | } |
@@ -111,22 +111,32 @@ class Track { | @@ -111,22 +111,32 @@ class Track { | ||
111 | class _TrackPlugin { | 111 | class _TrackPlugin { |
112 | 112 | ||
113 | static void pageView(Map<String, dynamic> params) { | 113 | static void pageView(Map<String, dynamic> params) { |
114 | - AutoTrackQueue.instance.appendQueue(TrackModel('page_view', DateTime.now().millisecondsSinceEpoch, params, params['page_manual_key'])); | 114 | + var model = TrackModel('page_view', DateTime.now().millisecondsSinceEpoch, params, params['page_manual_key']); |
115 | + AutoTrackConfigManager.instance.config.eventHandler?.call(model); | ||
116 | + AutoTrackQueue.instance.appendQueue(model); | ||
115 | } | 117 | } |
116 | 118 | ||
117 | static void pageLeave(Map<String, dynamic> params) { | 119 | static void pageLeave(Map<String, dynamic> params) { |
118 | - AutoTrackQueue.instance.appendQueue(TrackModel('page_leave', DateTime.now().millisecondsSinceEpoch, params, params['page_manual_key'])); | 120 | + var model = TrackModel('page_leave', DateTime.now().millisecondsSinceEpoch, params, params['page_manual_key']); |
121 | + AutoTrackConfigManager.instance.config.eventHandler?.call(model); | ||
122 | + AutoTrackQueue.instance.appendQueue(model); | ||
119 | } | 123 | } |
120 | 124 | ||
121 | static void click(Map<String, dynamic> params) { | 125 | static void click(Map<String, dynamic> params) { |
122 | - AutoTrackQueue.instance.appendQueue(TrackModel('click', DateTime.now().millisecondsSinceEpoch, params, params['element_manual_key'])); | 126 | + var model = TrackModel('click', DateTime.now().millisecondsSinceEpoch, params, params['element_manual_key']); |
127 | + AutoTrackConfigManager.instance.config.eventHandler?.call(model); | ||
128 | + AutoTrackQueue.instance.appendQueue(model); | ||
123 | } | 129 | } |
124 | 130 | ||
125 | static void customEvent(String type, Map<String, dynamic> params) { | 131 | static void customEvent(String type, Map<String, dynamic> params) { |
126 | - AutoTrackQueue.instance.appendQueue(TrackModel(type, DateTime.now().millisecondsSinceEpoch, params, params['key'] ?? type)); | 132 | + var model = TrackModel(type, DateTime.now().millisecondsSinceEpoch, params, params['key'] ?? type); |
133 | + AutoTrackConfigManager.instance.config.eventHandler?.call(model); | ||
134 | + AutoTrackQueue.instance.appendQueue(model); | ||
127 | } | 135 | } |
128 | 136 | ||
129 | static void drag(Map<String, dynamic> params) { | 137 | static void drag(Map<String, dynamic> params) { |
130 | - AutoTrackQueue.instance.appendQueue(TrackModel('drag', DateTime.now().millisecondsSinceEpoch, params, params['manual_key'])); | 138 | + var model = TrackModel('drag', DateTime.now().millisecondsSinceEpoch, params, params['manual_key']); |
139 | + AutoTrackConfigManager.instance.config.eventHandler?.call(model); | ||
140 | + AutoTrackQueue.instance.appendQueue(model); | ||
131 | } | 141 | } |
132 | } | 142 | } |
-
Please register or login to post a comment