1.2.1.6 JAVA SDK使用说明
1.1. 引入SDK(java)
1.1.1. maven项目
在pom中添加如下依赖
<dependency>
<groupId>com.netease.da.sdk</groupId>
<artifactId>HubbleDataSDK</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
1.1.2. 其他java项目
直接在官网链接下载相应的sdk jar包,引入到项目中
1.2. 初始化SDK
- 方式1:只使用埋点功能
DATracker daTracker=DATracker.init("MA-6RWE-XXXXXXXXXXXX");//MA-6RWE-XXXXXXXXXXXX为产品对应的server端的appkey
- 方式2:使用abtest功能(默认获取变量的超时时间为300ms,http建立连接时间2s)
DATracker daTracker=DATracker.init("MA-6RWE-QWHKHEKDF12",true);//打开abtest功能
//或
DATracker daTracker=DATracker.init("MA-6RWE-QWHKHEKDF12",true,300,500);//打开abtest功能,并配置获取变量的超时时间和http连接时间
//或
DATracker daTracker=DATracker.init("MA-6RWE-QWHKHEKDF12",true,true);//打开abtest功能并且缓存配置
//或
DATracker daTracker=DATracker.init("MA-6RWE-QWHKHEKDF12",true,true,300,500);//打开abtest功能并且缓存配置,并配置获取变量的超时时间和http连接时间
DATracker只需要init一次,以后每次获取DATracker实例,可以通过:
DATracker daTracker=DATracker.getDATrackInstance();
获取DATracker实例
1.2.1. Spring项目
建议spring的项目,通过在配置文件中配置bean,如:
<bean id="daTracker" class="com.netease.da.sdk.DATracker" factory-method="init">
<constructor-arg type="java.lang.String" value="MA-6RWE-XXXXXXXXXXXX"/>
</bean>
在需要埋点的类中通过注解注入即可:
@Autowired
protected DATracker daTracker;
也可以通过
DATracker daTracker=DATracker.getDATrackInstance();
获取DATracker实例
1.3. 追踪事件接口
1.3.1. 事件类型
事件主要分为两种类型,预定义事件和普通事件
预定义事件
系统预定义了2种事件,用户只需要调用接口即可追踪,如下:
1. 用户id关联,将匿名id和用户id相关联,匿名id为非登录状态下用户的唯一id
public void trackSignUp(String oldUserId,String newUserId)
2. 用户属性设置
- 设置用户属性,存在则覆盖
/**
* 设置用户属性,存在则覆盖
* @param userId 用户id
* @param property 用户属性名称
* @param value 用户属性值
*/
public void profileSet(String userId,String property,Object value)
- 设置用户属性集合
/**
* 设置用户属性集合
* @param userId 用户id
* @param userProfile 用户属性集合
*/
public void profileSet(String userId,Map<String,Object>userProfile)
- 设置用户属性,该属性如果存在则忽略
/**
* 设置用户属性,该属性如果存在则忽略
* @param userId 用户id
* @param property 用户属性名称
* @param value 用户属性值
*/
public void profileSetOnce(String userId,String property,Object value)
- 删除一个用户的属性
/**
* 设置用户属性,该属性如果存在则忽略
* @param userId 用户id
* @param property 用户属性名称
* @param value 用户属性值
*/
public void profileDelete(String userId)
- 设置用户年龄,存在则覆盖
/**
* 设置用户属性,该属性如果存在则忽略
* @param userId 用户id
* @param property 用户属性名称
* @param value 用户属性值
*/
public void profileSetAge(String userId,int age)
- 设置用户名字,存在则覆盖
/**
* 设置用户名字,存在则覆盖
* @param userId 用户id
* @param name 用户真实姓名
*/
public void profileSetName(String userId,String name)
- 设置用户性别,存在则覆盖,gender值:{"男"|"女"}
/**
* 设置用户性别,存在则覆盖
* @param userId 用户id
* @param gender 用户性别
*/
public void profileSetGender(String userId,String gender)
- 设置用户生日,存在则覆盖,birthday格式:"YYYY-MM-DD"
/**
* 设置用户生日,存在则覆盖
* @param userId 用户id
* @param birthday 用户生日,格式"YYYY-MM-DD"
*/
public void profileSetBirthday(String userId,String birthday)
- 设置用户账号,存在则覆盖 ``` /**
- 设置用户账号,存在则覆盖
- @param userId 用户id
- @param account 用户账号 */ public void profileSetAccount(String userId,String account) ```
- 设置用户位置信息,包括国家、省份、城市,存在则覆盖
/**
* 设置用户账号,存在则覆盖
* @param userId 用户id
* @param account 用户账号
*/
public void profileSetLocation(String userId,String country,String province,String city)
普通事件
用户自定义的事件通过调用:
/**
* 记录多个属性的事件
* @param userId 用户id
* @param eventId 事件名称
* @param properties 属性值
*/
public void trackEvent(String userId,String eventId,Map<String,Object>properties)
/**
* 记录多个属性的事件
* @param userId 用户id
* @param eventId 事件名
* @param ip 客户端ip
* @param properties 属性值
*/
public void trackEvent(String userId,String eventId,String ip,Map<String,Object>properties
/**
* 记录多个属性的事件,并记录事件耗时
*
* @param userId 用户id
* @param eventId 事件名称
* @param costTime 事件耗时
* @param properties 属性值
*/
public void trackEvent(String userId, String eventId, long costTime, Map<String, Object> properties)
/**
* 记录多个属性的事件,并记录事件耗时
*
* @param userId 用户id
* @param eventId 事件名称
* @param ip 客户端ip
* @param costTime 事件耗时
* @param properties 属性值
*/
public void trackEvent(String userId, String eventId, String ip, long costTime, Map<String, Object> properties)
获取abtest实验变量配置
/**
* 根据用户id获取abtest实验变量
* @param userId 用户id
* @param variableName 变量名称
* @return
*/
public String getAbTestVariable(String userId,String variableName)
/**
* 根据用户id获取abtest实验变量
* @param userId 用户id
* @param variableName 变量名称
* @param isCache 是否使用缓存
* @return
*/
public String getAbTestVariable(String userId,String variableName,boolean isCache)
获取abtest用户参与的所有的实验配置
/**
* 获取用户参与的所有实验
* @param userId 用户id
* @return
*/
public JSONObject getAbTestVariable(String userId)
/**
* 获取用户参与的所有实验
* @param userId 用户id
* @param isCache 是否使用缓存
* @return
*/
public JSONObject getAbTestVariable(String userId,boolean isCache)
返回数据类型格式:
{
"variables": {
"aColor": "1111",
"class": "C"
},
"experiments": [{
"versionId": "282",
"variables": ["aColor"],
"experimentId": "128"
}, {
"versionId": "146",
"variables": ["class"],
"experimentId": "65"
}]
}
1.4. 使用Demo
在这个 Demo 中,我们以一个典型的电商产品为例,描述一个用户从匿名访问网站,到下单购买商品,再到申请售后服务,这样一个整个环节,使用 Hubble Data Server(DA)的埋点,应该如何记录日志。
//demo示例
DATracker daTracker=DATracker.init("MA-6RWE-QWHKHEKDF12");
// 特别需要注意的是,这个 Demo 只是描述 DA的数据记录能力,并不是说使用者要完全照搬这些 Event 和 Property
// 的设计,使用者还是需要结合自己产品的实际需要,来做相应的设计和规划
// 1. 用户匿名访问网站
String cookieId = "ABCDEF123456789"; // 用户未登录时,可以使用产品自己生成的cookieId来标注用户
Map<String, Object> properties = new HashMap<String, Object>();
// 1.1 访问首页
// 前面有开头的property字段,是DA提供给用户的预置字段
// 对于预置字段,已经确定好了字段类型和字段的显示名
properties.clear();
daTracker.setSuperProperty("os","windows");
daTracker.setSuperProperty("osVersion","10.1.3"); // 操作系统的具体版本
properties.put("time", new Date()); // 这条event发生的时间,如果不设置的话,则默认是当前时间
properties.put("ip", "123.123.123.123"); // 请求中能够拿到用户的IP,则把这个传递给DA,DA会自动根据这个解析省份、城市
properties.put("Channel", "baidu"); // 用户是通过baidu这个渠道过来的
daTracker.trackEvent(cookieId, "ViewHomePage", properties); // 记录访问首页这个event
// 1.2 搜索商品
properties.clear();
properties.put("ip", "123.123.123.123"); // 请求中能够拿到用户的IP,则把这个传递给DA,DA会自动根据这个解析省份、城市
properties.put("KeyWord", "黑猪肉"); // 搜索引擎引流过来时使用的关键词
daTracker.trackEvent(cookieId, "SearchProduct", properties); // 记录搜索商品这个event
// 1.3 浏览商品
properties.clear();
properties.put("ip", "123.123.123.123"); // 请求中能够拿到用户的IP,则把这个传递给DA,DA会自动根据这个解析省份、城市
properties.put("ProductName", "网易黑猪肉"); // 商品名称
properties.put("ProductType", "生鲜"); // 商品类别
properties.put("ShopName", "四季生鲜"); // 店铺名称
daTracker.trackEvent(cookieId, "ViewProduct", properties); // 记录浏览商品这个event
// 2. 用户决定注册了
String registerId = "123456"; // 用户注册时,分配给用户的注册Id
// 2.1 通过,trackSignUP,把匿名ID和注册ID贯通起来
properties.clear();
properties.put("RegisterChannel", "baidu"); // 用户的注册渠道
daTracker.trackSignUp(registerId, cookieId);
// 2.2 用户注册时,填充了一些个人信息,可以用Profile接口记录下来
Map<String, Object> profiles = new HashMap<String, Object>();
profiles.put("city", "杭州"); // 用户所在城市
profiles.put("province", "浙江"); // 用户所在省份
profiles.put("name", "隔壁王小二"); // 用户的昵称
profiles.put("signup_time", new Date()); // 注册时间
profiles.put("Gender", "男"); // 用户的性别
profiles.put("Birthday", "1990-10-29"); // 用户的出生日期
profiles.put("RegisterChannel", "baidu"); // 用户的注册渠道
daTracker.profileSet(registerId, profiles); // 此时传入的是注册ID了
// 3. 用户注册后,进行后续行为
// 3.1 提交订单和提交订单详情
// 这个订单里面包含一2斤黑猪肉和2盒粽子
// 订单的信息
properties.clear();
properties.put("ip", "123.123.123.123"); // 请求中能够拿到用户的IP,则把这个传递给DA,DA会自动根据这个解析省份、城市
properties.put("OrderId", "N23234234"); // 订单ID
properties.put("ShipPrice", 18.0); // 运费
properties.put("OrderTotalPrice", 388.0); // 订单的总价格,默认是元
daTracker.trackEvent(registerId, "SubmitOrder", properties); // 注意,此时使用的已经是注册ID了
daTracker.profileSetOnce(registerId,"name","lip");
// 订单中黑猪肉这个商品的信息
properties.clear();
properties.put("ip", "123.123.123.123"); // 请求中能够拿到用户的IP,则把这个传递给DA,DA会自动根据这个解析省份、城市
properties.put("OrderId", "N123123123"); // 订单ID
properties.put("ProductName", "网易黑猪肉"); // 商品名称
properties.put("ProductType", "生鲜"); // 商品类别
properties.put("ShopName", "四季生鲜"); // 店铺名称
properties.put("ProductUnitPrice", 68.0); // 商品单价
properties.put("ProductAmount", 2.0); // 商品数量,可以是个数,也可以是重量
properties.put("ProductTotalPrice", 136.0); // 商品总价
daTracker.trackEvent(registerId, "SubmitOrderDetail", properties);
// 订单中黑猪肉粽这个商品的信息
properties.clear();
properties.put("ip", "123.123.123.123"); // 请求中能够拿到用户的IP,则把这个传递给DA,DA会自动根据这个解析省份、城市
properties.put("OrderId", "N223423423452"); // 订单ID
properties.put("ProductName", "黑猪肉粽"); // 商品名称
properties.put("ProductType", "零食"); // 商品类别
properties.put("ShopName", "四季生鲜"); // 店铺名称
properties.put("ProductUnitPrice", 28.0); // 商品单价
properties.put("ProductAmount", 2.0); // 商品数量,可以是个数,也可以是重量
properties.put("ProductTotalPrice", 56.0); // 商品总价
daTracker.trackEvent(registerId, "SubmitOrderDetail", properties);
// 3.2 支付订单和支付订单详情
// 整个订单的支付情况
properties.clear();
properties.put("ip", "123.123.123.123"); // 请求中能够拿到用户的IP,则把这个传递给DA,DA会自动根据这个解析省份、城市
properties.put("OrderId", "N12234234234"); // 订单ID
properties.put("ShipPrice", 18.0); // 运费
properties.put("OrderTotalPrice", 210.0); // 订单的总价格,默认是元
properties.put("PaymentMethod", "AliPay"); // 支付方式
properties.put("AllowanceAmount", 30.0); // 补贴金额
properties.put("AllowanceType", "首次下单立减"); // 补贴类型
properties.put("PaymentAmount", 180); // 实际支付的订单金额
daTracker.trackEvent(registerId, "PayOrder", properties);
// 黑猪肉这个商品的支付情况
properties.clear();
properties.put("ip", "123.123.123.123"); // 请求中能够拿到用户的IP,则把这个传递给DA,DA会自动根据这个解析省份、城市
properties.put("OrderId", "N234234234234"); // 订单ID
properties.put("ProductName", "网易黑猪肉"); // 商品名称
properties.put("ProductType", "生鲜"); // 商品类别
properties.put("ShopName", "四季生鲜"); // 店铺名称
properties.put("ProductUnitPrice", 68.0); // 商品单价
properties.put("ProductAmount", 2.0); // 商品数量,可以是个数,也可以是重量
properties.put("ProductTotalPrice", 136.0); // 商品总价
properties.put("ProductAllowanceAmount", 30.0); // 假设这个补贴是在黑猪肉上的折扣
properties.put("ProductAllowanceType", "首次下单红立减"); // 补贴类型
properties.put("ProductPaymentAmount", 106.0); // 黑猪肉实际支付了这么多
properties.put("PaymentMethod", "AliPay"); // 与订单保持一致
daTracker.trackEvent(registerId, "PayOrderDetail", properties);
// 黑猪肉粽这个商品的支付情况
properties.clear();
properties.put("ip", "123.123.123.123"); // 请求中能够拿到用户的IP,则把这个传递给DA,DA会自动根据这个解析省份、城市
properties.put("OrderId", "N1231242343"); // 订单ID
properties.put("ProductName", "黑猪肉粽"); // 商品名称
properties.put("ProductType", "零食"); // 商品类别
properties.put("ShopName", "四季生鲜"); // 店铺名称
properties.put("ProductUnitPrice", 28.0); // 商品单价
properties.put("ProductAmount", 2.0); // 商品数量,可以是个数,也可以是重量
properties.put("ProductTotalPrice", 56.0); // 商品总价
properties.put("ProductAllowanceAmount", 0.0); // 黑猪肉粽上并没有补贴
properties.put("ProductAllowanceType", "无补贴"); // 补贴类型
properties.put("ProductPaymentAmount", 56.0); // 黑猪肉粽实际支付了这么多
properties.put("PaymentMethod", "AliPay"); // 与订单保持一致
daTracker.trackEvent(registerId, "PayOrderDetail", properties);
// 3.3 假设这个用户支付后反悔了,要取消订单
// 整个订单的取消情况
properties.clear();
properties.put("ip", "123.123.123.123"); // 请求中能够拿到用户的IP,则把这个传递给DA,DA会自动根据这个解析省份、城市
properties.put("OrderId", "N123791273492734"); // 订单ID
properties.put("ShipPrice", 18.0); // 运费
properties.put("OrderTotalPrice", 210.0); // 订单的总价格,默认是元
properties.put("CancelReason", "地址填写错误"); // 取消订单的原因
properties.put("CancelTiming", "AfterPay"); // 取消订单的时机
daTracker.trackEvent(registerId, "CancelOrder", properties);
// 黑猪肉这个商品的取消情况
properties.clear();
properties.put("ip", "123.123.123.123"); // 请求中能够拿到用户的IP,则把这个传递给DA,DA会自动根据这个解析省份、城市
properties.put("OrderId", "N1232134234"); // 订单ID
properties.put("ProductName", "黑猪肉"); // 商品名称
properties.put("ProductType", "生鲜"); // 商品类别
properties.put("ShopName", "四季生鲜"); // 店铺名称
properties.put("ProductUnitPrice", 68); // 商品单价
properties.put("ProductAmount", 2.0); // 商品数量,可以是个数,也可以是重量
properties.put("ProductTotalPrice", 136.0); // 商品总价
properties.put("CancelReason", "地址填写错误"); // 取消订单的原因
properties.put("CancelTiming", "AfterPay"); // 取消订单的时机
daTracker.trackEvent(registerId, "CancelOrderDetail", properties);
// 黑猪肉粽这个商品的取消情况
properties.clear();
properties.put("ip", "123.123.123.123"); //请求中能够拿到用户的IP,则把这个传递给DA,DA会自动根据这个解析省份、城市
properties.put("OrderId", "N223423423452"); // 订单ID
properties.put("ProductName", "黑猪肉粽"); // 商品名称
properties.put("ProductType", "零食"); // 商品类别
properties.put("ShopName", "四季生鲜"); // 店铺名称
properties.put("ProductUnitPrice", 28.0); // 商品单价
properties.put("ProductAmount", 2.0); // 商品数量,可以是个数,也可以是重量
properties.put("ProductTotalPrice", 56.0); // 商品总价
properties.put("CancelReason", "地址填写错误"); // 取消订单的原因
properties.put("CancelTiming", "AfterPay"); // 取消订单的时机
daTracker.trackEvent(registerId, "CancelOrderDetail", properties);
// 4. 假设用户并没有取消订单,然后成功完成了配送
// 黑猪肉这个商品的配送情况
properties.clear();
properties.put("ip", "123.123.123.123"); // 请求中能够拿到用户的IP,则把这个传递给DA,DA会自动根据这个解析省份、城市
properties.put("OrderId", "N223423423452"); // 订单ID
properties.put("ProductName", "黑猪肉"); // 商品名称
properties.put("ProductType", "零食"); // 商品类别
properties.put("ShopName", "四季生鲜"); // 店铺名称
properties.put("ProductUnitPrice", 1200.0); // 商品单价
properties.put("ProductAmount", 1.0); // 商品数量,可以是个数,也可以是重量
properties.put("ProductTotalPrice", 1200.0); // 商品总价
properties.put("ProductAllowanceAmount", 30.0); // 假设这个补贴是在黑猪肉上的折扣
properties.put("ProductPaymentAmount", 1170.0); // 黑猪肉实际支付了这么多
properties.put("PaymentMethod", "AliPay"); // 与订单保持一致
properties.put("SupplyTime", 49.0); // 订单运送用了49小时
properties.put("SupplyMethod", "顺丰"); // 通过顺丰运送的
daTracker.trackEvent(registerId, "ReceiveProduct", properties);
// 黑猪肉粽这个商品的配送情况
properties.clear();
properties.put("ip", "123.123.123.123"); // 请求中能够拿到用户的IP,则把这个传递给DA,DA会自动根据这个解析省份、城市
properties.put("OrderId", "N223423423452"); // 订单ID
properties.put("ProductName", "黑猪肉粽"); // 商品名称
properties.put("ProductType", "零食"); // 商品类别
properties.put("ShopName", "四季生鲜"); // 店铺名称
properties.put("ProductUnitPrice", 12.0); // 商品单价
properties.put("ProductAmount", 2.0); // 商品数量,可以是个数,也可以是重量
properties.put("ProductTotalPrice", 24.0); // 商品总价
properties.put("ProductAllowanceAmount", 0.0); // 黑猪肉粽上并没有补贴
properties.put("ProductPaymentAmount", 24.0); // 黑猪肉粽实际支付了这么多
properties.put("PaymentMethod", "AliPay"); // 与订单保持一致
properties.put("SupplyTime", 98.0); // 订单运送用了98小时
properties.put("SupplyMethod", "圆通"); // 通过圆通运送的
daTracker.trackEvent(registerId,"delivery",properties);
daTracker.profileSetBirthday(registerId,null);
//使用abTest功能,获取实验配置
daTracker=DATracker.init("MA-6RWE-QWHKHEKDF12",true);
String color=daTracker.getAbTestVariable("hzlibuyi","color");
if("blue".equals(color))
{
//TODO
}else if("green".equals(color))
{
//TODO
}else {
//TODO
}
//删除该用户
daTracker.profileDelete(registerId);
1.5. 通过接口直接采集数据
1.5.1. 数据格式:
- 用户id 关联 ``` { "eventId": "da_u_signup", "dataType": "ie", "ip": null, "sdkType": "server", "time": 1495855781045, "sdkVersion": "1.0.0", "appKey": "MA-TF52-SDDFE56U1233", "userId": "ABCDEF123456789", "attributes": {
} }"newUserId": "ABCDEF123456789", "os": "windows", "osVersion": "10.1.3", "oldUserId": "123456"
+ 用户信息设置
{ "eventId": "da_user_profile", "dataType": "ie", "ip": null, "sdkType": "server", "time": 1495856262386, "sdkVersion": "1.0.0", "appKey": "MA-TF52-SDDFE56U1233", "userId": "ABCDEF123456789", "attributes": { "$userProfile": { "$account": "hubbletest@163.com", "$type": "profile_set" } } }
#### 自定义事件
{ "eventId": "SubmitOrderDetail", "dataType": "e", "ip": "123.123.123.123", "sdkType": "server", "time": 1495855791103, "sdkVersion": "1.0.0", "appKey": "MA-TF52-SDDFE56U1233", "userId": "123456", "attributes": { "ShopName": "四季生鲜", "ProductAmount": 2, "os": "windows", "osVersion": "10.1.3", "ProductName": "网易黑猪肉", "ProductUnitPrice": 68, "ip": "123.123.123.123", "ProductType": "生鲜", "OrderId": "N123123123", "ProductTotalPrice": 136 } }
### 数据发送格式,如下:
https://hubble.netease.com/track/s/?data=eyJldmVudElkIjoidGhyZWFkLXRlc3QiLCJkYXRhVHlwZSI6ImUiLCJpcCI6IjEyMy4xMjMuMTIzLjEyMyIsInNka1R5cGUiOiJzZXJ2ZXItamF2YSIsImF0dHJpYnV0ZXMiOnsiJHRpbWUiOjE1MDE2NjUwMjk5MTYsIm9zIjoid2luZG93cyIsIm9zVmVyc2lvbiI6IjEwLjEuMyIsImlwIjoiMTIzLjEyMy4xMjMuMTIzIiwiQ2hhbm5lbCI6ImJhaWR1In0sInNka1ZlcnNpb24iOiIxLjAuMCIsImFwcEtleSI6Ik1BLTZSV0UtUVdIS0hFS0RGMTIiLCJ0aW1lIjoxNTAxNjY1MDI5OTE2LCJ1c2VySWQiOiJsaWJ1eWktdGVzdCJ9
### 注意
+ 每一条数据都必须符合json格式
+ 需要将数据进行base64加密
+ 请求通过get的方式发送,请求参数为data
+ 请求增加两个request header
1.X-SHA1-APPKEY 如 java发送请求: httpGet.addHeader("X-SHA1-APPKEY", SHA1Util.encryptSHA(appkey)); 其中appkey要经过sha1加密 2.X-CLIENT-IP 移动端ip,获取不到可以不填 ```
- 自定义属性都需要放在attributes里
- eventId,dataType,sdkType,sdkVersion,time,appKey,userId为第一层级的数据,且必填