どのようにお手伝いできますか?

アドネットワーク向けクリック署名

  • 更新

概要:クリックに署名検証を導入することで、不正による損失や負担を防ぎ、不正なクリックが自社のアドネットワークのものとして扱われないようにします。 

クリック署名について

不正行為者は、ごく簡単な技術でアドネットワークを装い、数千件から数百万件もの偽のクリックをAppsFlyerに送信できます。アドネットワーク自身が、この問題に気付いていない場合もあります。 

アドネットワークは、クリックにHMAC-SHA256署名を付ける必要があります。これにより、AppsFlyerが自社にアトリビューションしたクリックが、不正行為者による偽のクリックではなく、実際に自社から発生したものであることを確認できます。

クリック署名は、クリック洪水によってアドネットワークのトラフィックがブロックされるのを防ぐことにも役立ちます。極端なクリック洪水によってクリックのブロック基準値に達すると、AppsFlyerはその日の残りの時間、当該アドネットワークのクリックの記録とアトリビューションを停止します。

AppsFlyerは署名を使ってクリックを検証し、クリック情報が不正行為者によって改ざんされていないことを確認します。

  • 検証に成功したクリックは記録され、アドネットワークがアトリビューション先となります。 
  • 検証に失敗したクリックは拒否され、以下のように扱われます。 
    • 広告主向けではなく、アドネットワーク向けのProtect360レポートで確認できます。詳細はこちら
    • アドネットワークのコンバージョン率や、クリックのブロック基準値には影響しません。

クリック署名の実装

実装の流れ

以下の図は、初期開発と基本テストから、本番環境でのテスト、本番運用の開始までの流れを示しています。 

Click_signing_integration_flow.png

実装手順

事前準備:API V2.0トークンを管理者から取得します。クリック署名APIの認証に使用します。

クリックに署名する手順:

  1. シークレットキー生成APIで、シークレットキーを生成します。
    推奨:有効期限を36時間に設定した新しいシークレットキーを、24時間ごとに生成して使用します。 
  2. コードを開発し、自社サーバーからシークレットキー生成APIを呼び出して、取得したキーでHMAC-SHA256署名を生成できるようにします。コードサンプルを参照してください。
    以下の表で説明するその他のAPIも使用できます。
  3. コードで、以下の情報をクリックURLに追加します。 
    • クリックの有効期限を示すUNIXタイムスタンプ(UTC)を含むexpiresパラメータ。この時刻以降、アドネットワークはそのクリックを有効とは認めません。
    • HMAC-SHA256署名。
      例:
      https://app.appsflyer.com/com.app.id?pid=adnetwork_int&c=my_campaign&clickid=sdkfjasksjskdfj9845weh&af_siteid=12345&expires=1597657118&signature_v2=8fnDVzZP_WRZnv3KNJaREOEfvB5p9oRc_XlKEvUo8gk

注意

リンク内の特殊文字やスペースのURLエンコードは、必ずクリック署名の生成前に行ってください。 先に署名を生成すると、検証に失敗します。

クリック署名の生成

クリック署名は、以下の手順で生成します。

  1. 後述の属性の一覧とJSONのルールに従って、JSONを作成します。
  2. このJSONから、HMAC56を使用して署名を生成します。

属性の一覧

クリックとエンゲージメントの署名では、以下の属性を使用できます。

順序 パラメータ 必須 説明
1 link_domain はい クリックURLのドメイン。例:
  • app.appsflyer.com
  • myapp.onelink.me
  • click.mycustomdomain.com
2 link_path はい 先頭のバックスラッシュを除いたクリックURLのパス。
単一プラットフォームのリンクの場合はapp-id、OneLinkの場合はtemplate-idです。
3 pid はい  
4 af_prt いいえ  
5 af_siteid はい  
6 clickid はい クリックごとに1回限り使用する、一意の識別子。
7 expires はい クリックの有効期限
8 af_engagement_type いいえ  
9 af_click_lookback いいえ  
10 af_viewthrough_lookback いいえ  
11 af_reengagement_window いいえ  
12 is_retargeting いいえ  
13 af_ip いいえ  
14 advertising_id いいえ  
15 oaid いいえ  
16 fire_advertising_id いいえ  
17 idfa いいえ  
18 idfv いいえ  

属性とJSONのルール

属性の指定と順序

  • エンゲージメントURLに含まれる対応パラメータのうち、値が設定されているものは、JSONにも必ず含めてください。
  • JSON内の属性は、上の表に記載された順序で指定してください。

空の属性値

  • JSONに含める属性の値は、空文字列やスペースのみにはできません。

JSONのデータ構造

  • JSONは、属性の配列として構成する必要があります。
    • 各属性は["key", "value"]形式で指定します。
      例:
      [["key-1","value-1"],["key-2","value-2"]...["key-n","value-n"]]

属性値のエスケープ処理

  • JSON内の値は、小文字の文字列で記述する必要があります。JSON標準の定義に従ってください。

JSON内の空白

  • JSONは、余分な空白を除去した形式にしてください。値と値の間に、スペース、タブ、改行を含めないでください。

署名アルゴリズム 

  • シークレットキーとHmacSHA256を使用して、JSONの署名を生成します。
  • 署名をBase64でエンコードします。パディングは付けないでください。
  • signature_v2パラメータで、署名をクリックURLに追加します。
//generate a signature from the click url and encode it with base64 without padding String generatedSignature = Base64.getUrlEncoder().withoutPadding().encodeToString(mac.doFinal(jsonString.getBytes()));

署名の例

署名の作成例

OneLink(複数プラットフォーム対応)のクリックURLの例:

https://yourbrand.onelink.me/qsWL?pid=mediasource_int&advertising_id=12345678-1234-1234-1234-123456789012
&af_ad_type=video&af_adset=MMP&clickid=sdkfjasksjskdfj9845weh&af_siteid=my_site&af_viewthrough_lookback=2h&c=my_campaign
&expires=1689695615

署名用のJSONオブジェクトの例(空白の除去前):

[
	["link_domain","yourbrand.onelink.me"],
	["link_path","qswl"],
	["pid","mediasource_int"],
	["af_siteid","my_site"],
	["clickid","12345"],
	["expires","1689695615"]
]

署名用のJSONオブジェクトの例(空白の除去後):

[["link_domain","yourbrand.onelink.me"],["link_path","qswl"],["pid","mediasource_int"],["template-id","qswl"],["af_siteid","my_site"],["clickid","12345"],["expires","1689695615"]]

署名を追加した最終的なクリックURL:

https://yourbrand.onelink.me/qsWL?pid=mediasource_int&advertising_id=12345678-1234-1234-1234-123456789012
&af_ad_type=video&af_adset=MMP&af_siteid=my_site&af_viewthrough_lookback=2h&c=my_campaign
&expires=1689695615
&signature_v2=WIfCmfLAPSsVrBTqCqfihMeLCnbE4dIAlhHF84WsiWA

コード例

signing-supported-params.json

[
  {"index":1, "name":"pid", "mandatory":true},
  {"index":2, "name":"af_prt", "mandatory":false},
  {"index":3, "name":"af_siteid", "mandatory":true},
  {"index":4, "name":"clickid", "mandatory":true},
  {"index":5, "name":"expires", "mandatory":true},
  {"index":6, "name":"af_engagement_type", "mandatory":false},
  {"index":7, "name":"af_click_lookback", "mandatory":false},
  {"index":8, "name":"af_viewthrough_lookback", "mandatory":false},
  {"index":9, "name":"af_reengagement_window", "mandatory":false},
  {"index":10, "name":"is_retargeting", "mandatory":false},
  {"index":11, "name":"af_ip", "mandatory":false},
  {"index":12, "name":"advertising_id", "mandatory":false},
  {"index":13, "name":"oaid", "mandatory":false},
  {"index":14, "name":"fire_advertising_id", "mandatory":false},
  {"index":15, "name":"idfa", "mandatory":false},
  {"index":16, "name":"idfv", "mandatory":false}
]

signature-example.go

package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/url"
	"os"
	"strings"
	"time"
)

type Param struct {
	Name      string
	Mandatory bool
}

func LoadSupportedParams() ([]Param, error) {
	path := "./signing-supported-params.json"
	jsonFile, _ := os.Open(path)
	defer jsonFile.Close()
	byteValue, err := io.ReadAll(jsonFile)
	if err != nil {
		return nil, errors.New("failed loading " + path)
	}
	var params []Param
	_ = json.Unmarshal(byteValue, &params)
	return params, nil
}

func computeHmac256(message, secret string) (res string, errResult error) {
	defer func() {
		if r := recover(); r != nil {
			errResult = r.(error)
			fmt.Println("failed to invoke ComputeHmac256. err: %+v", errResult)
			res = ""
			return
		}
	}()

	key := []byte(secret)
	h := hmac.New(sha256.New, key)
	h.Write([]byte(message))
	return base64.URLEncoding.WithPadding(base64.NoPadding).EncodeToString(h.Sum(nil)), nil
}

// this function accepts a click url, a ttl for the click in seconds, and the list of supported params
// the function:
// 1. adds the expiration to the click based on the provided ttl
// 2. builds a json for the signature
// 3. create an HMAC256 signature
// 4. adds the signature to the click url
func signURLV2(originalURL string, secret string, clickTtlSeconds int64, supportedParams []Param) (signedURL string, err error) {

	//add an expiration to the click
	expires := time.Now().UTC().Unix() + clickTtlSeconds
	urlWithExpired := fmt.Sprintf("%s%s%d", originalURL, "&expires=", expires)

	//parse the url
	parsedURL, err := url.Parse(urlWithExpired)
	if err != nil {
		return "", errors.New("failed parsing URL")
	}

	//build a json from the url
	jsonStr, err := buildJSONFromURLV2(parsedURL, supportedParams)
	if err != nil {
		return "", err
	}

	//create a signature
	signatureV2, err := computeHmac256(jsonStr, secret)
	if err != nil {
		fmt.Println("Failed to computeHMAC256 for url %s. err: %+v", jsonStr, err)
		return "", errors.New("fail to computeHMAC256 for url")
	}

	//add the signature to the url
	signedURL = fmt.Sprintf("%s%s%s", urlWithExpired, "&signature_v2=", signatureV2)

	return signedURL, nil

}

// this function builds a json from a given click url.
// It returns a string representation of the json ready to be signed.
func buildJSONFromURLV2(parsedURL *url.URL, supportedParams []Param) (string, error) {
	//initiate an empty json in the structure [[key-1,val-1],[key-2,val-2]...[key-n,val-n]]
	var jsonData [][2]string

	//add the url host domain to the json
	domain := parsedURL.Host
	param := [2]string{"link_domain", domain}
	jsonData = append(jsonData, param)

	//add the path (app-id or template-id) to the json
	path := parsedURL.Path
	if len(path) > 1 {
		param := [2]string{"link_path", path[1:]}
		jsonData = append(jsonData, param)
	}

	//loop over the ordered list of supported parameters and add them to the json
	for i := 0; i <len(supportedParams); i++ {name := supportedParams[i].Name val := parsedURL.Query().Get(name) if len(val) > 0 {
			param := [2]string{name, val}
			jsonData = append(jsonData, param)
		} else if supportedParams[i].Mandatory {
			return "", errors.New("missing mandatory param: " + name)
		}
	}

	//generate string representation of the json object
	jsonObj, _ := json.Marshal(jsonData)
	return strings.ToLower(string(jsonObj)), nil
}

func main() {

	supportedParams, err := LoadSupportedParams()
	if err != nil {
		fmt.Println("Error: ", err)
		os.Exit(1)
	}

	var secretKey = "tqJU4Qd/eFTEWfqW7KCG9asDO0bmZoFzv8GY3VPSPAM="
	var clickTtlSeconds int64 = 60
	var originalUrl = "https://yourbrand.onelink.me/qsWL?pid=mediasource_int&advertising_id=12345678-1234-1234-1234-123456789012&clickid=1234&af_ad_type=video&af_adset=MMP&af_siteid=my_site&af_viewthrough_lookback=2h&c=my_campaign"

	fmt.Println("Original URL: ", originalUrl)

	signedUrl, err := signURLV2(originalUrl, secretKey, clickTtlSeconds, supportedParams)
	if err != nil {
		fmt.Println("Error: ", err)
		os.Exit(1)
	} else {
		fmt.Println("Signed URL: ", signedUrl)
	}
}

クリック署名API

AppsFlyerは、アドネットワークがクリック署名の処理を管理・テストするためのAPIを提供しています。以下のAPI一覧と、各APIの使用に必要な情報を説明する後続のセクションを参照してください。 

クリック署名API

APIメソッド 説明
シークレットキーの生成 署名に使用するシークレットキーを生成します。
シークレットキーの無効化 漏えいなどによって安全性が損なわれたシークレットキーを無効にします。
テスト クリックを1件ずつ送信し、署名をテストします。
モードの設定 クリック署名のモードを設定します。 
  • disabled(無効、デフォルト):クリック署名の検証を行いません。
  • report-only(レポートのみ、テスト用):AppsFlyerはクリック署名を検証しますが、署名が無効でもクリックをブロックしません。アドネットワークは、レポートAPIで、検証に成功・失敗したクリックの統計を取得できます。本番環境や実際のトラフィックに影響を与えずにクリック署名をテストする場合に使用します。
  • enabled:AppsFlyerは、署名が無効または付いていないクリックをブロックします。
サーキットブレーカーの設定 クリックが大量にブロックされることからアドネットワークを保護する、サーキットブレーカーのモードを設定します。
  • enabled(有効、デフォルト):Protect360が大量のクリックを無効と判定した場合、誤ってブロックされている可能性を考慮し、アドネットワークを保護するために以下の処理を行います。
    • モード設定APIで設定する動作モードが、レポートのみモードに切り替わります。
    • アドネットワークにメール通知が送られ、クリック署名APIが正しく設定されているか確認を促します。
  • disabled:ブロックの割合が異常に高くても、Protect360は無効と判定したすべてのクリックのブロックを継続します。
設定の取得 現在のモードと、有効なシークレットキーのIDを取得します。
レポート report-only(レポートのみ)またはenabled(有効)モードで、直近3日間の検証に成功・失敗したクリックの統計を取得します。本番環境や実際のトラフィックに影響を与えずにクリック署名をテストする場合に使用します。
アプリの除外 クリック署名の対象から除外するアプリIDを設定します。 
除外したアプリの復帰 クリック署名の対象から除外したアプリIDを、再び対象に戻します。

旧バージョン

以下は参考情報として掲載している旧バージョンです。使用しないでください。

V1 | 旧バージョン

シークレットキー生成API

シークレットキー生成APIの基本仕様

区分 項目 説明
リクエスト HTTPメソッド POST
パス https://hq1.appsflyer.com/api/p360-click-signing/secret?ttlHours=<ttlHours>
Authorizationヘッダー 
レスポンス 取得結果 シークレットキーがJSON形式で返されます。
  利用上限 同時に有効にできるシークレットキーは、最大2つです。

APIリクエスト

メソッド

POST https://hq1.appsflyer.com/api/p360-click-signing/secret?ttlHours=<ttlHours>

パラメータ

パラメータ 説明
ttlHours
  • シークレットキーの有効期間。時間単位で、1~1440時間を指定できます。
  • デフォルトは36時間です。

JSONレスポンス

キー 説明
secret-key-id シークレットキーのID。
secret key クリック署名に使用するシークレットキー。
expiration ミリ秒単位のエポック時刻。

シークレットキー生成のcurl例とレスポンス

curlリクエスト

curl --location --request POST 'https://hq1.appsflyer.com/api/p360-click-signing/secret?ttlHours=36' \
-H 'Authorization: Bearer {API V2.0 token available to the admin in the dashboard.}'

JSONレスポンス

{
	"secret-key-id": "59ad6547-affc-45eb-a6c9-9805f88ee755",
	"secret-key": "zGW6Rhrmb8+vuhHtL/Kp6rW5Ci9PNsjH1J5MGO9SIeg=",
	"expiration": 1610533263
}

HTTPレスポンスコード

レスポンスコード

コード  メッセージ 説明
200 OK  
401 Not authorized Authorizationヘッダーが無効、または指定されていません。

シークレットキー無効化API

シークレットキー無効化APIの基本仕様

区分 項目 説明
リクエスト HTTPメソッド DELETE
パス https://hq1.appsflyer.com/api/p360-click-signing/secret/<secret-id>
Authorizationヘッダー 
レスポンス 取得結果 空のレスポンス

APIリクエスト

メソッド

DELETE https://hq1.appsflyer.com/api/p360-click-signing/secret/<secret-id>

パラメータ

パラメータ 説明
secret-id 無効にするシークレットキーのID。

シークレットキー生成のcurl例とレスポンス

curlリクエスト

curl --location --request DELETE 'https://hq1.appsflyer.com/api/p360-click-signing/secret/59ad6547-affc-45eb-a6c9-9805f88ee755' \
-H 'Authorization: Bearer {API V2.0 token available to the admin in the dashboard.}'

HTTPレスポンスコード

レスポンスコード

コード  メッセージ 説明
200 OK  
401 Not authorized Authorizationヘッダーが無効、または指定されていません。

テストAPI

テストAPIの基本仕様

区分 項目 説明
リクエスト HTTPメソッド POST
パス https://hq1.appsflyer.com/api/p360-click-signing/test
Authorizationヘッダー 
レスポンス 取得結果 JSON形式で返されます。

APIリクエスト

メソッド

POST https://hq1.appsflyer.com/api/p360-click-signing/test

パラメータ

パラメータ 説明
url テストするクリックURL(署名を含む)。

JSONレスポンス

キー 説明
test-status PassedまたはFailed。
message テストが失敗した理由。例:
  • Missing signature(署名なし)
  • Invalid signature(無効な署名)
  • Expired(有効期限切れ) 

テストのcurl例とレスポンス

curlリクエスト

curl --location --request POST 'https://hq1.appsflyer.com/api/p360-click-signing/test' \
-H 'Authorization: Bearer {API V2.0 token available to the admin in the dashboard.}' \
--header 'Content-Type: application/json' \
--data-raw '{
   "url": "https://app.appsflyer.com/com.app.id?pid=adnetwork_int&c=my_campaign&clickid=sdkfjasksjskdfj9845weh&af_site_id=12345&expires=1597657118&signature=8fnDVzZP_WRZnv3KNJaREOEfvB5p9oRc_XlKEvUo8gk"
}'

JSONレスポンス

{
	"test-status":"Passed / Failed",
	"message": "Invalid signature"
}

HTTPレスポンスコード

レスポンスコード

コード  メッセージ 説明
200 OK  
401 Not authorized Authorizationヘッダーが無効、または指定されていません。

モード設定API

モード設定APIの基本仕様

区分 項目 説明
リクエスト HTTPメソッド POST
パス https://hq1.appsflyer.com/api/p360-click-signing/config/mode/<mode>
Authorizationヘッダー 
レスポンス 取得結果 JSON形式で返されます。

APIリクエスト

メソッド

POST https://hq1.appsflyer.com/api/p360-click-signing/config/mode/<mode>

パラメータ

パラメータ 説明
mode 指定できる値:
  • enabled
    注意:レポートのみモードで数時間動作させ、レポートで設定が正しいことと、すべてのクリックが署名検証に成功していることを確認してから、モードをenabledに設定してください。
  • disabled
  • report-only

モード設定のcurl例

curlリクエスト

curl --location --request POST 'https://hq1.appsflyer.com/api/p360-click-signing/config/mode/report-only' \
-H 'Authorization: Bearer {API V2.0 token available to the admin in the dashboard.}'

HTTPレスポンスコード

レスポンスコード

コード  メッセージ 説明
200 OK  
400 Bad request 無効なモードが指定されています。
401 Not authorized Authorizationヘッダーが無効、または指定されていません。

サーキットブレーカー設定API

サーキットブレーカー設定APIの基本仕様

区分 項目 説明
リクエスト HTTPメソッド POST
パス https://hq1.appsflyer.com/p360-click-signing/config/circuit-breaker
Authorizationヘッダー 
レスポンス 取得結果 HTTPステータス

APIリクエスト

メソッド

POST https://hq1.appsflyer.com/p360-click-signing/config/circuit-breaker

リクエストボディのJSON

パラメータ 説明
status
  • enabled
  • disabled

サーキットブレーカー設定のcurl例とレスポンス

curlリクエスト

curl --location --request POST 'https://hq1.appsflyer.com/api/p360-click-signing/config/circuit-breaker' \
-H 'Authorization: Bearer {API V2.0 token available to the admin in the dashboard.}'
--data-raw '{
"status":"enabled"
}'

HTTPレスポンスコード

レスポンスコード

コード  メッセージ 説明
200 OK  
400 Bad request 無効なステータスが指定されています。
401 Not authorized Authorizationヘッダーが無効、または指定されていません。

設定取得API

設定取得APIの基本仕様

区分 項目 説明
リクエスト HTTPメソッド GET
パス https://hq1.appsflyer.com/api/p360-click-signing/config
Authorizationヘッダー 
レスポンス 取得結果 JSON形式で返されます。

APIリクエスト

メソッド

GET https://hq1.appsflyer.com/api/p360-click-signing/config

JSONレスポンス

キー 説明
mode 以下のいずれか:
  • enabled
  • disabled
  • report-only
circuit-breaker-config statusを含むJSONオブジェクト。値は以下のいずれかです。
  • enabled
  • disabled
     
active-key-ids 有効なキーを含むJSON配列:
 
  • secret-key-id:ランダムに生成されたシークレットキーのID。
  • expiration:シークレットキーの有効期限を示す、ミリ秒単位のエポック時刻。
excluded-app-ids 除外対象のapp-idsを含むJSON配列。

設定取得のcurl例とレスポンス

curlリクエスト

curl --location --request GET 'https://hq1.appsflyer.com/api/p360-click-signing/config' \
-H 'Authorization: Bearer {API V2.0 token available to the admin in the dashboard.}'

JSONレスポンス

{
	"mode": "report-only",
	"active-key-ids": [
		{
			"secret-key-id": "59ad6547-affc-45eb-a6c9-9805f88ee755",
			"expiration": 1610533263
		}
	],
	"excluded-app-ids": [
		"app-id-1", 	"app-id-2"
	]

}

HTTPレスポンスコード

レスポンスコード

コード  メッセージ 説明
200 OK  
401 Not authorized Authorizationヘッダーが無効、または指定されていません。

レポートAPI

レポートAPIの基本仕様

区分 項目 説明
リクエスト HTTPメソッド GET
パス https://hq1.appsflyer.com/api/p360-click-signing/report
Authorizationヘッダー 
レスポンス 取得結果 CSV形式で返されます。

APIリクエスト

メソッド

GET https://hq1.appsflyer.com/api/p360-click-signing/report

パラメータ

パラメータ 説明
start-date レポートの対象期間の開始日時。形式:yyyy-mm-ddThh
end-date レポートの対象期間の終了日時。形式:yyyy-mm-ddThh
start-dateとend-dateは、両方を指定するか、どちらも指定しないかのいずれかにする必要があります。開始日時と終了日時を指定しない場合、過去24時間の結果が表示されます。

CSVレスポンス

列 説明
time クリックの発生日時。形式:yyyy-mm-ddThh
total_clicks 対象期間中のクリックの総数
valid_clicks 対象期間中の有効なクリック数
missing_signature 対象期間中の署名が付いていないクリック数
expired_clicks 対象期間中の有効期限が切れたクリック数
invalid_signature 対象期間中の署名が無効なクリック数
no_active_secrets システム内に有効なシークレットキーがないために拒否されたクリック数(通常、レポートのみモードで発生)。

テストのcurl例とレスポンス

curlリクエスト

curl --location --request GET 'https://hq1.appsflyer.com/api/p360-click-signing/report?start-date=2021-01-07T07&end-date=2021-01-17T12' \
-H 'Authorization: Bearer {API V2.0 token available to the admin in the dashboard.}' \

CSVレスポンス

time total_clicks valid_clicks missing_signature expired_clicks invalid_signature no_active_signatures
2021-01-17T07 928082156 928082156  0  0  0  0
2021-01-17T08 923796132 923796132  0  0  0  0
2021-01-17T09 917541373 917541373  0  0  0  0
2021-01-17T10 909977064 909977064  0  0  0  0
2021-01-17T11 965104299 965104299  0  0  0  0
2021-01-17T12 975134824 975134824  0  0  0  0

HTTPレスポンスコード

レスポンスコード

コード  メッセージ 説明
200 OK  
401 Not authorized Authorizationヘッダーが無効、または指定されていません。

アプリ除外API

アプリ除外APIの基本仕様

区分 項目 説明
リクエスト HTTPメソッド POST
パス https://hq1.appsflyer.com/api/p360-click-signing/config/excluded-app/<app-id>
Authorizationヘッダー 
レスポンス 取得結果 空のレスポンス

APIリクエスト

メソッド

POST https://hq1.appsflyer.com/api/p360-click-signing/config/excluded-app/<app-id>

パラメータ

パラメータ 説明
app-id クリック署名の検証対象から除外するアプリのID。

アプリ除外のcurl例

curlリクエスト

curl --location --request POST 'https://hq1.appsflyer.com/api/p360-click-signing/config/excluded-app/appname.com' \
-H 'Authorization: Bearer {API V2.0 token available to the admin in the dashboard.}'

HTTPレスポンスコード

レスポンスコード

コード  メッセージ 説明
200 OK  
401 Not authorized Authorizationヘッダーが無効、または指定されていません。

除外したアプリの復帰API

除外したアプリの復帰APIの基本仕様

区分 項目 説明
リクエスト HTTPメソッド DELETE
パス https://hq1.appsflyer.com/api/p360-click-signing/config/excluded-app/<app-id>
Authorizationヘッダー 
レスポンス 取得結果 空のレスポンス

APIリクエスト

メソッド

DELETE https://hq1.appsflyer.com/api/p360-click-signing/config/excluded-app/<app-id>

パラメータ

パラメータ 説明
app-id クリック署名の検証対象の除外リストから削除するアプリのID。

除外したアプリの復帰のcurl例

curlリクエスト

curl --location --request DELETE 'https://hq1.appsflyer.com/api/p360-click-signing/config/excluded-app/appname.com' \
-H 'Authorization: Bearer {API V2.0 token available to the admin in the dashboard.}'

HTTPレスポンスコード

レスポンスコード

コード  メッセージ 説明
200 OK  
401 Not authorized Authorizationヘッダーが無効、または指定されていません。

コードサンプル

package sign;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

.
.
.

String clickUrl = "https://app.appsflyer.com/com.app.id?pid=adnetwork_int&c=my_campaign&clickid=sdkfjasksjskdfj9845weh&af_site_id=12345";
String secretKey = "secret_key"; 
int ttlMinutes = 5;


//add expiration to the click URL
long expiration = System.currentTimeMillis() + (60000L * ttlMinutes);
clickUrl += "&expires="+expiration;

//create a SecretKey object from the given key string
SecretKeySpec signingKey = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);

//generate a signature from the click url and encode it with base64 without padding
String generatedSignature =     
Base64.getUrlEncoder().withoutPadding().encodeToString(mac.doFinal(clickUrl.getBytes()));

//add the signature to the click URL
String signedClickUrl = clickUrl + "&signature=" + generatedSignature;

補足情報

トラブルシューティング

1時間のクリックの90%超が署名検証に失敗すると、AppsFlyerはクリック署名の検証を停止し、レポートのみモードに戻ります。

これは、技術的な問題によってビジネスに影響が及ぶのを防ぎ、異常の原因を調査できるようにするためです。

よくある質問

Q:本番環境に影響を与えずにクリック署名をテストする方法はありますか?

A:以下の2つの方法があります。

  1. テストAPIを使用します。開発段階で、クリックの署名を1件ずつテストする場合に適しています。
  2. レポートのみモードを使用します。レポートのみモードでは、本番環境のクリックの署名を検証し、ブロックの対象となるクリックを確認できますが、無効なクリックを実際にブロックすることはありません。そのため、実際のトラフィックに影響を与えずに、クリック署名が正しく動作するかテストできます。

Q:APIトークンとシークレットキーの違いは何ですか?

A:APIトークン:クリック署名APIの認証と実行に使用します。アドネットワークごとに1つだけ存在します。 AppsFlyer API V2.0トークンは、管理者から取得する必要があります。

シークレットキー:署名の生成に使用します。シークレットキー生成APIで生成できます。新しいシークレットキーの生成は、アドネットワーク自身が行う必要があります。詳しくは、仕様のセクションを参照してください。

Q:特定のキャンペーンにだけクリック署名を適用できますか?

A:いいえ。クリック署名は、そのアドネットワークのすべてのクリックに適用されます。特定のアプリを対象から除外することはできますが、特定のキャンペーンだけを除外することはできません。

仕様

項目 説明
クリック署名 署名の生成は、アドネットワークのサーバーで行う必要があります。
シークレットキー
  • アドネットワークが同時に有効にできるシークレットキーは、最大2つです。
  • シークレットキーには、それぞれ有効期限があります。
  • 有効期限が切れたシークレットキーで署名されたクリックは拒否されます。
レポートAPI クリックの有効性に関する最新の統計が、1時間単位で集計されます。