|
@@ -1,253 +1,669 @@
|
|
-### utm-params-extractor-test
|
|
|
|
|
|
+# utm-params-extractor-test
|
|
|
|
|
|
-#### 使用示例
|
|
|
|
|
|
+一个功能强大的 UTM 参数提取和浏览器指纹生成库,支持自动上报、跨环境指纹一致性、多种使用方式。
|
|
|
|
+
|
|
|
|
+## ✨ 主要特性
|
|
|
|
+
|
|
|
|
+- 🔍 **UTM 参数自动提取** - 支持 utm_source、utm_medium、utm_campaign、utm_term、utm_content
|
|
|
|
+- 🌐 **浏览器信息识别** - 自动识别浏览器类型、操作系统、设备类型
|
|
|
|
+- 🎯 **唯一指纹生成** - 基于设备特征生成稳定的浏览器指纹
|
|
|
|
+- 📊 **自动上报功能** - 支持自动/手动数据上报到后端
|
|
|
|
+- 🔄 **跨环境一致性** - 同一设备在不同项目环境下生成相同指纹
|
|
|
|
+- 📱 **多端支持** - 支持 PC、移动端、各种浏览器环境
|
|
|
|
+- 🛠 **灵活配置** - 支持多种使用方式和自定义配置
|
|
|
|
+- 📦 **多模块支持** - 支持 ES6、CommonJS、UMD 等多种模块规范
|
|
|
|
|
|
-##### 1. 安装包
|
|
|
|
|
|
+## 📦 安装
|
|
|
|
|
|
```bash
|
|
```bash
|
|
|
|
+# 安装主包
|
|
npm install utm-params-extractor-test
|
|
npm install utm-params-extractor-test
|
|
|
|
+
|
|
|
|
+# 安装依赖(FingerprintJS)
|
|
|
|
+npm install @fingerprintjs/fingerprintjs
|
|
```
|
|
```
|
|
|
|
|
|
-##### 2. 在项目中使用
|
|
|
|
|
|
+## 🚀 快速开始
|
|
|
|
+
|
|
|
|
+### 基础用法
|
|
|
|
|
|
```javascript
|
|
```javascript
|
|
-// ES6 模块
|
|
|
|
import UtmTracker from 'utm-params-extractor-test';
|
|
import UtmTracker from 'utm-params-extractor-test';
|
|
|
|
|
|
-// 方法1:使用静态方法直接获取
|
|
|
|
-const utmParams = UtmTracker.get();
|
|
|
|
-console.log('UTM参数:', utmParams);
|
|
|
|
|
|
+// 创建实例
|
|
|
|
+const tracker = new UtmTracker({
|
|
|
|
+ reportUrl: 'https://your-api.com/collect',
|
|
|
|
+ autoSend: false
|
|
|
|
+});
|
|
|
|
|
|
-// 方法2:实例化后获取(适合扩展)
|
|
|
|
-const tracker = new UtmTracker();
|
|
|
|
|
|
+// 获取参数
|
|
const params = tracker.getParams();
|
|
const params = tracker.getParams();
|
|
|
|
+console.log('UTM参数:', params);
|
|
|
|
|
|
-// 自行处理数据(例如发送到后端)
|
|
|
|
-fetch('https://your-api.com/track', {
|
|
|
|
- method: 'POST',
|
|
|
|
- headers: {
|
|
|
|
- 'Content-Type': 'application/json'
|
|
|
|
- },
|
|
|
|
- body: JSON.stringify(params)
|
|
|
|
-})
|
|
|
|
-.then(response => response.json())
|
|
|
|
-.then(data => console.log('发送成功:', data))
|
|
|
|
-.catch(error => console.error('发送失败:', error));
|
|
|
|
|
|
+// 手动上报
|
|
|
|
+tracker.send();
|
|
```
|
|
```
|
|
|
|
|
|
-##### 3. 在 HTML 中直接使用
|
|
|
|
|
|
+### 自动上报
|
|
|
|
|
|
-```html
|
|
|
|
-<script src="dist/main.js"></script>
|
|
|
|
-<script>
|
|
|
|
- // 你的库会挂载在 window.UtmTracker
|
|
|
|
- var utmParams = window.UtmTracker.get();
|
|
|
|
- console.log('UTM参数:', utmParams);
|
|
|
|
-</script>
|
|
|
|
|
|
+```javascript
|
|
|
|
+// 实例化时自动上报
|
|
|
|
+new UtmTracker({
|
|
|
|
+ reportUrl: 'https://your-api.com/collect',
|
|
|
|
+ autoSend: true
|
|
|
|
+});
|
|
```
|
|
```
|
|
|
|
|
|
-> **注意:**
|
|
|
|
-> - HTML 直接引用时,npm 包名(如 utm-params-extractor-test)与全局变量名无关。
|
|
|
|
-> - 全局变量名由 webpack.config.js 的 `library.name` 决定,默认是 `UtmTracker`。
|
|
|
|
-> - 如需自定义全局变量名,请在 webpack.config.js 中修改:
|
|
|
|
-> ```js
|
|
|
|
-> output: {
|
|
|
|
-> // ...
|
|
|
|
-> library: {
|
|
|
|
-> name: 'UtmTracker', // 你想要的全局变量名
|
|
|
|
-> type: 'umd',
|
|
|
|
-> },
|
|
|
|
-> globalObject: 'this',
|
|
|
|
-> }
|
|
|
|
-> ```
|
|
|
|
-> 这样 HTML 里就可以直接用 `window.UtmTracker.get()`。
|
|
|
|
- ---
|
|
|
|
-
|
|
|
|
-## 使用示例
|
|
|
|
|
|
+### 静态方法
|
|
|
|
|
|
-### 自动上报
|
|
|
|
-```js
|
|
|
|
-new UtmTracker({
|
|
|
|
- reportUrl: 'https://your-server.com/collect',
|
|
|
|
|
|
+```javascript
|
|
|
|
+// 快速获取参数
|
|
|
|
+const params = await UtmTracker.get({
|
|
|
|
+ reportUrl: 'https://your-api.com/collect',
|
|
autoSend: true
|
|
autoSend: true
|
|
});
|
|
});
|
|
```
|
|
```
|
|
|
|
|
|
-### 手动上报
|
|
|
|
-```js
|
|
|
|
-const tracker = new UtmTracker({ reportUrl: 'https://your-server.com/collect' });
|
|
|
|
|
|
+## 📋 API 文档
|
|
|
|
+
|
|
|
|
+### UtmTracker 构造函数
|
|
|
|
+
|
|
|
|
+```javascript
|
|
|
|
+new UtmTracker(config)
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+#### 配置参数 (config)
|
|
|
|
+
|
|
|
|
+| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
|
|
+|------|------|------|--------|------|
|
|
|
|
+| `reportUrl` | string | ✅ | `''` | 数据上报的接口地址 |
|
|
|
|
+| `autoSend` | boolean | ❌ | `true` | 是否在实例化时自动上报 |
|
|
|
|
+| `method` | string | ❌ | `'POST'` | 请求方法,支持 'POST' 或 'GET' |
|
|
|
|
+| `headers` | object | ❌ | `{ 'Content-Type': 'application/json' }` | 请求头设置 |
|
|
|
|
+| `extra` | object | ❌ | `{}` | 额外的自定义参数 |
|
|
|
|
+| `onParams` | function | ❌ | `null` | 获取参数后的回调函数 |
|
|
|
|
+| `onSend` | function | ❌ | `null` | 发送成功后的回调函数 |
|
|
|
|
+| `onError` | function | ❌ | `null` | 发送失败后的回调函数 |
|
|
|
|
+
|
|
|
|
+### 实例方法
|
|
|
|
+
|
|
|
|
+#### `getParams()` - 同步获取参数
|
|
|
|
+
|
|
|
|
+```javascript
|
|
const params = tracker.getParams();
|
|
const params = tracker.getParams();
|
|
-tracker.send(params);
|
|
|
|
```
|
|
```
|
|
|
|
|
|
-### 静态用法
|
|
|
|
-```js
|
|
|
|
-UtmTracker.get({
|
|
|
|
- reportUrl: 'https://your-server.com/collect',
|
|
|
|
|
|
+返回当前页面的 UTM 参数和浏览器信息(不包含指纹)。
|
|
|
|
+
|
|
|
|
+#### `getParamsAsync()` - 异步获取参数(含指纹)
|
|
|
|
+
|
|
|
|
+```javascript
|
|
|
|
+const params = await tracker.getParamsAsync();
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+返回包含浏览器指纹的完整参数对象。
|
|
|
|
+
|
|
|
|
+#### `send(data)` - 发送数据
|
|
|
|
+
|
|
|
|
+```javascript
|
|
|
|
+// 发送默认参数
|
|
|
|
+tracker.send();
|
|
|
|
+
|
|
|
|
+// 发送自定义数据
|
|
|
|
+tracker.send(customData);
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+### 静态方法
|
|
|
|
+
|
|
|
|
+#### `UtmTracker.get(config)` - 快速获取参数
|
|
|
|
+
|
|
|
|
+```javascript
|
|
|
|
+const params = await UtmTracker.get({
|
|
|
|
+ reportUrl: 'https://your-api.com/collect',
|
|
autoSend: true
|
|
autoSend: true
|
|
});
|
|
});
|
|
```
|
|
```
|
|
|
|
|
|
-### 返回参数说明
|
|
|
|
-
|
|
|
|
-`UtmTracker.get()` 或 `tracker.getParams()` 返回对象结构如下:
|
|
|
|
-
|
|
|
|
-| 字段 | 类型 | 说明 |
|
|
|
|
-| ------------ | ------- | -------------------------------------------------------------------- |
|
|
|
|
-| utm_source | string | UTM 来源渠道参数(如广告平台、搜索引擎等) |
|
|
|
|
-| utm_medium | string | UTM 媒介参数(如 cpc、email、banner 等) |
|
|
|
|
-| utm_campaign | string | UTM 活动名称参数 |
|
|
|
|
-| utm_term | string | UTM 关键词参数 |
|
|
|
|
-| utm_content | string | UTM 内容参数(用于区分广告内容) |
|
|
|
|
-| referrer | string | 上一个页面的 URL |
|
|
|
|
-| browser | object | 浏览器和设备信息对象(见下表) |
|
|
|
|
-| timestamp | string | 获取参数的时间戳(ISO 格式) |
|
|
|
|
-| url | string | 当前页面完整 URL |
|
|
|
|
-
|
|
|
|
-#### browser 字段结构
|
|
|
|
-
|
|
|
|
-| 字段 | 类型 | 说明 |
|
|
|
|
-| ---------- | ------- | ------------------------------------------------------------ |
|
|
|
|
-| isMobile | boolean | 是否为移动端设备 |
|
|
|
|
-| browser | string | 浏览器类型(如 Chrome、Safari、Edge、WeChat、HuaweiBrowser 等)|
|
|
|
|
-| userAgent | string | 浏览器的 User-Agent 字符串 |
|
|
|
|
-| osType | string | 操作系统类型(iOS、Android、HarmonyOS、Unknown) |
|
|
|
|
-| osVersion | string | 操作系统版本号(如 16.6、13.0、3.0.0、Unknown) |
|
|
|
|
-
|
|
|
|
-##### browser.browser 可能的值
|
|
|
|
-- Chrome
|
|
|
|
-- Safari
|
|
|
|
-- Edge
|
|
|
|
-- Firefox
|
|
|
|
-- IE
|
|
|
|
-- WeChat
|
|
|
|
-- QQBrowser
|
|
|
|
-- UCBrowser
|
|
|
|
-- HuaweiBrowser
|
|
|
|
-- Telegram
|
|
|
|
-- 其他
|
|
|
|
-
|
|
|
|
-##### browser.osType 可能的值
|
|
|
|
-- iOS
|
|
|
|
-- Android
|
|
|
|
-- HarmonyOS
|
|
|
|
-- Unknown
|
|
|
|
-
|
|
|
|
-##### 示例返回
|
|
|
|
-
|
|
|
|
-```json
|
|
|
|
|
|
+#### `UtmTracker.send(data, config)` - 快速发送数据
|
|
|
|
+
|
|
|
|
+```javascript
|
|
|
|
+await UtmTracker.send(customData, {
|
|
|
|
+ reportUrl: 'https://your-api.com/collect'
|
|
|
|
+});
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+## 📊 返回数据结构
|
|
|
|
+
|
|
|
|
+### 基础参数结构
|
|
|
|
+
|
|
|
|
+```javascript
|
|
{
|
|
{
|
|
- "utm_source": "google",
|
|
|
|
- "utm_medium": "cpc",
|
|
|
|
- "utm_campaign": "summer_sale",
|
|
|
|
- "utm_term": "shoes",
|
|
|
|
- "utm_content": "ad1",
|
|
|
|
- "referrer": "https://www.example.com/",
|
|
|
|
- "browser": {
|
|
|
|
- "isMobile": true,
|
|
|
|
- "browser": "Chrome",
|
|
|
|
- "userAgent": "Mozilla/5.0 (Linux; Android 13; ...)",
|
|
|
|
- "osType": "Android",
|
|
|
|
- "osVersion": "13"
|
|
|
|
|
|
+ // UTM 参数
|
|
|
|
+ utmSource: "google", // UTM 来源
|
|
|
|
+ utmMedium: "cpc", // UTM 媒介
|
|
|
|
+ utmCampaign: "summer_sale", // UTM 活动
|
|
|
|
+ utmTerm: "shoes", // UTM 关键词
|
|
|
|
+ utmContent: "ad1", // UTM 内容
|
|
|
|
+
|
|
|
|
+ // 页面信息
|
|
|
|
+ referrer: "https://www.google.com/", // 来源页面
|
|
|
|
+ url: "https://yoursite.com/?utm_source=google", // 当前页面
|
|
|
|
+ domain: "yoursite.com", // 当前域名
|
|
|
|
+ timestamp: "2024-01-01T12:00:00.000Z", // 时间戳
|
|
|
|
+
|
|
|
|
+ // 设备信息
|
|
|
|
+ isMobile: true, // 是否移动端
|
|
|
|
+ browser: "Chrome", // 浏览器类型
|
|
|
|
+ browserVersion: "120.0.0.0", // 浏览器版本号
|
|
|
|
+ userAgent: "Mozilla/5.0...", // 用户代理
|
|
|
|
+ osType: "Android", // 操作系统类型
|
|
|
|
+ osVersion: "13", // 操作系统版本
|
|
|
|
+
|
|
|
|
+ // 指纹信息
|
|
|
|
+ fingerprint: "stable_fp_1a2b3c4d5e" // 浏览器唯一指纹
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+### 浏览器类型支持
|
|
|
|
+
|
|
|
|
+| 浏览器 | 识别标识 |
|
|
|
|
+|--------|----------|
|
|
|
|
+| Chrome | `Chrome` |
|
|
|
|
+| Safari | `Safari` |
|
|
|
|
+| Firefox | `Firefox` |
|
|
|
|
+| Edge | `Edge` |
|
|
|
|
+| IE | `IE` |
|
|
|
|
+| 微信 | `WeChat` |
|
|
|
|
+| QQ浏览器 | `QQBrowser` |
|
|
|
|
+| UC浏览器 | `UCBrowser` |
|
|
|
|
+| 华为浏览器 | `HuaweiBrowser` |
|
|
|
|
+| Telegram | `Telegram` |
|
|
|
|
+
|
|
|
|
+### 操作系统支持
|
|
|
|
+
|
|
|
|
+| 系统 | 识别标识 | 版本获取 |
|
|
|
|
+|------|----------|----------|
|
|
|
|
+| iOS | `iOS` | ✅ |
|
|
|
|
+| Android | `Android` | ✅ |
|
|
|
|
+| HarmonyOS | `HarmonyOS` | ✅ |
|
|
|
|
+| 其他 | `Unknown` | ❌ |
|
|
|
|
+
|
|
|
|
+## 🔧 使用示例
|
|
|
|
+
|
|
|
|
+### Vue.js 项目
|
|
|
|
+
|
|
|
|
+```vue
|
|
|
|
+<template>
|
|
|
|
+ <div>
|
|
|
|
+ <h1>UTM 参数追踪</h1>
|
|
|
|
+ <button @click="sendData">发送数据</button>
|
|
|
|
+ <pre>{{ utmParams }}</pre>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script>
|
|
|
|
+import UtmTracker from 'utm-params-extractor-test';
|
|
|
|
+
|
|
|
|
+export default {
|
|
|
|
+ data() {
|
|
|
|
+ return {
|
|
|
|
+ tracker: null,
|
|
|
|
+ utmParams: null
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+ async mounted() {
|
|
|
|
+ this.tracker = new UtmTracker({
|
|
|
|
+ reportUrl: 'https://your-api.com/collect',
|
|
|
|
+ autoSend: false,
|
|
|
|
+ onSend: (response, params) => {
|
|
|
|
+ console.log('数据发送成功:', response);
|
|
|
|
+ },
|
|
|
|
+ onError: (error, params) => {
|
|
|
|
+ console.error('数据发送失败:', error);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 获取包含指纹的完整参数
|
|
|
|
+ try {
|
|
|
|
+ this.utmParams = await this.tracker.getParamsAsync();
|
|
|
|
+ console.log('参数获取成功:', this.utmParams);
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('参数获取失败:', error);
|
|
|
|
+ // 如果异步获取失败,使用同步方法
|
|
|
|
+ this.utmParams = this.tracker.getParams();
|
|
|
|
+ }
|
|
},
|
|
},
|
|
- "timestamp": "2024-07-01T12:00:00.000Z",
|
|
|
|
- "url": "https://your-site.com/?utm_source=google&utm_medium=cpc"
|
|
|
|
|
|
+ methods: {
|
|
|
|
+ async sendData() {
|
|
|
|
+ if (this.tracker) {
|
|
|
|
+ await this.tracker.send();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+</script>
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+### React 项目
|
|
|
|
+
|
|
|
|
+#### 安装依赖
|
|
|
|
+```bash
|
|
|
|
+npm install utm-params-extractor-test @fingerprintjs/fingerprintjs
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+#### 使用示例
|
|
|
|
+```jsx
|
|
|
|
+import React, { useEffect, useState } from 'react';
|
|
|
|
+
|
|
|
|
+// 方式1:标准导入(推荐)
|
|
|
|
+import UtmTracker from 'utm-params-extractor-test';
|
|
|
|
+
|
|
|
|
+// 方式2:如果标准导入失败,使用 require
|
|
|
|
+// const UtmTracker = require('utm-params-extractor-test');
|
|
|
|
+
|
|
|
|
+// 方式3:如果使用 CDN 或全局引入
|
|
|
|
+// const UtmTracker = window.UtmTracker;
|
|
|
|
+
|
|
|
|
+function App() {
|
|
|
|
+ const [utmParams, setUtmParams] = useState(null);
|
|
|
|
+ const [tracker, setTracker] = useState(null);
|
|
|
|
+ const [loading, setLoading] = useState(true);
|
|
|
|
+
|
|
|
|
+ useEffect(() => {
|
|
|
|
+ const initTracker = async () => {
|
|
|
|
+ const utmTracker = new UtmTracker({
|
|
|
|
+ reportUrl: 'https://your-api.com/collect',
|
|
|
|
+ autoSend: false,
|
|
|
|
+ onSend: (response, params) => {
|
|
|
|
+ console.log('数据发送成功:', response);
|
|
|
|
+ },
|
|
|
|
+ onError: (error, params) => {
|
|
|
|
+ console.error('数据发送失败:', error);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ setTracker(utmTracker);
|
|
|
|
+
|
|
|
|
+ // 获取包含指纹的完整参数
|
|
|
|
+ try {
|
|
|
|
+ const params = await utmTracker.getParamsAsync();
|
|
|
|
+ setUtmParams(params);
|
|
|
|
+ console.log('参数获取成功:', params);
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('参数获取失败:', error);
|
|
|
|
+ // 如果异步获取失败,使用同步方法
|
|
|
|
+ const syncParams = utmTracker.getParams();
|
|
|
|
+ setUtmParams(syncParams);
|
|
|
|
+ } finally {
|
|
|
|
+ setLoading(false);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ initTracker();
|
|
|
|
+ }, []);
|
|
|
|
+
|
|
|
|
+ const handleSend = async () => {
|
|
|
|
+ if (tracker) {
|
|
|
|
+ try {
|
|
|
|
+ await tracker.send();
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('发送失败:', error);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ if (loading) {
|
|
|
|
+ return <div>加载中...</div>;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return (
|
|
|
|
+ <div>
|
|
|
|
+ <h1>UTM 参数追踪</h1>
|
|
|
|
+ <button onClick={handleSend}>发送数据</button>
|
|
|
|
+ <pre>{JSON.stringify(utmParams, null, 2)}</pre>
|
|
|
|
+ </div>
|
|
|
|
+ );
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+export default App;
|
|
```
|
|
```
|
|
|
|
|
|
-## 跳转倒计时弹窗使用示例
|
|
|
|
|
|
+#### 常见问题解决
|
|
|
|
|
|
-当后端返回 { downloadUrl, type } 时,自动弹出3秒倒计时弹窗,倒计时结束后自动跳转到 downloadUrl。
|
|
|
|
|
|
+**问题1:`UtmTracker is not defined` 或 `is not a constructor` 错误**
|
|
|
|
|
|
-```js
|
|
|
|
-new UtmTracker({
|
|
|
|
- reportUrl: 'https://your-server.com/collect',
|
|
|
|
- autoSend: true,
|
|
|
|
- // 只需后端返回 { downloadUrl: '...', type: 'video'|'audio'|'image' },无需额外配置
|
|
|
|
|
|
+如果遇到这些错误,请尝试以下解决方案:
|
|
|
|
+
|
|
|
|
+```jsx
|
|
|
|
+// 方案1:标准导入(推荐)
|
|
|
|
+import UtmTracker from 'utm-params-extractor-test';
|
|
|
|
+
|
|
|
|
+// 方案2:如果标准导入失败,使用 require
|
|
|
|
+const UtmTracker = require('utm-params-extractor-test');
|
|
|
|
+
|
|
|
|
+// 方案3:如果使用 CDN 或全局引入
|
|
|
|
+const UtmTracker = window.UtmTracker;
|
|
|
|
+
|
|
|
|
+// 方案4:动态导入
|
|
|
|
+import('utm-params-extractor-test').then(module => {
|
|
|
|
+ const UtmTracker = module.default || module;
|
|
|
|
+ // 使用 UtmTracker
|
|
});
|
|
});
|
|
|
|
+
|
|
|
|
+// 方案5:检查导入的模块
|
|
|
|
+console.log('UtmTracker:', UtmTracker);
|
|
|
|
+console.log('typeof UtmTracker:', typeof UtmTracker);
|
|
```
|
|
```
|
|
|
|
|
|
-// 后端返回示例:
|
|
|
|
-// {
|
|
|
|
-// downloadUrl: 'https://your-server.com/file.mp4',
|
|
|
|
-// type: 'video'
|
|
|
|
-// }
|
|
|
|
|
|
+**问题2:FingerprintJS 依赖问题**
|
|
|
|
+
|
|
|
|
+确保安装了 FingerprintJS 依赖:
|
|
|
|
+```bash
|
|
|
|
+npm install @fingerprintjs/fingerprintjs
|
|
|
|
+```
|
|
|
|
|
|
-// 前端会自动弹出“即将跳转,3秒...”的弹窗,3秒后自动跳转到 downloadUrl。
|
|
|
|
|
|
+**问题3:ESLint 配置**
|
|
|
|
|
|
----
|
|
|
|
|
|
+如果 ESLint 报错,可以在 `.eslintrc.js` 中添加:
|
|
|
|
+```javascript
|
|
|
|
+module.exports = {
|
|
|
|
+ globals: {
|
|
|
|
+ UtmTracker: 'readonly'
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+```
|
|
|
|
|
|
-如需更多帮助或定制返回内容,请联系作者。
|
|
|
|
|
|
+**问题4:调试导入问题**
|
|
|
|
|
|
-## 配置项说明(config 参数)
|
|
|
|
|
|
+如果遇到导入问题,可以添加以下调试代码:
|
|
|
|
|
|
-| 配置项 | 类型 | 说明 | 是否必填 | 默认值 |
|
|
|
|
-|-------------|----------|--------------------------------------------------------------|----------|-----------------------------|
|
|
|
|
-| reportUrl | string | 上报数据的接口地址 | 是 | '' |
|
|
|
|
-| autoSend | boolean | 是否在实例化时自动上报一次 | 否 | true |
|
|
|
|
-| method | string | 请求方式,支持 'POST' 或 'GET' | 否 | 'POST' |
|
|
|
|
-| headers | object | 请求头设置 | 否 | { 'Content-Type': 'application/json' } |
|
|
|
|
-| extra | object | 额外自定义参数,会合并进最终上报数据 | 否 | {} |
|
|
|
|
-| onParams | function | 获取参数后回调,参数为 params | 否 | null |
|
|
|
|
-| onSend | function | 发送成功回调,参数为 (response, params) | 否 | null |
|
|
|
|
-| onError | function | 发送失败回调,参数为 (error, params) | 否 | null |
|
|
|
|
|
|
+```jsx
|
|
|
|
+// 在组件顶部添加调试代码
|
|
|
|
+console.log('=== 调试信息 ===');
|
|
|
|
+console.log('window.UtmTracker:', window.UtmTracker);
|
|
|
|
+console.log('typeof window.UtmTracker:', typeof window.UtmTracker);
|
|
|
|
|
|
-### 示例
|
|
|
|
|
|
+// 尝试不同的导入方式
|
|
|
|
+try {
|
|
|
|
+ const module = require('utm-params-extractor-test');
|
|
|
|
+ console.log('require result:', module);
|
|
|
|
+ console.log('module.default:', module.default);
|
|
|
|
+} catch (e) {
|
|
|
|
+ console.log('require failed:', e);
|
|
|
|
+}
|
|
|
|
|
|
-```js
|
|
|
|
-import UtmTracker from 'utm-params-extractor-test';
|
|
|
|
|
|
+try {
|
|
|
|
+ import('utm-params-extractor-test').then(module => {
|
|
|
|
+ console.log('dynamic import result:', module);
|
|
|
|
+ console.log('module.default:', module.default);
|
|
|
|
+ });
|
|
|
|
+} catch (e) {
|
|
|
|
+ console.log('dynamic import failed:', e);
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+### 普通 JavaScript
|
|
|
|
+
|
|
|
|
+```html
|
|
|
|
+<!DOCTYPE html>
|
|
|
|
+<html>
|
|
|
|
+<head>
|
|
|
|
+ <title>UTM 参数追踪</title>
|
|
|
|
+</head>
|
|
|
|
+<body>
|
|
|
|
+ <h1>UTM 参数追踪</h1>
|
|
|
|
+ <button onclick="sendData()">发送数据</button>
|
|
|
|
+ <pre id="params"></pre>
|
|
|
|
+
|
|
|
|
+ <script src="https://openfpcdn.io/fingerprintjs/v4"></script>
|
|
|
|
+ <script src="dist/main.js"></script>
|
|
|
|
+ <script>
|
|
|
|
+ let tracker = null;
|
|
|
|
+
|
|
|
|
+ // 页面加载完成后初始化
|
|
|
|
+ document.addEventListener('DOMContentLoaded', async function() {
|
|
|
|
+ tracker = new window.UtmTracker({
|
|
|
|
+ reportUrl: 'https://your-api.com/collect',
|
|
|
|
+ autoSend: false,
|
|
|
|
+ onSend: function(response, params) {
|
|
|
|
+ console.log('数据发送成功:', response);
|
|
|
|
+ alert('数据发送成功!');
|
|
|
|
+ },
|
|
|
|
+ onError: function(error, params) {
|
|
|
|
+ console.error('数据发送失败:', error);
|
|
|
|
+ alert('数据发送失败!');
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 获取包含指纹的完整参数
|
|
|
|
+ try {
|
|
|
|
+ const params = await tracker.getParamsAsync();
|
|
|
|
+ document.getElementById('params').textContent =
|
|
|
|
+ JSON.stringify(params, null, 2);
|
|
|
|
+ console.log('参数获取成功:', params);
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('参数获取失败:', error);
|
|
|
|
+ // 如果异步获取失败,使用同步方法
|
|
|
|
+ const syncParams = tracker.getParams();
|
|
|
|
+ document.getElementById('params').textContent =
|
|
|
|
+ JSON.stringify(syncParams, null, 2);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ async function sendData() {
|
|
|
|
+ if (tracker) {
|
|
|
|
+ await tracker.send();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ </script>
|
|
|
|
+</body>
|
|
|
|
+</html>
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+## 🎯 浏览器指纹说明
|
|
|
|
+
|
|
|
|
+### 指纹生成原理
|
|
|
|
+
|
|
|
|
+本库使用两种指纹生成方式:
|
|
|
|
+
|
|
|
|
+1. **FingerprintJS 方式**(默认)
|
|
|
|
+ - 使用 FingerprintJS 库生成
|
|
|
|
+ - 基于多种浏览器特征
|
|
|
|
+ - 更准确和稳定
|
|
|
|
+
|
|
|
|
+2. **自定义稳定指纹**
|
|
|
|
+ - 基于设备固定特征
|
|
|
|
+ - 确保跨环境一致性
|
|
|
|
+ - 包含屏幕信息、用户代理、时区等
|
|
|
|
+
|
|
|
|
+### 指纹特征
|
|
|
|
+
|
|
|
|
+指纹生成基于以下稳定特征:
|
|
|
|
+- 屏幕分辨率、颜色深度
|
|
|
|
+- 用户代理字符串(前50字符)
|
|
|
|
+- 时区信息
|
|
|
|
+- 语言设置
|
|
|
|
+- 平台信息
|
|
|
|
+- CPU核心数
|
|
|
|
+- 设备内存
|
|
|
|
+- Canvas指纹
|
|
|
|
+- WebGL渲染器信息
|
|
|
|
+
|
|
|
|
+### 指纹存储
|
|
|
|
+
|
|
|
|
+- 指纹生成后存储在 `localStorage` 中
|
|
|
|
+- 键名:`fingerprint_id`
|
|
|
|
+- 后续请求优先使用已存储的指纹
|
|
|
|
+- 清除 localStorage 后重新生成
|
|
|
|
+
|
|
|
|
+## 🔄 跨环境一致性
|
|
|
|
+
|
|
|
|
+### 问题背景
|
|
|
|
+
|
|
|
|
+在不同项目环境下,同一设备可能生成不同的指纹ID,影响用户追踪的准确性。
|
|
|
|
+
|
|
|
|
+### 解决方案
|
|
|
|
+
|
|
|
|
+本库通过以下方式确保跨环境一致性:
|
|
|
|
+
|
|
|
|
+1. **使用稳定的设备特征**
|
|
|
|
+ - 避免使用可能变化的特征
|
|
|
|
+ - 对长字符串进行截取,减少细微差异
|
|
|
|
+
|
|
|
|
+2. **统一的指纹算法**
|
|
|
|
+ - 相同的哈希算法
|
|
|
|
+ - 相同的特征组合方式
|
|
|
|
+
|
|
|
|
+3. **环境无关性**
|
|
|
|
+ - 不依赖域名、路径等环境相关特征
|
|
|
|
+ - 专注于设备本身的稳定特征
|
|
|
|
+
|
|
|
|
+### 测试验证
|
|
|
|
+
|
|
|
|
+```javascript
|
|
|
|
+// 在项目A中
|
|
|
|
+const trackerA = new UtmTracker({ reportUrl: 'http://localhost:3000/api' });
|
|
|
|
+const paramsA = await trackerA.getParamsAsync();
|
|
|
|
+console.log('项目A指纹:', paramsA.fingerprint);
|
|
|
|
+
|
|
|
|
+// 在项目B中(同一设备)
|
|
|
|
+const trackerB = new UtmTracker({ reportUrl: 'http://localhost:3001/api' });
|
|
|
|
+const paramsB = await trackerB.getParamsAsync();
|
|
|
|
+console.log('项目B指纹:', paramsB.fingerprint);
|
|
|
|
+
|
|
|
|
+// 两个指纹应该相同
|
|
|
|
+console.log('指纹一致:', paramsA.fingerprint === paramsB.fingerprint);
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+## 🛠 高级配置
|
|
|
|
+
|
|
|
|
+### 自定义请求头
|
|
|
|
+
|
|
|
|
+```javascript
|
|
|
|
+const tracker = new UtmTracker({
|
|
|
|
+ reportUrl: 'https://your-api.com/collect',
|
|
|
|
+ headers: {
|
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
|
+ 'Authorization': 'Bearer your-token',
|
|
|
|
+ 'X-Custom-Header': 'custom-value'
|
|
|
|
+ }
|
|
|
|
+});
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+### 添加额外参数
|
|
|
|
+
|
|
|
|
+```javascript
|
|
|
|
+const tracker = new UtmTracker({
|
|
|
|
+ reportUrl: 'https://your-api.com/collect',
|
|
|
|
+ extra: {
|
|
|
|
+ userId: '12345',
|
|
|
|
+ sessionId: 'abc123',
|
|
|
|
+ customField: 'customValue'
|
|
|
|
+ }
|
|
|
|
+});
|
|
|
|
+```
|
|
|
|
|
|
|
|
+### 自定义回调处理
|
|
|
|
+
|
|
|
|
+```javascript
|
|
const tracker = new UtmTracker({
|
|
const tracker = new UtmTracker({
|
|
- reportUrl: 'https://your-server.com/collect',
|
|
|
|
- autoSend: false,
|
|
|
|
- method: 'POST',
|
|
|
|
- headers: { 'Content-Type': 'application/json' },
|
|
|
|
- extra: { foo: 'bar' },
|
|
|
|
- onParams: params => console.log(params),
|
|
|
|
- onSend: (res, params) => console.log('sent', res, params),
|
|
|
|
- onError: (err, params) => console.error('error', err, params)
|
|
|
|
|
|
+ reportUrl: 'https://your-api.com/collect',
|
|
|
|
+ onParams: (params) => {
|
|
|
|
+ // 参数获取后的处理
|
|
|
|
+ console.log('获取到参数:', params);
|
|
|
|
+
|
|
|
|
+ // 可以修改参数
|
|
|
|
+ params.customField = 'modified';
|
|
|
|
+
|
|
|
|
+ // 可以存储到其他地方
|
|
|
|
+ localStorage.setItem('utm_params', JSON.stringify(params));
|
|
|
|
+ },
|
|
|
|
+ onSend: (response, params) => {
|
|
|
|
+ // 发送成功的处理
|
|
|
|
+ console.log('发送成功:', response);
|
|
|
|
+
|
|
|
|
+ // 可以触发其他操作
|
|
|
|
+ if (response.success) {
|
|
|
|
+ showSuccessMessage('数据上报成功');
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ onError: (error, params) => {
|
|
|
|
+ // 发送失败的处理
|
|
|
|
+ console.error('发送失败:', error);
|
|
|
|
+
|
|
|
|
+ // 可以重试或显示错误信息
|
|
|
|
+ showErrorMessage('数据上报失败,请重试');
|
|
|
|
+ }
|
|
});
|
|
});
|
|
```
|
|
```
|
|
|
|
|
|
-## 浏览器指纹(fingerprintId)说明
|
|
|
|
|
|
+## 🔧 构建和部署
|
|
|
|
|
|
-- `fingerprintId` 字段会自动添加到所有 UTM 参数和上报数据中。
|
|
|
|
-- 该字段用于唯一标识当前浏览器环境,便于后端做用户去重、分析等。
|
|
|
|
-- 指纹生成后会存储在本地 localStorage(key: fingerprint_id),后续请求会优先复用,确保唯一性和高效性。
|
|
|
|
-- **本包已自动集成 [FingerprintJS](https://github.com/fingerprintjs/fingerprintjs),无需单独安装或引入,无论 npm 还是浏览器全局都能直接用指纹功能。**
|
|
|
|
|
|
+### 开发环境
|
|
|
|
|
|
-### 示例
|
|
|
|
|
|
+```bash
|
|
|
|
+# 安装依赖
|
|
|
|
+npm install
|
|
|
|
|
|
-```js
|
|
|
|
-const tracker = new UtmTracker({ ... });
|
|
|
|
-const params = await tracker.getParamsAsync();
|
|
|
|
-console.log(params.fingerprintId); // 浏览器唯一指纹
|
|
|
|
|
|
+# 构建项目
|
|
|
|
+npm run build
|
|
|
|
+
|
|
|
|
+# 运行测试
|
|
|
|
+npm test
|
|
```
|
|
```
|
|
|
|
|
|
-## FingerprintJS 依赖说明
|
|
|
|
|
|
+### 生产环境
|
|
|
|
|
|
-本库自动适配两种场景:
|
|
|
|
|
|
+```bash
|
|
|
|
+# 构建生产版本
|
|
|
|
+npm run build
|
|
|
|
|
|
-### 1. npm/打包工具用户
|
|
|
|
-- 请在你的项目中安装依赖:
|
|
|
|
- ```bash
|
|
|
|
- npm install @fingerprintjs/fingerprintjs
|
|
|
|
- ```
|
|
|
|
-- 本库会自动 require 该依赖,无需手动引入。
|
|
|
|
-- 推荐在 package.json 中声明 peerDependencies:
|
|
|
|
- ```json
|
|
|
|
- "peerDependencies": {
|
|
|
|
- "@fingerprintjs/fingerprintjs": ">=4.0.0"
|
|
|
|
- }
|
|
|
|
- ```
|
|
|
|
|
|
+# 构建后的文件在 dist/ 目录
|
|
|
|
+# - main.js: 主文件
|
|
|
|
+# - main.js.map: 源码映射文件
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+### Webpack 配置
|
|
|
|
+
|
|
|
|
+```javascript
|
|
|
|
+// webpack.config.js
|
|
|
|
+module.exports = {
|
|
|
|
+ entry: './src/index.js',
|
|
|
|
+ output: {
|
|
|
|
+ filename: 'main.js',
|
|
|
|
+ path: path.resolve(__dirname, 'dist'),
|
|
|
|
+ library: {
|
|
|
|
+ name: 'UtmTracker',
|
|
|
|
+ type: 'umd',
|
|
|
|
+ },
|
|
|
|
+ globalObject: 'this',
|
|
|
|
+ },
|
|
|
|
+ // ... 其他配置
|
|
|
|
+};
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+## 🐛 常见问题
|
|
|
|
+
|
|
|
|
+### Q: 指纹ID在不同环境下不一致怎么办?
|
|
|
|
+
|
|
|
|
+**A:** 确保使用相同版本的库,并检查是否有环境特定的配置影响了指纹生成。
|
|
|
|
+
|
|
|
|
+### Q: 如何自定义指纹生成算法?
|
|
|
|
+
|
|
|
|
+**A:** 可以修改源码中的 `generateStableFingerprint()` 函数,或通过配置参数调整 FingerprintJS 的设置。
|
|
|
|
+
|
|
|
|
+### Q: 上报失败如何处理?
|
|
|
|
+
|
|
|
|
+**A:** 使用 `onError` 回调函数处理错误,可以实现重试机制或错误提示。
|
|
|
|
+
|
|
|
|
+### Q: 如何禁用指纹功能?
|
|
|
|
+
|
|
|
|
+**A:** 目前不支持完全禁用指纹功能,但可以通过配置调整指纹生成方式。
|
|
|
|
+
|
|
|
|
+### Q: 支持哪些浏览器?
|
|
|
|
+
|
|
|
|
+**A:** 支持所有现代浏览器,包括 Chrome、Firefox、Safari、Edge 等,以及移动端浏览器。
|
|
|
|
|
|
-### 2. 浏览器全局用户
|
|
|
|
-- 请在你的 HTML 中**先**引入 FingerprintJS,再引入本库:
|
|
|
|
- ```html
|
|
|
|
- <script src="https://openfpcdn.io/fingerprintjs/v4"></script>
|
|
|
|
- <script src="dist/your-utm-bundle.js"></script>
|
|
|
|
- ```
|
|
|
|
-- 本库会自动检测 window.FingerprintJS。
|
|
|
|
|
|
|
|
-如未正确引入依赖,指纹功能将无法使用,fingerprintId 字段会为空字符串。
|
|
|
|
|
|
+**注意:** 使用本库时请遵守相关法律法规和隐私政策,确保用户数据的安全和隐私保护。
|
|
|
|
|