本文介绍两种方式后端sdk上报埋点数据方法:java版本和nodejs版本。
一、Webfunny Event Java SDK
Webfunny 事件追踪 Java SDK,用于在 Java 应用中上报用户行为事件数据到 Webfunny 分析平台。
功能特性
- 异步批量上报,高性能低延迟
- 支持同步/异步两种上报模式
- 自动重试机制,确保数据不丢失
- 支持事件签名验证,保证数据安全
- 自动填充 IP、地理位置、时间等字段
- 支持自定义事件参数
环境要求
- Java 8 或更高版本
- Maven 3.6+ 或 Gradle
引入依赖
Maven
在 pom.xml 中添加依赖:
<dependency>
<groupId>com.webfunny</groupId>
<artifactId>webfunny-event-sdk</artifactId>
<version>1.0.0</version>
</dependency>
如果无法从 Maven Central 下载,需要添加阿里云私服仓库配置:
<repositories>
<repository>
<id>aliyun-maven</id>
<name>Aliyun Maven</name>
<url>https://packages.aliyun.com/maven/repository/22127846-release-7kTKfC/</url>
</repository>
</repositories>
Gradle
在 build.gradle 中添加依赖:
dependencies {
implementation 'com.webfunny:webfunny-event-sdk:1.0.0'
}
添加仓库配置:
repositories {
maven {
url 'https://packages.aliyun.com/maven/repository/22127846-release-7kTKfC/'
}
mavenCentral()
}
快速开始
1. 初始化客户端
yml文件配置:
webfunny:
event-url: https://xxx.webfunny.cn #上报域名
project-id: event_20250312_153829902 #项目id
up-now: false # false-延迟批量上报(默认),true-立即上报
batch-size: 1000 # 每批上报事件数(默认1000)
import com.webfunny.event.WebfunnyEventClient;
import com.webfunny.event.WebfunnyEventConfig;
// 方式一:使用配置对象
WebfunnyEventConfig config = new WebfunnyEventConfig();
config.setServerUrl("https://your-webfunny-server.com");
config.setProjectId("your-project-id");
config.setEventSecret("your-event-secret"); // 可选,用于签名验证
config.setUpNow(false);//延迟上报(默认)
config.setDebug(true); // 开启调试日志
WebfunnyEventClient client = new WebfunnyEventClient(config);
// 方式二:使用 Builder 模式(推荐)
WebfunnyEventClient client = WebfunnyEventClient.builder()
.serverUrl("https://your-webfunny-server.com")
.projectId("your-project-id")
.eventSecret("your-event-secret")
.debug(true)
.batchSize(1000) // 每批上报事件数
.flushIntervalMs(5000) // 自动刷新间隔(毫秒)
.build();
2. 上报事件
带参数上报
import java.util.HashMap;
import java.util.Map;
Map<String, Object> params = new HashMap<>();
params.put("buttonName", "立即购买");
params.put("productId", "SKU123456");
params.put("price", 99.99);
client.track("15", params);
完整事件对象上报
import com.webfunny.event.WebfunnyEvent;
WebfunnyEvent event = new WebfunnyEvent();
event.setPointId("12");
event.setWeUserId("user_12345"); // 用户ID
event.setWeCustomerKey("customer_key"); // 客户标识
event.setWePath("/login/page"); // 页面路径
event.addParam("loginType", "wechat"); // 自定义参数
event.addParam("deviceType", "mobile");
client.track(event);
批量上报![]()
import java.util.Arrays;
import java.util.List;
List<WebfunnyEvent> events = Arrays.asList(
new WebfunnyEvent("projectId", "event_1"),
new WebfunnyEvent("projectId", "event_2"),
new WebfunnyEvent("projectId", "event_3")
);
UploadResponse response = client.trackBatch(events);
3. 关闭客户端
应用关闭时,建议调用 shutdown 方法,确保队列中的事件都被上报:
// 在应用关闭时调用
client.shutdown();
配置说明
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| serverUrl | String | 必填 | Webfunny 服务器地址 |
| projectId | String | 必填 | 项目 ID |
| eventSecret | String | null | 事件密钥,用于签名验证 |
| signatureEnabled | boolean | false | 是否启用签名验证 |
| batchSize | int | 1000 | 每批上报事件数量 |
| flushIntervalMs | long | 5000 | 自动刷新间隔(毫秒) |
| maxQueueSize | int | 1000 | 事件队列最大容量 |
| maxRetries | int | 3 | 上报失败重试次数 |
| retryIntervalMs | long | 1000 | 重试间隔(毫秒) |
| connectTimeoutMs | int | 5000 | 连接超时(毫秒) |
| socketTimeoutMs | int | 10000 | 读取超时(毫秒) |
| debug | boolean | false | 是否开启调试日志 |
事件字段说明
系统字段(we 开头)
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| projectId | String | 是 | 项目 ID |
| pointId | String | 是 | 点位 ID,用于路由到对应的日志表 |
| weUserId | String | 否 | 用户 ID |
| weCustomerKey | String | 否 | 客户标识 |
| weIp | String | 否 | IP 地址(自动填充) |
| weCountry | String | 否 | 国家(自动填充) |
| weProvince | String | 否 | 省份(自动填充) |
| weCity | String | 否 | 城市(自动填充) |
| weHappenTime | Long | 否 | 发生时间戳(毫秒) |
| weHappenDate | String | 否 | 发生日期(yyyy-MM-dd) |
| weHappenHour | String | 否 | 发生小时(HH) |
| weHappenMinute | String | 否 | 发生分钟(HH:mm) |
| wePath | String | 否 | 页面路径 |
| weFirstStepDay | String | 否 | 首次访问日期 |
| weRelationPointId | String | 否 | 关联点位 ID |
| weRelationField | String | 否 | 关联字段 |
自定义参数
自定义参数名不能以 we 开头(大小写不敏感),否则会被过滤。
event.addParam("productName", "iPhone 15"); // 有效
event.addParam("WeProduct", "iPhone 15"); // 会被过滤
event.addParam("wePrice", 9999); // 会被过滤
完整示例
在 application.yml 中配置:
webfunny: server-url: https://event.webfunny.com project-id: your-project-id event-secret: your-event-secret
up-now: false # 是否立即上报(默认false,延迟批量上报;true-立即上报)
batch-size: 1000 # 每批上报事件数(默认1000)
@RunWith(SpringRunner.class)
@SpringBootTest
public class UploadEventTest {
@Value("${webfunny.server-url}")
private String serverUrl;
@Value("${webfunny.project-id}")
private String projectId;
@Value("${webfunny.up-now}")
private Boolean upNow;
@Value("${webfunny.batch-size}")
private Integer batchSize;
@Test
public void testBasicUsage() {
// 创建配置
WebfunnyEventConfig config = new WebfunnyEventConfig();
config.setServerUrl(serverUrl);
config.setProjectId(projectId);
config.setUpNow(upNow); // 延迟批量上报(默认)
config.setDebug(true);
WebfunnyEventClient client = new WebfunnyEventClient(config);
// 上报事件
WebfunnyEvent event = new WebfunnyEvent();
event.setPointId("15");
event.setWeUserId("user_123");
// 添加业务自定义字段 (非we开头)
event.addParam("behaviorType", "啊啊");
event.addParam("xingWeiMiaoShu", "请求");
event.addParam("yeMianYuMing", "啊啊");
event.addParam("wangZhanLaiYuan", "啊啊");
event.addParam("tuiGuangChuangYiId", "啊啊");
event.addParam("tuiGuangDanYuan", "问问");
boolean result = client.track(event);
System.out.println("上报结果: " + result);
// 等待批量上报完成
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 关闭客户端
client.shutdown();
}
}
点位细查中查看上报结果:
注意事项
- 必填字段:
projectId和pointId是必填字段,用于路由到对应的日志表。如果 pointId 为空,会抛出IllegalArgumentException - 线程安全:
WebfunnyEventClient是线程安全的,可以作为单例使用 - 资源释放:应用关闭时务必调用
shutdown()方法,避免事件丢失 - 队列满处理:当事件队列满时,新事件会被丢弃,可以通过日志监控
- 签名验证:生产环境建议开启签名验证,防止数据被篡改
二、Webfunny Event Node SDK
Webfunny事件上报Node.js SDK,对齐Java SDK API设计。
安装
npm install webfunny-event-node-sdk-public
快速开始
1. 创建客户端
import { WebfunnyEventClient, WebfunnyEvent } from 'webfunny-event-node-sdk-public';
// 方式1: 使用Builder模式(推荐)
const client = WebfunnyEventClient.builder()
.serverUrl('https://your-server.com')
.projectId('your-project-id')
.eventSecret('your-secret') // 可选,开启签名
.debug(true) // 可选,开启调试日志
.build();
// 方式2: 直接使用配置对象
const client = new WebfunnyEventClient({
serverUrl: 'https://your-server.com',
projectId: 'your-project-id',
debug: true
});
2. 上报事件
// 简单上报 - 只传点位ID
client.track('12');
// 带参数上报
client.track('13', {
productId: 'P001',
amount: 99.99,
currency: 'CNY'
});
// 使用事件对象上报
const event = new WebfunnyEvent('your-project-id', '12')
.setWeUserId('user123')
.setWeIp('192.168.1.1')
.addParam('platform', 'web')
.addParam('version', '1.0.0');
client.track(event);
3. 立即上报
// 同步立即上报(阻塞等待结果)
const response = client.trackImmediately(event);
console.log(response.code); // 200表示成功
4. 批量上报
const events = [
new WebfunnyEvent('project-id', 'event_1'),
new WebfunnyEvent('project-id', 'event_2'),
new WebfunnyEvent('project-id', 'event_3')
];
const response = client.trackBatch(events);
5. 关闭客户端
// 应用关闭时调用,会刷新队列中剩余的事件
client.shutdown();
配置项
| 配置项 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| serverUrl | string | 是 | - | 服务端点地址 |
| projectId | string | 是 | - | 项目ID |
| eventSecret | string | 否 | - | 事件密钥,用于签名 |
| signatureEnabled | boolean | 否 | false | 是否开启签名验证 |
| batchSize | number | 否 | 10 | 批量上报大小 |
| flushIntervalMs | number | 否 | 5000 | 自动刷新间隔(ms) |
| maxQueueSize | number | 否 | 1000 | 最大队列大小 |
| maxRetries | number | 否 | 3 | 最大重试次数 |
| retryIntervalMs | number | 否 | 1000 | 重试间隔(ms) |
| connectTimeoutMs | number | 否 | 5000 | 连接超时(ms) |
| socketTimeoutMs | number | 否 | 10000 | 读取超时(ms) |
| debug | boolean | 否 | false | 调试模式 |
WebfunnyEvent 事件对象
系统字段(we开头)
| 字段 | 类型 | 说明 |
|---|---|---|
| projectId | string | 项目ID(必填) |
| pointId | string | 点位ID(必填) |
| weUserId | string | 用户ID |
| weCustomerKey | string | 客户Key |
| weIp | string | IP地址 |
| weCountry | string | 国家 |
| weProvince | string | 省份 |
| weCity | string | 城市 |
| weHappenTime | number | 发生时间戳 |
| weHappenDate | string | 发生日期 |
| weHappenHour | string | 发生小时 |
| weHappenMinute | string | 发生分钟 |
| wePath | string | 页面路径 |
| weFirstStepDay | string | 首次访问日期 |
| weRelationPointId | string | 关联点位ID |
| weRelationField | string | 关联字段 |
自定义参数
const event = new WebfunnyEvent('project-id', 'custom_event')
.addParam('productName', 'iPhone 15') // 添加单个参数
.addParams({ // 批量添加参数
category: 'electronics',
price: 6999,
count: 2
});
注意:自定义参数名不能以we开头,会被自动过滤。
生命周期钩子
client.setHooks({
beforeInit: () => {
console.log('SDK初始化前');
},
afterInit: () => {
console.log('SDK初始化后');
},
beforeReport: (event) => {
console.log('上报前:', event);
// 返回false可拦截上报
return true;
},
afterReport: (response) => {
console.log('上报后:', response);
},
onError: (error) => {
console.error('上报错误:', error);
}
});
手动刷新队列
// 同步刷新
client.flush();
// 异步刷新
client.flushAsync();
// 获取队列大小
const size = client.getQueueSize();
异常处理
import { WebfunnyEventException } from 'webfunny-event-node-sdk-public';
try {
client.track(event);
} catch (e) {
if (e instanceof WebfunnyEventException) {
console.error('错误码:', e.getCode());
console.error('错误信息:', e.message);
}
}
签名验证
开启签名验证可防止数据篡改:
const client = WebfunnyEventClient.builder()
.serverUrl('https://your-server.com')
.projectId('your-project-id')
.eventSecret('your-secret-key') // 设置密钥自动开启签名
.build();
完整示例
import { WebfunnyEventClient, WebfunnyEvent, WebfunnyEventException } from 'webfunny-event-node-sdk-public';
async function main() {
// 创建客户端
const client = WebfunnyEventClient.builder()
.serverUrl('https://event.webfunny.com')
.projectId('event_20261201_1213211')
.eventSecret('sk_abcdef')
.debug(true)
.batchSize(5)
.flushIntervalMs(3000)
.build();
// 设置钩子
client.setHooks({
beforeReport: (event) => {
console.log('准备上报:', event.pointId);
return true;
},
afterReport: (response) => {
console.log('上报完成:', response.code);
}
});
// 上报各种事件
client.track('app_start');
client.track('page_view', {
page: '/home',
duration: 30
});
const clickEvent = new WebfunnyEvent('proj_123456', 'button_click')
.setWeUserId('user_001')
.addParam('buttonId', 'submit')
.addParam('page', '/checkout');
client.track(clickEvent);
// 模拟应用关闭
setTimeout(() => {
client.shutdown();
}, 10000);
}
main().catch(console.error);
API 参考
WebfunnyEventClient
| 方法 | 说明 |
|---|---|
track(event) |
上报事件到队列 |
track(pointId, params) |
快速上报带参数 |
trackImmediately(event) |
立即同步上报 |
trackBatch(events) |
批量上报 |
flush() |
刷新队列 |
flushAsync() |
异步刷新队列 |
shutdown() |
关闭客户端 |
getQueueSize() |
获取队列大小 |
setHooks(hooks) |
设置生命周期钩子 |
builder() |
获取Builder实例 |
WebfunnyEvent
| 方法 | 说明 |
|---|---|
setProjectId(id) |
设置项目ID |
setPointId(id) |
设置点位ID |
setWeUserId(id) |
设置用户ID |
setWeIp(ip) |
设置IP地址 |
setWeCountry(country) |
设置国家 |
setWeProvince(province) |
设置省份 |
setWeCity(city) |
设置城市 |
setWeHappenTime(time) |
设置发生时间 |
setWePath(path) |
设置页面路径 |
addParam(key, value) |
添加自定义参数 |
addParams(params) |
批量添加参数 |
toObject() |
转换为普通对象 |
与Java SDK对比
| 功能 | Java SDK | Node.js SDK |
|---|---|---|
| 创建客户端 | WebfunnyEventClient.builder() |
WebfunnyEventClient.builder() |
| 上报事件 | track(event) |
track(event) |
| 立即上报 | trackImmediately(event) |
trackImmediately(event) |
| 批量上报 | trackBatch(events) |
trackBatch(events) |
| 关闭客户端 | shutdown() |
shutdown() |
| 事件对象 | WebfunnyEvent |
WebfunnyEvent |
| 异常类 | WebfunnyEventException |
WebfunnyEventException |
| 签名工具 | SignatureUtil |
SignatureUtil |
技术支持
如有问题,请联系 Webfunny 技术支持团队。