【说明】 完成第一部分基础SDK集成,就可以实现APP的用户统计,启动次数统计,使用时长统计,PV统计,APP崩溃的统计。如果您需要更多的自定义统计,请参考第二部分的“自定义代码集成”。
您可以选择如下任意一种方式,将SDK导入App工程:
1.1 拖拽导入
直接拖拽下载下来的相关SDK(正式版为: PtTrackSDK.framework)到App工程中的Frameworks目录下,并选中”Copy item if needed”,点击Finish,以保证SDK拷贝到当前工程目录中,如图:
1.2 右键导入
选中App工程中的Frameworks文件夹或者工程文件,右键菜单选择”Add Files to ‘demo.project’””, 以保证SDK(正式版为: PtTrackSDK.framework)拷贝到当前工程目录中,如图:
在App -> TARGETS -> Build Phases 配置项中通过+号加入图示中的依赖框架,并在Other Linker Flag配置项中添加-ObjC(此处务必添加,否则可导致SDK部分功能不可用):
Appkey,即Ptengine for App中获取的AppID。
当app启动时,需要先通过SDK接口注册appKey,此方法必须调用:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [[PtAgent sharedInstance] PTStartWithAppKey:@"**********" channel:**]; }
请确保该方法在application didFinishLaunchingWithOptions:的第一行处调用,已确保在程序启动时要加载的所有ViewController都被成功监听。
AppKey:为后台创建应用后生成的key值,不能为空, 此处可替换为相应的值。
channel:为app发布的渠道名称,如果传nil, 则使用默认值“AppStore”, 如果app要发布到其他渠道,请填写相关渠道名称。
您可以通过调用如下接口,实现pageView、自定义事件和App错误信息的统计监测。
4.1 部署自定义事件并添加属性接口
如果想要部署自定义事件,并给该事件设置自定义属性,可通过调用如下接口实现。
/** * Use this method to track an event with user-defined value. * @param eventName, this value can't be nil or empty * @param properties, you can bind some event properties for this event, if you don't need it, just pass nil. * ************************************************************************************************************************************ * [[PtAgent sharedInstance]PTTrackEvent:@"Buy" withProperties:@{@"price":@"200.00", @"title":@"xxx", ...}]; ************************************************************************************************************************************ * */ - (void)PTTrackEvent:(NSString *)eventName withProperties:(nullable NSDictionary *)properties;
4.2 自定义事件开始时间接口,用于统计事件时长
开始记录时间接口与结束记录时间接口的事件名要保持一致,用于统计某一个事件的执行时间
/** * Mark the begin time for defined event. */ - (void)PTBeginEvent:(NSString *)eventName;
4.3自定义事件结束时间接口,用于统计事件时长
开始记录时间接口与结束记录时间接口的事件名要保持一致,用于统计某一个事件的执行时间。
结束记录时间接口也可传递其他的变量值作为自定义属性。
/** * Mark the end time for defined event, you can specify the event properties for yourself. * This method should be paired with PTBeginEvent, and eventName must be same. */ - (void)PTEndEvent:(NSString *)eventName withProperties:(nullable NSDictionary*)properties;
4.4 自定义用户登录事件接口
登录成功之后请把当前的登入用户作为值传入
/** * Track the user login info with specific properties. */ - (void)PTTrackUserLogin:(NSString *)userID withProperties(nullable NSDictionary*)properties;
如果某个特殊业务场景或者一个自定义UIView想作为一个PV统计,可调用该接口实现。对于UIViewController容器类,SDK会自动采集PV数据,所以不要使用该接口对UIViewController类进行重复的PV数据采集。
/** * If you want to track 'PV' data for user-defined UIView, you can invoke this API. But DON'T use it for UIViewController container, because our SDK has tracked 'PV' data automatically for UIViewController. */ - (void)PTTrackPVForCustomViewController:(NSString *) withProperties(nullable NSDictionary*)properties;
基础SDK包已经默认采集了UIViewController 的PV数据,默认采集的页面名称为当前Controller类名,但如果您想要自定义当前ViewController的页面名称,可通过如下接口调用:
/** * Because the 'PV' data with default page name for UIViewController has been tracked automatically by PTTrackSDK, * so if you want to re-define the page name value, you can invoke this API as soon as [viewWillAppear:] is triggered. * The default value is current class name of UIViewController * @param redefinedName: new page name value. * @param properties: bind the page properties for PV data. * @param viewController: the instance of current UIViewController. */ - (void)PTRedefinePVName:(NSString*)redefinedName withProperties:(nullable NSDictionary*)properties forViewController:(id)viewContainer;
如果想要采集某些场景下的错误信息,比如app中请求http失败,或者登陆失败等等,请调用如下接口:
/** * Track the error info if you want to define in some scene. For example, http request is failed... * @param exceptionInfo error info * @param code error code */ - (void)PTTrackException:(nullable NSString *)exceptionInfo exceptionCode:(NSInteger)code;
SDK提供了支持对HTML界面的事件统计javascript接口,使用这些接口之前需要先进行简单的注册配置。如果你的App中包含UIWebView 或者WKWebView页面,想要自定义统计App中网页界面的事件信息,可以在App中想关的avaScript代码进行事件埋点。
8.1: 针对UIWebView,WKWebView分别在FinishLoad回调中注册Ptengine javascript bridge protocol, 如果使用的是第三方库,可在第三方库相关的抛出的回调中注册该接口。
具体参看接口注释中的代码示例
/** * You should register PtAgent javaScript bridge module after webView is finished loading. * We register this bridge module as the properties of javaScript window object. * And then you can invoke the ptmind javaScript API for packing js event for yourself. * @param webView current webView object * * If you are using UIWebView, please invoke this method in delegate method: * - (void)webViewDidFinishLoad:(UIWebView *)webView { * [[PtAgent sharedInstance]PTRegisterJavascriptBridgeForWebView:webView]; * } * If you are using WKWebView, please invoke this method in delegate method: * - (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation { * [[PtAgent sharedInstance]PTRegisterJavascriptBridgeForWebView:webView]; * } * */ - (void)PTRegisterJavascriptBridgeForWebView:(id)webView;
8.2:注册完成之后,还需要针对UIWebView, WKWebView分别在StartLoad相关的回调中过滤掉关于ptengine的请求跳转,我们SDK提供了两个常量PT_WebView_Bridge_Scheme, PT_WebView_Bridge_Host。具体参看接口注释中的代码示例
/** * Parse the web URL request scheme and host info, if they equal to PT_WebView_Bridge_Scheme and PT_WebView_Bridge_Host, * then, DO NOT to navigate URL, just return NO. * @param NSURL: NSURLRequest.URL, WKNavigationAction.request.URL * ************************************************************************************************************************************ * If you are using UIWebView, please invoke this method in this way: * - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ * NSURL *requestURL = [request URL]; * if ([[requestURL scheme] isEqualToString:PT_WebView_Bridge_Scheme] && [[requestURL host] isEqualToString:PT_WebView_Bridge_Host]) { * [[PtAgent sharedInstance]PTJavascriptTrackEventBridgeProtocol:requestURL]; * return NO; * } * * //Your code implementation... * return YES; * } * * If you are using WKWebView, please invoke this method in this way: * - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{ * NSURL *requestURL = [navigationAction.request URL]; * if ([[requestURL scheme] isEqualToString:PT_WebView_Bridge_Scheme] && [[requestURL host] isEqualToString:PT_WebView_Bridge_Host]) { * [[PtAgent sharedInstance]PTJavascriptTrackEventBridgeProtocol:requestURL]; * decisionHandler(WKNavigationActionPolicyCancel); * }else { * decisionHandler(WKNavigationActionPolicyAllow); * } * } ************************************************************************************************************************************ * */ - (void)PTJavascriptTrackEventBridgeProtocol:(NSURL *)webRequestURL;
8.3: 到此所以配置结束,可以在html中使用javascript接口来埋点事件了,具体参看如下代码示例
* Finally, you can collect your js event with our methods in javascript level. ************************************************************************************************************************************ * We have provided the following APIs for you: * * PtAgentWebViewJSBridge.PTTrackEvent(eventName, eventProperties); * PtAgentWebViewJSBridge.PTPackVirtualPageView(virtualPageViewName, PVProperties); * PtAgentWebViewJSBridge.PTTrackException(exceptionInfo, exceptionCode); * PtAgentWebViewJSBridge.PTBeginEvent(eventName); * PtAgentWebViewJSBridge.PTEndEvent(eventName, eventProperties); * * and recommend you to invoke these methods by this following way: * if (window.PtAgentWebViewJSBridge) { * var attributes = { * 'product': 'English Book', * 'price': 100 * }; * var attributes_json = JSON.stringify(attributes); * PtAgentWebViewJSBridge.PTTrackEvent('TestEventName', attributes_json); * } * * if (window.PtAgentWebViewJSBridge) { * var attributes = { * 'product': 'English Book', * 'price': 100 * }; * var attributes_json = JSON.stringify(attributes); * PtAgentWebViewJSBridge.PTPackVirtualPageView('WebViewDemoPage', attributes_json); * } * * if (window.PtAgentWebViewJSBridge) { * PtAgentWebViewJSBridge.PTTrackException('this is an test error info', 110); * } * * if (window.PtAgentWebViewJSBridge) { * PtAgentWebViewJSBridge.PTBeginEvent('loginTime'); * } * * if (window.PtAgentWebViewJSBridge) { * var attributes = { * 'userName': 'xxxx', * 'email': 'xx@xx.com' * }; * var attributes_json = JSON.stringify(attributes); * PtAgentWebViewJSBridge.PTEndEvent('loginTime', attributes_json); * } * ************************************************************************************************************************************ *
当集成完SDK后,SDK 调试log默认关闭状态,可通过设置log接口关闭log输出。
/** * Set all level log disabled, default is NO */ - (void)PTEnableLogOutput;
由于苹果系统的限制和某些API的不确定性,我们默认采用Advertising Identifier来作为设备的唯一标识,已最大化的保证数据的准确性,所以需要在开发者在上架AppStore时进行关于Advertising Identifier的简单配置:
11.1 /** * 用户注册具体信息接口,用于采集用户注册事件。 * pt_xxx字段为协议内定字段,不可随意改变,其他类型字段可根据业务随意变更。 * pt_xxx内定字段需要传哪些请参考协议接口文档中[是否必须]==是 && [传值方式] == 用户 */
[[PtAgent sharedInstance]PTTrackUserRegister:@{ @"pt_account_id": @"", //内定字段,用户注册的账户信息, 必传 @"pt_gender": @"", //内定字段,用户性别, 选传 @"pt_age": @"", //内定字段,用户年龄, 选传 @"pt_register_country": @"", //内定字段,用户注册时选择的国家信息, 选传 @"pt_register_subdivision": @"", //内定字段,用户注册时选择的国家下属行政地区信息, 选传 @"pt_register_city": @"" //内定字段,用户注册时选择的城市信息, 选传 } withProperties:@{//用户注册时的自定义变量信息,选传,key为非内定字段,可自定义 @"email": @"pt@ptmind.com", @"address": @"beijing" }];
11.2 /** * 用户登录接口,用于采集用户登录事件。 */
[[PtAgent sharedInstance]PTTrackUserLogin:@"userid" withProperties:@{//用户登录时的自定义变量信息,选传,key为非内定字段,可自定义. @"用户自定义Key1": @"Value1", @"用户自定义Key2": @"Value2" }];
11.3
电商事件采集接口
/** * Use this method to track an event with user-defined value for ecommerce App. * @param actionCategory, this value can't be nil or empty, category list is: pt_user_register, pt_user_login, pt_impression, pt_product_detail, pt_add_cart, pt_remove_cart, pt_check_out, pt_purchase, pt_refund, pt_add_favorite, pt_remove_favorite * @param productDetails, you MUST pass the specific key-values according to documents for collecting product detail info. * @param properties, if the specific productDetails can't cover your requirements, you can pass the custom properties info. ************************************************************************************************************************************ * [[PtAgent sharedInstance]PTTrackEventForEcommerce:@"pt_user_register" withProductDetails:@{@"pt_gender":@"man", @"pt_age":@"20", ...} withCustomProperties:@{@"pt_register_properties": {}}]; ************************************************************************************************************************************ */ - (void)PTTrackEventForEcommerce:(PTEcommerceCategory)actionCategory withProductDetails:(NSDictionary *)productDetails withCustomProperties:(nullable NSDictionary *)properties;
Demo示例如下:
NSDictionary *all_products_info = @{ @"pt_account_id": @"", //用户登录的账号id, 选填 @"pt_source": @"", //显示商品展示的来源,比如通过主页,搜索等方式显示出来的。必填 @"pt_ad_creative_id": @"", ///促销活动的 ID(例如 PROMO_1234)。*此字段与 name 字段必须至少设置一个。选填 @"pt_ad_position": @"", //广告素材的位置(例如 banner_slot_1). 选填 @"pt_promo_info": @"", //促销活动的名称(例如夏季促销).选填 @"pt_promo_properties": @{//与促销活动相关的自定义属性,{}.选填 @"pt_promo_properties_k1": @"pt_promo_properties_v1", @"pt_promo_properties_k2": @"pt_promo_properties_v2", }, @"pt_products":@[ @{ @"pt_product_id": @"",//商品ID 或 SKU(例如 P67890).必填 @"pt_product_name": @"",//商品名称.选填 @"pt_product_brand": @"",//商品品牌.选填 @"pt_product_category": @"",//产品所属的类别(例如服装),可以使用 / 作为分隔符来指定最多 5 个层级(例如服装/男装/T 恤)。选填 @"pt_product_variant": @"",//产品的细分款式(例如黑色).选填 @"pt_product_position": @(2),//产品在列表或集合中的位置(例如 2).选填 @"pt_product_price": @(20.20),//产品的价格(例如 29.20)。选填 @"pt_product_currency_code": "RMB", //产品的货币代码(USD, RMB),列表参看:https://support.google.com/analytics/answer/6205902?hl=zh-Hans#supported-currencies. 是否必须根据具体接口来定 @"pt_product_coupon": @"", //与产品关联的优惠券代码(例如 SUMMER_SALE13).选填 @"pt_product_quantity": @(3),//产品数量,选填 @"pt_product_properties": @{//与产品相关的自定义属性,{}. 选填 @"product_key3": @"product_value4", @"product_key4": @"product_value4" }, @"pt_product_list":@'search result'//产品在列表或集合(例如搜索结果),选填 } ] } NSDictionary *product_info = @{ @"pt_account_id": @"", //用户登录的账号id, 选填 @"pt_source": @"", //显示商品展示的来源,比如通过主页,搜索等方式显示出来的。必填 @"pt_ad_creative_id": @"", ///促销活动的 ID(例如 PROMO_1234)。*此字段与 name 字段必须至少设置一个。选填 @"pt_ad_position": @"", //广告素材的位置(例如 banner_slot_1). 选填 @"pt_promo_info": @"", //促销活动的名称(例如夏季促销).选填 @"pt_promo_properties": @{//与促销活动相关的自定义属性,{}.选填 @"pt_promo_properties_k1": @"pt_promo_properties_v1", @"pt_promo_properties_k2": @"pt_promo_properties_v2", }, @"pt_product_id": @"",//商品ID 或 SKU(例如 P67890).必填 @"pt_product_name": @"",//商品名称.选填 @"pt_product_brand": @"",//商品品牌.选填 @"pt_product_category": @"",//产品所属的类别(例如服装),可以使用 / 作为分隔符来指定最多 5 个层级(例如服装/男装/T 恤)。选填 @"pt_product_variant": @"",//产品的细分款式(例如黑色).选填 @"pt_product_position": @(2),//产品在列表或集合中的位置(例如 2).选填 @"pt_product_price": @(20.20),//产品的价格(例如 29.20)。选填 @"pt_product_currency_code": @"RMB", //产品的货币代码(USD, RMB),列表参看:https://support.google.com/analytics/answer/6205902?hl=zh-Hans#supported-currencies. 是否必须根据具体接口来定 @"pt_product_coupon": @"", //与产品关联的优惠券代码(例如 SUMMER_SALE13).选填 @"pt_product_quantity": @(3),//产品数量,选填 @"pt_product_properties": @{//与产品相关的自定义属性,{}. 选填 @"product_key3": @"product_value4", @"product_key4": @"product_value4" }, @"pt_product_list":@'search result'//产品在列表或集合(例如搜索结果),选填 } //商品展示采集示例 [[PtAgent sharedInstance]PTTrackEventForEcommerce:PT_Category_Impression withProductDetails:all_products_info withCustomProperties:@{ @"impress_pro_key1": @"impress_pro_value1", @"impress_pro_key2": @"impress_pro_value2" }]; //商品详情采集示例 [[PtAgent sharedInstance]PTTrackEventForEcommerce:PT_Category_Product_Detail withProductDetails:product_info withCustomProperties:@{ @"detail_pro_key1": @"detail_pro_value1", @"detail_pro_key2": @"detail_pro_value2" }]; //添加购物车采集示例 [[PtAgent sharedInstance]PTTrackEventForEcommerce:PT_Category_Add_Cart withProductDetails:product_info withCustomProperties:@{ @"add_cart_pro_key1": @"add_cart_pro_value1", @"add_cart_pro_key2": @"add_cart_pro_value2" }]; //删除购物车采集示例 [[PtAgent sharedInstance]PTTrackEventForEcommerce:PT_Category_Remove_Cart withProductDetails:product_info withCustomProperties:@{ @"remove_cart_pro_key1": @"remove_cart_pro_value1", @"remove_cart_pro_key2": @"remove_cart_pro_value2" }]; //生成订单采集示例 //为当前接口在product_info字典结构中增加以下两个字段的值 NSMutableDictionary * ec_checkout = [NSMutableDictionary new]; [ec_checkout addEntriesFromDictionary:all_products_info]; [ec_checkout setObject:@"pt_order_id_value" forKey:@"pt_order_id"]; [ec_checkout setObject:@(50.33) forKey:@"pt_payment_amount"]; [[PtAgent sharedInstance]PTTrackEventForEcommerce:PT_Category_Check_Out withProductDetails:ec_checkout withCustomProperties:@{ @"checkout_pro_key1": @"checkout_pro_value1", @"checkout_pro_key2": @"checkout_pro_value2" }]; //商品购买接口 NSMutableDictionary * ec_purchase = [NSMutableDictionary new]; [ec_purchase addEntriesFromDictionary:all_products_info]; [ec_purchase setObject:@"pt_order_id1111" forKey:@"pt_order_id"]; [ec_purchase setObject:@(50.33) forKey:@"pt_payment_amount"]; [ec_purchase setObject:@"pt_payment_type" forKey:@"pt_payment_type"]; [ec_purchase setObject:@"pt_tax" forKey:@"pt_tax"]; [ec_purchase setObject:@"pt_shipping" forKey:@"pt_shipping"]; [[PtAgent sharedInstance]PTTrackEventForEcommerce:PT_Category_Purchase withProductDetails:ec_purchase withCustomProperties:@{ @"pt_purchase_pro_key1": @"pt_purchase_pro_value1", @"pt_purchase_pro_key2": @"pt_purchase_pro_value2" }]; //商品退货采集示例 NSMutableDictionary * ec_refund = [NSMutableDictionary new]; [ec_refund addEntriesFromDictionary:all_products_info]; [ec_refund setObject:@"pt_payment_type" forKey:@"pt_payment_type"]; [ec_refund setObject:@"pt_tax" forKey:@"pt_tax"]; [ec_refund setObject:@"pt_shipping" forKey:@"pt_shipping"]; [[PtAgent sharedInstance]PTTrackEventForEcommerce:PT_Category_Refund withProductDetails:ec_refund withCustomProperties:@{ @"pt_refund_pro_key1": @"pt_refund_pro_value1", @"pt_refund_pro_key2": @"pt_refund_pro_value2" }]; //添加收藏夹采集示例 [[PtAgent sharedInstance]PTTrackEventForEcommerce:PT_Category_Add_Favorite withProductDetails:product_info withCustomProperties:@{ @"pt_add_favorite_pro_key1": @"pt_add_favorite_pro_value1", @"pt_add_favorite_pro_key2": @"pt_add_favorite_pro_value2" }]; //删除收藏夹采集示例 [[PtAgent sharedInstance]PTTrackEventForEcommerce:PT_Category_Remove_Favorite withProductDetails:product_info withCustomProperties:@{ @"pt_remove_favorite_pro_key1": @"pt_remove_favorite_pro_value1", @"pt_remove_favorite_pro_key2": @"pt_remove_favorite_pro_value2" }];