概要 :サーバー間(S2S)イベントAPIを使用して、アプリの外部で発生したイベントをAppsFlyerへ送信します。S2SイベントはSDKイベントと同様にメディアソースへ紐付けられ、プラットフォーム全体で使用できます。
サーバー間 (S2S) イベントAPI for モバイル
AppsFlyerのプラットフォームは、AppsFlyer SDKおよびAPIによって送信されたモバイルアプリイベントをメディアソースに紐づけて記録します。S2S APIを使用することで、アプリの外部で発生したイベント(例:Webサイト上での定期購読登録の更新など)を計測できます。S2Sイベントが記録されると、通常のイベントデータと同様、管理画面、ローデータ、各種レポート画面など、プラットフォーム全体で利用できます。PBAのWebイベントについては、 Web S2S for PBA をご参照ください。
AppsFlyerはS2Sイベントに以下情報を入力します。
- S2Sメッセージで送信されたイベントの値
- インストール時間やメディアソースなどのAppsFlyerのインストール計測の値に
APIの利用手順
以下のセクションに含まれる情報を使用して、APIコールを作成してください。
S2S API 仕様
API endpoint |
|
HTTP method | POST |
Content Type | application/json |
認証 |
|
レスポンスメッセージの受信用サーバーをホワイトリスト登録 |
AWSのIPアドレスをホワイトリストに登録して、サーバーがファイアウォールの背後にある場合にもレスポンスメッセージを取得できるようにしてください。 |
JSON ペイロード制限 |
JSONペイロードサイズ:最大1KBまで |
レート制限 |
POSTのボリューム制限:60,000 POST /分この上限を増やしたい場合には、CSMに連絡してください。 |
コーディング仕様 |
|
URLのエンコード |
メソッドURLを形成する前に、予約文字(Reserved Characters)をパーセントエンコードしてください。 (https://tools.ietf.org/html/rfc3986#section-2.1 ) |
TLS |
TLS 1.2以上を使用してください。Ciphersもサポートしています。 |
ペイロードパラメータ
- ペイロードパラメータは、1 つ以上のデバイス識別子で構成されます(オペレーティングシステムによって異なります)。
-
デバイス識別子を送信できない場合はどうしますか?
- ユーザーが広告トラッキングの制限をオンにしている (LAT端末) の場合や、iOS 14を使用しており ATT に同意していないの場合など、特定の理由により広告IDを送信できないことがあります。IDFAがある場合は、送信してください。
- 広告ID/デバイス識別子を送信しないと次のような問題が起こる場合があります。
- ポストバックの問題:メディアソースはデバイス識別子なしでポストバックを受信するため、メディアソース側でユーザーと成果を紐づけることができません。
- オーディエンスセブメントとルールの失敗。オーディエンスのルールセットは識別子が必要です。ルールセットが使用するIDタイプに従って、デバイスID、または顧客ユーザーIDを送信してください。
OS | 識別子名 | 説明 |
---|---|---|
iOS
|
idfa |
利用可能な場合は、端末のIDFAを入力してください。 フォーマット:String 例: |
idfv |
利用可能な場合は、端末のIDFVを入力してください。 形式:String |
|
Android |
advertising_id |
利用可能な場合は、端末のGAID(Google Advertising ID)を入力してください。 フォーマット:String 例: |
oaid |
フォーマット:String 例: |
|
amazon_aid |
フォーマット:String |
|
imei |
フォーマット:String 例: |
パラメータ名 | 必須 | 説明 | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
appsflyer_id |
はい |
アプリの初回起動時に AppsFlyerによって生成されるユニークなID
|
|||||||||
customer_user_id |
いいえ |
カスタマーユーザーID: アプリの所有者が設定した一意のユーザーID。
|
|||||||||
att |
いいえ |
注意! 高プライバシーモードの設定はどの識別子がパートナーに共有されるかに影響するため、 |
|||||||||
IP |
いいえ |
イベント発生時のモバイルデバイスのIPアドレス
|
|||||||||
非推奨 |
|
||||||||||
eventName |
はい |
イベント名を指定してください。イベント名がマーケティング担当者からの要件と一致していることを確認してください。
|
|||||||||
Event Value |
はい |
値なしでイベントを送信する場合は、次のように送信してください。:
|
|||||||||
app_version_name |
いいえ |
アプリのバージョンまたは識別子。
|
|||||||||
app_store |
いいえ |
Androidアプリの AF_STORE に相当します。アプリがダウンロードされたストア。
|
|||||||||
Event Time |
いいえ |
UTCタイムゾーンでの、イベントの発生時刻。
イベント計測の締切
例
|
|||||||||
eventCurrency |
いいえ |
ISO 4217の3文字コード、もしくはBCN(ビットコイン)の通貨コード
|
|||||||||
bundleIdentifier |
いいえ* |
一意のアプリ識別子。ローデータにて、パラメーターにはBundle IDが入力されます。[ベストプラクティス] このパラメーターを常に入力してください。多くのアドネットワークでは、この値がキャンペーン最適化に必要です。
|
|||||||||
sharing_filter |
いいえ |
共有フィルタを使用すると、連携済みパートナーや他の第三者連携ツールとポストバックやAPI経由でS2Sイベントを共有することを防ぎます。 このフィルタは、GDPRやCCPAなどの規制要件を満たしたり、ユーザーのオプトアウトメカニズムに準拠したり、または他のビジネスロジックを実行する際に使用できます。 sharing_filter には次のオプションがあります。
パートナーIDリストについては、CSM またはAppsFlyerサポートへお問い合わせください。 |
|||||||||
custom_dimension |
いいえ |
AppsFlyerが将来的に利用するために準備してあります |
|||||||||
app_type |
いいえ |
iOSアプリ向け。 許可される値: ユーザーイベントが app_clip で発生する場合は、パラメーターを送信してください。それ以外の場合はパラメータを送信しないでください。 |
|||||||||
custom_data |
いいえ |
カスタムデータをAppsFlyerプラットフォームに送信します。 ローデータ: 形式:JSON、以下の例をご覧ください。 例:
|
|||||||||
* 多くのアドネットワークで、最適化のためにこの値が必要です |
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",
"eventValue":
"{
\"af_revenue\": \"1006\",
\"af_content_type\": \"wallets\",
\"af_content_id\": \"15854\",
\"af_quantity\" :\"1\"
}"
}
'
Response codes
応答コード | Message | 処理方法 |
---|---|---|
200 | OK |
メッセージを受信すると、最低限のデータ検証が実行されます。そのため、イベントがAppsFlyerに完全に記録されない場合でも、OKのレスポンスを受け取ることがあります。イベントをデバッグするには:
|
400 | Failed to Authenticate | 認証キーが正しいことを確認してください。 |
400 | appsflyer_id is a mandatory field |
|
401 | Unauthorized | authentication headerで提供されたキーがこのアプリの<dev_key>ではない場合。 |
400 | Bad request |
リクエストに関して少なくとも1つの条件が検証できず失敗した場合 |
400 | Payload is missing or failed to parse |
|
500 | Internal Server Error | JSONが文字列(String)化され、正しい形式で記述されていることを確認してください。 |
テスト
特記事項:
- テストには、非オーガニックインストールのAppsFlyer IDを使用してください。そうすればイベント計測はリアルタイムで行われますがオーガニックユーザーのイベント計測の場合、最長数時間の遅延を伴います。
- 一部のイベントフィールドは、ユーザーのインストールアトリビューションイベントを使用して入力されます。たとえば、時間とメディアソースをインストールします。
テスト端末を非オーガニックインストールとして紐付けるには:
- S2Sメッセージをテストするために、カスタム計測リンクを用意してください。リンク上のメディアソースパラメーターを s2s_test と設定し、計測リンクの例に示すように、リンク上に広告ID(GAID、IDFA等)を設定します。
- テストデバイスの登録
- テスト端末からアプリをアンインストールしてください。
- テスト端末にリンクを送信してください。
- リンクをクリックしてください。
- アプリをインストールして起動してください。
- 管理画面のオーバービュー上で、インストールが計測されているか確認してください。
- S2Sメッセージ送信で使用するAppsFlyer IDを取得してください。
S2Sメッセージをテスト送信するには :
- 先程の工程で取得したAppsFlyer IDを使用して、S2Sメッセージを準備してください。コード例については、以下を参照してください。
- S2Sメッセージを送信してください。
- 次のいずれかを実行して、S2SメッセージがどのようにAppsFlyerに記録されたかを確認してください。
- アプリ内イベントのローデータレポートをダウンロードしてください。送信したデータがローデータレポートに反映されるのに、イベントを送信後15分ほど掛かることがあります。
- Push API ( Postman および Webhookサイトなどのツール利用をおすすめします。)
- 以下を確認してください。
- S2Sメッセージで送信された値が、レポートに正しく入力されているか特に、イベントの日付、イベントの通貨、イベントの収益、イベントの値に注意してください。
- アトリビューションソースとインストールタイムは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メッセージを送信する際のコードサンプル
/* 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\"" +
"eventCurrency\": \"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();
}
}
}
''' using the requests python package, install using pip install requests '''
import requests
url = "https://api2.appsflyer.com/inappevent/[Insert app ID here]"
payload = "{\r\n \"appsflyer_id\": \"9999999999999999999999\",\r\n\t\"IDFA\":\"999999999999999999999999\",\r\n\t\"customer_user_id\" : \"14mar\",\r\n\t\"ip\": \"10.0.0.1\",\r\n\t\"app_version_name\" : \"example_version_name\",\r\n\t\"eventTime\" : \"2020-04-25 08:59:01.23\",\r\n\t\"eventName\": \"gaf_purchase\",\r\n\t\"eventCurrency\": \"ZAR\",\r\n\t\"eventValue\": \r\n\t\"{\r\n\t\t\\\"af_revenue\\\": \\\"1000\\\",\r\n\t\t\\\"af_content_type\\\": \\\"wallets\\\",\r\n\t\t\\\"af_content_id\\\": \\\"15854\\\",\r\n\t\t\\\"af_quantity\\\" :\\\"1\\\"\r\n }\"\r\n}"
headers = {
'authentication': '[Insert web dev key]',
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data = payload)
print(response.text.encode('utf8'))
/* using the request npm package, install using npm install request */
var request = require("request");
var options = { method: 'POST',
url: 'https://api2.appsflyer.com/inappevent/<APP_ID>',
headers:
{
"authentication": '<YOUR_DEV_KEY>',
'Content-Type': 'application/json'
},
body:
{ appsflyer_id: '<APPS_FLYER_ID>',
customer_user_id: '123456',
eventName: 'node_js',
eventValue: '{"node_js":"6" ,"af_content_id":"15854"}',
eventCurrency: 'USD',
ip: '1.0.0.0',
eventTime: '2018-07-09 4:17:00.000'
},
json: true };
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
/* using the RestSharp package, install using NuGet */
using System;
using RestSharp;
namespace CS
{
class Event
{
static void Main(string[] args)
{
var client = new RestClient("https://api2.appsflyer.com/inappevent/<APP_ID>");
var request = new RestRequest(Method.POST);
request.AddHeader("authentication", "<YOUR_DEV_KEY>");
request.AddHeader("Content-Type", "application/json");
var body = "{\"appsflyer_id\": \"<APPS_FLYER_ID>\"," +
"\"customer_user_id\": \"123456\"," +
"\"eventName\": \"af_purchase\"," +
"\"eventValue\": \"{\\\"af_revenue\\\":\\\"6\\\" ,\\\"af_content_id\\\":\\\"15854\\\"}\"," +
"\"eventCurrency\": \"USD\"," +
"\"eventTime\": \"2018-07-08 4:17:00.000\"
}";
request.AddParameter("undefined", body, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
// handle response by reading response.StatusCode
Console.WriteLine(response.Content);
}
}
}
$purchase_event = array(
'appsflyer_id' => <APPS_FLYER_DEVICE_ID>,
'idfa' => <IDFA>,
'eventCurrency' => <PURCHASE_CURRENCY>,
'ip' => <DEVICE_ID_ADDRESS>,
'eventTime' => date("Y-m-d H:i:s.000", time())
);
$purchase_event['eventName'] = 'af_purchase';
$purchase_event['eventValue'] = json_encode(array('af_revenue' => <PURCHASE_REVENUE>,
'af_price' => <PURCHASE_PRICE>,
'af_order_id' => <PURCHASE_ORDER_ID>,
'af_currency' => <PURCHASE_CURRENCY>,
'af_content_type' => <PURCHASE_TYPE>,
'af_quantity' => <PURCHASE_QUANTITY>,
'af_content' => <PRODUCT_NAME>,
'af_content_id' => <PRODUCT_ID>)
);
$data_string = json_encode($purchase_event);
$ch = curl_init('https://api2.appsflyer.com/inappevent/<YOUR_APP_ID>');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'authentication: <YOUR_APPS_FLYER_DEV_TOKEN>',
'Content-Length: ' . strlen($data_string))
);
$result = curl_exec($ch);
$curl = curl_init();
AppsFlyer Go script on Github
広告ID / デバイス識別子を送信する重要性
- 広告ID / デバイス識別子は、FacebookやGoogle AdsなどのSRNへポスバックをするために必須です。IDを送信できない場合は、ポストバックを送信できないということを考慮してください。
- AppsFlyer IDのみを送信する場合、アプリ内イベントは記録され正常に成果が紐づきます。
パラメータについて
オーガニックと非オーガニックの違い
AppsFlyerがS2Sのアプリ内イベントを処理するとき、アトリビューションフィールドはAppsFlyer IDを使用して入力され、アプリ内イベントよりも前に発生していた関連するインストールイベントを識別します。
つまり、AppsFlyerが非オーガニックサーバー間アプリ内イベントに関連付けるデータは、オーガニックサーバー間アプリ内イベントに紐付けられないということです。
例
たとえば、非オーガニックとオーガニックサーバー間アプリ内イベントのローデータレポートを比較する場合、非オーガニックイベントにはオーガニックアプリ内イベントにはないデータが含まれます。
非オーガニックのアプリ内イベントには、メディアソース、キャンペーン、アトリビューションタッチタイプ、アトリビューションタッチタイムに関するデータが含まれます。
一方、オーガニックのアプリ内イベントは、オーガニックのインストールに従います。オーガニックインストールには、キャンペーン、メディアソース、またはアトリビューションのタッチタイプと時間に関連するデータはありません。
AppsFlyer IDとカスタマーユーザーID(CUID)のマッピング
パラメーターに入力する特定の値を取得するには、バックエンドロジックが必要です。以下では、AppsFlyer IDの取得方法について説明しています。
- AppsFlyer IDは必須であり、イベントの紐付けに使用されます。
- このIDはユーザーが最初にアプリをインストールしたときに発行されます。
- CUIDをAppsFlyer IDにマップできるようにするには、アプリでCUIDを設定する必要があります。
どのユーザーがどのイベントを実行したかを簡単に把握できるようにするには、以下のフローを実装してください。
- ユーザーがアプリをインストールしたときにカスタマーユーザーID を付与(設定)してください。
- AppsFlyerのローデータレポートにCUIDとAppsFlyer IDが記録されるので、AppsFlyerのPush APIなどのデータ提供機能を利用して取得してください。
- ローデータレポートを使って、CUIDとAppsFlyer IDを照合させてください。
- AppsFlyer IDは、実装したSDKからも取得することが可能です。(Android/iOS)
- お客様自身のデータベース上でも、AppsFlyer IDをカスタマーユーザーIDにマッピングしてください。(将来的な使用においても重要です)。
AppsFlyer IDをお客様側のカスタマーユーザーIDにマッピングすると、どのユーザーがどのイベントを実行したかを簡単に知ることができます。その後、他の値(イベント値、イベント通貨、イベント時間など)を取得してサーバー間アプリ内イベントを送信できます。
Request bodyの例
{
"appsflyer_id": "1415211453000-6513894",
"advertising_id": "38412345-8cf0-aa78-b23e-10b96e40000d",
"eventName": "af_purchase",
"eventValue":
"{
\"af_revenue\": \"6\",
\"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はcontent typeなどの追加のプロパティと一緒に、収益を含む購入イベントであるS2Sのアプリ内イベントを受信します。
AppsFlyer IDの取得
appsflyer_id
はサーバー間イベントメッセージの必須パラメータです。AppsFlyerでは、このパラメーターを使用して、オリジナルの端末とメディアソースにイベントを紐付けます。 次のいずれかの方法でIDを取得できます。
- AppsFlyer SDKのAPIを呼んで、モバイル端末から取得する場合:Android / iOS
- 次のいずれかを使用してAppsFlyerプラットフォームから: Pull API / Push API / インストールのローデータエクスポート
ヒント
S2S メッセージをテストする際にローデータを使用する場合は、メディアソース名「s2s_test」の記録を確認してください。これがテスト時のデバイスで、その「AppsFlyer Device ID」がここで必要な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",
}}
イベント値なしでのイベント送信
イベント値なしでイベントを送信する場合は、単に空の文字列をイベント値に渡します: "eventValue":""
AppsFlyerは、広告主の設定に応じて、高度なターゲティングや最適化、オーディエンスの作成を目的に、このようなリッチアプリ内イベントをメディアソースに送信できます。
トラブルシューティング
イベントが管理画面に表示されない
- エンドポイント:使用されているエンドポイントが正しいことを確認してください。
- ペイロードに必須のパラメータが含まれていることを確認してください。詳細はこちらです。
- イベント計測に使用しているAppsFlyerIDが、(このガイドで提示しているサンプルのIDでなく)そのアプリがインストールされている実際のappsflyer_idであることを確認してください。詳細はこちらです。
- S2Sイベントは、イベントの一括送信をサポートしていません。各S2Sイベントは個別に送信する必要があります。
- オーバービューの画面で指定する日付は、イベントの発生日ではなく、アプリのインストール日(LTV)になります。
- 正しい日付範囲を選択していることを確認してください。
- 管理画面でイベントを確認するには、管理画面で選択した日付が、イベントの発生日ではなく、端末(appsflyer_id)のインストール日と一致していることを確認してください。
- イベントローデータレポート:日付範囲は、インストール日ではなくイベントの発火日が関係します。
イベントに収益が含まれない
S2Sイベントを送信しても、その収益が記録されない場合には、送信したJSONが文字列化されているかどうかを確認してください。最も重要な部分は、JSONのイベント値パラメーターです。次の例に示すように、文字列化する必要があります。
"{\"af_revenue\":\"6\" ,\"af_content_type\":\"wallets\"}"
文字列(String)化されていない場合、イベント値は正しく処理されず、収益は記録されません。
収益の値は書式化しないでください。小数点のコンマは使用可能ですが、必須ではありません。通貨記号や通貨コード、 ,
のような値の区切り文字も含めないでください。収益の値の冒頭には -
(マイナス)を付与することも可能です。
- 有効な値の例:
123
,-123.45
,123.456
- 無効な値の例:
1,234.56
,1,234
S2Sイベントのすべてのフィールドが入力されない
ローデータのフィールドはS2Sのコールで送信された値と、インストールイベントのデータを使用して入力されます。AppsFlyerのSDKを使って計測するアプリ内イベントと似たような挙動になりますが、まったく同一ではなくいくつかの違いがあります。具体的には、次のフィールドはS2Sイベントでは入力されません。
- WIFI
- Operator
- Language
- Device Type
- Device Category
- アプリバージョン:
app_version_name
を使用して設定します。 - App Name