1.IOS统计SDK接入说明

1.1 功能描述

此文档是统计日志sdk接入说明。
在游戏及应用开发商需要接入掌趣SDK时,根据该日志向掌趣统计后台发送游戏内统计日志。

1.2 阅读对象

接入掌趣的游戏及应用开发者,包括客户端及服务器端工程师。

1.3 名词解释

玩家:玩家指下载安装和运行游戏及应用的用户,在统计时,玩家这个词本身又包含三层意义,即设备、账户、角色;
设备:指玩家用于安装运行游戏和应用的手机,平板,电脑等硬件设施;
账户:指玩家为了登录游戏和应用而注册的通行证,账户等信息;
角色:指玩家为了进入游戏创建的游戏内角色信息。

用户行为:玩家在游戏和应用内每一个值得被记录的动作都可以称为一次用户行为或者事件或者动作,我们在统计sdk中将玩家用户行为分为基础事件和游戏内事件两大类;
基础事件:包括启动和初始化应用,注册和登录账户,注册和登录角色,客户端心跳等;
游戏内事件:包括玩家的充值,虚拟物品获得与使用,任务、关卡、副本、交互等等。

日志:当玩家在游戏中发生了一次应该被记录的事件,而且这次事件通过统计sdk成功记录,则产生了一条记录对应事件的日志,每个日志都包含多个不同的字段,用于描述事件的不同角度的信息。掌趣统计后台通过对日志的搜集、分析和计算,算出各种事件的统计数据,并将其在掌趣BI后台中展示出来。

维度:在一条日志里,会对一个事件的不同角度的信息进行记录,例如新闻六要素,who,when,where,what,why和how,六要素其实就是同一事件在六个维度上坐标值。在掌趣统计sdk中,会有时间、产品、联运、推广渠道、游戏逻辑服等维度信息来标识一个事件。一些维度信息在掌趣sdk跟应用打包时就已经固化在客户端的配置文件中了,另外一些维度信息则需要客户端开发人员在事件发生时实时获取和记录日志。因此日志接口的每一个参数都是必要和有意义的,请接入时务必确保维度信息的完整性和正确性。

2 日志接入流程

2.1 流程说明

日志接入流程大致分为三个步骤:
1.客户端日志接入开发负责人根据日志接入流程文档,调用日志接口,完成几个基础日志的记录;
2.掌趣科技数据中心对客户端接入的日志进行格式和字段内容检查;
3.客户端日志接入开发负责人与掌趣技术人员通过日志接入测试用例后,日志接入工作正式完成。

2.2 接口说明

SDK日志接口,用于采集客户端的诸如玩家注册,玩家登录,玩家充值,玩家虚拟物品变更,玩家属性变更等用户行为,为产品运营,推广营销等工作提供数据支持。

在调用日志接口时,客户端需要为日志接口提供日志ID,日志关键字,日志内容三个参数,其中,日志内容(val)是一个json格式的字符串,里面详细描述了该次事件的具体信息。例如,一个玩家充值日志,他的几个参数大概是这样的:

  1. {
  2. "val": "{
  3. \"orderNo\":\"0162014101420092117000\",
  4. \"payChannelId\":\"支付宝\",
  5. \"currencyType\":\"1\",
  6. \"currencyAmount\":\"10000\",
  7. \"virtualCurrencyId\":\"diamond\",
  8. \"virtualCurrencyAmount\":\"1000\"
  9. }",
  10. "id": "8",
  11. "key": "role-credit"
  12. }

从示例中可见,
日志的id为8,
本次充值的订单号为0162014101420092117000(由开发者自行决定订单号作为订单唯一标识)
本次充值的支付渠道为支付宝
本次充值的货币类型为1 (人民币,见附2.1货币规范)
本次充值的实际支付金额为100元(单位为分,所以接口中的参数值是10000)
本次充值的虚拟币类型为钻石
本次充值的虚拟币发放金额为1000

除了货币类型是附2.1货币规范指定之外,其余信息皆为该游戏的产品人员和开发人员自行设定,其余一些虚拟币类型和商品ID的代码由游戏开发和运营人员自行指定。

需要注意的地方:

当传入中文字符串时,务必确保该中文字符串使用的是utf8编码。例如,商品名称,任务名称,副本场景名称等。

由的产品人员和开发人员自行设定的字段信息,也必须由相应的负责人确保内容的一致性。 例如同一个逻辑服下,如果在用户登录注册时调用日志接口传递的逻辑服标识是1001,那么在调用计费中心的充值计费接口时逻辑服标识也应该是同样的1001,而不应该是其他的值。同样的,如果A用户在购买一个极品武器时记录的物品id是001weapon,那么另外一个用户在拍卖同样一个极品武器时物品id也应该是001weapon。

系统库添加
请于Link Binary With Libraries处添加以下库文件

请在build settings处做一下设置

iOS Deployment Target最低为iOS 5.0
其他请参照DEMO

2.2.1 统计SDK初始化(客户端调用,必须)

功能说明
1、初始化统计SDK,以便正常使用各项功能
2、获取初始化数据。

接口定义

  1. /**
  2. * 统计SDK初始化
  3. *
  4. * @param gameVer 游戏版本号
  5. * @param gameResVer 游戏资源版本号,无资源版本号可传""
  6. * @return null
  7. */
  8. void initStatisticsLog(string gameVer, string gameResVer);

参数说明

参数名称 重要性 类型 说明
gameVer 必填 string 游戏版本号
gameResVer 可选 string 游戏资源版本号,如游戏无此概念则可以传””

接口示例

  1. 1)对于coco2d-x引擎:
  2. 建议初始化接口放在cocos2d::CCApplication::sharedApplication()->run();之后
  3. - (BOOL)application:(UIApplication *)application
  4. didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  5. {
  6. //掌趣SDK初始化
  7. ourpalmLog::OPLogSDK::GetInstance().initStatisticsLog("4.0.0", "");
  8. }
  9. 2)对于unity3d引擎:
  10. 建议初始化接口放在OnUnityReady();之后。
  11. - (void)startUnity:(UIApplication*)application
  12. {
  13. //。。。。。。
  14. OnUnityReady();
  15. //掌趣SDK初始化
  16. ourpalmLog::OPLogSDK::GetInstance().initStatisticsLog("4.0.0", "");
  17. }

2.2.2 设置用户信息(客户端调用,必须)

功能说明
1、登录成功后调用,传入用户登录类型(用户注册和用户登录)、用户ID、用户名;
2、这个接口会根据传入的用户登录类型自动发送账户注册及账户登录日志。

接口定义

  1. /**
  2. * 设置用户信息
  3. * @param type kGameRegister:用户注册,kGameLogin:用户登陆
  4. * @param userId 用户ID
  5. * @param userName 用户名
  6. */
  7. void setUserInfo(OPGameType type, string userId, string userName);

参数说明

参数名称 重要性 类型 说明
type 必填 OPGameType kGameRegister表示用户注册, kGameLogin 表示用户登录
userId 必填 string 用户ID,登录或注册成功后,返回的用户ID
userName 必填 string 用户名

接口示例

  1. 请在用户注册之后调用
  2. OPLogSDK::GetInstance().setUserInfo(kGameRegister, "008", "James Bond");
  3. 请在用户登录之后调用
  4. OPLogSDK::GetInstance().setUserInfo(kGameLogin, "008", "James Bond");

2.2.3 设置游戏信息(客户端调用,必须)

功能说明
当游戏角色注册(登录)成功时设置游戏角色注册(登录)信息。在调用此接口后SDK会自动生成并发送相应的角色注册(登录)日志

接口定义

  1. /**
  2. * 设置游戏角色信息
  3. * @param type kGameRegister:角色注册,kGameLogin:角色登陆
  4. * @param gameInfo 获取游戏信息的回调
  5. * @return null
  6. */
  7. void setGameInfo(OPGameType type, OPGameInfo gameInfo);

参数说明

参数名称 重要性 类型 说明
opGameInfo 必须 OPGameInfo 设置游戏账号信息
opGameType 必须 OPGameType 用户标识游戏角色注册登录状态,注册:kGameRegister, 登录:kGameLogin

OPGameInfo参数说明

参数名称 重要性 类型 说明
mGame_RoleName 必须 std::string 游戏角色名称
mGame_RoleId 必须 std::string 游戏角色 id
mGame_ServerId 必须 std::string 游戏服务器id
mGame_RoleLevel 必须 std::string 游戏角色等级
mGame_RoleVipLevel 必须 std::string 游戏角色vip等级

接口示例

  1. OPGameInfogameInfo;
  2. gameInfo.mGame_RoleId = "123456"; //游戏角色id
  3. gameInfo.mGame_RoleName = "Jack"; //游戏角色名称
  4. gameInfo.mGame_ServerId = "123"; //游戏服务器id
  5. gameInfo.mGame_RoleLevel = "1"; //游戏角色等级
  6. gameInfo.mGame_RoleVipLevel = "1"; //游戏角色vip等级
  7. //游戏角色注册成功时调用
  8. OPLogSDK::GetInstance().setGameInfo(kGameRegister, registerInfo);
  9. //游戏角色登录成功时调用
  10. OPLogSDK::GetInstance().setGameInfo(kGameLogin, gameInfo);

2.2.4 开启SDK日志输出(客户端调用,可选)

功能说明
打开后能在xcode下方工具栏看到统计SDK客户端相关日志输出,以便游戏接入SDK的时
候进行调试,出正式游戏包时请务必关闭日志输出。

接口定义

  1. /**
  2. * 是否打开日志
  3. * @param showLogs
  4. */
  5. void setLogs(bool showLogs);

参数说明

参数名称 重要性 类型 说明
showLogs 必须 bool 是否打开日志输出

2.2.5 发送游戏内日志(客户端调用,必须)

功能说明
收集游戏玩家行为信息,用于统计分析玩家行为。

接口定义

  1. /**
  2. * 游戏端需发送的统计日志
  3. * @param logID 日志ID
  4. * @param logKey 日志KEY
  5. * @param logValJson 日志属性JSON字符串
  6. */
  7. void sendGameLog(string logID, string logKey, string logValJson);

参数说明

参数名称 重要性 类型 说明
logID 必须 std::string 日志ID
logKey 必须 std::string 日志KEY
logValJson 必须 std::string 日志内容,json格式

接口示例

  1. Json::Value logJson;
  2. logJson["key1"] = "value1";
  3. logJson["key2"] = "value2";
  4. Json::FastWriter fast_writer;
  5. const char* log = fast_writer.write(logJson).c_str();
  6. OPLogSDK::GetInstance().sendGameLog (logID,logKey,log);

logId和LogKey对应表

logId Logkey 描述
8 role-credit 玩家充值日志
9 role-item-update 玩家虚拟物品变更
10 role-prop-update 玩家属性变更
1001 role-task 任务
1002 role-stage 副本,场景
1003 role-act 自定义事件
2001 role-interact 自定义交互事件

跟踪玩家充值(客户端调用,必须)

当用户已经启动游戏客户端,且通过发货通知接口收到发货通知并给用户成功发货时,需要记录一条对应的发货成功日志来跟踪玩家充值。
支付方式ID:如支付宝,神州付,财付通,微信支付等,由开发者自行指定,需要在同一个产品的所有订单中保持支付方式id的一致性
订单号:由开发者自行指定该笔充值的唯一标识
订单金额:即发货通知接口的订单金额
货币类型:玩家支付的是人民币还是美元或者欧元,见附2.1货币规范
商品ID:用于记录本次充值给用户发放了哪一个商品,商品id建议由英文字母或数字组成,以避免乱码等问题。
商品名称:商品名称建议为中文信息。
日志时间字段,sdk会根据调用日志接口时间自行填充。
用户id,角色名称,角色id等字段,sdk会根据角色登录时保存的信息自行填充。

LogId 日志名称 LogKey
8 玩家充值日志 role-credit
字段名 字段类型 字段说明 备注
roleLevel Integer 角色等级 必需
roleVipLevel Integer 角色vip等级 必需
payChannelId String 支付方式 例如,91支付,UC支付等,非必需
orderNo String 订单号 必需
currencyType String 货币类型 (参照附2.1货币规范)必需
currencyAmount Integer 订单金额 单位:分,必需
itemId String 商品ID 游戏中商品或者道具ID,必需
itemName String 商品名称 便于运营人员识别商品,一般传入中文,必需
itemCount Integer 商品个数 必需

日志格式示例:

  1. Json::Value logJson;
  2. logJson["roleLevel"]=1;
  3. logJson["roleVipLevel"]=0;
  4. logJson["payChannelId"]="3100052033100012";
  5. logJson["orderNo"]=0012014090110143611500;
  6. logJson["currencyType"]=1;
  7. logJson["currencyAmount"]=100;
  8. logJson["itemId"]="gold";
  9. logJson["itemName"]="金币";
  10. logJson["itemCount"]=100;
  11. Json::FastWriter fast_writer;
  12. const char* log = fast_writer.write(logJson).c_str();
  13. OPGameSDK::GetInstance().SendLog("8", "role-credit", log);

该记录表示当前登录的角色马克.吐温充值100分人民币购买游戏内100钻石

跟踪玩家虚拟物品(虚拟币、道具)变更(客户端调用,必须)

当用户在游戏内,因为种种原因产生虚拟物品(含虚拟货币)的增加和消耗时,需要记录一条对应的虚拟物品变更日志。
变更类型:用于标识本次变更是新增了虚拟物品还是消耗了虚拟物品,新增记录1,消耗记录0。
变更描述:用于标识用户因为什么原因变更虚拟物品(虚拟货币),如任务获得,怪物掉落,系统赠送,副本奖励,世界喊话,家族奉献,婚姻喜宴等等。

商品ID:用于记录用户本次是因为哪一个游戏内的商品引发的虚拟物品变更,例如购买游戏内的装备、经验、头衔、坐骑等。商品名称由游戏策划人员自行定义,比如 0001对应装备图纸,0002对应黄金翅膀,0003对应经验丹,0004对应体力等等。传入0001,0002,0003……这些ID即可

商品名称:用于记录用户本次是因为哪一个游戏内的商品引发的虚拟物品变更,例如购买游戏内的装备、经验、头衔、坐骑等。商品名称由游戏策划人员 自行定义,比如0001装备图纸,0002黄金翅膀,0003经验丹,0004体力等等。统计结果也会直接将日志中的商品名称展示出来,如果用户本次变更行为 与具体商品道具无关,则该字段置空即可。

商品个数:用于记录用户本次消费行为涉及多少个商品,如果用户本次消费行为与具体商品无关,则该字段置空即可。

需要注意的是,如果玩家的一次事件导致多种虚拟物品变更,比如完成一次史诗副本同时获得1000珍珠20000石币,则需要记录相应的两条虚拟物品变更日志。

LogId 日志名称 LogKey
9 玩家虚拟物品变更日志 role-item-update
字段名 字段类型 字段说明 备注
roleLevel Integer 角色等级 必需
roleVipLevel Integer 角色vip等级 必需
updateType String 变更类型 1:新增 0:消耗 必需
itemId String 商品ID 必需
itemName String 商品名称 便于运营人员识别商品,一般传入中文,必需
itemCount Integer 商品个数 必需
custom String 变更描述 描述变更的原因或途径

日志格式示例:

  1. logJson["roleLevel"] = 1;
  2. logJson["roleVipLevel"] =0;
  3. logJson["updateType"] ="0";
  4. logJson["itemId"] = "diamond";
  5. logJson["itemName"] = "钻石";
  6. logJson["itemCount"] =1;
  7. logJson["custom"] = "购买";
  8. Json::FastWriter fast_writer;
  9. const char* log = fast_writer.write(logJson).c_str();
  10. OPGameSDK::GetInstance().SendLog("9", "role-item-update", log);
  11. Json::Value logJson;
  12. logJson["roleLevel"] = 1;
  13. logJson["roleVipLevel"] =0;
  14. logJson["updateType"] ="1";
  15. logJson["itemId"] = "001weapon";
  16. logJson["itemName"] = "玛格汉铁锤";
  17. logJson["itemCount"] =1;
  18. logJson["custom"] = "购买";
  19. Json::FastWriter fast_writer;
  20. const char* log = fast_writer.write(logJson).c_str();
  21. OPGameSDK::GetInstance().SendLog("9", "role-item-update", log);

上面两条日志表示当前登录的角色马克.吐温为了购买id为玛格汉铁锤 的武器花了100钻石。

跟踪玩家属性变更(客户端调用,必须)

当用户的角色,发生一些属性上的变化时,记录相应的角色属性变更日志。例如等级提升,军衔提升,VIP等级提升,属性点重配,种族天赋变更等等。
属性标识:角色变更了哪种属性,其中等级标识为level,VIP等级标识为viplevel,其余属性标识由游戏产品和开发人员自行设定。
新属性值:角色完成属性变更之后,该属性的值变成了什么。
变更值:如果该属性值是一个数字,比如等级level,那么本次用户的等级变更了多少,例如购买大礼包level连升三级,则变更值为3。

LogId 日志名称 LogKey
10 玩家属性变更日志 role-prop-update
字段名 字段类型 字段说明 备注
roleLevel Integer 角色等级 必需
roleVipLevel Integer 角色vip等级 必需
propKey String 属性标识 必需
propValue String 新属性值 必需
rangeability String 变更值 必需

日志格式示例:

  1. Json::Value logJson;
  2. logJson["roleLevel"]=1;
  3. logJson["roleVipLevel"]=0;
  4. logJson["payChannelId"]="3100052033100012";
  5. logJson["orderNo"]=0012014090110143611500;
  6. logJson["currencyType"]=1;
  7. logJson["currencyAmount"]=100;
  8. logJson["itemId"]="gold";
  9. logJson["itemName"]="金币";
  10. logJson["itemCount"]=100;
  11. Json::FastWriter fast_writer;
  12. const char* log = fast_writer.write(logJson).c_str();
  13. OPGameSDK::GetInstance().SendLog("8", "role-credit", log);

该记录表示当前角色马克.吐温连升了两级,目前等级为3。他的vip等级升了一级,目前vip等级为1

自定义事件

当运营人员需要对游戏内的任务完成情况,关卡完成情况进行记录时,即可记录一条游戏自定义事件。在记录日志之前,游戏运营人员有必要向掌趣科技统计后台提供一份任务,关卡,以及其他自定义事件的id和名称对照表,并在掌趣科技统计后台描述任务,关卡,道具之间的关系。

任务,副本关卡日志的格式均为stageId,stageName,detail三个字段,三个字段的值完全由游戏研发人员和运营人员自行指定,例如新手引导任务可以用 newbieguide标识stageId,也可以用task001或其他字符串标识来表示stageId,任务完成,既可以用 SUCC表示,也可以用complete表示,还可以根据任务的中断,放弃,失败等多种状况,为同一个任务记录多条日志。对于同一种事件结果,建议使用同样的detail内容来描述。尽量做到同一个detail的含义一致,同一个事件结果的detail一致。

需要注意的地方:
无论是任务,关卡还是其他自定义事件日志,taskId/stageId/actId字段都必须是相对于该日志的logId唯一,不能够与其他任务,关卡或道具的id字段重复。

尽管任务,副本/场景,以及游戏自定义事件三个日志的字段数量和格式相同,但是我们希望研发人员能够按照预设的不同logid和logkey分别记录这三类日志,这样一来,便于将相对重要的日志同其它日志区分出来,也便于我们对任务和场景副本日志采用预设的特定算法来进行统计运算。

我们要求用以下的默认字段来记录事件日志的detail,以便统计后台可以用默认的配置来对游戏自定义事件进行计算成功率,通过率等进一步指标。
如果列表中的detail无法满足游戏的日志记录要求,也允许各个游戏使用自己定义的detail来记录日志。

LogId 日志名称 key
1001 任务 role-task
字段名 字段类型 字段说明
roleLevel Integer 角色等级
roleVipLevel Integer 角色vip等级
taskId String 任务编码,英文或数字
taskName String 人物名称,最好传中文
detail String 相关信息,全为英文

其中detail字段建议取值如下所示:

detail 含义
accept 接任务
fail 任务失败
cancel 放弃任务
succ 达成任务条件
complete 任务完成

日志格式示例:

  1. Json::Value logJson;
  2. logJson["roleLevel"] ="10";
  3. logJson["roleVipLevel"] ="2";
  4. logJson["taskId"] ="newbieguide1";
  5. logJson["taskName"] ="新手任务";
  6. logJson["detail"] ="accept";
  7. Json::FastWriter fast_writer;
  8. const char* log = fast_writer.write(logJson).c_str();
  9. OPGameSDK::GetInstance().SendLog("1001", "role-task", log);
  10. Json::Value logJson;
  11. logJson["roleLevel"] ="10";
  12. logJson["roleVipLevel"] ="2";
  13. logJson["time"] ="2014-04-18 17:12:30";
  14. logJson["taskId"] ="newbieguide1";
  15. logJson["taskName"] ="新手任务";
  16. logJson["detail"] ="complete";
  17. Json::FastWriter fast_writer;
  18. const char* log = fast_writer.write(logJson).c_str();
  19. OPGameSDK::GetInstance().SendLog("1001", "role-task", log);

这两条日志表示,当前角色马克.吐温在17:11:30接受了新手流程任务1,在17:12:30完成了新手流程任务1.

LogId 日志名称 key
1002 副本场景日志 role-stage
字段名 字段类型 字段说明
roleLevel Integer 角色等级
roleVipLevel Integer 角色vip等级
stageId String 副本场景标识,英文或数字
stageName String 副本场景名称,最好传中文
detail String 相关信息,全为英文

其中detail字段建议取值如下所示:

detail 含义
begin 场景开始
fail 场景失败
cancel 场景取消
end 场景结束

日志格式示例:

  1. Json::Value logJson;
  2. logJson["roleLevel"] ="10";
  3. logJson["roleVipLevel"] ="2";
  4. logJson["stageId"] ="DeadminesIstanc";
  5. logJson["stageName"] ="死亡矿井";
  6. logJson["detail"] ="begin";
  7. Json::FastWriter fast_writer;
  8. const char* log = fast_writer.write(logJson).c_str();
  9. OPGameSDK::GetInstance().SendLog("1002", "role-stage", log);

以上日志表示,当前角色进入死亡矿井。

LogId 日志名称 key
1003 游戏自定义事件 role-act
字段名 字段类型 字段说明
roleLevel Integer 角色等级
roleVipLevel Integer 角色vip等级
actId String 事件标识,英文或数字
actName String 事件名称,最好传中文
detail String 相关信息,全为英文

日志格式示例:

  1. Json::Value logJson;
  2. logJson["roleLevel"] ="10";
  3. logJson["roleVipLevel"] ="2";
  4. logJson["actId"] ="fight.minner";
  5. logJson["actName"] ="战斗.狗头人矿工";
  6. logJson["detail"] ="begin";
  7. Json::FastWriter fast_writer;
  8. const char* log = fast_writer.write(logJson).c_str();
  9. OPGameSDK::GetInstance().SendLog("1003", "role-act", log);

以上日志表示,当前角色和狗头人旷工进行战斗。

3.日志接入功能开发建议

以下是我们对日志接入功能的一些开发建议,由于网游服务端和客户端技术复杂多变,我们无法面面俱到的为所有游戏提供一套统一的接入规范,因此分享一些接入过程中我们认为对日志发送功能较为有利的开发经验和建议。

3.1日志发送协议

详细观察我们的日志发送接口,会发现它仅仅由三个参数组成,分别是logId,logKey和logJson,其中logJson是key-val形式的一个映射表。因此我们希望游戏接入日志时,能够预先在客户端和服务器端之间架设这样一个协议:
消息头——日志发送协议ID
消息体——由三个参数组成,分别为logId,logKey和logJson(一个将key-val映射转换为json格式的字符串)
只要服务器端通过该协议向客户端推送了这样一个消息,那么客户端就把消息体的三个参数转换为样例代码中的logId,logKey和logJson对象,然后调用掌趣sdk提供的日志发送接口发送即可。
将来如果有日志格式的改变或者有新的日志需要发送,我们不需要更新已经上线的客户端,只要在服务端增加相应的代码即可完成新日志发送。这样可以避免由于统计数据需求导致强制更新客户端。

附录1:客户端状态码(错误码)

状态码 含义
102 网络异常,请检查网络
103 数据异常
104 SDK初始化参数错误
105 SDK语言配置文件错误
106 Ourpalm.cfg配置文件错误
107 SDK未初始化成功
108 SDK未设置登录回调
109 未设置服务器id
110 未设置价格
111 未设置货币类型
112 未设置商品名称
113 未设置商品id

附录2:通用局数据

附2.1 货币规范

货币ID 货币名称 货币单位
1 人民币
2 美元 美分
3 日元
4 港币
5 英镑 便士
6 新加坡币
7 越南盾
8 台币
9 韩币
10 泰铢 萨当
11 卢布 戈比