AdServices归因和iAd归因集成

AdServices framework 是 Apple 专门为 ASA 提供的归因框架 。尤其在ATT 政策推出以后,app 获取用户 IDFA 的比例大幅降低,传统的依靠IDFA 的方法也无法准确归因。


但是 Apple 为 ASA 开了一个后门,其他广告渠道无法获取用户的 IDFA 作为身份标识符进行归因,而 ASA 可以获取一个甚至比 IDFA 更好的用户token 进行归因-因为即便 ATT 之前,用户在 iPhone 的设置也会导致无法完全获取 IDFA,但是 ASA 的用户 token ,只要接入 AdServicesframework,就可以获取到。


另外要注意的是,除了 AdServices framework, ASA 还有一个 iAdframework。但是后者仅适用于 ioS 14.3 之前版本,且此框架已经停用iOS 14.3 之前的用户占比也很小,所以不接入对归因也没有太大影响,所以这节课不会涉及 iAd framework。


官方文档
https://ads.apple.com/cn/help/reporting/0028-apple-ads-attribution-api

 

AdServices 接入目的
通过 AdServices framework,可以让我们对每一个激活用户获取一个Token 标识符,用此 Token 可以得知该用户是否点击过 ASA 广告、点击过那个广告系列/广告组/关键词/素材等广告信息。
 

AdServices 接入步骤
        1.选择项目主文件-TARGETS-General
        2.入 AdServices framework
        3.进入 link binary with Libraries 将 AdServices 改为 optional
        4.导入AdServices framework
        5.添加获取用户 Token 的代码
        6.更新 App 并发布至 App Store


AdServices 接入流程

AdServices归因和iAd归因集成

前提:AdServices归因框架的集成必须是iOS14.3以上版本xcode版本12.3以上;旧版本依旧使⽤iAd 归因框架。

第一步:找到framework的添加入

添加framework

第二步:分别搜索AdServices.framework、AdSupport.framework、iAd.framework,进行添加

AdServices.framework


AdSupport.framework

iAd.framework

第三步:在Build Phases中Link Binary With Libraries 修改 AdServices.framework、AdSupport.framework、iAd.framework的类型为Optional

AdServices.framework、AdSupport.framework、iAd.framework的类型为Optional

第四部:将AdServices.framework、AdSupport.framework、iAd.framework的头文件加入到项目

#pragma mark -- 归因
#import "iAd/iAd.h"
#import "AdServices/AdServices.h"
#import "AppTrackingTransparency/AppTrackingTransparency.h"

添加头文件

第五步:代码集成,可在AppDelegate中添加 

5.1 AdServices获取token               

+(void)getAdToken
{
    if (@available(iOS 14.3, *)) {
        NSError *error;
        NSString *token = [AAAttribution attributionTokenWithError:&error];
        if (token != nil) {
            // 发送POST请求归因数据
            [self sendToken:[self getANullableString:@"token" content:token]completeBlock:^(NSDictionary *attrData) {
                NSLog(@"成功==:14.3+ Dict: %@", attrData);
                //可将数据发送给服务端
            }];
        }
    } else {
        // 老版本请求
        if ([[ADClient sharedClient]respondsToSelector:@selector(requestAttributionDetailsWithBlock:)]) {
            NSLog(@"LogAds:iAd called");
            [[ADClient sharedClient]requestAttributionDetailsWithBlock:^(NSDictionary *attrData, NSError *error) {
                //异步,会延后
                NSLog(@"成功:14- Dict: %@", attrData);
                //可将数据发送给服务端
                // ... ...
            }];
        }
    }
}

5.2 AdServices获取归因数据     

/** 读取可能为空的字符串*/

-(nullable NSString *)getANullableString:(NSString *)desc content:(NSString *)content{
    if(content == nil){
        return @"";
    }
    return [NSString stringWithFormat:@"%@", content];
}

/** 发送归因token得到数据 */

-(void)sendToken:(NSString *)token completeBlock:(void(^)(NSDictionary* data))completeBlock{
    NSString *url = [NSString stringWithFormat:@"https://api-adservices.apple.com/api/v1/"];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
    request.HTTPMethod = @"POST";
    [request addValue:@"text/plain" forHTTPHeaderField:@"Content-Type"];
    NSData* postData = [token dataUsingEncoding:NSUTF8StringEncoding];
    [request setHTTPBody:postData];
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response,NSError * _Nullable error) {
        NSDictionary * result = NULL;
        if (error) {
            //请求失败
            NSLog(@"请求失败LogAds:sendToken ERR");
            if (completeBlock) {
                NSMutableDictionary *nulldict = [NSMutableDictionary dictionary];
                completeBlock(nulldict);
            }
        }else{
            // 请求成功
            NSLog(@"请求成功");
            NSError *resError;
            NSMutableDictionary *resDic = [NSJSONSerialization JSONObjectWithData:data         options:kNilOptions error:&resError];
            result = [[NSDictionary alloc] initWithDictionary:resDic];
            if (completeBlock) {
                completeBlock(result);
            }
        }
    }];
    [dataTask resume];
}

5.3 AdServices 返回归因数据包示例

经测试,IDFA允许用户跟踪后,得到的数据是详细数据包

{
adGroupId = 1234567890;
attribution = 1;
campaignId = 1234567890;
clickDate = "2022-04-27T07:59Z";
conversionType = Download;
countryOrRegion = US;
creativeSetId = 1234567890;
keywordId = 12323222;
orgId = 1234567890;
}

未允许,得到的数据是标准数据包,没有clickDate字段

{
"attribution": true,
"orgId": 40669820,
"campaignId": 542370539,
"conversionType": "Download",
"adGroupId": 542317095,
"countryOrRegion": "US",
"keywordId": 87675432,
"creativeSetId": 542317136
}

5.4 iAd 代码

// 老版本请求
if ([[ADClient sharedClient]respondsToSelector:@selector(requestAttributionDetailsWithBlock:)]) {
    NSLog(@"LogAds:iAd called");
    [[ADClient sharedClient]requestAttributionDetailsWithBlock:^(NSDictionary *attrData, NSError *error) {
        //异步,会延后
        NSLog(@"成功:14- Dict: %@", attrData);
        //可将数据发送给服务端
        // ... ...
    }];
}

5.5iAd返回归因数据包示例

{
"iad-adgroup-id" = 1234567890;
"iad-adgroup-name" = AdGroupName;
"iad-attribution" = true;
"iad-campaign-id" = 1234567890;
"iad-campaign-name" = CampaignName;
"iad-click-date" = "2022-04-27T07:31:36Z";
"iad-conversion-date" = "2022-04-27T07:31:36Z";
"iad-conversion-type" = Download;
"iad-country-or-region" = US;
"iad-creativeset-id" = 1234567890;
"iad-creativeset-name" = CreativeSetName;
"iad-keyword" = Keyword;
"iad-keyword-id" = 12323222;
"iad-keyword-matchtype" = Broad;
"iad-lineitem-id" = 1234567890;
"iad-lineitem-name" = LineName;
"iad-org-id" = 1234567890;
"iad-org-name" = OrgName;
"iad-purchase-date" = "2022-04-27T07:31:36Z";
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/154608.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【读点论文】FMViT: A multiple-frequency mixing Vision Transformer-期待源码

FMViT: A multiple-frequency mixing Vision Transformer Abstract transformer模型近年来在计算机视觉任务中得到了广泛的应用。然而,由于自关注的时间和内存复杂度是二次的,并且与输入token的数量成正比,大多数现有的(Vision transformer,…

性能测试【第三篇】Jmeter的使用

线程数:10 ,设置10个并发 Ramp-Up时间(秒):所有线程在多少时间内启动,如果设置5,那么每秒启动2个线程 循环次数:请求的重复次数,如果勾选"永远"将一直发送请求 持续时间时间:设置场景运行的时间 启动延迟:设置场景延迟启动时间 响应断言 响应断言模式匹配规则 包括…

进程间通信

进程间通信 是什么? 两个或者多个进程实现数据层面的交互 为什么? 怎么办? a.进程间通信的本质:必须让不同的进程看到同一份"资源" b."资源"就是特定形式的内存空间 c.这个"资源"谁提供?一般是操作系统&…

EtherCAT从站EEPROM分类附加信息详解:SM(同步管理器)

0 工具准备 1.EtherCAT从站EEPROM数据(本文使用DE3E-556步进电机驱动器)1 分类附加信息——SM(同步管理器) 1.1 分类附加信息规范 在EEPROM字64开始的区域存储的是分类附加信息,这里存储了包括设备信息、SM配置、FM…

小程序如何添加打印机来打印订单

在采云小程序中,支持打印订单的小票、标签、发货单和电子面单。小票打印机用于打印小票,类似于超市小票、外卖小票等。标签打印机用于打印商品标签,类似于奶茶上面粘贴的标签,用于表示饮料名称和规格等。货单打印机用于打印发货单…

关于 内部类 你了解多少?(详解!!)

目录 1. 什么是内部类? 2. 内部类的分类 3. 内部类 3.1 实例内部类 3.2 静态内部类 4. 局部内部类 5. 匿名内部类 6.对象的打印 “不积跬步无以至千里,不积小流无以成江海。”每天坚持学习,哪怕是一点点!!&a…

sqlserver配置管理器无法启动解决方案

在SQL server configuration manager配置管理器中遇到SQL server browser呈灰色,无法启动 右击选择属性 进入服务 将启动模式改为自动 可以启动了

Java面向对象2

代码块 代码块的构造顺序优先于构造器 细节

redis运维(七)基础通用命令

一 基础通用命令 备注: 与具体数据类型无关Tab键 自动补全补充: redis 命令是不区分大小写 通用不到 10 个提升逼格的 redis 命令 后续: slowlog、rename-command、monitor、set ① help command 需求: 显示有关redis命令的…

DVWA - 4

文章目录 JavaScriptlowmedium JavaScript 前端攻击。token 不能由前端生成,js 很容易被攻击者获取,从而伪造 token。同样其他重要的参数也不能由前端生成。 low 不修改输入,点击提交报错: 根据提示改成 success,还是报错&…

趣学python编程 (一、计算机基础知识科普)

未来是高度科技化和智能化的时代。过去不识字的叫“文盲”,如今不懂点计算机知识,则可能是新时代的“文盲”。不论从事什么行业,了解下计算机和编程都是有益的。Python 连续多年占据最受欢迎的编程语言榜首,未来Python有机会成为像…

C++之异常处理

目录 一、C语言处理错误 1、终止程序 2、返回错误码 二、C异常 异常的抛出和匹配原则 异常安全 异常规范 异常优缺点 一、C语言处理错误 传统处理错误的两种方式: 1、终止程序 使用assert是直接终止程序,包含头文件assert.h即可 缺点&#xf…

NEFTune: 通过简单的噪声提升指令精调效果

NEFTune指的是Noise Embedding Finetuning(噪声嵌入精调),提出自论文:NEFTune: NOISY EMBEDDINGS IMPROVE INSTRUCTION FINETUNING。 NEFTune方法的原理仅使用一句话就可以描述清楚:在finetune过程的词向量中引入一些…

众安保险面试题

文章目录 1.说一下Java内存模型?2.List、Set、Map的区别?3.介绍一下设计模式?4.MySQL存储结构?5.索引失效的场景?6.为什么使用函数索引会失效?7.Spring事务有哪两种?7.1 编程式事务@RestController7.2 声明式事务8.@Transactional实现原理?9.事务如何合并@Transactiona…

es head 新增字段、修改字段、批量修改字段、删除字段、删除数据、批量删除数据

目录 一、新增字段 二、修改字段值 三、批量修改字段值 ​四、删除字段 五、删除数据/文档 六、批量删除数据/文档 一、新增字段 put http://{ip}:{port}/{index}/_mapping/{type} 其中,index是es索引、type是类型 数据: {"_doc"…

听GPT 讲Rust源代码--library/core/src(7)

题图来自 Hello, crustaceans.[1] File: rust/library/core/src/ptr/metadata.rs 在Rust的源代码中,rust/library/core/src/ptr/metadata.rs 文件的作用是定义了与指针(ptr)和元数据(metadata)相关的结构体和 trait&am…

C#源代码生成器深入讲解二

在阅读本文前需掌握源代码生成器相关知识C#源代码生成器深入讲解一 C#源代码生成器深入讲解二—增量生成器 源代码生成器有个非常大的弊病,每次都会遍历所有的语法树来分析,这样就有个问题,每次可能只修改了很少一部分或者只有很少一部分的代码需要分析…

异行星平台--CRM系统搭建

使用异行行低代码平台搭建的CRM系统。CRM系统中,包括“客户”、“商机”、“合同”、“回款”、“开票”、“营销”、“回访”、“产品”、“联络人”、“销售订单”、“线索”。 “管理后台”可能是指一个用于管理后台系统的应用,可能包括对各种功能和数…

基于django电影推荐系统

基于django电影推荐系统 摘要 该Django电影推荐系统是一个简单而基础的框架,旨在展示系统的基本组件。系统包括两个主要模型,即Movie和Rating,用于存储电影信息和用户评分。视图层包括展示电影列表和电影详情的功能,使用模板进行页…

从底层认识哈希表【C++】

目录 一. unordered系列关联式容器 二. unordered_map的文档介绍 接口使用 三. 底层实现 (1)哈希概念 例: (2)哈希冲突 (3)冲突解决 1.闭散列​​​​​​​ 闭散列框架 插入 查找 删除 2.开散…