AdServices归因和iAd归因集成

news2024/11/26 14:48:18

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";
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MatrixOne完成与欧拉、麒麟信安的兼容互认

近日,超融合异构云原生数据库MatrixOne企业版软件V1.0完成了与欧拉开源操作系统(openEuler简称“欧拉”)、麒麟信安操作系统系列产品和虚拟化平台的相互兼容认证,通过了欧拉兼容性测评,获得了《openEuler技术测评证书》…

unity3d与vs 附加到unity debug报错

点击 附加到unity报错 选择在 调试-》附加unity->选择unity实例

KT148A语音芯片使用串口uart本控制的完整说明_包含硬件和指令举例

一、功能简介 KT148A肯定是支持串口的,有客户反馈使用一线还是不方便,比如一些大型的系统不适合有延时的操作,所以更加倾向于使用uart控制,这里我们也给出解决方案 延伸出来另外一个版本,KT158A 注意次版本芯片还是…

MySQL/SQLServer判断字符是纯数字或者是其它字符

如下是MySQL表结构设计(演示所用): MySQL表关联数据如下所示: 【场景:查询所有数字,包含小数点】,SQL如下所示: SELECT * FROM data WHERE message not REGEXP [^0-9].[^0-9] My…

【AI视野·今日CV 计算机视觉论文速览 第277期】Fri, 27 Oct 2023

AI视野今日CS.CV 计算机视觉论文速览 Fri, 27 Oct 2023 Totally 93 papers 👉上期速览✈更多精彩请移步主页 Daily Computer Vision Papers A Coarse-to-Fine Pseudo-Labeling (C2FPL) Framework for Unsupervised Video Anomaly Detection Authors Anas Al lahham…

C++ 模板 (一)

1. 泛型编程 如何实现一个通用的交换函数呢? void Swap(int& left, int& right) { int temp left; left right; right temp; } void Swap(double& left, double& right) { double temp left; left right; right temp; } void Swap(char&…

《C++避坑神器·二十二》VS能正常运行程序,但运行exe程序无响应解决办法

原因是某个文件只是放在了项目路径下,没有放在exe路径下,比如Json文件原来只放在了mlx项目下,导致VS可以运行,但运行exe无响应或报错如下: 两种方式修改: 1、把Json文件拷贝一份放到exe路径下 2、利用生成…

云ES使用集群限流插件(aliyun-qos)

aliyun-qos插件是阿里云Elasticsearch团队自研的插件,能够提高集群的稳定性。该插件能够实现集群级别的读写限流,在关键时刻对指定索引降级,将流量控制在合适范围内。例如当上游业务无法进行流量控制时,尤其对于读请求业务,可根据aliyun-qos插件设置的规则,按照业务的优先…

【AI视野·今日Robot 机器人论文速览 第六十五期】Mon, 30 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Mon, 30 Oct 2023 Totally 18 papers 👉上期速览✈更多精彩请移步主页 Daily Robotics Papers Gen2Sim: Scaling up Robot Learning in Simulation with Generative Models Authors Pushkal Katara, Zhou Xian, Katerina F…

Linux输入设备应用编程(键盘,触摸屏,按键,鼠标)

目录 一 输入设备编程介绍 1.1 什么是输入设备呢? 1.2 什么是输入设备的应用编程? 1.3 input子系统 1.4 数据读取流程 1.5 应用程序如何解析数据 1.5.1 按键类事件: 1.5.2 相对位移事件 1.5.3 绝对位移事件 二 读取 struct input_e…

【152.乘积最大子数组】

目录 一、题目描述二、算法原理三、代码实现 一、题目描述 二、算法原理 三、代码实现 class Solution { public:int maxProduct(vector<int>& nums) {int nnums.size();vector<int> f(n);vector<int> g(n);f[0]g[0]nums[0];int retnums[0];for(int i1;…

代码随想录算法训练营第五十四天丨 动态规划part15

392.判断子序列 思路 &#xff08;这道题也可以用双指针的思路来实现&#xff0c;时间复杂度也是O(n)&#xff09; 这道题应该算是编辑距离的入门题目&#xff0c;因为从题意中我们也可以发现&#xff0c;只需要计算删除的情况&#xff0c;不用考虑增加和替换的情况。 所以…

【问题处理】WPS提示不能启动此对象的源应用程序如何处理?

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 最近在用WPS打开word文件中&#xff0c;插入的Excel附件时&#xff0c;无法打开&#xff0c;提示&#xff1a;“不能启动此对象的源应用程序”。 经过上网查找处理办法&#xff0c;尝试解决&#xff0c;现将解决过程记…

MIB 6.1810实验Xv6 and Unix utilities(2)sleep

难度:easy Implement a user-level sleep program for xv6, along the lines of the UNIX sleep command. Your sleep should pause for a user-specified number of ticks. A tick is a notion of time defined by the xv6 kernel, namely the time between two interrupts f…

leetcode:移除链表元素

1.题目描述 题目链接&#xff1a;203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; 2.解题思路 我们定义一个cur指向当前结点&#xff0c;定义prev指向前一个结点&#xff0c;next指向下一个结点 如果cur->valval&#xff0c;那我们就删除这个结点 怎么删除呢…

如何在聊天记录中实时查找大量的微信群二维码

10-5 如果你有需要从微信里收到的大量信息中实时找到别人发到群里的二维码&#xff0c;那本文非常适合你阅读&#xff0c;因为本文的教程&#xff0c;可以让你在海量的微信消息中&#xff0c;实时地把二维码自动挑出来&#xff0c;并且帮你分类保存。 如果你是做网推的&#…

桂院校园导航 静态项目 二次开发教程 1.3

Gitee代码仓库&#xff1a;桂院校园导航小程序 GitHub代码仓库&#xff1a;GLU-Campus-Guide 升级日志 1.3 优化了小程序的数据存储方式&#xff0c;对部分页面进行了调整&#xff0c;调整了功能和代码。 引入weui组件库&#xff0c;使地点的呈现方式更加美观 序号内容详情…

例解什么是Python装饰器

Python中的装饰器一直是一个比较难理解的概念&#xff0c;我自己理解的就是用一个函数去修改另一个函数&#xff0c;主要是为另一个函数添加计时等功能&#xff0c;而且不用改变另一个函数&#xff0c;这样就大大减少了另一个函数的维护成本。 这个装饰器&#xff0c;英文名就…

前端404页面的制作

1、背景 前端开发经常遇到输入路径不存在的问题&#xff0c;为此&#xff0c;把之前项目的404拿出来供大家参考。代码很简单&#xff0c;适合新手入手&#xff0c;效果如下&#xff1a; 2、代码引用的是element-plus框架 <template><div><el-result icon"…

jQuery【事件处理器、鼠标事件、表单事件、键盘事件、浏览器事件、事件对象、jQuery遍历】(三)-全面详解(学习总结---从入门到深化)

目录 事件之绑定事件处理器 事件之鼠标事件 事件之表单事件 事件之键盘事件 事件之浏览器事件 事件对象 jQuery遍历 事件之绑定事件处理器 1、 .on() 在选定的元素上绑定一个或多个事件处理函数 $("#button").on("click", function(event){console…