1.如何查看埋点方案
在进行埋点前,需要确定在哪里埋点、埋哪些点等,即需要梳理清楚明确的埋点需求。在Quick Tracking平台中将明确的埋点需求称为埋点方案,并为埋点方案设计了规范模板。如下:
在埋点方案中,明确的所需埋点内容有:
1、事件主体:指“谁”触发了这个事件,分为设备ID和账号ID,上报的事件务必具备其中之一。
设备ID:Windows设备默认设备ID为应用级别唯一的设备ID,由Quick Tracking SDK自动生成或者通过调用setCustomDeviceId接口设置。
账号ID:客户端用户登录体系的账号标识,当一个用户在不同的设备进行登录时,设备ID会发生变化,但是账号ID不会发生变化。例如一个用户使用电脑和pad分别登录。
2、用户属性:针对账号ID的属性,例如账号ID为“testdemo@111”的用户,“生日”为“1999-02-13”,“会员等级”为“铂金”等。“生日”和“会员”等级就为用户属性。
3、全局属性:在全局设置一次后,每一个事件都会携带的属性
4、页面浏览事件:页面加载时上报的事件(埋点方案中页面编码和事件编码相等的事件,也是标记为蓝色的事件)
5、点击、曝光、自定义事件:客户端用户与客户端发生任意交互时上报的事件。
2 埋点须知
传入的参数不支持单引号、数据类型等特殊字符串,否则可能导致事件落库失败而使数据丢失。
使用中文参数时需要源码文件编码是合法的 Unicode(UTF-8 无签名)编码。
除日志开关接口,其他接口的使用需要在调用initQTPC之后使用才能正常生效。
windows10.x版本通过GetVersionEx获取系统版本不准确问题,需要在项目文件夹里添加manifest文件,并在项目属性->清单工具->输入和输出->附加清单文件里增加manifest文件,以下为示例文件。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"> <asmv3:application> <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings"> <dpiAware>false</dpiAware> </asmv3:windowsSettings> </asmv3:application> <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> <!-- Windows 10 and Windows 11 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> <!-- Windows 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> <!-- Windows 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> <!-- Windows 7 --> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> <!-- Windows Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> </application> </compatibility> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <security> <requestedPrivileges> <!-- UAC settings: - app should run at same integrity level as calling process - app does not need to manipulate windows belonging to higher-integrity-level processes --> <requestedExecutionLevel level="asInvoker" uiAccess="false" /> </requestedPrivileges> </security> </trustInfo> </assembly>
传入参数大小限制:
//自定义属性以及全局属性的key和value超过上限则无法设置成功
const size_t kStringPropertyValueMaxLength = 4096; //自定义属性以及全局属性value的字符串上限
const size_t kStringPropertyKeyMaxLength = 1024; //自定义属性以及全局属性key的字符串上限
const size_t kStringArrayValueMaxSize = 100; //自定义属性字符串数组长度的上限,超过上限则截断
const size_t kStringMapValueMaxSize = 50; //全局属性集合的上限,超过上限则无法继续插入
const size_t kStringEventCodeMaxLength = 500; //事件编码最大的长度
3. 设备ID&账号ID&用户属性设置
3.1 设备ID
SDK支持自定义设备ID,如果要使用自定义设备ID,需要设置setCustomDeviceId 接口为有效值(非空)。
接口函数:
// 设置自定义设备ID
QTFORPC_API QT_VOID setCustomDeviceId(QT_CSTR deviceId);
参数:
参数 | 类型 | 描述 | 是否必填 |
deviceId | const char * | 自定义设备ID,非空字符串 | 是 |
示例:
string customDeviceId = "testId";
qtInterface->setCustomDeviceId(customDeviceId.c_str());
3.2 账号ID
3.2.1 用户登入
Quick Tracking SDK在统计用户时以设备为标准,如果需要统计自身的账号,请使用以下方法。
接口函数:
// 登录
QTFORPC_API QT_VOID onProfileSignIn(QT_CSTR userID, QT_CSTR nick);
参数:
参数 | 类型 | 描述 | 是否必填 |
userID | const char * | 用户账号ID,非空字符串 | 是 |
nick | const char * | 用户昵称 | 否,没有可传空字符串 |
示例:
qtInterface->onProfileSignIn("userId", "userNick");
3.2.2 用户登出
如果不再需要绑定用户账号,可以调用SDK提供的用户登出方法,调用后SDK不再发送用户账号相关内容。
接口函数:
// 登出
QTFORPC_API QT_VOID onProfileSignOff();
示例:
qtInterface->onProfileSignOff();
3.3 用户属性上传
使用事件编码固定为$$_user_profile
自定义事件上传,该事件所携带的事件属性会被作为用户属性放在用户表中。
注:使用uploadUserProfile需要保证在onPageStart后以及onPageEnd前调用才能保证数据准确性。
接口函数:
// 用户属性上传
QTFORPC_API QT_VOID uploadUserProfile(QT_VSTR pageObj, QT_MAP customProperties);
参数:
参数 | 类型 | 描述 | 是否必填 |
pageObj | void * | 建议使用容器对WNDCLASS | 是 |
customProperties | const char * | 业务参数,参数需要传入json字面量模板字符串 | 是 |
示例:
WNDCLASS *wndClass = new WNDCLASS();
qtInterface->onPageStart(wndClass, "PageName");
std::string cusp = R"({
"age": 18,
"level": "王者",
"name": "coolboy",
})";
qtInterface->uploadUserProfile(wndClass, cusp.c_str());
qtInterface->onPageEnd(wndClass);
4. 全局属性
4.1 注册全局属性
接口函数:
// 设置全局属性
QTFORPC_API QT_VOID registerGlobalProperty(QT_CSTR key, QT_CSTR value);
参数:
参数 | 类型 | 描述 | 是否必填 |
key | const char * | 设置的全局属性key | 是 |
value | const char * | 设置的全局属性value | 是 |
示例:
qtInterface->registerGlobalProperty("key", "value");
注意:如果和已经存在的全局属性key重复,则更新已有值;如果和已经存在的全局属性key不一致,则插入新的全局属性。
4.2 删除一个全局属性
接口函数:
// 根据Key删除全局属性
QTFORPC_API QT_VOID unregisterGlobalProperty(QT_CSTR key);
参数:
参数 | 类型 | 描述 | 是否必填 |
key | const char * | 要删除的全局属性key | 是 |
示例:
qtInterface->unregisterGlobalProperty("key");
4.3 根据key获取单个全局属性
接口函数:
// 根据Key获取全局属性
QTFORPC_API QT_VOID getGlobalProperty(QT_CSTR key, QT_STR value, QT_INT size);
参数:
参数 | 类型 | 描述 | 是否必填 |
key | const char * | 要获取的全局属性key | 是 |
value | char * | 要获取的全局属性value | 是 |
size | int | 全局属性value长度 | 是 |
示例:
// 大小根据需求设定
char value[64] = { 0 };
qtInterface->getGlobalProperty("key", value, 64);
string myValue = value;
4.4 获取所有全局属性
接口函数:
// 获取全部全局属性
QTFORPC_API QT_VOID getGlobalProperties(QT_STR properties, QT_INT size);
参数:
参数 | 类型 | 描述 | 是否必填 |
properties | char * | 要获取的全局属性集合 | 是 |
size | int | 全局属性value长度 | 是 |
示例:
// 大小根据需求设定
char properties[128] = { 0 };
qtInterface->getGlobalProperties(properties);
std::map<string, string> myProperties = QT::Helper::QT_DeserializePerson(properties, 128);
注意:获取到的properties需要通过QT::Helper::QT_DeserializePerson接口来转成std::map。
5. 页面浏览事件
5.1 页面手动采集
注意:
onPageStart 是SDK记录页面进入的信息,onPageStart不会上报事件,只有调用onPageEnd的时候才会上报页面浏览事件。
onPageStart和onPageEnd必须成对调用,且传值的pageObj需要保持一致,如果没有onPageEnd或者onPageEnd与onPageStart传值的pageObj不一致,则onPageStart记录的信息不会生效,影响页面事件采集的准确性。
接口函数:
// 页面开始展现
QTFORPC_API QT_VOID onPageStart(QT_VSTR pageObj, QT_CSTR pageName);
// 页面开始消失
QTFORPC_API QT_VOID onPageEnd(QT_VSTR pageObj);
参数:
参数 | 类型 | 描述 | 是否必填 |
pageObj | void * | 建议使用容器对象WNDCLASS,在同一个页面内,调用onPageEnd时,需要传入onPageStart相同的pageObj | 是 |
pageName | const char * | 页面事件的事件编码 | 是 |
示例:
WNDCLASS *wndClass = new WNDCLASS();
qtInterface->onPageStart(wndClass, "PageName");
qtInterface->onPageEnd(wndClass);
5.2 设置页面事件属性
接口函数:
// 设置页面事件参数
QTFORPC_API QT_VOID updatePageProperties(QT_VSTR pageObj, QT_MAP pageProperties);
参数:
参数 | 类型 | 描述 | 是否必填 |
pageObj | void * | 建议使用容器对象WNDCLASS,在同一个页面内,调用updatePageProperties时,需要传入onPageStart相同的pageObj | 是 |
pageProperties | const char * | 页面参数,对应页面事件日志中的事件属性,参数需要传入json字面量模板字符串 | 是 |
示例:
WNDCLASS *wndClass = new WNDCLASS();
qtInterface->onPageStart(wndClass, "PageName");
std::string cusp = R"({
"param_str": "hello c++",
"param_num": 1900,
"param_bool": true,
"param_list": ["hello", "world", "c++"]
})";
qtInterface->updatePageProperties(wndClass, cusp.c_str());
qtInterface->onPageEnd(wndClass);
5.3 容器跳过
跳过当前页面(容器内的子页面)的前一个页面(来源页为容器页)。
接口函数:
// 跳过某个容器,用于多容器嵌套
QTFORPC_API QT_VOID skipPage(QT_VSTR pageObj);
参数 | 类型 | 描述 | 是否必填 |
pageObj | void * | 建议使用容器对象WNDCLASS,在同一个页面内,调用skipPage时,需要传入onPageStart相同的pageObj | 是 |
示例:
WNDCLASS *wndClass = new WNDCLASS();
qtInterface->onPageStart(wndClass, "firstPage");
std::string cusp = R"({
"param_str": "hello c++",
"param_num": 1900,
"param_bool": true,
"param_list": ["hello", "world", "c++"]
})";
qtInterface->updatePageProperties(wndClass, cusp.c_str());
qtInterface->onPageEnd(wndClass);
WNDCLASS *wndClass1 = new WNDCLASS();
qtInterface->onPageStart(wndClass1, "secondPage");
qtInterface->onPageEnd(wndClass1);
WNDCLASS *wndClass2 = new WNDCLASS();
//跳过thirdPage的上一个页面,也就是secondPage,此时thirdPage的ref_page_name(来源页)为firstPage,如果不调用skipPage则ref_page_name(来源页)为secondPage。
qtInterface->skipPage(wndClass2);
qtInterface->onPageStart(wndClass2, "thirdPage");
qtInterface->onPageEnd(wndClass2);
6. 事件埋点
自定义事件可以用于追踪用户行为,记录行为发生的具体细节。
注:使用trackEvent或trackEventWithPageName需要保证在onPageStart后以及onPageEnd前调用才能保证数据准确性。
接口函数:
//埋点事件
QTFORPC_API QT_VOID trackEvent(QT_VSTR pageObj, QT_CSTR id, QT_MAP customProperties);
//埋点事件带页面名称
QTFORPC_API QT_VOID trackEventWithPageName(QT_VSTR pageObj, QT_CSTR id, QT_MAP customProperties, QT_CSTR pageName);
参数:
参数 | 类型 | 描述 | 是否必填 |
pageObj | void * | 建议使用容器对象WNDCLASS,在同一个页面内,调用trackEvent或trackEventWithPageName时,需要传入onPageStart相同的pageObj | 是 |
id | const char * | 事件编码,不能传递以”$$_“开头的参数作为id的非空字符串 | 是 |
customProperties | const char * | 事件属性,参数需要传入json字面量模板字符串 | 否 |
pageName | const char * | 页面编码 | 否 |
示例:
WNDCLASS *wndClass = new WNDCLASS();
qtInterface->onPageStart(wndClass, "PageName");
std::string cusp = R"({
"param_str": "hello c++",
"param_num": 1900,
"param_bool": true,
"param_list": ["hello", "world", "c++"]
})";
qtInterface->trackEventWithPageName(wndClass, "test_event", cusp.c_str(), "PageName");
qtInterface->onPageEnd(wndClass);
7. 手动采集应用启动、退出事件
注:使用enterForeground/enterForegroundWithPageName或enterBackground/enterBackgroundWithPageName需要保证在onPageStart以及和onPageEnd前调用才能保证数据准确性。
接口函数:
// 进入前台
QTFORPC_API QT_VOID enterForeground(QT_VSTR pageObj, QT_MAP customProperties);
// 进入前台带PageName
QTFORPC_API QT_VOID enterForegroundWithPageName(QT_VSTR pageObj, QT_MAP customProperties, QT_CSTR pageName);
// 进入后台
QTFORPC_API QT_VOID enterBackground(QT_VSTR pageObj, QT_MAP customProperties);
// 进入后台带PageName
QTFORPC_API QT_VOID enterBackgroundWithPageName(QT_VSTR pageObj, QT_MAP customProperties, QT_CSTR pageName);
参数:
参数 | 类型 | 描述 | 是否必填 |
pageObj | void * | 建议使用容器对象WNDCLASS,在同一个页面内,调用trackEvent或trackEventWithPageName时,需要传入onPageStart相同的pageObj | 是 |
customProperties | const char * | 业务参数,参数需要传入json字面量模板字符串 | 否 |
pageName | const char * | 页面编码 | 否 |
示例:
WNDCLASS *wndClassForeground = new WNDCLASS();
qtInterface->onPageStart(wndClassForeground, "StartPageName");
std::string start_cusp = R"({
"param_str": "hello c++",
"param_num": 1900,
"param_bool": true,
"param_list": ["hello", "world", "c++"]
})";
qtInterface->enterForeground(wndClassForeground, start_cusp.c_str());
qtInterface->onPageEnd(wndClassForeground);
WNDCLASS *wndClassBackground = new WNDCLASS();
qtInterface->onPageStart(wndClassBackground, "EndPageName");
std::string end_cusp = R"({
"param_str": "hello c++",
"param_num": 1900,
"param_bool": true,
"param_list": ["hello", "world", "c++"]
})";
qtInterface->enterBackground(wndClassBackground, end_cusp.c_str());
qtInterface->onPageEnd(wndClassBackground);
8. 其他
8.1 停止数据保存到本地
调用finiQTPC停止数据落库,目前只有停止方法。
接口函数:
// 反初始化QT
QTFORPC_API QT_VOID finiQTPC(QT_CB cb);
参数:
参数 | 类型 | 描述 | 是否必填 |
cb | void | 回调方法 | 是 |
示例:
void callBackFunc()
{
fprintf(stderr, "finiQTPC callback\n");
}
qtInterface->finiQTPC(callBackFunc);
8.2 实时调试模式
调用turnOnRealTimeDebug开启实时调试模式,上报数据间隔变为三十秒;调用turnOffRealTimeDebug关闭实时调试。
注:应用程序正式上线前请关闭SDK实时调试模式
接口函数:
//开启实时调试模式
QTFORPC_API QT_VOID turnOnRealTimeDebug(QT_MAP configs);
//关闭实时调试
QTFORPC_API QT_VOID turnOffRealTimeDebug();
参数:
参数 | 类型 | 描述 | 是否必填 |
configs | const char * | 配置参数,传入的参数形式必须是map集合,再调用QT::Helper::QT_Serializable序列化 | 是 |
示例:
map<string, string> configs;
configs["debug_key"] = "test";
std::string sconfig;
QT::Helper::QT_Serializable(sconfig, configs);
qtInterface->turnOnRealTimeDebug(sconfig.c_str());
qtInterface->turnOnRealTimeDebug();
8.3 开启快速上传模式
调用setFastUploadMode开启快速上传模式,上报数据间隔变为每秒一上报,默认是三秒一上报。
注:应用程序正式上线前请关闭SDK快速上传模式
接口函数:
//开启快速上传模式
QTFORPC_API QT_VOID setFastUploadMode();
示例:
qtInterface->setFastUploadMode();