# Apple Search Ads 集成方案
本文将介绍如何在 TE 后台接入 Apple Search Ads 数据,目前 TE 后台支持接入的是 Apple Search Ads 的 Reporting API (opens new window)。
如果您正在使用 TE 4.2 之前的版本,请参考 Apple Search Ads 数据集成解决方案 (opens new window) 进行数据集成
TIP
请注意,第三方数据集成产生的数据会被纳入集群的消耗数据量
# 概要
# 接口简介
接口名 | 类型 | 粒度 | 归因 | 成本 | 收益 | 展示 | 点击 | 转化 |
---|---|---|---|---|---|---|---|---|
Reporting API | API | 聚合数据 | ✅ | ✅ | ✅ | ✅ |
Apple Search Ads 的 Reporting API 提供了从广告计划(Campaign-Level)至广告(Ad-Level)等多个层级的数据报表,目前 TE 系统支持以下几个层级的数据拉取:
- Campaign 层级报告 (opens new window)(Campaign-Level Reports)
- Ad Group 层级报告 (opens new window)(Ad Group-Level Reports)
- Keyword 层级报告 (opens new window)(Keyword-Level Reports)
请注意,由于 Apple Search Ads 的功能调整,Creative Set 层级报告 (opens new window)(Creative Set-Level Reports)已不再支持,历史配置可能会失效
# 集成流程
Apple Search Ads 数据的接入流程如下:
- 完成 Apple Search Ads API 的授权
- 登录 TE 后台,进入三方集成模块,新增 Apple Search Ads 集成方案,并完成相关配置
- 查看 TE 系统否成功接收数据,并完成报表搭建
# 一、完成 Apple Search Ads API 的授权
在接入 ASA 的数据之前,首先需要完成 ASA 的授权工作,整个流程分为以下几个步骤:
- 创建一个拥有 API 访问权限的用户
- 生成私钥与公钥,并将公钥上传到 ASA 后台
- 创建客户端密钥(Client Secret)
- 请求获取访问令牌(Access Token)
您可以直接查看 Apple Search Ads 的官方文档 (opens new window),完成授权工作。或者按照本节流程完成授权,以下内容均来自该官网文档。
# 1.1 创建拥有 API 访问权限的用户
首先,您需要登录管理员账号,并按照以下流程创建一个带有 API 权限的用户:
- 进入 Apple Search Ads UI (opens new window),登录管理员账号
- 进入「Account Settings」-「User Management」(「账号设置」-「用户管理」)
- 点击「Invite Users」邀请一个在您的 ASA 组织内的用户
- 在「User Details」栏目,输入用户的姓名以及 Apple ID
- 在「User Access and Role」栏目,选择具有 API 访问权限的用户角色
- 点击「Send Invite」发送邀请邮件,受邀请用户会收到一份带有 secure code 的邮件,用户点击邮件中的 Apple 网址并输入 secure code 即可激活用户的账号
# 1.2 生成私钥与公钥,并将公钥上传到 ASA 后台,获取客户端密钥
接下来,您需要通过代码生成私钥与公钥,本节需要一定的技术背景。如果您不是开发人员,请您联系开发人员或者 TE 工作人员完成该步骤
TIP
如果您使用的是 Windows 系统,请下载并安装 OpenSSL (opens new window)
- 在命令行中输入以下命令,生成私钥文件,文件名为 private-key.pem
openssl ecparam -genkey -name prime256v1 -noout -out private-key.pem
- 接着,在同一目录下,继续执行如下命令,生成公钥文件,文件名为 public-key.pem
openssl ec -in private-key.pem -pubout -out public-key.pem
- 进入 Apple Search Ads UI (opens new window),登录我们在上一步中创建的带有 API 权限的用户。选择「Account Settings」-「API」,将公钥复制到「Public Key」板块。点击保存后,您将可以在「Public Key」板块上方看到
clientId
、teamId
与keyId
,以下是数据样例:
clientId SEARCHADS.aeb3ef5f-0c5a-4f2a-99c8-fca83f25a9
teamId SEARCHADS.hgw3ef3p-0w7a-8a2n-77c8-scv83f25a7
keyId a273d0d3-4d9e-458c-a173-0db8619ca7d7
# 1.3 创建客户端密钥
接下来,您还需要通过代码生成客户端密钥。本节需要一定的技术背景。如果您不是开发人员,请您联系开发人员或者 TE 工作人员完成该步骤。
Apple Search Ads 的客户端密钥是一个 JSON web token(JWT)。官方提供了 Python 3 的代码样例,请在完成依赖库的安装后,执行以下代码完成客户端密钥的创建:
import os
import datetime as dt
from authlib.jose import jwt
from Crypto.PublicKey import ECC
# 建议您将私钥与公钥文件置于 py 文件的同一目录下
private_key_file = "private-key.pem"
public_key_file = "public-key.pem"
# 此处需要替换成上一步中获取的 clientId、teamId 与 keyId
client_id = "SEARCHADS.9703f56c-10ce-4876-8f59-e78e5e23a152"
team_id = "SEARCHADS.9703f56c-10ce-4876-8f59-e78e5e23a152"
key_id = "d136aa66-0c3b-4bd4-9892-c20e8db024ab"
audience = "https://appleid.apple.com"
alg = "ES256"
# 如果私钥文件不存在,则创建私钥文件
if os.path.isfile(private_key_file):
with open(private_key_file, "rt") as file:
private_key = ECC.import_key(file.read())
else:
private_key = ECC.generate(curve='P-256')
with open(private_key_file, 'wt') as file:
file.write(private_key.export_key(format='PEM'))
# 如果公钥文件不存在,创建公钥文件
public_key = private_key.public_key()
if not os.path.isfile(public_key_file):
with open(public_key_file, 'wt') as file:
file.write(public_key.export_key(format='PEM'))
# 获取当前时间戳
issued_at_timestamp = int(dt.datetime.utcnow().timestamp())
# 定义过期时间,不能超过 180 天,否则 Client Secert 会失效
expiration_timestamp = issued_at_timestamp + 86400*180
# 定义 JWT headers.
headers = dict()
headers['alg'] = alg
headers['kid'] = key_id
# 定义 JWT payload.
payload = dict()
payload['sub'] = client_id
payload['aud'] = audience
payload['iat'] = issued_at_timestamp
payload['exp'] = expiration_timestamp
payload['iss'] = team_id
# 获取私钥内容
with open(private_key_file, 'rt') as file:
private_key = ECC.import_key(file.read())
# 编码 JWT 并用私钥做签名
client_secret = jwt.encode(
header=headers,
payload=payload,
key=private_key.export_key(format='PEM')
).decode('UTF-8')
# 将 Client secret 写入文件中
with open('client_secret.txt', 'w') as output:
output.write(client_secret)
在以上代码中,您需要注意以下几个地方:
- 将上一步中生成的私钥与公钥文件,置于 .py 文件的统一目录下,或者修改代码中私钥与公钥文件的路径
- 将上一步中获取的 clientId、teamId 与 keyId 替换代码中的相应位置
接下来执行该代码,客户端密钥将记录在该目录下的 client_secret.txt 文件中,请将该信息记录下来,以下是客户端密钥的样例:
eyJraWQiOiJiYWNhZWJkYS1lMjE5LTQxZWUtYTkwNy1lMmMyNWIyNGQxYjIiLCJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJEcmVhbWNvbXBhbnkiLCJhdWQiOiJBdXRoZW50aWNhdG9yIiwiZXhwIjoxNTcxNjcwNjIxLCJuYmYiOjE1NzE2NjcwMjEsInN1YiI6Im11c3RlciIsImNsaWVudF9pZCI6ImFiY2QxMjM0IiwiYWRtaW4iOiJ0cnVlIn0.s4C3p9kVNFeRAB5tChatC3ldQX07v9mG7thL7FeEO6cClfNuiaLSgq8f8ymbfO3OQYW_KuwaA1KYRuoy1JmKk 4DBbYLcz6aoABe0pzI5Z_6wgMzAyqz8pQtwDAcd4Idoi8JdRbtzZce9o-0nZiFA4hVAXqYwpEYC4UU8ZmJO_z8tY4juHPTV3nDugdtqyNnmAiBoLryOfGNngQZccdY1_QvkXS1y0bg1a0k8cVVtnq- _93fYJIt9Z64CTvlH3uOeh7uaEv3nIxpXhvhkTySpUmY8e04TO09oTyZijiloByv3KFQ92OOJ8L 5N5_CeEc5p9LWjT1pcX8ATamOycZz2Q
# 1.4 获取 Org ID
最后,您需要获取 Org ID,也就是 ASA 后台的 Campaign Group ID。您可以在 ASA 后台查看到,即下图中红框圈出的 ID:
# 1.5 您需要的内容
最后,请确认您在上述授权流程中获取并记录了以下内容:
- client_id
- org_id
- client_secret
# 二、方案配置
当您完成了 ASA 的授权工作后,您可以登录 TE 系统,在「三方集成」模块中完成新方案的配置。下图是 ASA 的配置界面,请您按照本章节内容完成方案的创建:
# 2.1 授权信息配置
点击「授权信息」按钮,在弹出框内填写您在授权工作中获取到的信息
其中 Org ID 即 Apple Search Ads 后台中的 Account Id
# 2.2 定时拉取
您可以在「定时拉取」模块设置 TE 系统定时拉取 ASA 数据的策略,可以选择在每天的某时或者每小时拉取一段时间的数据。由于拉取的数据也会计算再数据量中,建议您在不要定时拉取太长时间的数据
# 2.3 入库设置
您可以控制 ASA 数据是否以事件的形式写入,由于 ASA 数据只会写入事件表,因此请不要关闭该配置。
# 2.4 集成配置
最后,您可以在集成配置模块对数据拉取的细节配置进行控制。包括数据的时间聚合粒度,拉取的指标字段与维度,以及入库后的事件名等。
集成配置中的内容是一个 JSON,您可以按照以下内容进行自定义配置:
模块 | 名称 | 含义 |
---|---|---|
sink_event | event_name | 入库后的事件名,可以自定义 |
source | time_granularity | 数据的时间聚合粒度,即拉取的数据以天还是小时进行聚合 可选值: day、hour |
report_types | 数据拉取的层级,列表类型,建议您只填入一个元素,即一次只拉取一个层级的数据 可选值: campaign、ad_group、keyword | |
metrics | 数据中的指标,列表类型,不同层级支持不同的 metrics,填写时需要注意 | |
group_by | 数据中的分组维度,列表类型,不同层级支持不同的 group_by,填写时需要注意 |
由于不同层级的数据配置有较大区别,建议您直接使用各层级的配置模板,或对模板进行微调。
# 2.4.1 Campaign 层级模板
Campaign 层级报告 (opens new window)的模板如下:
{
"sink_event": {
"event_name": "asa_campaign_level_data"
},
"source": {
"time_granularity": "hour",
"group_by": [
"countryOrRegion"
],
"report_types": [
"campaign"
]
}
}
- 模板中使用的时间粒度为小时,系统将使用数据中的 date 字段,即数据的日期+小时数,作为数据的时间
- 模板中使用的事件名为 -- asa_campaign_level_data
- 以下是 Campaign 层级报告的入库字段
------------------------维度字段------------------------
campaignid
campaignname
deleted
campaignstatus
app_adamid
app_appname
servingstatus
servingstatereasons
countriesorregions
modificationtime
totalbudget_amount
totalbudget_currency
dailybudget_amount
dailybudget_currency
displaystatus
supplysources
adchanneltype
orgid
countryorregionservingstatereasons
countryorregion
billingevent
------------------------指标字段------------------------
impressions
taps
installs
newdownloads
redownloads
latoninstalls
latoffinstalls
ttr
avgcpa_amount
avgcpa_currency
avgcpt_amount
avgcpt_currency
avgcpm_amount
avgcpm_currency
localspend_amount
localspend_currency
conversionrate
# 2.4.2 Ad Group 层级模板
{
"sink_event": {
"event_name": "asa_adgroup_level_data"
},
"source": {
"time_granularity": "hour",
"group_by": [
"countryOrRegion"
],
"report_types": [
"ad_group"
]
}
}
- 模板中使用的时间粒度为小时,系统将使用数据中的 date 字段,即数据的日期+小时数,作为数据的时间
- 模板中使用的事件名为 -- asa_adgroup_level_data
- 以下是 Ad Group 层级报告的入库字段
------------------------维度字段------------------------
campaignid
adgroupid
adgroupname
adgroupdisplaystatus
adgroupstatus
adgroupservingstatus
adgroupservingstatereasons
deleted
cpagoal
orgid
modificationtime
pricingmodel
defaultbidamount_amount
defaultbidamount_currency
countryorregion
------------------------指标字段------------------------
impressions
taps
installs
newdownloads
redownloads
latoninstalls
latoffinstalls
ttr
avgcpa_amount
avgcpa_currency
avgcpt_amount
avgcpt_currency
avgcpm_amount
avgcpm_currency
localspend_amount
localspend_currency
conversionrate
# 2.4.3 Keyword 层级模板
{
"sink_event": {
"event_name": "asa_keyword_level_data"
},
"source": {
"time_granularity": "hour",
"group_by": [
"countryOrRegion"
],
"report_types": [
"keyword"
]
}
}
- 模板中使用的时间粒度为小时,系统将使用数据中的 date 字段,即数据的日期+小时数,作为数据的时间
- 模板中使用的事件名为 -- asa_keyword_level_data
- 以下是 Keyword 层级报告的入库字段
------------------------维度字段------------------------
keywordid
keyword
keywordstatus
matchtype
bidamount_amount
bidamount_currency
deleted
keyworddisplaystatus
adgroupid
adgroupname
adgroupdeleted
modificationtime
countryorregion
------------------------指标字段------------------------
impressions
taps
installs
newdownloads
redownloads
latoninstalls
latoffinstalls
ttr
avgcpa_amount
avgcpa_currency
avgcpt_amount
avgcpt_currency
avgcpm_amount
avgcpm_currency
localspend_amount
localspend_currency
conversionrate
# 2.4.4 多层级模板
如果您希望一次拉取多个层级的数据,则建议采用以下模板,主要的改动为:
- report_types 中写入需要拉取的层级名
- 使用 event_mapping 管理多个层级的事件名,event_mapping 中的每个元素的 key 对应 report_types 中的层级名,value 为入库后的事件名
- 各层级的数据将按照同一套配置,即同样的 time_granularity、group_by 拉取数据
{
"sink_event": {
"event_mapping":{
"campaign": "asa_campaign_level_data",
"ad_group": "asa_adgroup_level_data",
"keyword": "asa_keyword_level_data"
}
},
"source": {
"time_granularity": "hour",
"group_by": [
"countryOrRegion"
],
"report_types": [
"campaign",
"ad_group",
"keyword"
]
}
}
# 2.5 标准化字段
以下展示的是 Apple Search Ads 的标准化字段:
原字段 | 标准化字段 | 含义 |
---|---|---|
orgid | te_ads_object.ad_account_id | 广告账号 ID |
campaignname | te_ads_object.campaign_name | 广告计划名 |
campaignid | te_ads_object.campaign_id | 广告计划 ID |
adgroupname | te_ads_object.ad_group_name | 广告组名,变现广告的 Unit 名 |
adgroupid | te_ads_object.ad_group_id | 广告组 ID,变现广告的 Unit ID |
adname | te_ads_object.ad_name | 广告名 |
adid | te_ads_object.ad_id | 广告 ID |
app_adamid | te_ads_object.app_id | 应用 ID |
app_appname | te_ads_object.app_name | 应用名 |
【iOS】(定值) | te_ads_object.platform | 平台,即 Android、iOS 等 |
countryorregion | te_ads_object.country | 国家地区编码 |
localspend_currency | te_ads_object.currency | 成本或收益的币种 |
impressions | te_ads_object.impressions | 曝光量 |
taps | te_ads_object.clicks | 点击量 |
installs | te_ads_object.installs | 转化量(安装) |
localspend_amount | te_ads_object.cost | 买量成本 |
# 三、后续使用
# 3.1 数据入库检查
您可以在「数据管理」页面查看回传事件是否入库:
- asa_campaign_level_data:Campaign 层级数据
- asa_adgroup_level_data:Ad Group 层级数据
- asa_keyword_level_data:Keyword 层级数据
# 3.2 单次拉取数据
如果您希望接入之前一段时间的数据,比如历史数据或者补上拉取失败的数据。可以在保存方案后再次进入方案页面,点击右上角的单次拉取按钮进行一次确定时间范围的数据拉取。需要注意的是,如果您拉取的数据的时间段与之前有重叠,比如拉取了 2023-08-01 的数据,而这一天的数据在之前已经拉取过,则最新一次拉取的数据将覆盖之前的数据: