mcpField
A
adattributionkit

adattributionkit

github.com/dpearson2699マーケティング・グロース1.2k3.1k 回インストール13 週間前に更新
リポジトリ

adattributionkit について

AdAttributionKit による iOS 広告アトリビューションの実装を支援する開発スキルです。プライバシー保護、コンバージョンのポストバック、SKAdNetwork との相互運用を含む再エンゲージメントを扱います。

主な機能

  1. 01プライバシー保護アトリビューション
  2. 02署名付きインプレッション処理
  3. 03コンバージョン値とポストバック
  4. 04再エンゲージメント計測
  5. 05実装チェックリスト

活用シーン

  1. 01パブリッシャーアプリと広告対象アプリの設定
  2. 02広告の表示とタップの記録
  3. 03コンバージョン値と計測期間の設定
  4. 04ポストバックのエンドポイントと処理の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/dpearson2699/swift-ios-skills --skill adattributionkit

インストール後、Claude Code で/adattributionkitを入力して読み込まれたか確認します。

同梱ファイルevals/evals.jsonreferences/adattributionkit-patterns.md

詳細

AdAttributionKit

iOS 17.4以降向けの、プライバシーを保護する広告アトリビューションです。AdAttributionKitを利用すると、広告ネットワークはユーザーレベルのデータを公開せずに、コンバージョン(インストールと再エンゲージメント)を測定できます。App Storeと代替マーケットプレイスに対応し、SKAdNetworkとの相互運用も可能です。

アトリビューションのフローには、広告ネットワーク(インプレッションに署名し、ポストバックを受信)、パブリッシャーアプリ(広告を表示)、広告対象アプリ(宣伝対象のアプリ)の3つの役割があります。

目次

概要とプライバシーモデル

AdAttributionKitは、いくつかの仕組みを通じてユーザーのプライバシーを保護します。

  • クラウド匿名性のティア -- デバイスは、広告に関連付けられたクラウドの規模に基づいてポストバックデータの粒度を制限します。ティア0(最小限のデータ)からティア3(パブリッシャーIDや国コードを含む最大限のデータ)まであります。
  • 遅延ポストバック -- ポストバックは、コンバージョン期間の終了から24~48時間後(最初の期間)、または24~144時間後(2番目/3番目の期間)に送信されます。
  • ユーザーレベルの識別子なし -- ポストバックには、デバイスIDやユーザーIDではなく、集約されたソース識別子とコンバージョン値が含まれます。
  • 階層型ソース識別子 -- 2桁、3桁、または4桁のソースIDです。返される桁数はクラウド匿名性のティアによって異なります。

移行と相互運用性のレビューでは、システムがAdAttributionKitとSKAdNetworkのインプレッションをまとめて評価すること、コンバージョンごとに有効なインプレッションは1つだけであること、クリック経由がビュー経由より優先されること、クリック経由のインプレッション間では新しさで優先順位を決め、その後に最も新しいビュー経由のインプレッションを選ぶことを明記してください。

パブリッシャーアプリの設定

パブリッシャーアプリは、登録済みの広告ネットワークの広告を表示します。インプレッションがインストール検証の対象となるよう、各広告ネットワークのIDをアプリのInfo.plistに追加します。

広告ネットワーク識別子を追加する
<key>AdNetworkIdentifiers</key>
<array>
    <string>example123.adattributionkit</string>
    <string>another456.adattributionkit</string>
</array>

広告ネットワークIDは小文字にする必要があります。.skadnetworkで終わるSKAdNetwork IDも使用できます。両方のフレームワークでIDを共有しています。

UIEventAttributionViewを表示する

クリック経由のカスタム描画広告では、タップ可能な広告/コントロールごとに、その上にUIEventAttributionViewを配置します。タップ可能な領域を覆い、handleTap()が成功する前にタッチを捕捉してしまうビューよりも上に表示されている必要があります。

import UIKit

let attributionView = UIEventAttributionView()
attributionView.frame = adContentView.bounds
attributionView.isUserInteractionEnabled = true
adContentView.addSubview(attributionView)

広告対象アプリの設定

広告対象アプリは、広告を見た後にユーザーがインストールする、または再エンゲージするアプリです。ポストバックのコンバージョン期間を開始するには、少なくとも1回、コンバージョン値を更新する必要があります。

有効なポストバックのコピーを受信する

デバイスからサーバーに有効なポストバックのコピーが送信されるよう、最上位のAdAttributionKit Info.plistディクショナリにAttributionCopyEndpointを追加します。

<key>AdAttributionKit</key>
<dict>
    <key>AttributionCopyEndpoint</key>
    <string>https://example.com</string>
</dict>

システムは、URL内の登録可能ドメインから、既知のエンドポイントを導き出します。サブドメインは無視されます。

https://example.com/.well-known/appattribution/report-attribution/

そのパスでHTTPS POSTリクエストを受け付けるようにサーバーを設定します。ドメインには有効なSSL証明書が必要です。

再エンゲージメントのポストバックコピーを受信する

有効な再エンゲージメントのポストバックのコピーも受信するには、同じAdAttributionKitディクショナリに2つ目のキーを追加します。

<key>AdAttributionKit</key>
<dict>
    <key>AttributionCopyEndpoint</key>
    <string>https://example.com</string>
    <key>OptInForReengagementPostbackCopies</key>
    <true/>
</dict>
初回起動時にコンバージョン値を更新する

コンバージョン期間を開始するため、初回起動後できるだけ早くコンバージョン値を更新します。

import AdAttributionKit

func applicationDidFinishLaunching() async {
    do {
        try await Postback.updateConversionValue(0, lockPostback: false)
    } catch {
        print("Failed to set initial conversion value: \(error)")
    }
}

インプレッション

広告ネットワークは、JWS(JSON Web Signature)を使用して署名済みインプレッションを作成します。パブリッシャーアプリはAppImpressionを使用して、それらのインプレッションを登録し、処理します。

JWS からインプレッションを作成する
import AdAttributionKit

let impression = try await AppImpression(compactJWS: signedJWSString)

JWS には、広告ネットワーク ID、広告対象アイテム ID、パブリッシャーアイテム ID、ソース識別子、タイムスタンプ、および任意の再エンゲージメント対象フラグが含まれます。JWS の生成方法については、references/adattributionkit-patterns.md を参照してください。

デバイスの対応状況を確認する
guard AppImpression.isSupported else {
    // Fall back to alternative ad display
    return
}
ビュー経由インプレッション

広告コンテンツが表示され、閉じられたときにビューインプレッションを記録します。

func handleAdViewed(impression: AppImpression) async {
    do {
        try await impression.handleView()
    } catch {
        print("Failed to record view-through impression: \(error)")
    }
}

広告を長時間表示する場合は、beginView() と endView() を使って表示時間を追跡します。

try await impression.beginView()
// ... ad remains visible ...
try await impression.endView()
クリック経由インプレッション

広告のタップに応答するには、AppImpression の作成から 15 分以内に handleTap() を呼び出します。これを過ぎた場合は、新しいインプレッションをリクエストしてください。広告対象アプリがインストールされていない場合、システムは App Store またはマーケットプレイスのページを開きます。インストールされている場合は、アプリを直接起動します。

func handleAdTapped(impression: AppImpression) async {
    do {
        try await impression.handleTap()
    } catch {
        print("Failed to record click-through impression: \(error)")
    }
}

handleTap() を成功させるには、広告の上に UIEventAttributionView を重ねる必要があります。

StoreKit で描画される広告

インプレッションを StoreKit のオーバーレイまたは商品ビューコントローラーの API に渡します。StoreKit は、表示から 2 秒後にビュー経由インプレッションを、タップ時にクリック経由インプレッションを自動的に記録します。

import StoreKit

let config = SKOverlay.AppConfiguration(appIdentifier: "1234567890",
                                         position: .bottom)
config.appImpression = impression

ポストバック

ポストバックは、コンバージョンイベント後にデバイスから広告ネットワーク(および任意で広告対象アプリの開発者)に送信されるアトリビューションレポートです。

コンバージョンウィンドウ

勝者となったアトリビューションでは、複数のコンバージョンウィンドウにわたって複数のポストバックが生成される場合があります。データティアが低い場合や、勝者ではないアトリビューションでは、開示される情報が少なくなります。最新のウィンドウと遅延時間の一覧については、references/adattributionkit-patterns.md を読み込んでください。

イベントの時間ウィンドウ

アトリビューションの対象期間は、コンバージョン/ポストバックのウィンドウとは異なります。現在のドキュメントとリファレンスを参照して、ビュー経由、クリック経由、インストール更新、再エンゲージメントの制限を設定して確認してください。この 2 つの概念を混同しないでください。

コンバージョン値を早めにロックする

ウィンドウが終了する前にポストバックをロックしてコンバージョン値を確定すると、ポストバックを早く受信できます。

try await Postback.updateConversionValue(
    42,
    coarseConversionValue: .high,
    lockPostback: true
)

ロック後、システムはそのコンバージョンウィンドウでの以降の更新を無視します。

ティアごとのポストバックデータ

開示される情報は、システムによって割り当てられたデータティアが高いほど増えます。コードと分析では、ソースの桁、詳細/概略コンバージョン値、パブリッシャーアイテム ID、国が存在しない場合にも対応する必要があります。詳細なティア一覧については、リファレンスを参照してください。

コンバージョン値

詳細値

詳細値は 0...63 の整数(6 ビット)です。最初のポストバックでのみ、かつティア 2 以上でのみ利用できます。

try await Postback.updateConversionValue(
    35,
    coarseConversionValue: .medium,
    lockPostback: false
)
概略値

低いティアおよび 2 回目/3 回目のポストバック向けの 3 段階の値です。

// CoarseConversionValue cases: .low, .medium, .high
try await Postback.updateConversionValue(
    10,
    coarseConversionValue: .high,
    lockPostback: false
)
コンバージョンタイプごとの更新(iOS 18+)

インストール用と再エンゲージメント用のポストバックで、コンバージョン値を分けます。サーバー JSON ではハイフン付きの "conversion-type": "re-engagement" を使用します。Swift API ではハイフンなしの .reengagement を使用します。

let installUpdate = PostbackUpdate(
    fineConversionValue: 20,
    lockPostback: false,
    conversionTypes: [.install]
)
try await Postback.updateConversionValue(installUpdate)

let reengagementUpdate = PostbackUpdate(
    fineConversionValue: 12,
    lockPostback: false,
    conversionTypes: [.reengagement]
)
try await Postback.updateConversionValue(reengagementUpdate)
コンバージョンタグ(iOS 18.4+)

コンバージョンウィンドウが重複する場合は、コンバージョンタグを使って特定のポストバックのみを選択的に更新します。

let update = PostbackUpdate(
    fineConversionValue: 15,
    lockPostback: false,
    conversionTag: savedConversionTag,
    conversionTypes: [.reengagement]
)
try await Postback.updateConversionValue(update)

システムは、再エンゲージメント URL の AdAttributionKitReengagementOpen クエリパラメーターを通じてコンバージョンタグを渡します。

再エンゲージメント

再エンゲージメントでは、広告対象アプリをすでにインストールしているユーザーが広告に反応し、そのアプリに戻る動きを追跡します。

インプレッションを再エンゲージメント対象として設定する

インプレッションの生成時に、JWS ペイロードの eligible-for-re-engagement を true に設定します。

URL で再エンゲージメントのタップを処理する

システムが広告対象アプリで開くユニバーサルリンクを渡します。

let reengagementURL = URL(string: "https://example.com/promo/summer")!
try await impression.handleTap(reengagementURL: reengagementURL)

システムは AdAttributionKitReengagementOpen をクエリパラメーターとして追加します。広告対象アプリでは、このパラメーターを確認して AdAttributionKit による起動を検出します。

func handleUniversalLink(_ url: URL) {
    let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
    let isReengagement = components?.queryItems?.contains(where: {
        $0.name == Postback.reengagementOpenURLParameter
    }) ?? false

    if isReengagement {
        // AdAttributionKit opened this app via a re-engagement ad
    }
}
再エンゲージメントの制限
  • 再エンゲージメントのポストバックが作成されるのは、クリック経由のインタラクションのみです(ビュー経由では作成されません)。
  • デバイスは、アプリごとの月間制限とデバイスごとの年間制限を適用します。
  • システムがポストバックを作成しない場合でも、AdAttributionKitReengagementOpen パラメーターは常に URL に含まれます。

よくある間違い

間違い修正方法
初回起動時にコンバージョン値が更新されない意図した期間が経過する前に、正規の初回起動時更新を呼び出します。
広告ネットワーク ID に大文字が含まれている正確な小文字のネットワーク識別子を使用します。
handleTap() が古いインプレッションを使用している、または現在のアトリビューションビューのタップを取得できていない広告を UIEventAttributionView で覆い、インプレッションを最新の状態に保ち、検証済みのタップフローから呼び出します。
タップエラーが破棄されている期限切れのインプレッションやビューの欠落を明示的に処理します。
ポストバックエンドポイントが応答を遅延または破棄するリクエストを受け付け、処理を永続化またはキューに登録し、期待される成功応答を速やかに返します。

レビューチェックリスト

  • パブリッシャーアプリの AdNetworkIdentifiers にすべての広告ネットワーク ID が含まれている(小文字)
  • 広告ネットワーク ID が、パブリッシャーアプリの Info.plist と JWS の kid で一致している
  • タップ可能なクリック経由の広告/コントロールに UIEventAttributionView が重ねられている
  • クリック経由の AppImpression が、handleTap() の呼び出し時点で15分以内のものである
  • 広告対象のアプリが初回起動時に updateConversionValue を呼び出している
  • 周知のパスにあるサーバーエンドポイントが、有効な SSL を使った HTTPS POST を受け付ける
  • ポストバックの検証で、環境に応じた正しい Apple 公開鍵を使用している
  • postback-identifier によって重複ポストバックを除外している
  • サーバーがポストバックリクエストに HTTP 200 で応答する
  • 再エンゲージメント URL が、広告対象アプリの登録済みユニバーサルリンクである
  • コンバージョン値の戦略が、3つすべてのコンバージョン期間を考慮している
  • インプレッション API を使う前に AppImpression.isSupported を確認している

参考資料

コメント