全渠道「API回传」技术开发说明

published on: 2022-05-10 15:01:49

一、背景

客户跨媒体投放行为较为普遍,媒体间形成的转化信息孤岛不利于广告主充分利用数据优化投放,尤其是对于转化事件相对稀疏的行业和客户,数据分散导致模型学习不充分,造成成本高、跑量少,目标人群触达效率低,而在符合法律规定的前提下,通过把跨渠道转化数据回传给巨量引擎(不计入巨量引擎转化,只帮助模型学习),可以帮助模型充分的学习已转化人群特征,达到提高跑量,优化成本的作用。

二、什么是助攻?

image.png

TIPS:归因和助攻的区别

  • 归因:在巨量引擎产生过广告的触达,且最终转化渠道判定为巨量引擎,记巨量引擎转化(计入广告后台转化数),同时进入模型学习

  • 助攻:在巨量引擎产生过广告的触达(展示、播放、点击),但是最终转化渠道归因给其他媒体。这类事件数据只进模型,帮助模型学习,提升模型精准度,不记巨量引擎转化(客户无需付费)

三、数据对接回传实现方案

数据回传前,请填写全渠道助攻API回传问卷: 问卷

广告主投放的转化目标,跟回传的转化事件必须保持一致 。如:投放目标是付费,但回传的是激活,助攻模型是无法正常生效的。



方案一(建议采用)适用于线索类和应用下载(非调起)

方案二(可选)适用于线索类和应用下载类

简述

客户进行归因判定,并把非巨量引擎转化(自然转化及其他媒体转化)回传给巨量引擎,巨量引擎进行助攻判定

客户进行归因及助攻判定,并将判定结果回传给巨量引擎相应接口

特点

* 客户需要完成全部归因部分的开发,不需要开发助攻判定部分,基本无需多余技术成本
* 对客户来说数据存储量较方案二小

* 客户开发成本较高(所有的开发成本都在客户侧))
* 巨量引擎侧全部的展示/点击/播放数据集中在客户侧,对客户侧的存储空间要求较高


接入流程

1. 广告主实时回传助攻/非巨量引擎转化数据
2. 通知巨量引擎运营,巨量引擎侧确认样本上报传输无误,广告主确认后开启助攻模型

3. 进行一周的流量测试,广告主只需制定测试账户,巨量引擎方反馈测试效果

4. 效果正向后应用至广告主整体投放模型


归因及数据流转过程


image.png


image.png
助攻部分,如果客户区分click和show,可增加match_type回传,便于模型对人群特征的学习

接口方案

* 接口一:巨量引擎正常下发展示、点击、播放
* 接口二:客户回传归因给巨量引擎的转化
* Valuable接口:客户回传其他渠道全部转化事件,由巨量引擎判定是否属于可应用的助攻事件

* 接口一:巨量引擎正常下发展示、点击、播放
* 接口二:客户回传归因给巨量引擎的转化
* Assist接口:客户回传其巨量引擎助攻的转化

接口地址

接口二:https://ad.oceanengine.com/track/activate/
Valuable接口:https://analytics.oceanengine.com/api/v2/valuable

接口二:https://ad.oceanengine.com/track/activate/
Assist接口:https://analytics.oceanengine.com/api/v2/assist

回传方式技术对接介绍

详见附件 方案一接入流程

详见附件 方案二接入流程

回传字段简述

见方案一 参数列表
如果是应用场景,必须传包名

Assist接口接入参数列表
如果是应用场景,必须传包名
四、客户对接流程

image.png

附件:方案一接入流程
  1. 回传方案:

客户自行进行归因判断回传至接口二,其他渠道全部转化事件回传至valuable接口,由巨量引擎判定是否属于可应用的助攻事件,将巨量助攻过的数据用于模型优化,提高转化率,降低广告主成本

  1. 技术对接方式介绍

接口地址 :https://analytics.oceanengine.com/api/v2/valuable

请求方式POST

Content-Typeapplication/json

参数列表:


字段

必要

类型

举例

说明

event_type



string

active

事件类型

event_weight



number

0.561

事件权重,广告主自定义该事件的价值权重用于模型优化

biz_channel



number

0

业务类型,默认值:0,应用下载:0;线索收集:5;如果不传该值则当做应用下载类型,其他支持业务类型待补充

context



object


广告上下文信息

context.ad



object


广告信息

context.ad.ad_id



number

16521212134

广告计划id

context.ad.campaign_id



number

123455666

广告组id

context.ad.advertiser_id



number

1234567890

广告主id

context.ad.customer_id



number

123123123123

客户id

context.device



object


设备信息

context.device.platform



string

android

设备平台,android/ios

context.device.imei



string

0c2bd03c39f19845bf54ea0abafae70e

安卓系统 imei的 md5 摘要,32位

context.device.idfa



string

FCD369C3-F622-43B8-AFDE-12012349F35B

iOS系统idfa的原值

context.device.idfa_md5





context.device.idfv



string

FCD369C3-F622-43B8-AFDE-12012349F35B

iOS系统idfv的原值

context.device.gaid



string

FCD369C3-F622-43B8-AFDE-12012349F35B

Android Google 广告id

context.device.oaid



string

b305ee2fefdd1234

Android系统的 oaid 原值

context.device.oaid_md5



string

5f1c6587f0d6c35fc9e7fb0d4412b80f

Android系统oaid 的md5摘要,32位

context.device.android_id



string

9774d56d682e1234

Andoid 系统唯一标识

context.device.android_id_md5



string

a5dc9f6cb53ec2755af66ec7a7a6a51d

Andoid 系统唯一标识的md5摘要,32位

context.device.phone_num



string

62b2d12650ccf2ef170bdf8d8420318356693dbf9b382894e3f3c241c36f106a

手机号 SHA256加密,54位

context.device.ip



string

8.8.8.8

事件发生的ip

context.device.user_agent



string

Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36

事件发生的user_agent

context.app



object


应用信息

context.app.package_name



string

com.oceanengine.app

应用包名

properties



object

{}

自定义回传属性信息,支持字段待补充

timestamp



number

1604299664

事件发生的时间戳,自1970/01/01(UTC)以来的秒数

注:

  • 设备ID(idfa/gaid/oaid/imei/phone_num)中,至少得传一个

  • 广告信息(ad_id/campaign_id/advertiser_id/customer_id)中,至少得传一个,否则不能正常归因

完整请求示例:

curl -X POST \\

https://analytics.oceanengine.com/api/v2/valuable \\

\-H 'content-type: application/json' \\

\-d '{

"event\_type": "form",

"event\_weight": 0.561,

"biz\_channel": 5,

"context":{

"device":{

"platform": "ios",

"idfa": "FCD369C3-F622-43B8-AFDE-12012349F35B"

},

"ad": {

"ad\_id": 16521212134

}

},

"timestamp": 1604299664

}'

成功请求assist接口后,返回的HTTP状态码皆为200,如果有错误则通过错误码表示。

成功返回示例: **{"code": 0, "message": "成功"}**

状态码说明:


code

message

说明

0

成功

成功

10

服务暂时不可用

服务暂时不可用,可稍后再试

100

无效的请求,请求数据解析失败

上报请求消息体不能解析,请校验一下回传的字段和数据完整性

101

鉴权认证失败

鉴权失败,回传的签名字段不正确

102

参数:event_type无效

event_type为空,或者不合法

104

不支持的biz_channel

暂时不支持的业务场景,应用下载默认为0

105

参数:context.app.package_name不能为空

应用包名不能为空,必传字段

106

device信息不能全为空(idfa,gaid,imei,oaid,android_id至少得填一项)

context.device中的设备id(idfa/imei/oaid/gaid)至少需要传一个,否则不能归因

117

ad_id, campaign_id, advertiser_id, customer_id 不能全部为空

广告信息不能全部为空

118

imei/idfa(md5)/oaid(md5)/android_id(md5)/phone_num/ip&user_agent 不能全部为空

线索场景对应的设备号不能全为空

代码示例

以应用下载场景为例

Go示例

func main() {
    url := "https://analytics.oceanengine.com/api/v2/valuable"
    data := `{
        "event_type": "active",
        "event_weight": 0.561,
        "biz_channel": 0,
        "context":{
            "device":{
                "platform": "ios",
                "idfa": "FCD369C3-F622-43B8-AFDE-12012349F35B"
            },
            "app": {
                "package_name": "com.oceanengine.app"
            }
        },
        "timestamp": 1604299664
    }`
    payload := bytes.NewReader([]byte(data))
    req, _ := http.NewRequest(http.MethodPost, url, payload)
    req.Header.Add("content-type", "application/json")
    res, err := http.DefaultClient.Do(req)
    if err != nil {
        // handle error
    }
    defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)
    fmt.Println(string(body))
}

Python 示例

import requests

url = "https://analytics.oceanengine.com/api/v2/valuable"
payload = {
        "event_type": "active",
        "event_weight": 0.561, 
        "biz_channel": 0,
        "context":{
            "device":{
                "platform": "ios",
                "idfa": "FCD369C3-F622-43B8-AFDE-12012349F35B"
            },
            "app": {
                "package_name": "com.oceanengine.app"
            }
        },
        "timestamp": 1604299664
    }
headers = {
    'content-type': "application/json",
    }

response = requests.request("POST", url, data=json.dumps(payload), headers=headers)

print(response.text)

Nodejs 示例

const request = require("request");

let options = {
    method: 'POST',
    url: "https://analytics.oceanengine.com/api/v2/valuable",
    headers: { 'content-type': 'application/json' },
    body: {
        "event_type": "active",
        "event_weight": 0.561, 
        "biz_channel": 0,
        "context":{
            "device":{
                "platform": "ios",
                "idfa": "FCD369C3-F622-43B8-AFDE-12012349F35B"
            },
            "app": {
                "package_name": "com.oceanengine.app"
            }
        },
        "timestamp": 1604299664
    },
    json: true
};

request(options, function (error, response, body) {
    if (error) throw new Error(error);

    console.log(body);
});

PHP 示例

<?php

$request = new HttpRequest();
$request->setUrl('https://analytics.oceanengine.com/api/v2/valuable');
$request->setMethod(HTTP_METH_POST);

$request->setHeaders(array(
  'content-type' => 'application/json'
));

$request->setBody('{
        "event_type": "active",
        "event_weight": 0.561, 
        "biz_channel": 0,
        "context":{
            "device":{
                "platform": "ios",
                "idfa": "FCD369C3-F622-43B8-AFDE-12012349F35B"
            },
            "app": {
                "package_name": "com.oceanengine.app"
            }
        },
        "timestamp": 1604299664
    }');

try {
  $response = $request->send();

  echo $response->getBody();
} catch (HttpException $ex) {
  echo $ex;
}
?>

JAVA示例

OkHttpClient client = new OkHttpClient();

MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
JSONObject json = new JSONObject();
json.put("event_type", "active")
  .put("event_weight", 0.561)
  .put("biz_channel", 0)
  .put("context", new JSONObject()
    .put("device", new JSONObject()
        .put("platform", "ios")
        .put("idfa", "FCD369C3-ABCD-1234-EFGH-1234567890B")
        )
    .put("app", new JSONObject()
        .put("package_name": "com.oceanengine.app")
        )
    )
  .put("timestamp", 1604299664)
RequestBody body = RequestBody.create(mediaType, String.valueOf(json));
Request request = new Request.Builder()
  .url("https://analytics.oceanengine.com/api/v2/valuable")
  .post(body)
  .addHeader("content-type", "application/json")
  .build();

Response response = client.newCall(request).execute();

常用event_type

注意回传的取值是英文事件名称

event_type(需回传) 事件名称(中文) 定义
active 激活 用户下载安装完毕应用之后,在联网环境下打开应用
next_day_open 次留 用户激活后次日联网环境下打开应用
active_register 注册 完成应用下载并且在联网环境打开应用后,完成个人账号/游戏角色注册信息提交
active_pay 付费 完成应用下载并且在联网环境打开应用后,应用内完成一笔付款
form 表单 完成表单填写并提交
consult 在线咨询 用户点击在线咨询按钮
consult_effective 有效咨询 用户在消息咨询页面内完成至少一句消息对话
game_addiction 关键行为 用户在应用内发生的关键行为/行为集合,若是关键行为集合一般是有关联的行为路径。(举例:某直播类客户以注册+发送弹幕作为关键行为转化目标,电商用注册+收藏商品+加入购物车+下单等)
in_app_order app内下单 在应用内完成一次订单提交,例如:点击“立即下单”
in_app_uv app内访问 用户成功打开访问应用
in_app_cart app内添加购物车 在应用内成功将商品加入购物车,例如:点击“加入购物车”
in_app_pay app内付费 在应用内完成一次订单付费。目前主要是电商行业使用,常规建议使用付费事件
authorization 授权 完成授权电商/支付/社交等账号登陆
in_app_detail_uv app内详情页到站uv 成功访问应用内指定页面的UV数
customer_effective 有效获客 用户完成了一次有价值的动作,如预约到店,完成授权等,支持广告主根据业务场景自定义
方案二接入流程
  1. 回传方案

客户需自己进行归因及助攻判定,并将判定结果回传给巨量引擎,巨量引擎转化回传到接口二,巨量引擎助攻拼接相应字段后回传到assist接口

  1. 设置监测链接:
    1. 监测链接设置:可参考开发文档
    2. 填写展示、点击监测链接
      1. 填写入口
        1. 新建计划—创意—展示监测链接
        2. 资产—转化跟踪—新建转化—展示监测链接

image.png

  1. 技术对接方式介绍
  • 接口地址 :https://analytics.oceanengine.com/api/v2/assist

  • 请求方式POST

  • Content-Typeapplication/json

  • 参数列表


字段

必要

类型

举例

说明

event_type



string

active

事件类型

event_weight



number

0.561

事件权重,广告主自定义该事件的价值权重用于模型优化

context



object


广告上下文信息

context.ad



object


广告信息

context.ad.callback



string

EJiw267wvfQCGKf2g74ZIPD89-vIATAMOAFCIjIwMTkxMTI3MTQxMTEzMDEwMDI2MDc3MjE1MTUwNTczNTBIAQ==

巨量引擎下发的广告事件信息中的callback(clickid)部分,广告主需将该字段内容原样回传

context.ad.match_type



number

0

归因方式,0:点击 1:展示 2:有效播放归因

context.device



object


设备信息

context.device.platform



string

android

设备平台,android/ios

context.device.imei



string

0c2bd03c39f19845bf54ea0abafae70e

安卓系统 imei 的md5摘要

context.device.idfa



string

FCD369C3-ABCD-1234-EFGH-1234567890B

iOS系统idfa的原值

context.device.oaid



string

b305ee2abcdefgh2

Android系统的 oaid 原值

properties



object

{}

自定义回传属性信息,支持字段待补充

timestamp



number

1604299664

事件发生的时间戳,自1970/01/01(UTC)以来的秒数

完整请求示例

curl -X POST \\

https://analytics.oceanengine.com/api/v2/assist \\

\-H 'content-type: application/json' \\

\-d '{

"event\_type": "active",

"event\_weight": 0.561,

"context":{

"ad": {

"callback": "EJiw267wvfQCGKf2g74ZIPD89-vIATAMOAFCIjIwMTkxMTI3MTQxMTEzMDEwMDI2MDc3MjE1MTUwNTczNTBIAQ==",

"match\_type": 0

},

"device":{

"platform": "ios",

"idfa": "FCD369C3-ABCD-1234-EFGH-1234567890B"

}

},

"timestamp": 1604299664

}'

返回值:

成功请求assist接口后,返回的HTTP状态码皆为200,如果有错误则通过错误码表示。

成功返回示例: {"code": 0, "message": "成功"}

状态码说明


code

message

说明

0

成功

成功

10

服务暂时不可用

服务暂时不可用,可稍后再试

100

无效的请求,请求数据解析失败

上报请求消息体不能解析,请校验一下回传的字段和数据完整性

101

鉴权认证失败

鉴权失败,回传的签名字段不正确

102

参数:event_type无效

event_type为空,或者不合法

103

参数:callback无效

callback为空,或者不能解析

示例

Go示例

func main() {

url := "https://analytics.oceanengine.com/api/v2/assist"

data := \`{

"event\_type": "active",

"event\_weight": 0.561,

"context": {

"ad": {

"callback": "EJiw267wvfQCGKf2g74ZIPD89-vIATAMOAFCIjIwMTkxMTI3MTQxMTEzMDEwMDI2MDc3MjE1MTUwNTczNTBIAQ==",

"match\_type": 0

},

"device": {

"platform": "ios",

"idfa": "FCD369C3-ABCD-1234-EFGH-1234567890B"

}

},

"timestamp": 1604299664

}\`

payload := bytes.NewReader(\[\]byte(data))

req, \_ := http.NewRequest(http.MethodPost, url, payload)

req.Header.Add("content-type", "application/json")

res, err := http.DefaultClient.Do(req)

if err != nil {

// handle error

}

defer res.Body.Close()

body, \_ := ioutil.ReadAll(res.Body)

fmt.Println(string(body))

}

Python示例

import requests

url = "https://analytics.oceanengine.com/api/v2/assist"

payload = {

"event\_type": "active",

"event\_weight": 0.561,

"context": {

"ad": {

"callback": "EJiw267wvfQCGKf2g74ZIPD89-vIATAMOAFCIjIwMTkxMTI3MTQxMTEzMDEwMDI2MDc3MjE1MTUwNTczNTBIAQ==",

"match\_type": 0

},

"device": {

"platform": "ios",

"idfa": "FCD369C3-ABCD-1234-EFGH-1234567890B"

}

},

"timestamp": 1604299664

}

headers = {

'content-type': "application/json",

}

response = requests.request("POST", url, data=json.dumps(payload), headers=headers)

print(response.text)

Nodejs示例

const request = require("request");

let options = {

method: 'POST',

url: "https://analytics.oceanengine.com/api/v2/assist",

headers: { 'content-type': 'application/json' },

body: {

"event\_type": "active",

"event\_weight": 0.561,

"context": {

"ad": {

"callback": "EJiw267wvfQCGKf2g74ZIPD89-vIATAMOAFCIjIwMTkxMTI3MTQxMTEzMDEwMDI2MDc3MjE1MTUwNTczNTBIAQ==",

"match\_type": 0

},

"device": {

"platform": "ios",

"idfa": "FCD369C3-ABCD-1234-EFGH-1234567890B"

}

},

"timestamp": 1604299664

},

json: true

};

request(options, function (error, response, body) {

if (error) throw new Error(error);

console.log(body);

});

PHP示例

<?php

$request = new HttpRequest();

$request->setUrl('https://analytics.oceanengine.com/api/v2/assist');

$request->setMethod(HTTP\_METH\_POST);

$request->setHeaders(array(

'content-type' => 'application/json'

));

$request->setBody('{

"event\_type": "active",

"event\_weight": 0.561,

"context": {

"ad": {

"callback": "EJiw267wvfQCGKf2g74ZIPD89-vIATAMOAFCIjIwMTkxMTI3MTQxMTEzMDEwMDI2MDc3MjE1MTUwNTczNTBIAQ==",

"match\_type": 0

},

"device": {

"platform": "ios",

"idfa": "FCD369C3-ABCD-1234-EFGH-1234567890B"

}

},

"timestamp": 1604299664

}');

try {

$response = $request->send();

echo $response->getBody();

} catch (HttpException $ex) {

echo $ex;

}

?>

JAVA示例

OkHttpClient client = new OkHttpClient();

MediaType mediaType = MediaType.parse("application/json; charset=utf-8");

JSONObject json = new JSONObject();

json.put("event\_type", "active")

.put("event\_weight", 0.561)

.put("context", new JSONObject()

.put("ad", new JSONObject()

.put("callback", "EJiw267wvfQCGKf2g74ZIPD89-vIATAMOAFCIjIwMTkxMTI3MTQxMTEzMDEwMDI2MDc3MjE1MTUwNTczNTBIAQ==")

.put("match\_type", 0)

)

.put("device", new JSONObject()

.put("platform", "ios")

.put("idfa", "FCD369C3-ABCD-1234-EFGH-1234567890B")

)

)

.put("timestamp", 1604299664)

RequestBody body = RequestBody.create(mediaType, String.valueOf(json));

Request request = new Request.Builder()

.url("https://analytics.oceanengine.com/api/v2/assist")

.post(body)

.addHeader("content-type", "application/json")

.build();

Response response = client.newCall(request).execute();
Q&A

Q: 为什么巨量引擎下发的数据里面没有callback字段信息

A: 有些情况下,广告主收到的是clickid字段,含义和callback是一样的,即把收到的clickid值当做callback进行回传即可,注意不要进行url encode

常用event_type

注意回传的取值是英文事件名称

event_type(需回传) 事件名称(中文) 定义
active 激活 用户下载安装完毕应用之后,在联网环境下打开应用
next_day_open 次留 用户激活后次日联网环境下打开应用
active_register 注册 完成应用下载并且在联网环境打开应用后,完成个人账号/游戏角色注册信息提交
active_pay 付费 完成应用下载并且在联网环境打开应用后,应用内完成一笔付款
form 表单 完成表单填写并提交
consult 在线咨询 用户点击在线咨询按钮
consult_effective 有效咨询 用户在消息咨询页面内完成至少一句消息对话
game_addiction 关键行为 用户在应用内发生的关键行为/行为集合,若是关键行为集合一般是有关联的行为路径。(举例:某直播类客户以注册+发送弹幕作为关键行为转化目标,电商用注册+收藏商品+加入购物车+下单等)
in_app_order app内下单 在应用内完成一次订单提交,例如:点击“立即下单”
in_app_uv app内访问 用户成功打开访问应用
in_app_cart app内添加购物车 在应用内成功将商品加入购物车,例如:点击“加入购物车”
in_app_pay app内付费 在应用内完成一次订单付费。目前主要是电商行业使用,常规建议使用付费事件
authorization 授权 完成授权电商/支付/社交等账号登陆
loan_credit 互联网金融——授信
in_app_detail_uv app内详情页到站uv 成功访问应用内指定页面的UV数
customer_effective 有效获客 用户完成了一次有价值的动作,如预约到店,完成授权等,支持广告主根据业务场景自定义