移动设备的S2S事件API(S2S-mobile)

概要:本文讲解了如何从广告主服务器向AppsFlyer发送事件数据,以衡量在应用外部发生的移动事件。

S2S_us-zh.png

适用于移动设备的服务器到服务器事件API

对于iOS 14以上的应用版本,您需要发送OS(操作系统)参数。

AppsFlyer平台会对由AppsFlyer SDK和API发送的移动应用事件进行归因和记录,因此您可以使用S2S API上报应用程序外部发生的事件(如用户在您的网页端完成的续订)。记录到的S2S事件会反映在AF后台的所有面板/报告中,包括控制面板,原始数据和分析报告。另请参阅适用于PBA的网页S2S,了解有关PBA网页事件的详情。

AppsFlyer会将以下信息填充到S2S事件中:

  • S2S消息中发送的值
  • AppsFlyer的部分归因信息,例如激活时间和媒体渠道。

API使用说明

请根据以下各章节中的信息创建API调用。

关于S2S API的基础知识

API端点(endpoint)

https://api2.appsflyer.com/inappevent/app_id

  • app_id:在AppsFlyer面板中使用的应用程序标识符。请完全按照面板上显示的方式填入。
  • iOS应用:请确保添加前缀id否则虽然会返回有效的200 OK状态码,但不会记录事件。
  • Windows:请从Microsoft App Store获取应用ID。
  • Android示例: https://api2.appsflyer.com/inappevent/com.appsflyer.myapp
    iOS示例: https://api2.appsflyer.com/inappevent/id123456789
    Windows示例: https://api2.appsflyer.com/inappevent/a1b2c3d4e5f6
HTTP方法 POST
内容类型要求 application/ json
授权

--header'authentication: dev_key'

  • 开发者秘钥 dev_key 是header中的认证令牌(authentication token)。 
  • 要获取开发者密钥(dev key),请从AppsFlyer后台进入应用设置 > 开发者秘钥(dev key)
为服务器加白以获取响应消息

如果您的服务器设置了防火墙,请务必将appsflyer.com的域名加白,否则可能会收不到响应消息。

JSON的payload限制

JSON的payload大小不能超过1KB

拉取频次限制

POST限制数量:每分钟60,000次。如需提高限额,请联系您的CSM。

编码说明
编码URLs

在生成最终的URL之前,请将所有的保留字符进行URL编码(百分比编码)处理 (https://tools.ietf.org/html/rfc3986#section-2.1 )。

TLS

请使用TLS 1.2或更高版本。详见适用密码

关于S2S API的基础知识

Payload参数

  • Payload(关键信息)参数包含一个或多个设备标识符(具体取决于操作系统)。
  • 如果无法发送设备标识符怎么办
    • 有时可能会出于一些广告主不可控的因素而导致标识符无法发送,比如用户选择了限制广告追踪(Limit ad tracking,简称LAT)或者用户在iOS 14+系统中拒绝授权追踪。出现这种情况时,如果IDFV可用,则请发送IDFV。
    • 如果不发送广告ID/设备ID会导致下列问题:
      • 回传问题:媒体渠道会收到回传,但其中没有设备ID,因此无法关联到用户。
      • 受众细分及规则失效:受众细分规则组中需要用到标识符,请根据您的规则组中使用的ID类型来发送设备ID或客户用户ID(CUID)。
操作系统 标识符名称 描述

iOS

iconAFios.png

 

idfa 

如可获取,此处填充设备IDFA

格式:字符串

例如: "idfa": " 9876F1SS-2983-3855-27RR-2R626772VFNB "

idfv

如可获取,此处填充设备IDFA

格式: 字符串
示例: "idfv": "95C9BD22-4A4C-41C8-9548-ED07C5C8C145"

Android

iconAFand.png

advertising_id

如可获取,此处填充设备GAID(广告ID)

格式:字符串

示例: "advertising_id": " 9c9a82fb-d5de-4cd1-90c3-527441c11828 "

oaid

格式:字符串

例如: "oaid": " 1fe9a970-efbb-29e0-0bdd-f5dbbf751ab5 "

amazon_aid

格式:字符串

imei

格式:字符串

例如: "imei": " AA-BBBBBB-CCCCCC-D "

设备标识符
参数 是否必须配置 描述

appsflyer_id

应用首次启动时由AppsFlyer生成的唯一标识符。

  • 格式:字符串
  • 示例: "appsflyer_id": "1415211453000-6513894"

CUSTOMER_USER_ID

客户用户ID(CUID),  由广告主设置的用户唯一标识符。

  • 格式:字符串。
  • 示例: "customer_user_id": "my_customer_number1234"

att

iOS ATTrackingManager授权状态

  • 如果设备操作系统版本为iOS 14或更高版本,请使用ATTrackingManager填充att
    • 格式:个位整数。请勿在该值的前后加引号
    • 示例: 1
  • ATTrackingManager可能出现的值为:
    • 0: Not determined(不明确)
    • 1: Restricted(限制追踪)
    • 2: Denied(拒绝追踪)
    • 3: Authorize(授权追踪)

注意!

建议以ATTrackingManager的值来填充att参数,因为这会影响与渠道共享的ID类型(按照广告主设置的汇总层级高级隐私保护进行共享)。

 

ip

事件发生期间的移动设备的IP地址。

  • 如果发送,则使用IP地址填充地理位置字段。
  • 如果未发送,AppsFlyer会使用激活时的地理位置信息填充geo字段,但不填充IP地址。
  • 格式:包含IPV4或IPV6地址的字符串
  • 示例: "ip": "192.0.2.1
af_events_api 弃用
  • 从2020年7月6日开始弃用。
  • 您无需再发送此参数,不发送此参数不会对归因造成任何影响。

eventName

请指定事件名称,并确保事件名称符合营销人员的要求。

  • 格式:字符串
  • 示例: "eventName": "af_purchase"

eventValue

如果要发送不带值的事件,请发送: "event_value":""

  • 发出的事件值中不能出现其他符号或格式。
  • af_revenue中可以带有一个小数点,负值前需带有-
  • 格式:JSON中的字符串
  • 示例: "eventValue": " { \"af_revenue\": \"6\", \"af_currency\": \"USD\" \"af_content_type\": \"wallets\", \"af_content_id\": \"15854\", \"your_custom_attribute\" :\"456.123\" } "
  • 另请参见针对TikTok For Business的详细指南

app_version_name

您的应用版本或标识符。

  • 格式:字符串
  • 示例: "app_version_name": "my_app_version"

app_store

相当于安卓应用中的AF_STORE,用于说明用户是从哪个应用商店下载的应用。

  • 原始数据字段:Install App Store
  • 格式:字符串
  • 示例:my_android_store_is_best

eventTime

即事件发生的时间,以UTC时间显示。

  • 默认值:如果未发送eventTime ,则事件时间默认为HTTP消息接收时间。
  • 格式:字符串yyyy-mm-dd hh:mm:ss.sss,须使用UTC时间。
  • 示例: "eventTime":"2019-05-15 12:17:01.123",即表示UTC时间12:17:01。

一天结束:

  • eventTime生效的条件是该事件必须在第二天的02:00前到达AppsFlyer。也就是说,如果事件发生在UTC时间的星期一17:00,那么就必须在UTC时间的星期二02:00之前到达AppsFlyer服务器。
  • 一天结束后接收到的事件均按照实际接收时间来标记。
  • 带有未来时间(即超过接收时间)的事件会以接收时间来标记。

示例

  • 以UTC时间显示
  • 发送一个事件,事件数据中带有eventTime = Monday 21:00
接收时间 AppsFlyer记录的时间 备注
星期二01:00 星期一21:00 在工作时间结束前接收到的事件。
星期三09:00 星期三09:00 在工作时间结束后接收到的事件时间记为实际接收时间。

eventCurrency

ISO 4217中的3字符代码和BCN(比特币)

  • 默认值:美金
  • 示例: "eventCurrency": "ZAR"

bundleIdentifier

否*

应用唯一标识符。在原始数据中,该参数会填充Bundle ID字段。请务必填充该参数,因为许多广告平台都要求有该参数才能进行投放优化。

  • 格式:字符串
  • 示例:"bundleIdentifer": "com.myapp"

sharing_filter

sharing filter(数据分流)用于屏蔽对接渠道和其他第三方通过回传/API共享S2S事件数据。

该参数可帮助您满足GDPR和CCPA等法规要求、在用户拒绝授权时确保合规,同时应对其他的业务逻辑。

Sharing_filter具有以下选项:

  • all(全部):屏蔽所有渠道,即不与任何渠道共享事件数据。示例: "sharing_filter": "all"
  • 以数组的形式列出渠道ID。格式为[“ partnerid_1”,“ partnerid_2”,“ partnerid_n”]。示例: “ sharing_filter”:[“ googleadwords_int”,“ adcolony_int”]

如果需要渠道ID列表,请联系您的CSM或AppsFlyer技术支持。

custom_dimension

AppsFlyer留作后用

app_type

适用于iOS应用。

允许的值:app_clip

请仅针对app clip中发生的事件发送该参数。

custom_data

用于向AppsFlyer发送自定义数据,类似于使用setAdditionalData从SDK发送数据。

在原始数据中:填充custom_data字段。

格式为JSON,具体见下图示例。

示例:

"custom_data" : {"key_group" : { 
"key_a1" : "value a1", 
"key_a2" : "value a2" 
},
"key_b" : "value b"
}

OS

否**

设备的操作系统版本。不管您的应用在哪个操作平台中运行,都请务必配置该参数。

格式:字符串

示例:"os":"14.5.1"

注意!

从2021年7月1日起,对于iOS应用,如果广告主不发送该参数,AF会默认设备的操作系统版本为iOS 14.5。

aie

该参数用于判断用户是否拒绝共享其广告ID。

该字段适用于安卓(所有版本)或iOS 14以下的设备。请注意:对于iOS 14.5+,请使用att参数

该字段可能出现的值为:

  • 如果用户同意分享广告ID则为"true",即"aie":"true"
  • 如果用户启用了LAT(限制广告追踪)则为"false",即"aie":"false"

*许多广告平台要求有该参数才能进行投放优化。

**请务必发送该参数,以确保数据处理无误。我们没有将其标记为必须配置字段是出于向下兼容性的考虑。

Curl示例

curl --location --request POST 'https://api2.appsflyer.com/inappevent/<app_id_placeholder>'\
--header 'authentication: <dev_key_placeholder>
' \
--header 'Content-Type: application/json' \
--data-raw '{
  "appsflyer_id": "9999999999999-9999999999999999999",
	"advertising_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
	"customer_user_id" : "example_customer_id_123",
	"ip": "199.0.2.1",
	"app_version_name" : "example_version_name",
	"eventTime" : "2020-02-25 12:00.000",
	"eventName": "af_purchase",
	"eventCurrency": "ZAR",
"os" : "14.6",
"att" : 3, "eventValue": "{ \"af_revenue\": \"1006\", \"af_content_type\": \"wallets\", \"af_content_id\": \"15854\", \"af_quantity\" :\"1\" }" } '

响应代码

响应代码 信息 如何处理
200 OK

接收消息时所做的数据验证是比较有限的,因此即使事件没有完全录入AppsFlyer服务器,您也会收到OK的响应消息。请按以下步骤调试事件:

  • 请参考本文中的CURL示例
    • 更新应用ID(app id)和开发者密钥(dev key)。
    • 更改appsflyer_id和eventTime参数。使用当前时间和最近归因于非自然的appsflyer_id。
  • 调用API。
    • 须收到200 OK的响应消息。
    • 检查事件是否记录正确,包括收入
    • 根据需要进行其他更改,然后再次测试。
400 Failed to Authenticate
(无法进行身份验证)
请确保身份验证密钥(authentication key)正确无误。
400 appsflyer_id is a mandatory field
(appsflyer_id是必填字段)
  • 请确保JSON中的AppsFlyer ID正确无误。
  • 请确保JSON是字符串格式且格式正确。
401 Unauthorized
(未授权)
authentication header中提供的密钥不是此应用的开发者秘钥(dev_key)。
403 Forbidden
(禁止请求)
URL中的应用ID有误。
400 Bad request
(错误的请求)

只要有一项验证标准不符合,就会导致请求失败。

400 Payload is missing or failed to parse
(Payload缺失或解析失败)
  • 请确保JSON是字符串格式且格式正确。
  • 请检查JSON的payload中是否包含多个事件,并确保每次请求只发送一个事件。
500 Internal Server Error
(内部服务器错误)
请确保JSON是字符串格式且格式正确。

测试

注意事项:

  • 在测试时,请使用非自然激活的AppsFlyer ID,这样AF就能对测试事件进行实时归因。自然事件的归因会有几个小时的延迟。
  • 事件的某些字段是根据用户的激活归因事件填充的,如激活时间和媒体渠道。

请按以下步骤在测试设备上完成非自然激活:

  1. 请准备一条自定义归因链接,用于测试S2S消息。在该链接中,将媒体渠道参数设置为s2s_test,并按归因链接示例中的代码设置广告ID(GAID、IDFA等)。
  2. 为测试设备加白
  3. 从测试设备上卸载应用程序。
  4. 将链接发送到测试设备。
  5. 点击链接
  6. 安装并启动该应用程序。
  7. 进入AF面板检查该激活是否已被归因。
  8. 提取AppsFlyer ID,在S2S消息中会用到该信息。

请按以下步骤发送S2S测试消息

  1. 使用上一步中获取的AppsFlyer ID准备S2S消息。具体的代码示例请参见下文相关部分。
  2. 发送消息。
  3. 请执行以下任一项操作,以查看AppsFlyer是如何记录该消息的:
  4. 查看报告并注意以下几点:
    • S2S消息中发送的值正确填充了报告。请特别注意Event date(事件日期)、Event currency(事件货币)、Event revenue(事件收入)和Event value(事件值)这几个字段。
    • 归因渠道和激活时间由AppsFlyer填充。
    • SDK本身提供的值(例如SDK版本)不会被填充。

归因链接示例

Android

https://app.appsflyer.com/<app_id>?pid=s2s_test&c=test&advertising_id=<GAID>

iOS

https://app.appsflyer.com/<app_id>?pid=s2s_test&c=test&idfa=<IDFA>

发送S2S消息的示例代码

JavaPythonNode JSC#PHPGo
/* using the okhttp package 
install from maven https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp*/
import okhttp3.*;
import java.io.IOException;

public class SendRequest {
  public static void main(String[] args) {

    OkHttpClient client = new OkHttpClient();
    MediaType mediaType = MediaType.parse("application/json");

RequestBody body = RequestBody.create(mediaType," +
        "{\r\n\t\"appsflyer_id\": \"<APPS_FLYER_ID>\"," +
        "\r\n\t\"customer_user_id\": \"123456\",\r\n\t\"eventName\": \"af_purchase\",\r\n\t\" +
        "eventValue\": \"{\\\"af_revenue\\\":\\\"6\\\" ,\\\"af_content_id\\\":\\\"15854\\\"}\",\r\n\t\" +
        "af_currency\": \"USD\",\r\n\t\" +
        "eventTime\": \"2018-08-10 4:17:00.000\",\r\n\t\");

Request request = new Request.Builder()
        .url("https://api2.appsflyer.com/inappevent/<APP_ID>")
.post(body)
.addHeader("Content-Type","application/json")
        .addHeader("authentication","<YOUR_DEV_KEY>")
        .build();

try {
      Response response = client.newCall(request).execute();
      System.out.println(response.code());
      System.out.println(response.body().string());
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

广告ID/设备ID的重要性

  • 广告ID/设备ID是必须配置的参数,这是为了确保将数据回传到Facebook和Google Ads等SRN。如果您不发送该ID,我们是无法发送回传数据的。
  • 如果不发送广告ID/设备ID而仅发送AppsFlyer ID,不会影响应用内事件的正确记录及归因。

填充参数

自然量与非自然量的区别

AppsFlyer处理S2S应用内事件时,会通过AppsFlyer ID来识别相关应用内事件之前的激活事件,从而填充归因字段。

也就是说,AppsFlyer会将某些数据与非自然的S2S应用内事件相关联,而这些数据与自然的S2S应用内事件是不相关的。

 示例

如果对比非自然和自然的S2S应用内事件原始数据报告, 会发现非自然事件中包含自然事件所没有的数据。

这些数据包括媒体渠道、广告系列、触点类型、触达时间等。

这是因为自然事件来自于自然激活,而自然激活本来就没有广告系列、媒体渠道、触点类型和触达时间等数据。

AppsFlyer ID与客户用户ID(CUID)之间的映射

需要通过后端逻辑获取相关的值来填充参数。请按以下步骤获取AppsFlyer ID:

  • AppsFlyer ID是必须配置的参数,用于归因事件。
  • 该ID是在用户首次激活应用时生成的。
  • 如果需要将CUID映射到AppsFlyer ID,请务必在应用中设置CUID。

请部署以下链路,以便将用户关联到事件:

  • 在用户激活应用时设置客户用户ID(CUID)
  • AppsFlyer原始数据报告中会包含CUID和AppsFlyer ID。您可以使用任意数据传输工具或AppsFlyer的Push API来获取该数据。
  • 使用原始数据报告将CUID与AppsFlyer ID进行匹配。
  • 您在应用(安卓/iOS)中接入AppsFlyer SDK后,SDK会在用户激活应用时生成AppsFlyer ID。
  • 将AppsFlyer ID映射到内部系统中的客户用户ID(CUID)(后续会有重要作用)。

AppsFlyer ID与CUID之间形成映射后,就可以将用户匹配到他们完成的事件。然后,您可以获取其他值(事件值,事件币种,事件时间等),并发送S2S应用内事件。  

请求示例

{
  "appsflyer_id": "1415211453000-6513894",
	"advertising_id": "38412345-8cf0-aa78-b23e-10b96e40000d",
	"eventName": "af_purchase",
	"eventValue": 
	"{
		\"af_revenue\": \"6\",
\"af_currency\" \"USD"\", \"af_content_type\": \"wallets\", \"af_content_id\": \"15854\", \"af_quantity\" :\"1\" }", "eventCurrency": "USD", "ip": "1.2.3.4", "eventTime": "2014-05-15 12:17:00.000" }


本示例中,AppsFlyer收到一个S2S应用内事件。根据参数和对应的值可以判断,这是一个包含收入、内容类型等属性的购买事件。

提取AppsFlyer ID

appsflyer_id是服务器到服务器事件消息中的必须配置的参数。AppsFlyer需要使用该参数才能将事件归因到原始设备和媒体渠道。您可以使用以下任一种方法获取该ID:

 提示

测试S2S消息时,如果使用的是原始数据,请查找媒体渠道为“s2s_test”的记录。由于这是您的测试设备,因此您需要用到的ID是其AppsFlyer Device ID。

发送负收入

您可以发送收入值为负的事件(如订单被取消)。af_revenue参数可以通过负值来记录此信息。

如果使用af_quantity,请根据您的系统逻辑来决定是否在其中填充负值。AppsFlyer是不使用af_quantity的。

负收入示例

{ 
 “ eventName”:“ cancel_purchase”, 
 “ eventValue”: 
 “ {
		\"af_revenue\": \"-6\",
		\"af_content_type\": \"wallets\",
		\"af_content_id\": \"15854\",
		\"af_quantity\" :\"1\"
   } ”, 
 “ eventCurrency”:“ USD”, 
 
 }

疑难解答

事件未显示在面板上

  • 端点(endpoint):请检查您所使用的节点(endpoint)是否正确。
  • 请检查Payload中是否包含必需参数。详情请见此处
  • 请确保您用来触发事件的AppsFlyer ID是真实的appsflyer_id,并且已存入应用中。这里的ID不是文档中提供的测试ID,详情请见此处
  • 一个S2S请求中不能包含多个事件,每个事件都必须单独发送。
  • 在数据总览面板中,日期范围中的日期是指应用激活日期(即LTV维度),而非事件发生日期。
    • 确保您选择正确的日期范围。
    • 确保面板日期范围对应于设备的激活日期(appsflyer_id),而不是事件的日期。
  • 事件原始数据报告:日期范围中的日期是事件发生日期,而非应用激活日期。

事件不包含收入

如果发送的S2S事件中未记录收入:请确保JSON是字符串格式的。其中最重要的部分是事件值参数,请务必将其转化为下图示例中的格式。

"{\"af_revenue\":\"6\" ,\"af_content_type\":\"wallets\"}"

如果事件值未转化成字符串格式,则无法得到正确处理,导致记录不到收入。

收入值不能带有任何格式。该值可以包含一个小数点,但不能带有货币符号、代码或,分隔符,数值前可以带有-

  • 有效值示例: 123-123.45123.456 
  • 无效值示例: 1,234.561,234

S2S事件中并非所有字段都要填充

原始数据的字段是在调用S2S事件API后根据发送的值填充的,有的字段是根据SDK侧的应用激活填充的。由AppsFlyer SDK上报的应用内事件也会出现类似情况,但不完全相同,具体差别在于S2S事件不填充以下字段:

  • WIFI
  • Operator(运营商)
  • Language(语言)
  • Device Type(设备型号)
  • Device Category(设备类别)
  • App Version(应用版本,您可以使用app_version_name参数填充该值)
  • App Name(应用名称)