1. 集成流程
1.1 从MavenCentral引入SDK
点开 MavenCentral中心仓库 ,并搜索关键字 coraool-android-sdk
,如下图:
1.1.1 Gradle项目
在build.gradle增加指定版本的依赖
1. 项目中添加从 mavenCentral() 仓库获取依赖
2. 添加依赖
dependencies {
implementation 'com.coraool:coraool-android-sdk:2.0.9'
}
1.1.2 Maven项目
在pom.xml中增加指定版本的依赖
<dependency>
<groupId>com.coraool</groupId>
<artifactId>coraool-android-sdk</artifactId>
<version>${version}</version>
</dependency>
1.2 从本地Lib库引入SDK
把sdk拷贝到应用的 libs
目录下,在对应模块的 build.gradle
中添加aar包的依赖
implementation files("libs/coraool-android-sdk-2.0.9.aar")
SDK Version | VersionDate | Release Notes | Assets |
---|---|---|---|
2.0.9 | 20240820 | Native+Jsbridge埋点功能远程接口调用ABTest功能GTX流量追踪 |
1.3 配置SDK
1.3.1 权限授予
权限 | 权限用途 |
---|---|
ACCESS_NETWORK_STATE | 检测联网方式,在网络异常状态下避免数据发送,节省流量和电量。 |
INTERNET | 允许应用程序联网和发送统计数据的权限,以便提供统计分析服务。 |
ACCESS_FINE_LOCATION(可选) | 通过获取位置信息,为开发者提供反作弊功能,剔除作弊设备;同时校正用户的地域分布数据,使报表数据更加准确。 |
ACCESS_COARSE_LOCATION(可选) | 通过获取位置信息,为开发者提供反作弊功能,剔除作弊设备;同时校正用户的地域分布数据,使报表数据更加准确。 |
<uses-sdk android:minSdkVersion="8"></uses-sdk>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
1.3.1 配置混淆
如果您的应用使用了代码混淆,请添加如下配置,避免SDK被错误混淆
-keep class com.coraool.** { *; }
-keepclassmembers class * {
public <init> (org.json.JSONObject);
}
1.4 初始化步骤
1.4.1 申请AK
每个app接入前,需要申请 AppId、AppKey、AppSecret
1.4.2 SDK初始化
SDK对外提供的接口类名为 com.coraool.CoraoolSDK
,所有的方法都通过这个类对外提供服务。
首先在Application的onCreate方法中,使用Coraool分配的Token对SDK进行初始化:
/**
* Call this method to initialize Coraool SDK when launch the application.
*
* @param application application object
* @param paramProvider interface
*/
public void initialize(Application application, IParamProvider paramProvider);
初始化化示例:
public class CApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// 用户身份标识请在SDK初始化之前设置,因为后续初始化过程需要用到
CoraoolSDK.setting.setUserId("your_user_id");
CoraoolSDK.setting.setCustomDeviceId("my_unique_device_id");
CoraoolSDK.initialize(this, new IParamProvider() {
@Override
public String getAppId() {
return "${coraool_appId}"; // 在coraool申请
}
@Override
public String getAppKey() {
return "${coraool_appKey}"; // 在coraool申请
}
@Override
public String getAppSec() {
return "${coraool_appSec}"; // 在coraool申请
}
@Override
public boolean isEnableLog() {
return true;
}
});
Logger.getLogger("Application").info("Init coraool sdk done");
}
}
1.5 其他SDK配置
SDK配置相关的API统一由 CoraoolSDK.setting 接口对象管理
1.5.1 登录用户ID
用户登录、退出的时候,需要实时更新登录信息
/**
* Call this api to update the login account whenever login, logout or switch account.
*
* @param userId login user id
*/
public void setUserId(String userId);
1.5.2 日志开关
开发阶段建议打开日志开关,方便检查SDK的关键流程,以及打点日志的内容。线上发布前请关闭此开关,避免日志打印影响到APP性能
/**
* Turn on this switch in DEBUG mode to trace sdk logs in different levels.
* Turn it off before publishing app to ensure better performance in production situation.
*
* @param enableLog switch
*/
public void setEnableLog(boolean enableLog);
1.5.3 严格模式
开发阶段的debug模式建议打开,用于检查各类埋点参数使用是否合理。线上发布前请关闭,保证App的稳定性。
/**
* Enable [StrictMode] will check all api criteria while running and throw errors if wrong.
* It is recommended to turn on strict mode in DEBUG mode and turn it off before publish.
* This will make sure all usages are correct and make the data engineering easier.
*
* @param strictMode default false
*/
public void setStrictMode(boolean strictMode);
2. 埋点接口
2.1 Tracking埋点
埋点相关的API统一由 CoraoolSDK.tracker
接口对象管理。
2.1.1 点击埋点
接口定义:为点击事件增加埋点
/** * Track click event * @param eventName Event name * @param eventValue Event value map */ public void click(String eventName, Map<String, Object> eventValue);
参数说明:
字段 | 类型 | 是否必须 | 解释 | 说明 |
---|---|---|---|---|
eventName | string | 是 | 事件名称 | 标识用户在页面上操作的位置 |
eventValue | Map<String, Object> | 否 | 事件参数 | 和当前事件关联的业务参数,用于离线分析 |
eventValue_key | string | 否 | 事件参数key | 和当前事件关联的业务参数,用于离线分析 |
eventValue_value | string | 否 | 事件参数value | 和当前事件关联的业务参数,用于离线分析 |
示例代码:
Map<String, Object> eventValue = new HashMap<>();
eventValue.put("业务参数key1", 200)
eventValue.put("业务参数key2", "业务参数value2")
CoraoolSDK.tracker.click(String eventName, Map<String, Object> eventValue);
2.1.2 曝光埋点
接口定义:为模块曝光事件增加埋点
/** * Track expose event * @param eventName Event name * @param eventValue Event value map */ public void expose(String eventName, Map<String, Object> eventValue);
参数说明:
字段 | 类型 | 是否必须 | 解释 | 说明 |
---|---|---|---|---|
eventName | string | 是 | 事件名称 | 标识用户在页面上操作的位置 |
eventValue | Map<String, Object> | 否 | 事件参数 | 和当前事件关联的业务参数,用于离线分析 |
eventValue_key | string | 否 | 事件参数key | 和当前事件关联的业务参数,用于离线分析 |
eventValue_value | string | 否 | 事件参数value | 和当前事件关联的业务参数,用于离线分析 |
示例代码:
Map<String, Object> eventValue = new HashMap<>();
eventValue.put("业务参数key1", 200)
eventValue.put("业务参数key2", "业务参数value2")
CoraoolSDK.tracker.expose(String eventName, Map<String, Object> eventValue);
2.1.3 自定义埋点
接口定义:增加自定义埋点
/** * Track custom event * @param eventName Event name * @param eventValue Event value map */ public void custom(String eventName, Map<String, Object> eventValue)
参数说明:
字段 | 类型 | 是否必须 | 解释 | 说明 |
---|---|---|---|---|
eventName | string | 是 | 事件名称 | 标识用户在页面上操作的位置 |
eventValue | Map<String, Object> | 否 | 事件参数 | 和当前事件关联的业务参数,用于离线分析 |
eventValue_key | string | 否 | 业务参数key | 和当前事件关联的业务参数,用于离线分析 |
eventValue_value | string | 否 | 业务参数value | 和当前事件关联的业务参数,用于离线分析 |
示例代码:
Map<String, Object> eventValue = new HashMap<>();
eventValue.put("业务参数key1", 200)
eventValue.put("业务参数key2", "业务参数value2")
CoraoolSDK.tracker.custom(String eventName, Map<String, Object> eventValue);
2.1.4 页面埋点
2.1.4.1 采集模式
接口定义:
public void setPageCollectionMode(int mode);
参数说明:
参数 | 解释 | 说明 |
---|---|---|
mode | 页面事件的采集方式 | CoraoolLibConst.PageMode.Manual 手动(默认方式)CoraoolLibConst.PageMode.AUTO 自动 |
示例代码:
// 自动采集选择:仅支持采集activity,在使用AUTO模式时,可以叠加手动模式,实现方式看#自动埋点API
CoraoolSDK.tracker.setPageCollectionMode(CoraoolLibConst.PageMode.AUTO);
//手动采集选择:支持activity和非activity,默认手动
CoraoolSDK.tracker.setPageCollectionMode(CoraoolLibConst.PageMode.Manual);
2.1.4.2 自动埋点
接口定义:增加页面事件的埋点参数
/** * Add properties to this page which will be submitted in the Page Event. * Example: * When a customer opens a product detail page in a shopping app, we can append * the product itemId to the page event using this method. Later we can do some * analysis based on these properties. * * @param pageObject Activity * @param properties data */ public void updatePageProperties(Object pageObject, Map<String, Object> properties)
参数说明:
方法名称 | 参数 | 解释 | 说明 |
---|---|---|---|
updatePageProperties | pageObject | 页面Activity对象 | |
properties | 更新参数 | 只应用于当前页面 |
示例代码
/**
* 添加页面事件的参数,仅对当前页面实例生效
*/
Map<String, Object> properties = new HashMap<>();
eventValue.put("业务参数key1", 200)
eventValue.put("业务参数key2", "业务参数value2")
CoraoolSDK.tracker.updatePageProperties(Object pageObject, Map<String, Object> properties);
2.1.4.3 手动埋点
接口定义
1.1 页面展现的时候调用(onResume)
public void trackPageStart(Object pageObject)
1.2 页面展现的时候调用,并通过API指定页面名称(onResume)
public void trackPageStart(Object pageObject, String customPageName);
1.3页面展现的时候调用,并通过API指定页面名称,仅在页面自动埋点时需要(onResume)
public void trackPageStart(Object pageObject, String customPageName, boolean skipPage)
2. 页面退出的时候调用(onPause)
public void trackPageEnd(Object pageObject);
参数说明:
方法名称 | 参数 | 解释 | 说明 |
---|---|---|---|
trackPageStart | pageObject | 页面Activity对象 | |
customPageName | 自定义页面名称 | ||
skipPage | 是否跳过本次的页面事件 | 仅开启页面自动埋点时有用 | |
trackPageEnd | pageObject | 页面Activity对象 | |
customPageName | 自定义页面名称 |
/**
* 页面展现的时候调用(onResume)
*/
protected void onResume() {
super.onResume();
CoraoolSDK.tracker.trackPageStart(homeActivity);
}
/**
* 页面退出的时候调用(onPause)
*/
protected void onPause() {
super.onPause();
CoraoolSDK.tracker.trackPageEnd(Object pageObjet);
}
2.2 GTX埋点协议
请查看 AndroidGTX对接手册
3. Invoke API接口
Coraool SDK提供了基于API的数据服务,并且定义了一套通用且对调用方非常友好的接口,通过Coraool SDK发起 Invoke 接口调用通常包含以下4个步骤:
3.1 构造Response
com.coraool.CoraoolResponse
是对Coraool API协议的封装,包含了3个字段,如果不关心请求的结果,那么直接用这个类接收请求结果即可;如果有业务数据需要处理,则需要继承这个类,并增加 result 字段,并提供getter和setter方法,按照Coraool API协议的约定,API调用返回的业务参数会保存在这个Map结构内。SDK会自动进行反序列化,方便应用层直接使用。
参数说明:
参数 | 类型 | 解释 | 说明 |
---|---|---|---|
success | boolean | 本次请求是否成功 | 当且仅当这个字段为true时,返回结果才有效 |
code | int | 错误码 | 200表示成功,其他值类似http状态的定义,如果返回负数表示SDK自己发生了异常,具体的错误码由CoraoolResponse 的常量进行定义 |
message | string | 请求结果的文本描述 | 仅仅用于协助排查请求过程,不能用于业务逻辑的判断。在请求成功的状态下总是返回 "SUCCESS" ,如果请求出现错误或者异常,则返回对应的错误描述信息,可以根据错误描述信息进行排查或者反馈给技术支持; |
result | any | 自定义的业务数据类型 | 如果需要关注请求的结果,按照Coraool API的协议约定,数据会保存在以 result 为Key的JSON对象内 |
示例代码:
public class CoraoolRankingResponse extends CoraoolResponse {
// RankingData表示具体的业务数据
public RankingData result;
public RankingData getResult() {
return result;
}
public void setResult(RankingData result) {
this.result = result;
}
}
public class RankingData {
public JsonArray ranking;
public JsonObject track;
public String version;
}
3.2 构造Request
通过创建 CoraoolRequest 类型的对象,构造符合 Coraool API 协议的请求参数
参数说明:
参数 | 类型 | 解释 | 说明 |
---|---|---|---|
apiName | string | 接口名称 | 在Coraool open API 上注册的业务接口,例如open.coraool.home.game.ranking |
apiVersion | string | 接口版本 | 在Coraool open API 上注册的业务版本,例如1.0.0 |
data | any | 请求参数 | 具体的请求参数对象 |
connectTimeout | int | 链接超时,单位毫秒 | 网络连接超时 |
readTimeout | int | 读超时,单位毫秒 | 返回数据流读取超时 |
callbackOnMainThread | boolean | 回调主线程的开关 | 是否回调到UI主线程,默认是true,对于非直接显示的数据,建议设置为false,让请求回调到后台线程,方便对数据进行二次处理 |
示例代码:
CoraoolRequest request = new CoraoolRequest();
request.setApiName("open.coraool.home.game.ranking");
request.setApiVersion("1.0.0");
request.setCallbackOnMainThread(true);
request.setReadTimeout(3 * 1000);
request.setData(new HashMap<String, Object>(){{
put("userId", "登录用户ID");
put("afId", "appsFlyer的ID");
put("deviceId", "设备ID");
}});
3.3 发起请求
SDK的请求API分为同步请求和异步请求,统一封装在 CoraoolSDK.api 的接口对象下
3.3.1 同步请求
接口定义:
/**
* Send a coraool request synchronously.
*
* @param clz Response class type
* @param request request complies with coraool api protocol
* @return response complies with coraool api protocol
* @param <T> { body }
*/
public <T extends CoraoolResponse> T syncInvoke(Class<T> clz,
CoraoolRequest request)
/**
* Send a request synchronously. If the callback interface is provided,
* the interface will be invoked before this method returns.
*
* @param clz Response class type
* @param request request complies with coraool api protocol
* @param callback callback when done
* @return response complies with coraool api protocol
* @param <T> { body }
*/
public <T extends CoraoolResponse> T syncInvoke(Class<T> clz,
CoraoolRequest request,
CoraoolNetCallback<T> callback)
参数说明:
参数名 | 类型 | 解释 | 说明 |
---|---|---|---|
clz | Class<T> | 返回对象类的Class | 对应第一步Reponse对象类的Class |
request | CoraoolRequest | 请求参数 | 对应第二步请求参数对象 |
callback | CoraoolNetCallback<T> | 回调Callback | 如果提供了Callback接口参数,则本次请求总是会回调到Callback接口中的一个方法,接口方法的定义看下一步 |
返回值说明:
返回值 | 类型 | 解释 | 说明 |
---|---|---|---|
response | <T extends CoraoolResponse> | 返回对象类 | 对应第一步Reponse的对象实例,仅当对象无法被反射实例化的时候,才会出现null,所以一定要保留无参构造器 |
示例说明:
private void syncRequest() {
CoraoolRequest request = new CoraoolRequest();
request.setApiName("open.coraool.home.game.ranking");
request.setApiVersion("1.0.0");
request.setData(new HashMap<String, Object>(){{
put("userId", "123");
put("afId", "afIdx");
put("deviceId", "devicedevice");
}});
CoraoolRankingResponse response = CoraoolSDK.api.
.syncInvoke(CoraoolRankingResponse.class, request);
}
3.3.2 异步请求
接口定义:
/**
* Send a request asynchronously. If the callback interface is provided,
* the interface will be invoked before this method returns.
*
* @param clz Response class type
* @param request request complies with coraool api protocol
* @param <T> { body }
*/
public <T extends CoraoolResponse> void asyncInvoke(Class<T> clz,
CoraoolRequest request)
/**
* Send a request asynchronously. If the callback interface is provided,
* the interface will be invoked before this method returns.
*
* @param clz Response class type
* @param request request complies with coraool api protocol
* @param callback callback when done
* @param <T> { body }
*/
public <T extends CoraoolResponse> void asyncInvoke(Class<T> clz,
CoraoolRequest request,
CoraoolNetCallback<T> callback)
参数说明:
参数名 | 类型 | 解释 | 说明 |
---|---|---|---|
clz | Class<T> | 返回对象类的Class | 对应第一步Reponse对象类的Class |
request | CoraoolRequest | 请求参数 | 对应第二步请求参数对象 |
callback | CoraoolNetCallback<T> | 回调Callback | 如果提供了Callback接口参数,则本次请求总是会回调到Callback接口中的一个方法,接口方法的定义看下一步 |
示例说明:
private void asyncRequest() {
CoraoolRequest request = new CoraoolRequest();
request.setApiName("open.coraool.home.game.ranking");
request.setApiVersion("1.0.0");
request.setCallbackOnMainThread(true);
request.setReadTimeout(5 * 1000);
request.setData(new HashMap<String, Object>(){{
put("userId", "123");
put("afId", "afIdx");
put("deviceId", "devicedevice");
}});
CoraoolSDK.api.asyncInvoke(CoraoolRankingResponse.class, request, new CoraoolNetCallback<CoraoolRankingResponse>() {
@Override
public void onSuccess(CoraoolRankingResponse response) {
Log.e("TAG", "Success: " + JSON.toJSONString(response));
}
@Override
public void onFailed(int code, String message) {
Log.e("TAG", String.format("Failed: code=%d, message=%s", code, message));
}
@Override
public void onSystemError(int code, String message) {
Log.e("TAG", String.format("Error: code=%d, message=%s", code, message));
}
});
}
3.4 接口回调
接口回调用于接收正确和异常的结果
接口 | 参数 | 类型 | 解释 | 说明 |
---|---|---|---|---|
onSuccess | response | T | 返回对象的类型 | 请求被正确处理的时候返回,对应 success=true |
onFailed | code | int | 请求错误码 | 对应success=false的场景,如果签名错误、无效token等 |
message | string | 错误描述 | ||
onSystemError | code | int | 请求错误码 | 各类系统错误,如网络未连接、授权错误、数据解析异常等 |
message | string | 错误描述 |
public interface CoraoolNetCallback<T> {
/**
* Totally success including network and business
*
* @param response response body {@link CoraoolResponse}
*/
void onSuccess(T response);
/**
* Send request successfully but the response data contains business error, like
* invalid appKey, signature mismatch, params illegal and so on.
*
* @param code error reason code leverages http status definition
* @param message plaintext explaining the error reason.
*/
void onFailed(int code, String message);
/**
* Errors like network not connected, auth error, protocol error and so on
*
* @param code {@link CoraoolLibConst}
* @param message plaintext explaining the error reason.
*/
void onSystemError(int code, String message);
}
4. Abtest 接口
ABTest相关的API统一由 CoraoolSDK.ab
接口对象管理。
4.1 初始化Abtest功能
通过重载 com.coraool.IParamProvider
接口的 isEnableAbtest
方法,即可开启Abtest功能。需要注意的事项:
- Abtest模块的功能默认是打开的;
- 用户身份标识会用于实验分桶的计算,所以类似userId的参数需要尽早设置,建议在调用initialize方法前完成
public class CApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// 用户身份标识请在SDK初始化之前设置,因为后续初始化过程需要用到
CoraoolSDK.setting.setUserId("123abc");
CoraoolSDK.setting.setCustomDeviceId("my_unique_device_id");
CoraoolSDK.initialize(this, new IParamProvider() {
...
// 通过重载此方法,开始Abtest模块功能
@Override
public boolean isEnableAbtest() {
return true;
}
});
}
}
4.2 获取单实验分桶
接口定义
public String getABTest(String experimentName)
参数说明
参数 | 解释 | 说明 |
---|---|---|
experimentName | 实验名称 | 在实验平台上创建的实验名称 |
示例代码
String bucket = CoraoolSDK.ab.getABTest("HP_SEARCH_ENTRY_POS");
if ("bucket_a".equals(bucket)) {
// do something for a
} else if ("bucket_b".equals(bucket)) {
// do something for b
}
4.3 获取单实验分桶对象
接口定义
public CoraoolABTest getABTestObject(String experimentName)
参数说明
参数 | 解释 | 说明 |
---|---|---|
experimentName | 实验名称 | 在实验平台上创建的实验名称 |
示例代码
CoraoolABTest abtest = CoraoolSDK.ab.getABTestObject("HP_SEARCH_ENTRY_POS");
4.4 获取全部实验分桶
接口定义
List<CoraoolAbtest> getABTestListAll()
参数说明
参数 | 解释 | 说明 |
---|---|---|
无 | 无 | 无 |
示例代码
List<CoraoolABTest> buckets = CoraoolSDK.ab.getABTestListAll();
AndroidGTX对接手册
1. GTP/GTC流量追踪
GTX埋点用于页面流量的追踪和分析,可以解决如下关键业务问题:
- 统计指定页面的PV、UV等基础指标;
- 追踪页面流量的来源和去向,分析用户路径的流量漏斗;
- 基于流量和转化评估,告知业务方,每个页面以及页面内坑位的流量效率;
- Global Tracking Position(GTP):全局位置跟踪模型,用于追踪位置以及不同位置之间流量的流转;
- Global Tracking Content(GTC):全局内容跟踪模型,用于跟踪投放内容以及引导转化效率;
- Global Tracking X (GTX):指代 GTP、GTC 构成的解决方案;
- pageName:页面事件的事件名
1.1 GTP参数定义
GTP参数定义:a.b.c.d = ${appId}.${pageName}.${module}.${point}
,GTP需要严格按照如下规范进行构造和使用,UI层通过结构化的数据构造这4层结构(建议用这种方式),也可以通过手动的方式构造。
GTP | 含义 | 说明 |
---|---|---|
a位 | ${appId} | 不同端独立分配,对应SDK初始化参数的appId,全局唯一 |
b位 | ${pageName} | 由产品指定并申请,在当前 ${app} 内唯一,b位由接入方维护,通过文档或者系统登记 |
c位 | ${moduleId} | 页面的楼层或者区块编号,在当前页面 ${pageName} 内唯一 |
d位 | ${pointId} | 楼层内细分的点位编号,在当前模块 ${moduleId} 内唯一 |
1.2 GTC参数定义
GTC参数定义:a.b.c.d = ${sysId}.${algoId}.${algoVer}.${audienceId}
,GTC也包含4层结构,在不同层级上的定义
GTC | 含义 | 说明 |
---|---|---|
a位 | ${sysId} | 投放系统 ID,用来标识不同的内容投放方 |
b位 | ${algoId} | 投放算法 ID,用来标识投放系统产生不同内容的投放算法 |
c位 | ${algoVer} | 投放算法版本 ID,用来标识投放算法的不同版本 |
d位 | ${audienceId} | 投放人群 ID,用来标识不同的投放人群 |
2.埋点接入
2.1 埋点时机说明
每个页面事件包含: [开始 -> 过程 -> 结束] 这三个阶段,每个阶段需要严格按照文档说明调用CoraoolSDK的API方法,使得每个页面事件的区间完整闭合,最终页面事件会构成一个序列来表述用户的动线。
首先需要定义清楚页面是什么?从用户视角看,页面应该是用户在手机上看到一屏内容,典型的比如:由Activity实现的搜索结果页、由Activity实现的详情页、会场页由Fragment实现多个Tab,每个tab也可以被定义为一个页面,请遵循您的产品或者业务方对页面的定义来进行划分。
下面按不同的页面定义来说明埋点API应该在什么时刻被调用,请关注下图红线的指示:
暂时无法在Lark文档外展示此内容
2.2 GTX传参方式
上面介绍完GTX调用时机,这一节讲解怎么把GTX参数从一个页面传到另一个页面。因为Android系统提供了多种传参方式,不同类型的页面也不尽相同,所以前后两个页面的传参方式需要事先约定好协议,下面分别对Activity和Fragment进行说明。
2.2.1 Activity页面传参
方式1:通过Intent#putExtra(key, value)
,可以把参数从 FromActivity 传递到 ToActivity,对于CoraoolSDK,我们定义了 CoraoolLibConst.KEY_GTP
和CoraoolLibConst.KEY_GTC
两个常量Key作为约定,ToActivity会尝试读取这两个key的值:
findViewById(R.id.you_view_id).setOnClickListener(v -> {
// 把GTX参数从FromActivity传到ToActivity,这样ToActivity读取KEY_GTP/KEY_GTC就可以知道页面来源
Intent intent = new Intent(FromActivity.this, ToActivity.class);
intent.putExtra(CoraoolLibConst.KEY_GTP, "四位gtp构成的值,指代当前页面");
intent.putExtra(CoraoolLibConst.KEY_GTC, "四位gtc构成的值,指代当前内容");
FromActivity.this.startActivity(intent);
}
方式2:通过Intent#setData(Uri)
,可以把参数从FromActivity传递到ToActivity,对于CoraoolSDK,我们定义了 CoraoolLibConst.KEY_GTP
和CoraoolLibConst.KEY_GTC
两个常量Key作为约定,ToActivity会尝试读取这两个key的值:
findViewById(R.id.you_view_id).setOnClickListener(v -> {
// 执行切换Activity
Uri uri = Uri.parse("protocol://your.uri?k1=v1&k2=v2").buildUpon()
.appendQueryParameter(CoraoolLibConst.KEY_GTP, "四位gtp构成的值,指代当前页面");
.appendQueryParameter(CoraoolLibConst.KEY_GTC, "四位gtc构成的值,指代当前内容");
.build();
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
方式3:通过在点击事件上增加gtp,gtc参数,系统会自动捕获点击事件里的gtp,gtc作为页面的来源
findViewById(R.id.you_view_id).setOnClickListener(v -> {
Map<String, Object> eventValue = new HashMap<>();
String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "item", "1");
eventValue.put(CoraoolLibConst.KEY_GTP, "四位gtp构成的值,指代当前页面");
eventValue.put(CoraoolLibConst.KEY_GTC, "四位gtc构成的值,指代当前页面");
CoraoolSDK.tracker.click("GotoNextActivity", eventValue);
// 执行切换Activity
Intent intent = new Intent(FromActivity.this, ToActivity.class);
FromActivity.this.startActivity(intent);
});
CoraoolSDK同时支持这3种传参方式,使用的时候三选一,如果存在多个,则优先级:方式1 > 方式2 > 方式3
对于大多数场景,第三种的接入方式最优化,只需要关注对应的点击事件即可,第1/2种方式需要用户对GTP/GPC的原理有比较深入的理解;
2.2.2 Fragment页面传参
通过 Framgent.setArguments(Bundle)
,可以把参数从 FromFragment 传递到 ToFragment,对于CoraoolSDK,我们定义了 CoraoolLibConst.KEY_GTP
和CoraoolLibConst.KEY_GTC
两个常量Key作为约定,ToFragment会尝试读取这两个key的值:
方式1:通过Bundle#putString(key, value)
,可以把参数从 FromFragment 传递到 ToFragment,对于CoraoolSDK,我们定义了 CoraoolLibConst.KEY_GTP
和CoraoolLibConst.KEY_GTC
两个常量Key作为约定,ToFragment会尝试读取这两个key的值:
findViewById(R.id.you_view_id).setOnClickListener(v -> {
Fragment toFragment = new Fragment();
Bundle bundle = new Bundle();
bundle.putString(CoraoolLibConst.KEY_GTP, "四位gtc构成的值,指代当前页面");
bundle.putString(CoraoolLibConst.KEY_GTC, "四位gtc构成的值,指代当前内容");
toFragment.setArguments(bundle);
// 执行切换Fragment
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, toFragment)
.commit();
}
方式2:通过在点击事件上增加gtp,gtc参数,系统会自动捕获点击事件里的gtp,gtc作为页面的来源
findViewById(R.id.you_view_id).setOnClickListener(v -> {
Map<String, Object> eventValue = new HashMap<>();
String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "item", "1");
eventValue.put(CoraoolLibConst.KEY_GTP, "四位gtp构成的值,指代当前页面");
eventValue.put(CoraoolLibConst.KEY_GTC, "四位gtc构成的值,指代当前页面");
CoraoolSDK.tracker.click("GotoNextFragment", eventValue);
// 执行切换Fragment
Fragment toFragment = new Fragment();
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, toFragment)
.commit();
});
2.2.3 TabView传参
以TabView为容器的页面,没有类似Activity和Fragment的标准生命周期,需要以点击的方式增加gtp,gtc参数,类似 #Activity页面传参 的方式3;
方式1:通过在点击事件上增加gtp,gtc参数,系统会自动捕获点击事件里的gtp, gtc作为页面的来源
findViewById(R.id.you_view_id).setOnClickListener(v -> {
Map<String, Object> eventValue = new HashMap<>();
String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "item", "1");
eventValue.put(CoraoolLibConst.KEY_GTP, "四位gtp构成的值,指代当前页面");
eventValue.put(CoraoolLibConst.KEY_GTC, "四位gtc构成的值,指代当前页面");
CoraoolSDK.tracker.click("GotoNextView", eventValue);
// 此处执行切换到下一个TabView的代码实现// 注意:TabView也需要执行在显示和隐藏的时候分别调用 trackPageStart 和 trackPageEnd
...
});
2.3 GTX埋点接口
2.3.1 页面开始
接口定义:
/* 记录页面开始 */ public void trackPageStart(Object pageObject); /* 记录页面开始,并自定页面名称 */ public void trackPageStart(Object pageObject, String customPageName); /* 记录页面开始,并自定页面名称,仅在开启自动埋点的时候使用 */ public void trackPageStart(Object pageObject, String customPageName, boolean skipPage);
参数说明:
参数 | 类型 | 解释 | 是否必须 | 说明 |
---|---|---|---|---|
pageObject | Activity、Fragment、 WebView | 当前页面对象 | 是 | 如果是 Activity 就传入 Activity 对象实例;如果是 Fragment 就传入 Fragment 对象实例;强烈建议让 Activity 和 Fragment 实现 ICoraoolPage 接口,并在接口方法中定义pageName,统一命名方式 |
customPageName | string | 自定义页面名 | 否 | 如果页面对象没有实现 ICoraoolPage 接口,通过这个入参可以自定义页面名称,否则SDK默认会以类名作为页面名,埋点验证时可解释性较差 |
skipPage | boolean | 是否跳过当前页 | 否 | 仅在使用Activity作为页面,并开启自动页面埋点时有意义,其他是否不应该设置该参数 |
示例代码:
public class MyActivity extends AppCompatActivity implements ICoraoolPage {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onResume() {
super.onResume();
CoraoolSDK.tracke.getInstance().trackPageStart(this);
}
}
2.3.2 添加页面参数
接口定义:
public void updatePageProperties(Object pageObject, Map<String, Object> properties);
参数说明:
参数 | 类型 | 解释 | 是否必须 | 说明 |
---|---|---|---|---|
pageObject | Activity、Fragment、 WebView | 当前页面对象 | 是 | 如果是 Activity 就传入 Activity 对象实例;如果是 Fragment 就传入 Fragment 对象实例;强烈建议让 Activity 和 Fragment 实现 ICoraoolPage 接口,并在接口方法中定义pageName,统一命名方式 |
properties | Map<String, Object> | 自定义业务参数 | 否 | 把这些业务参数附加到当前页面事件中,用于离线业务分析,比如当前页面的展示的商品ID、SKU ID等,在页面结束之前,任意时刻都可以调用这个方法来收集运行使用过程中的业务参数。请参考上面的 #埋点时机说明 |
示例代码:
Map<String, Object> bizProps = new HashMap<String, Object>() {{
put("例如itemId", "123456789");
put("例如skuId", "987654321");
}};
CoraoolSDK.tracker.updatePageProperties(this, bizProps);
2.3.3 页面结束
调用这个方法意味着当前页面已经结束了,所有参数已经收集完成,将会触发页面事件提交。
接口定义:
public void trackPageEnd(Object pageObject);
参数说明:
参数 | 类型 | 是否必须 | 解释 | 说明 |
---|---|---|---|---|
pageObject | Activity、Fragment、 WebView | 是 | 当前页面对象 | 如果是 Activity 就传入 Activity 对象实例;如果是 Fragment 就传入 Fragment 对象实例;强烈建议让 Activity 和 Fragment 实现 ICoraoolPage 接口,并在接口方法中定义pageName,统一命名方式 |
示例代码:
public class MyActivity extends AppCompatActivity implements ICoraoolPage {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onPause() {
super.onPause();
CoraoolSDK.tracker.trackPageEnd(this);
}
}
2.3.4 构造GTP参数
接口定义:
public String buildGtp(String gtp_b, String gtp_c, String gtp_d) ;
参数说明:
参数 | 类型 | 是否必须 | 解释 | 说明 |
---|---|---|---|---|
gpt_b | string | 是 | GTP 的 b 位 | |
gpt_c | string | 是 | GTP 的 c 位 | |
gpt_d | string | 是 | GTP 的 d 位 |
示例代码:
// 构造gtp参数
String gtp = CoraoolSDK.tracker.buildGtp("home", "topbar", "btn_show_number");
String gtp = CoraoolSDK.tracker.buildGtp("home", "topbar", "btn_new_fresh");
// 如果页面对象已经实现了 ICoraoolPage 接口,可以直接调用 getPageName() 获取GTP的B位
String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "topbar", "btn_new_fresh");
3. 完整示例
3.1 Activity页面示例
/**
* 备注:接入方的App通过定义接口 ICoraoolPage,可以规范各个页面获取名称和ID的方式
*/
public class MyPageActivity extends AppCompatActivity implements ICoraoolPage {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_track_home_page);
// 选择方式1:通过putExtra传参
findViewById(R.id.you_view_id_intent).setOnClickListener(v -> {
String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "topbar", "btn_checkin");
Intent intent = new Intent(HomePageActivity.this, ListPageActivity.class);
intent.putExtra(CoraoolLibConst.KEY_GTP, gtp);
intent.putExtra(CoraoolLibConst.KEY_GTC, "四位gtc构成的值");
HomePageActivity.this.startActivity(intent);
});
// 选择方式2:通过构造Uri传参
findViewById(R.id.you_view_id_uri).setOnClickListener(v -> {
String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "topbar", "btn_checkin");
Uri uri = Uri.parse("protocol://your.uri?k1=v1&k2=v2").buildUpon()
.appendQueryParameter(CoraoolLibConst.KEY_GTP, gtp)
.appendQueryParameter(CoraoolLibConst.KEY_GTC, "四位gtc构成的值");
.build();
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
});
// 选择方式3:在点击事件里增加gtp参数
findViewById(R.id.you_view_id_click).setOnClickListener(v -> {
// 先提交点击事件
String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "topbar", "btn_checkin");
Map<String, Object> eventValue = new HashMap<>();
eventValue.put(CoraoolLibConst.KEY_GTP, gtp);
eventValue.put(CoraoolLibConst.KEY_GTC, "四位gtc构成的值");
CoraoolSDK.tracker.click("TopbarButtonCheckIn", eventValue);
// 再执行页面跳转
Intent intent = new Intent(HomePageActivity.this, ListPageActivity.class);
HomePageActivity.this.startActivity(intent);
});
}
@Override
protected void onResume() {
super.onResume();
CoraoolSDK.tracker.trackPageStart(this);
}
@Override
protected void onPause() {
super.onPause();
CoraoolSDK.tracker.trackPageEnd(this);
}
@Override
public String getPageName() {
return "home"
}
}
3.2 Fragment页面示例
Fragment切换时的生命周期回调和Activity不同,系统会先调用ToFragment的创建方法并启动,再回调FromFragment的结束和销毁方法,针对这种情况,SDK已经做了兼容处理:
/**
* 备注:接入方的App通过定义接口 ICoraoolPage,可以规范各个页面获取名称和ID的方式
*/
public static final class MyPageFragment extends Fragment implements ICoraoolPage {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_track_tab, container, false);
// 选择方式1:通过Bundle传递gtp参数
findViewById(R.id.you_view_id).setOnClickListener(v -> {
Bundle bundle = new Bundle();
String gtp = ;CoraoolSDK.tracker.buildGtp(getPageName(), "topbar", "btn_checkin")
bundle.putString(CoraoolLibConst.KEY_GTP, gtp);
bundle.putString(CoraoolLibConst.KEY_GTC, "四位gtc构成的值");
MyFragment fragment = new MyFragment();
fragment.setArguments(bundle);
getFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment).commit();
});
// 选择方式2:在点击事件里增加gtp参数
findViewById(R.id.you_view_id).setOnClickListener(v -> {
// 先提交点击事件
Map<String, Object> eventValue = new HashMap<>();
String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "item", "1");
eventValue.put(CoraoolLibConst.KEY_GTP, gtp);
eventValue.put(CoraoolLibConst.KEY_GTC, "四位gtc构成的值");
CoraoolSDK.tracker.click("GotoNextFragment", eventValue);
// 再执行切换Fragment
Fragment toFragment = new Fragment();
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, toFragment)
.commit();
});
return root;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
@Override
public void onStart() {
super.onStart();
}
@Override
public void onResume() {
super.onResume();
CoraoolSDK.tracker.trackPageStart(this);
}
@Override
public void onPause() {
super.onPause();
CoraoolSDK.tracker.trackPageEnd(this);
}
@Override
public void onStop() {
super.onStop();
}
@Override
public String getPageName() {
return "Category";
}
}
3.3 TabView页面示例
/**
* 备注:接入方的App通过定义接口 ICoraoolPage,可以规范各个页面获取名称和ID的方式
*/
public static final class MyPageTab extends TabLayout implements ICoraoolPage {
private void onCreateTab() {
// 选择方式2:在点击事件里增加gtp参数
findViewById(R.id.you_view_id).setOnClickListener(v -> {
// 先提交点击事件
Map<String, Object> eventValue = new HashMap<>();
String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "item", "1");
eventValue.put(CoraoolLibConst.KEY_GTP, gtp);
eventValue.put(CoraoolLibConst.KEY_GTC, "四位gtc构成的值");
CoraoolSDK.tracker.click("GotoNextTabt", eventValue);
// 再执行切换TabView
...
});
}
/** 在Tab页出现的时候调用此方法 */
private void viewAppear() {
CoraoolSDK.tracker.trackPageStart(this);
}
/** 在Tab页消失的时候调用此方法 */
private void viewDisappear() {
CoraoolSDK.tracker.trackPageEnd(this);
}
}
3.4 H5页面示例
H5页面可以在单个WebView内跳转,而Webview可以使用Activity或Fragment作为容器,SDK无法感知页面的跳转时机,所以对于H5页面的GTP、GTC打点,完全由H5控制,通过JsBridge调用页面事件的API。
Comments (0)