詳閱 Android 版 Privacy Sandbox 說明文件時,請利用「開發人員預覽版」或「Beta 版」按鈕選取您要使用的計畫版本,因為兩者的操作說明可能不盡相同。
Android 版 Protected Audience API (舊稱 FLEDGE) 包含 Custom Audience API 和 Ad Selection API。廣告技術平台和廣告主可利用這些 API,根據先前的應用程式參與情形放送自訂廣告,藉此限制不同應用程式間的 ID 分享,並限制與第三方分享使用者的應用程式互動資訊。
Custom Audience API 以「自訂目標對象」抽象層為中心,代表有共通意圖的使用者群組。廣告主可以向自訂目標對象登錄使用者,並為相關廣告建立關聯。此資訊會儲存在本機中,並且可用以提供廣告主出價、廣告篩選和廣告顯示的相關資訊。
Ad Selection API 提供的架構可讓多名開發人員針對自訂目標對象在本機上進行競價。因此,系統會考慮與自訂目標對象相關的廣告,並針對廣告技術平台傳回裝置的廣告進行額外的處理。
廣告技術平台可以整合這些 API 以實作再行銷,藉此保護使用者隱私。我們計劃在未來的版本中提供更多用途的支援 (包括應用程式安裝廣告)。如要進一步瞭解 Android 版 Protected Audience API,請參閱設計提案。
本指南將說明如何使用 Android 版 Protected Audience API 執行下列操作:
事前準備
在開始之前,請先完成下列操作:
- 在 Android 裝置上為 Privacy Sandbox 設定開發環境。
- 將系統映像檔安裝到支援的裝置上,或者設定支援 Android 版 Privacy Sandbox 的模擬器。
在終端機中,使用以下 ADB 指令啟用 Protected Audience API 的存取權 (預設為停用)。
adb shell device_config put adservices ppapi_app_allow_list \"*\"
在應用程式資訊清單中加入
ACCESS_ADSERVICES_CUSTOM_AUDIENCE
權限:<uses-permission android:name="android.permission.ACCESS_ADSERVICES_CUSTOM_AUDIENCE" />
在資訊清單的
<application>
元素中參照廣告服務設定:<property android:name="android.adservices.AD_SERVICES_CONFIG" android:resource="@xml/ad_services_config" />
指定資訊清單所參照的廣告服務 XML 資源,例如
res/xml/ad_services_config.xml
。進一步瞭解廣告服務權限和 SDK 存取權控管。<ad-services-config> <custom-audiences allowAllToAccess="true" /> </ad-services-config>
根據預設,Ad Selection API 會限制競價或曝光報表指令碼可分配的記憶體最大容量。記憶體限制功能需要搭配使用 WebView 105.0.5195.58 以上版本。平台會強制執行版本檢查,如不符合上述版本條件,就無法呼叫
selectAds
和reportImpression
API。您可以透過以下兩種做法進行設定:做法 1:執行下列 ADB 指令以停用這項檢查:
adb device_config put fledge_js_isolate_enforce_max_heap_size false
做法 2:從 Google Play 商店安裝 WebView Beta 版。這個版本必須等於或高於上述版本。
加入自訂目標對象
「自訂目標對象」代表由廣告主應用程式決定,且具有共同意圖或興趣的使用者。應用程式或 SDK 可以使用自訂目標對象來表示特定目標對象,例如曾將商品放入購物車的使用者。如要以非同步的方式建立或加入自訂目標對象,請按照下列步驟操作:
- 將
CustomAudienceManager
物件初始化。 - 指定買家套件和相關名稱等重要參數以建立
CustomAudience
物件。然後,使用CustomAudience
物件初始化JoinCustomAudienceRequest
物件。 - 使用
JoinCustomAudienceRequest
物件和相關的Executor
及OutcomeReceiver
物件呼叫非同步joinCustomAudience()
。
Kotlin
val customAudienceManager: CustomAudienceManager =
context.getSystemService(CustomAudienceManager::class.java)
// Initialize a custom audience.
val audience = CustomAudience.Builder()
.setBuyer(buyer)
.setName(name)
...
.build()
// Initialize a custom audience request.
val joinCustomAudienceRequest: JoinCustomAudienceRequest =
JoinCustomAudienceRequest.Builder().setCustomAudience(audience).build()
// Request to join a custom audience.
customAudienceManager.joinCustomAudience(joinCustomAudienceRequest,
executor,
outcomeReceiver)
Java
CustomAudienceManager customAudienceManager =
context.getSystemService(CustomAudienceManager.class);
// Initialize a custom audience.
CustomAudience audience = new CustomAudience.Builder()
.setBuyer(buyer)
.setName(name)
...
.build();
// Initialize a custom audience request.
JoinCustomAudienceRequest joinCustomAudienceRequest =
new JoinCustomAudienceRequest.Builder().setCustomAudience(audience).build();
// Request to join a custom audience.
customAudienceManager.joinCustomAudience(joinCustomAudienceRequest,
executor,
outcomeReceiver);
下列參數的組合可明確識別裝置上的每個 CustomAudience
物件:
owner
:擁有者應用程式的套件名稱。以隱含形式設定為呼叫端應用程式的套件名稱。buyer
:管理此自訂目標對象廣告的買家廣告聯播網 ID。name
:自訂目標對象的任意名稱或 ID。
使用 CustomAudience
的不同執行個體重複呼叫 joinCustomAudience()
,將以比對符合的 owner, buyer
,以及 name
參數更新任何現有的 CustomAudience
。為保護隱私,API 的結果不會區分「建立」和「更新」。
此外,建立 CustomAudience
時必須使用以下必要參數:
- 每日更新網址:每天在背景中查詢的 HTTPS 網址,可更新自訂目標對象的使用者出價信號、受信任的出價資料,以及廣告的顯示網址和中繼資料。
- 出價邏輯網址:在廣告選擇期間查詢的 HTTPS 網址,以擷取買家的 JavaScript 出價邏輯。請參閱此 JavaScript 中所需的函式簽章。
- 廣告顯示 ID:買方廣告技術設定的任意 ID。這是針對 B&A 產生酬載的最佳化作業。
CustomAudience
物件的選用參數可能包括:
- 啟用時間:自訂目標對象只能於啟用時間過後參與廣告選擇和每日更新。舉例來說,您可以利用此方式吸引很久沒有使用應用程式的使用者進行互動。
- 到期時間:自訂目標對象從裝置中移除的未來時間。
- 使用者出價信號:包含使用者信號 (例如使用者偏好語言) 的 JSON 字串,廣告選擇程序期間,買家的出價邏輯 JavaScript 將會用以產生出價。此格式可協助廣告技術平台在多個平台之間重複使用程式碼,並減少 JavaScript 函式的使用量。
- 受信任的出價資料:廣告選擇程序期間使用的 HTTPS 網址和字串清單,可從受信任的鍵/值服務擷取出價信號。
- 廣告:
AdData
物件清單,對應至參與廣告選擇的廣告。每個AdData
物件都由以下項目組成:- 顯示網址:要查詢以顯示最終廣告的 HTTPS 網址。
- 中繼資料:已序列化為字串的 JSON 物件,包含買方出價邏輯在廣告選擇程序中需使用的資訊。
- 廣告篩選條件:此類別包含在廣告選擇期間套用應用程式安裝廣告篩選功能與展示頻率上限的所有必要資訊。
以下是 CustomAudience
物件例項化的範例:
Kotlin
// Minimal initialization of a CustomAudience object
val customAudience: CustomAudience = CustomAudience.Builder()
.setBuyer(AdTechIdentifier.fromString("my.buyer.domain.name"))
.setName("example-custom-audience-name")
.setDailyUpdateUrl(Uri.parse("https://DAILY_UPDATE_URL"))
.setBiddingLogicUrl(Uri.parse("https://BIDDING_LOGIC_URL"))
.build()
Java
// Minimal initialization of a CustomAudience object
CustomAudience customAudience = CustomAudience.Builder()
.setBuyer(AdTechIdentifier.fromString("my.buyer.domain.name"))
.setName("example-custom-audience-name")
.setDailyUpdateUrl(Uri.parse("https://DAILY_UPDATE_URL"))
.setBiddingLogicUrl(Uri.parse("https://BIDDING_LOGIC_URL"))
.build();
處理 joinCustomAudience() 結果
非同步 joinCustomAudience()
方法會使用 OutcomeReceiver
物件以指出 API 呼叫的結果。
onResult()
回呼代表自訂目標對象已成功建立或更新。onError()
回呼代表兩種可能的條件。- 如果用於將
JoinCustomAudienceRequest
初始化的引數無效,AdServicesException
會指出IllegalArgumentException
為錯誤原因。 - 發生其他錯誤時,收到的
AdServicesException
則會指出IllegalStateException
是錯誤原因。
- 如果用於將
以下是處理 joinCustomAudience()
結果的範例:
Kotlin
var callback: OutcomeReceiver<Void, AdServicesException> =
object : OutcomeReceiver<Void, AdServicesException> {
override fun onResult(result: Void) {
Log.i("CustomAudience", "Completed joinCustomAudience")
}
override fun onError(error: AdServicesException) {
// Handle error
Log.e("CustomAudience", "Error executing joinCustomAudience", error)
}
};
Java
OutcomeReceiver callback = new OutcomeReceiver<Void, AdServicesException>() {
@Override
public void onResult(@NonNull Void result) {
Log.i("CustomAudience", "Completed joinCustomAudience");
}
@Override
public void onError(@NonNull AdServicesException error) {
// Handle error
Log.e("CustomAudience", "Error executing joinCustomAudience", error);
}
};
退出自訂目標對象
如果使用者不再滿足特定自訂目標對象的業務條件,應用程式或 SDK 可呼叫 leaveCustomAudience()
,從裝置中移除自訂目標對象。如要根據專用參數移除特定的 CustomAudience
,請執行下列步驟:
- 將
CustomAudienceManager
物件初始化。 - 使用自訂目標對象的
buyer
和name
初始化LeaveCustomAudienceRequest
。如要進一步瞭解這些輸入欄位,請參閱「加入自訂目標對象」。 - 使用
LeaveCustomAudienceRequest
物件和相關的Executor
及OutcomeReceiver
物件呼叫非同步leaveCustomAudience()
方法。
Kotlin
val customAudienceManager: CustomAudienceManager =
context.getSystemService(CustomAudienceManager::class.java)
// Initialize a LeaveCustomAudienceRequest
val leaveCustomAudienceRequest: LeaveCustomAudienceRequest =
LeaveCustomAudienceRequest.Builder()
.setBuyer(buyer)
.setName(name)
.build()
// Request to leave a custom audience
customAudienceManager.leaveCustomAudience(
leaveCustomAudienceRequest,
executor,
outcomeReceiver)
Java
CustomAudienceManager customAudienceManager =
context.getSystemService(CustomAudienceManager.class);
// Initialize a LeaveCustomAudienceRequest
LeaveCustomAudienceRequest leaveCustomAudienceRequest =
new LeaveCustomAudienceRequest.Builder()
.setBuyer(buyer)
.setName(name)
.build();
// Request to leave a custom audience
customAudienceManager.leaveCustomAudience(
leaveCustomAudienceRequest,
executor,
outcomeReceiver);
與呼叫 joinCustomAudience()
類似,OutcomeReceiver
會發出 API 呼叫已結束的通知。為保護隱私,錯誤結果不會區分內部錯誤和無效引數。API 呼叫完成時,不論是否成功移除相符的自訂目標對象,系統都會呼叫 onResult()
回呼。
執行廣告選擇
如要使用 Protected Audience API 選擇廣告,請呼叫 selectAds()
方法:
- 初始化
AdSelectionManager
物件。 - 建構
AdSelectionConfig
物件。 - 使用
AdSelectionConfig
物件和相關的Executor
及OutcomeReceiver
物件呼叫非同步selectAds()
。
Kotlin
val adSelectionManager: AdSelectionManager =
context.getSystemService(AdSelectionManager::class.java)
// Initialize AdSelectionConfig
val adSelectionConfig: AdSelectionConfig =
AdSelectionConfig.Builder().setSeller(seller)
.setDecisionLogicUrl(decisionLogicUrl)
.setCustomAudienceBuyers(customAudienceBuyers)
.setAdSelectionSignals(adSelectionSignals)
.setSellerSignals(sellerSignals)
.setPerBuyerSignals(perBuyerSignals)
.setBuyerContextualAds(
Collections.singletonMap(
contextualAds.getBuyer(), contextualAds
)
).build()
// Run ad selection with AdSelectionConfig
adSelectionManager.selectAds(
adSelectionConfig, executor, outcomeReceiver
)
Java
AdSelectionManager adSelectionManager =
context.getSystemService(AdSelectionManager.class);
// Initialize AdSelectionConfig
AdSelectionConfig adSelectionConfig =
new AdSelectionConfig.Builder()
.setSeller(seller)
.setDecisionLogicUrl(decisionLogicUrl)
.setCustomAudienceBuyers(customAudienceBuyers)
.setAdSelectionSignals(adSelectionSignals)
.setSellerSignals(sellerSignals)
.setPerBuyerSignals(perBuyerSignals)
.setBuyerContextualAds(
Collections.singletonMap(contextualAds.getBuyer(), contextualAds)
)
.build();
// Run ad selection with AdSelectionConfig
adSelectionManager.selectAds(adSelectionConfig, executor, outcomeReceiver);
selectAds()
方法需要 AdSelectionConfig
輸入內容,您必須在其中指定以下必要參數:
- 賣方:賣方廣告聯播網 ID,這用於指出啟動廣告選擇程序的賣方廣告聯播網。
- 決策邏輯網址:為取得賣方廣告聯播網的 JavaScript 邏輯而查詢的 HTTPS 網址。
- HTTPS 網址:為取得賣方廣告聯播網的 JavaScript 邏輯而查詢的網址。請參閱必要的函式簽章。
- 預先建立的 URI:依循 FLEDGE 廣告選擇格式。如果傳遞不受支援或格式錯誤的預先建構 URI,會擲回
IllegalArgumentException
。
- 自訂目標對象買方:買方廣告聯播網的完整 ID 清單,皆獲得賣方允許,可參與廣告選擇程序。這些買方 ID 會對應至參與廣告選擇的自訂目標對象的
CustomAudience.getBuyer()
。
您可以選擇指定下列參數,進一步自訂廣告選擇程序:
- 廣告選擇信號:已序列化為字串的 JSON 物件,包含
CustomAudience.getBiddingLogicUrl()
中買家出價邏輯 JavaScript 所使用的信號。 - 賣家信號:序列化為字串的 JSON 物件,包含
AdSelectionConfig.getDecisionLogicUrl()
中賣家擷取 JavaScript 決策邏輯所使用的信號。 - 個別買方信號:已序列化為字串的 JSON 物件對應,包含從
CustomAudience.getBiddingLogicUrl()
擷取的特定買方出價邏輯 JavaScript 所使用的信號,且辨識信號的方法為使用參與廣告選擇的自訂目標對象的買方欄位。 - 內容相關廣告:在 Protected Audience 競價以外的競價期間,直接向買方收集的候選廣告集合。
選擇廣告之後,系統會在內部保留結果、出價和信號,用於製作報表。OutcomeReceiver.onResult()
回呼會傳回包含以下內容的 AdSelectionOutcome
:
- 從
AdData.getRenderUrl()
取得的得標廣告顯示網址。 - 裝置使用者專屬的廣告選擇 ID。這個 ID 的作用是回報廣告曝光。
如果廣告選擇程序因為引數無效、逾時或資源消耗過多等因素而未能順利完成,OutcomeReceiver.onError()
回呼就會提供 AdServicesException
以指出下列行為:
- 如果用於啟動廣告選擇程序的引數無效,
AdServicesException
會指出IllegalArgumentException
是錯誤原因。 - 發生其他錯誤時,收到的
AdServicesException
則會指出IllegalStateException
是錯誤原因。
內容相關廣告
應用程式安裝廣告篩選功能
應用程式安裝廣告篩選功能可針對裝置上已安裝的應用程式篩選安裝廣告。
此程序的第一步是定義哪些廣告主可篩選已安裝的套件。這項作業需要在利用廣告指定的應用程式中進行。
Kotlin
//Create a request for setting the app install advertisers
val adtech = AdTechIdentifier.fromString("your.enrolled.uri")
val adtechSet = setOf(adtech)
val request = SetAppInstallAdvertisersRequest(adtechSet)
//Set the app install advertisers in the ad selection manager
mAdSelectionManager.setAppInstallAdvertisers(
request,
mExecutor,
object : OutcomeReceiver<Any?, Exception?>() {
fun onResult(@NonNull ignoredResult: Any?) {
Log.v("[your tag]", "Updated app install advertisers")
}
fun onError(@NonNull error: Exception?) {
Log.e("[your tag]", "Failed to update app install advertisers", error)
}
})
Java
//Create a request for setting the app install advertisers
AdTechIdentifier adtech = AdTechIdentifier.fromString("your.enrolled.uri");
Set<AdTechIdentifier> adtechSet = Collections.singleton(adtech);
SetAppInstallAdvertisersRequest request = new SetAppInstallAdvertisersRequest(adtechSet);
//Set the app install advertisers in the ad selection manager
mAdSelectionManager.setAppInstallAdvertisers(
request,
mExecutor,
new OutcomeReceiver<Object, Exception>() {
@Override
public void onResult(@NonNull Object ignoredResult) {
Log.v("[your tag]", "Updated app install advertisers");
}
@Override
public void onError(@NonNull Exception error) {
Log.e("[your tag]", "Failed to update app install advertisers", error);
}
});
執行上述程式碼時,傳入的廣告主可篩除您在出價產生期間指定的已安裝應用程式。如果您需要移除廣告主對此應用程式安裝狀態的存取權,請移除該廣告主的資訊,然後再次執行這段程式碼。
下一步是在發布商應用程式內設定廣告篩選功能。在發布商應用程式中放送廣告的一方 (最有可能是供應端 SDK) 必須初始化 AdFilters
物件,並提供資訊,指出要篩除哪些應用程式相關廣告:
Kotlin
// Instantiate AdFilters object with package names.
val filters: AdFilters = Builder().setAppInstallFilters(
Builder().setPackageNames(setOf("example.target.app")).build()
).build()
Java
// Instantiate AdFilters object with package names.
AdFilters filters = new AdFilters.Builder()
.setAppInstallFilters(
new AppInstallFilters.Builder()
.setPackageNames(Collections.singleton("example.target.app"))
.build())
.build();
需求端發布商也可以為自訂目標對象內的廣告設定 AdFilter
。
AdFilters
也可在新 AdData
物件例項化時傳入:
Kotlin
// Instantiate an AdData object with the AdFilters created in the
// previous example.
val appInstallAd: AdData =
Builder().setMetadata("{ ... }") // Valid JSON string
.setRenderUri(Uri.parse("www.example-dsp1.com/.../campaign123.html"))
.setAdFilters(filters).build()
Java
// Instantiate an AdData object with the AdFilters created in the
// previous example.
AdData appInstallAd = new AdData.Builder()
.setMetadata("{ ... }") // Valid JSON string
.setRenderUri(Uri.parse("www.example-dsp1.com/.../campaign123.html"))
.setAdFilters(filters)
.build();
展示頻率上限篩選功能
展示頻率上限篩選功能可讓廣告技術人員限制廣告的顯示次數。此功能可以降低廣告過度曝光率,並針對特定廣告活動選擇最佳的備用廣告。
展示頻率上限篩選器內含兩個主要元件:廣告事件類型和廣告計數器鍵。可用的廣告事件類型如下:
- 勝出:勝出事件表示廣告贏得競價。勝出事件會自動由 Protected Audience API 更新,且無法讓開發人員直接呼叫。勝出資料只會向特定自訂目標對象中的廣告顯示。
- 曝光:與
reportImpression
不同,裝置端的呼叫端 (賣方平台或 MMP) 會使用updateAdCounterHistogram()
在所選程式碼的特定位置叫用曝光事件。曝光事件會向隸屬於特定 DSP 的所有廣告顯示,不僅限於同一個自訂目標對象的廣告。 - 觀看:裝置端的呼叫端 (賣方平台或 MMP) 會使用對
updateAdCounterHistogram()
的呼叫,在所選程式碼的某個位置叫用事件。觀看事件會向隸屬於特定 DSP 的所有廣告顯示,不僅限於同一個自訂目標對象的廣告。 - 點擊:裝置端的呼叫端 (賣方平台或 MMP) 會使用對
updateAdCounterHistogram()
的呼叫,在所選程式碼的某個位置叫用事件。點擊事件會向隸屬於特定 DSP 的所有廣告顯示,不僅限於同一個自訂目標對象的廣告。
在發布商應用程式中,位於裝置上的賣方平台或 MMP 會叫用廣告事件。當系統呼叫 updateAdCounterHistogram()
時,展示頻率上限篩選器的計數器會逐步遞增,好讓日後競價獲得使用者對特定廣告的最新曝光率資訊。廣告事件類型不一定要與對應的使用者動作有關,這只是一套協助呼叫端自行建構事件系統的規範。為了在事件發生時增加廣告計數器,裝置端操作者會提供勝出廣告競價的廣告選擇 ID。
廣告計數器鍵是由買家廣告技術指派的任意 32 位元帶正負號整數,對應於 DSP 定義的一組特定廣告。由於廣告計數器鍵僅對應隸屬於特定 DSP 的廣告,因此您可選取這些鍵,而不必擔心與其他廣告技術的直方圖重疊。廣告計數器鍵可用於在 DSP 的廣告或特定自訂目標對象中增加 DSP 專屬 ID,以便從未來的競價中篩除廣告。
計數器鍵還可用於在指定買家廣告技術提供其他廣告後,根據特定使用者與這些廣告的互動情形,優先放送他們更可能感興趣的廣告。舉例來說,如果廣告透過勝出的廣告競價、觀看和點擊事件而提高參與度,即可做為推斷的資料點。為了進一步說明這個概念,我們舉左手高爾夫球桿的廣告為例。這類廣告可能暗示使用者不會對右手球桿感興趣。此時若為指派給左手桿廣告的計數器鍵設定展示頻率上限篩選器,可能就會篩除右手球桿的廣告。
如要在競價中使用展示頻率上限,您必須先建立 KeyedFrequencyCap
物件,如下所示:
Kotlin
// Value used when incrementing frequency counter
val adCounterKey = 123
// Frequency cap exceeded after 2 counts
val keyedFrequencyCapForImpression: KeyedFrequencyCap = Builder(
adCounterKey, 2, Duration.ofSeconds(10)
).build()
// Frequency cap exceeded after 1 counts
val keyedFrequencyCapForImpression: KeyedFrequencyCap = Builder(
adCounterKey, 1, Duration.ofSeconds(10)
).build()
Java
// Value used when incrementing frequency counter
int adCounterKey = 123;
// Frequency cap exceeded after 2 counts
KeyedFrequencyCap keyedFrequencyCapForImpression =
new KeyedFrequencyCap.Builder(
adCounterKey, 2, Duration.ofSeconds(10)
).build();
// Frequency Cap exceeded after 1 counts
KeyedFrequencyCap keyedFrequencyCapForClick =
new KeyedFrequencyCap.Builder(
adCounterKey, 1, Duration.ofSeconds(10)
).build();
建立 KeyedFrequencyCap
物件後,您可以將這些物件傳遞至 AdFilters
物件中。
Kotlin
val filters: AdFilters = Builder()
.setFrequencyCapFilters(
Builder()
.setKeyedFrequencyCapsForImpressionEvents(
ImmutableObject.of(keyedFrequencyCapForImpression)
)
.setKeyedFrequencyCapsForClickEvents(
ImmutableObject.of(keyedFrequencyCapForClick)
)
).build()
Java
AdFilters filters = new AdFilters.Builder()
.setFrequencyCapFilters(new FrequencyCapFilters.Builder()
.setKeyedFrequencyCapsForImpressionEvents(
ImmutableObject.of(keyedFrequencyCapForImpression)
)
.setKeyedFrequencyCapsForClickEvents(
ImmutableObject.of(keyedFrequencyCapForClick)
)
).build();
在 AdFilters
物件填入展示頻率上限篩選器後,系統會在建立自訂目標對象時一併傳遞該物件:
Kotlin
// Initialize a custom audience.
val audience: CustomAudience = Builder()
.setBuyer(buyer)
.setName(name)
.setAds(
listOf(
Builder()
.setRenderUri(renderUri)
.setMetadata(JSONObject().toString())
.setAdFilters(filters)
.setAdCounterKeys(adCounterKeys)
.build()
)
).build()
Java
// Initialize a custom audience.
CustomAudience audience = new CustomAudience.Builder()
.setBuyer(buyer)
.setName(name)
.setAds(Collections.singletonList(new AdData.Builder()
.setRenderUri(renderUri)
.setMetadata(new JSONObject().toString())
.setAdFilters(filters)
.setAdCounterKeys(adCounterKeys)
.build()))
.build();
為自訂目標對象實作展示頻率上限篩選器後,賣方平台就可以叫用必要的點擊、觀看或曝光事件。
Kotlin
val callerAdTech: AdTechIdentifier = mAdSelectionConfig.getSeller()
val request: UpdateAdCounterHistogramRequest = Builder(
adSelectionId,
FrequencyCapFilters.AD_EVENT_TYPE_CLICK, //CLICK, VIEW, or IMPRESSION
callerAdTech
).build()
Java
AdTechIdentifier callerAdTech = mAdSelectionConfig.getSeller();
UpdateAdCounterHistogramRequest request =
new UpdateAdCounterHistogramRequest.Builder(
adSelectionId,
FrequencyCapFilters.AD_EVENT_TYPE_CLICK, //CLICK, VIEW, or IMPRESSION
callerAdTech
).build();
如果廣告達到預設的展示頻率上限篩選器限制,就會從競價中篩除。篩選作業發生的時間點,是在裝置端競價執行出價邏輯之前,以及在為出價和競價服務競價產生酬載時。藉由這個工具包,廣告技術可靈活運用使用者與自訂目標對象中廣告的互動情形,在盡量降低廣告過度曝光的同時,也可將重點鎖定在指定廣告目標。
沒有網路呼叫的內容相關廣告篩選功能
如果沒有在裝置上進行再行銷的需求,您可以對內容相關廣告執行廣告選擇功能,無需使用網路呼叫。透過預先建構的 URI 和含有出價的內容相關廣告清單,平台可以略過擷取出價邏輯、出價信號和評分信號的程序。平台會利用預先建構的 URI 選取出價最高的內容相關廣告。
為了縮短延遲時間,廣告技術可以使用廣告篩選功能,執行僅含內容相關廣告的廣告選擇流程,無需使用網路呼叫,方法是使用預先建構的 URI 取得評分信號。如需 scoreAds
實作項目的清單,請參閱「支援的預建 URI 用途和名稱」一節。
如何執行廣告選擇功能,但不使用網路呼叫:
- 設定廣告篩選功能
- 建立內容相關廣告
請使用以下項目建立
AdSelectionConfig
物件:- 空白買家清單
- 用於選取最高出價的預先建構 URI
- 內容相關廣告
- 評分信號的空白 URI。空白 URI 可指出您不想透過擷取受信任的信號來進行評分:
Uri prebuiltURIScoringUri = Uri.parse("ad-selection-prebuilt://ad-selection/highest-bid-wins/?reportingUrl=your.registered.uri/reporting"); // Initialize AdSelectionConfig AdSelectionConfig adSelectionConfig = new AdSelectionConfig.Builder() .setSeller(seller) .setDecisionLogicUri(prebuiltURIScoringUri) .setCustomAudienceBuyers(Collections.emptyList()) .setAdSelectionSignals(adSelectionSignals) .setSellerSignals(sellerSignals) .setPerBuyerSignals(perBuyerSignals) .setBuyerContextualAds(buyerContextualAds) .setTrustedScoringSignalsUri(Uri.EMPTY) .build();
執行廣告選擇:
adSelectionManager.selectAds( adSelectionConfig, executor, outcomeReceiver);
使用預先建構的 URI 自行執行報表 JavaScript
目前,Privacy Sandbox 平台只有基本報表的 JavaScript 實作項目,供預先建構的 URI 使用。如果您想執行自己的報表 JavaScript,但仍要使用預先建構的 URI 來縮短廣告選擇時的延遲時間,可以覆寫廣告選擇和報表執行間的 DecisionLogicUri
。
- 執行相關步驟,使用預先建構的 URI 針對內容相關廣告執行廣告選擇
執行報表之前,請建立
AdSelectionConfig
的副本adSelectionConfigWithYourReportingJS = adSelectionConfig.cloneToBuilder() // Replace <urlToFetchYourReportingJS> with your own URL: .setDecisionLogicUri(Uri.parse(<urlToFetchYourReportingJS>)) .build();
執行曝光報表
// adSelectionId is from the result of the previous selectAds run ReportImpressionRequest request = new ReportImpressionRequest( adSelectionId, adSelectionConfigWithYourReportingJS); adSelectionManager.reportImpression( request, executor, outcomeReceiver);
執行刊登序列中介服務
刊登序列中介服務需要讓多個第三方 SDK (第三方聯播網) 接受第一方 SDK 中介服務聯播網的調度。無論競價是在裝置上進行,還是在出價與競價服務 (B&A) 上執行,刊登序列中介服務的做法都相同'。
第三方聯播網
第三方聯播網必須提供轉接程式,讓中介服務聯播網能夠叫用執行競價需要的方法:
- 執行廣告選擇
- 回報曝光
中介服務聯播網轉接程式示例如下:
Kotlin
class NetworkAdaptor {
private val adSelectionManager : AdSelectionManager
init {
adSelectionManager = context.getSystemService(AdSelectionManager::class.java)
}
fun selectAds() {...}
fun reportImpressions() {...}
}
Java
class NetworkAdaptor {
AdSelectionManager adSelectionManager;
public NetworkAdaptor() {
AdSelectionManager adSelectionManager =
context.getSystemService(AdSelectionManager.class);
}
public void selectAds() {...}
public void reportImpressions() {...}
}
每個 SDK 都有專屬的廣告選擇服務管理工具和用戶端,以及自己的 selectAds
和 reportImpressions
實作項目。SDK 供應商可以參閱裝置端競價的「執行廣告選擇」章節,如想瞭解 B&A 競價,可以參閱「B&A 說明」。請按照「單一賣方平台曝光報表」的說明回報廣告曝光。
中介服務聯播網
中介服務聯播網和第三方聯播網一樣需要導入 selectAds
和 reportImpression
。如需瞭解詳情,請參閱介紹如何「執行廣告選擇」和「回報廣告曝光」的章節。
中介服務聯播網負責執行中介服務鏈,也會將自身置於中介服務鏈中。下一節將說明此程序的設定與執行做法。
擷取中介服務鏈和出價下限
中介服務聯播網會負責擷取第一方的內容相關廣告、中介服務鏈和第三方聯播網的出價下限。每當有人要求擷取中介服務聯播網提供的內容相關廣告,中介服務聯播網就可能採取上述行動。中介服務鏈會決定逐一查看第三方聯播網的方式,出價下限則能以 adSelectionSignals
的形式傳遞至競價程序。
聯播網在中介服務鏈中的排名
中介服務 SDK 可以根據第一方廣告出價的即時有效千次曝光出價,決定自身在中介服務鏈中的排名。Protected Audience API 中的廣告出價是不透明的。中介服務 SDK 應使用 AdSelectionFromOutcomesConfig
,才能將指定第一方廣告的出價與服務鏈中下一個第三方聯播網的出價下限進行比較。如果第一方出價高於第三方出價下限,中介服務 SDK 的排名就會在第三方聯播網前面。
執行廣告選擇
中介服務聯播網在擷取第一方候選廣告時,可以按照「執行廣告選擇」一節的步驟進行裝置端競價,從而產生第一方候選廣告、出價和中介服務程序所用的 AdSelectionId
。
建立 AdSelectionFromResultsConfig
AdSelectionFromOutcomesConfig
可讓中介服務聯播網傳遞 AdSelectionIds
清單 (先前競價的結果)、廣告選擇信號及 URI,以便根據 URI 擷取 JavaScript,再利用 JavaScript 從多個候選廣告中選出得標廣告。這份列有 AdSelectionId 和相應出價的清單會跟信號一起傳遞至 JavaScript,如果當中有高於出價下限的出價,JavaScript 就會傳回其中一個 AdSelectionIds
;如果中介服務鏈應繼續執行,則不會傳回內容。
中介服務聯播網在建立 AdSelectionFromOutcomesConfig
時,會使用上一節提到的第一方 AdSelectionId
,並參考第三方聯播網的出價下限。您應針對中介服務鏈中的每個步驟建立新的 AdSelectionFromOutcomesConfig
。
Kotlin
fun runSelectOutcome(
adSelectionClient : AdSelectionClient,
outcome1p : AdSelectionOutcome,
network3p : NetworkAdapter) : ListenableFuture<AdSelectionOutcome?> {
val config = AdSelectionFromOutcomesConfig.Builder()
.setSeller(seller)
.setAdSelectionIds(listOf(outcome1p))
.setSelectionSignals({"bid_floor": bid_floor})
.setSelectionLogicUri(selectionLogicUri)
.build()
return adSelectionClient.selectAds(config)
}
Java
public ListenableFuture<AdSelectionOutcome> runSelectOutcome(AdSelectionOutcome outcome1p,
NetworkAdapter network3p) {
AdSelectionFromOutcomesConfig config = new AdSelectionFromOutcomesConfig.Builder()
.setSeller(seller)
.setAdSelectionIds(Collection.singletonList(outcome1p))
.setSelectionSignals({"bid_floor": bid_floor})
.setSelectionLogicUri(selectionLogicUri)
.build();
return adSelectionClient.selectAds(config){}
}
刊登序列中介服務的 selectAds()
方法覆寫需要 AdSelectionFromOutcomesConfig
輸入內容,當中須指定下列必要參數:
- 賣方:賣方廣告聯播網 ID,這用於指出啟動廣告選擇程序的賣方廣告聯播網。
- AdSelectionId:之前針對第一方廣告執行的
selectAds()
的單例模式清單。 - 廣告選擇信號:序列化為字串的 JSON 物件,含有買方出價邏輯所用的信號。上例中也加入了針對指定第三方聯播網擷取的出價下限。
- 選擇邏輯 URI:在廣告選擇期間查詢的 HTTPS 網址。中介服務聯播網會從這個網址擷取用來選出得標廣告的 JavaScript。請留意這個 JavaScript 必須包含的函式簽章。JavaScript 應於出價高於出價下限時傳回第三方廣告,並在其他情況下傳回
null
。如此一來,中介服務 SDK 就能在找到得標廣告後截斷中介服務鏈。
建立 AdSelectionOutcomesConfig
後,即可呼叫服務鏈中首個第三方聯播網的 selectAds()
方法。
Kotlin
val adSelectionManager = context.getSystemService(AdSelectionManager::class.java)
// Initialize AdSelectionFromOutcomesConfig
AdSelectionFromOutcomesConfig adSelectionFromOutcomesConfig =
AdSelectionFromOutcomesConfig.Builder()
.setSeller(seller)
.setAdSelectionIds(listof(outcome1p))
.setSelectionSignals({"bid_floor": bid_floor})
.setSelectionLogicUri(selectionLogicUri)
.setAdSelectionIds(outcomeIds)
.build()
// Run ad selection with AdSelectionConfig
adSelectionManager.selectAds(
adSelectionFromOutcomesConfig,
executor,
outcomeReceiver)
Java
AdSelectionManager adSelectionManager =
context.getSystemService(AdSelectionManager.class);
// Initialize AdSelectionFromOutcomesConfig
AdSelectionFromOutcomesConfig adSelectionFromOutcomesConfig =
new AdSelectionFromOutcomesConfig.Builder()
.setSeller(seller)
.setAdSelectionIds(Collection.singletonList(outcome1p))
.setSelectionSignals({"bid_floor": bid_floor})
.setSelectionLogicUri(selectionLogicUri)
.setAdSelectionIds(outcomeIds)
.build();
// Run ad selection with AdSelectionConfig
adSelectionManager.selectAds(
adSelectionFromOutcomesConfig,
executor,
outcomeReceiver);
調度刊登序列中介服務
以下是執行中介服務的作業順序。
- 執行第一方廣告選擇。
- 逐一查看中介服務鏈中的每個項目。針對每個第三方聯播網執行下列操作:
- 建立
AdSelectionFromOutcomeConfig
並納入第一方outcomeId
和第三方 SDK 出價下限。 - 使用上一個步驟的設定呼叫
selectAds()
。 - 若結果不為空,就會傳回廣告。
- 呼叫當前 SDK 廣告聯播網轉接程式的
selectAds()
方法。若結果不為空,就會傳回廣告。
- 建立
- 如果無法從服務鏈中找到得標廣告,就會傳回第一方廣告。
Kotlin
fun runWaterfallMediation(mediationChain : List<NetworkAdapter>)
: Pair<AdSelectionOutcome, NetworkAdapter> {
val outcome1p = runAdSelection()
var outcome : AdSelectionOutcome
for(network3p in mediationChain) {
outcome = runSelectOutcome(outcome1p, network3p)
if (outcome1p.hasOutcome() && outcome.hasOutcome()) {
return Pair(outcome, this)
}
outcome = network3p.runAdSelection()
if(outcome.hasOutcome()) {
return Pair(outcome, network3p)
}
}
return Pair(outcome1p, this)
}
Java
class MediationNetwork {
AdSelectionManager adSelectionManager;
public MediationNetwork() {
AdSelectionManager adSelectionManager =
context.getSystemService(AdSelectionManager.class);
}
public void runAdSelection() {...}
public void reportImpressions() {...}
public Pair<AdSelectionOutcome, NetworkAdapter> runWaterfallMediation(
List<NetworkAdapter> mediationChain) {
AdSelectionOutcome outcome1p = runAdSelection();
AdSelectionOutcome outcome;
for(NetworkAdapter network3p: mediationChain) {
if (outcome1p.hasOutcome() &&
(outcome = runSelectOutcome(outcome1p, network3p)).hasOutcome()) {
return new Pair<>(outcome, this);
}
if((outcome = network3p.runAdSelection()).hasOutcome()) {
return new Pair<>(outcome, network3p);
}
}
return new Pair<>(outcome1p, this);
}
/* Runs comparison by creating an AdSelectionFromOutcomesConfig */
public AdSelectionOutcome runSelectOutcome(AdSelectionOutcome outcome1p,
NetworkAdapter network3p) { ... }
}
回報廣告曝光
廣告曝光的回報流程依競價方式而異,共有兩套流程。如果您是進行競價的賣方平台,請參閱本節資訊。若您要實作刊登序列中介服務,請按照「刊登序列中介服務回報曝光」一節的步驟執行。
單一賣方平台回報曝光
透過廣告選擇工作流程選出得標的廣告後,您可以使用 AdSelectionManager.reportImpression()
方法向參與的買方和賣方平台回報曝光。如何回報廣告曝光:
- 初始化
AdSelectionManager
物件。 - 使用廣告選擇 ID 建立
ReportImpressionRequest
物件。 - 使用
ReportImpressionRequest
物件和相關的Executor
及OutcomeReceiver
物件呼叫非同步reportImpression()
。
Java
AdSelectionManager adSelectionManager =
context.getSystemService(AdSelectionManager.class);
// Initialize a ReportImpressionRequest
ReportImpressionRequest reportImpressionRequest =
new ReportImpressionRequest.Builder()
.setAdSelectionId(adSelectionId)
.setAdSelectionConfig(adSelectionConfig)
.build();
// Request to report the impression with the ReportImpressionRequest
adSelectionManager.reportImpression(
reportImpressionRequest,
executor,
outcomeReceiver);
Kotlin
val adSelectionManager = context.getSystemService(AdSelectionManager::class.java)
// Initialize a ReportImpressionRequest
val adSelectionConfig: ReportImpressionRequest =
ReportImpressionRequest.Builder()
.setAdSelectionId(adSelectionId)
.setAdSelectionConfig(adSelectionConfig)
.build()
// Request to report the impression with the ReportImpressionRequest
adSelectionManager.reportImpression(
reportImpressionRequest,
executor,
outcomeReceiver)
使用下列必要參數初始化 ReportImpressionRequest
:
- 廣告選擇 ID:裝置使用者專屬 ID,用於表示成功選出廣告。
- 廣告選擇設定:與提供的廣告選擇 ID 辨識的
selectAds()
呼叫中使用設定相同的設定。
非同步 reportImpression()
方法會使用 OutcomeReceiver
物件,指出 API 呼叫的結果。
onResult()
回呼會指出是否已建立曝光報表網址,以及是否已排定要求執行時間。onError()
回呼代表可能發生下列情況:- 如果呼叫是因為輸入無效引數才初始化,
AdServicesException
會指出IllegalArgumentException
是錯誤原因。 - 發生其他錯誤時,收到的
AdServicesException
則會指出IllegalStateException
是錯誤原因。
- 如果呼叫是因為輸入無效引數才初始化,
刊登序列中介服務回報曝光
中介服務 SDK 必須追蹤勝出的 SDK 來觸發回報流程。參與中介服務鏈的 SDK 應讓中介服務可藉由叫用特定方法,觸發自身的回報流程。參與中介競價的 SDK 可以按照上述步驟,自行實作回報機制。
賣方平台可以將下方的第三方 SDK 程式碼範例當成原型,瞭解如何加入中介服務流程:
Pair<AdSelectionOutcome, NetworkAdapter> winnerOutcomeAndNetwork =
mediationSdk.orchestrateMediation(mediationChain);
if (winner.first.hasOutcome()) {
winner.second.reportImpressions(winner.first.getAdSelectionId());
曝光回報端點
曝光回報 API 會向賣方平台和得標買方平台提供的端點發出 HTTPS GET 要求:
買方平台端點:
- API 使用自訂目標對象中指定的出價邏輯網址擷取買方提供的 JavaScript,該 JavaScript 包含傳回曝光報表網址所需的邏輯。
- 叫用
reportWin()
JavaScript 函式,該函式應會傳回買方的曝光報表網址。
賣家平台端點:
- 使用
AdSelectionConfig
物件中指定的 決策邏輯網址擷取賣家的決策邏輯 JavaScript。 - 叫用
reportResult()
JavaScript 函式,該函式應傳回買方的曝光回報網址。
出價與競價服務報表
在出價與競價服務執行的競價,會在伺服器端競價的加密回應中提供所有必要的報表資訊,包括針對廣告互動報表產生的網址。將回應解密後,系統會向平台註冊對應的網址,因此廣告和曝光報表都會遵循上述的步驟。
最佳效果曝光報表
reportImpression()
方法的用意是盡可能提供最佳報表。
回報廣告互動
Protected Audience 可提供支援,針對顯示的廣告回報更精細的互動資料。這類資料包括瀏覽時間、點擊、懸停等互動,或任何其他可收集的實用指標。只需兩個步驟,即可設定接收報表的程序。首先,買方和賣方必須完成註冊,才能在報表 JavaScript 中查看這些報表。接著,用戶端需要回報這些事件。
註冊以接收互動事件
系統註冊互動事件時,會在買方的 reportWin()
和賣方的 reportResult()
JavaScript 函式中,使用平台提供的 JavaScript 函式:registerAdBeacon
。如要註冊以接收事件報表,只要從報表 JavaScript 呼叫平台 JavaScript 函式即可。下列程式碼片段使用買家的 reportWin()
,但同樣做法也適用於 reportResult()
。
reportWin(
adSelectionSignals,
perBuyerSignals,
signalsForBuyer,
contextualSignals,
customAudienceSignals) {
...
// Calculate reportingUri, clickUri, viewUri, and hoverUri
registerAdBeacon("click", clickUri)
registerAdBeacon("view", viewUri)
registerAdBeacon("hover", hoverUri)
return reportingUrl;
}
回報互動事件
回報曝光後,用戶端可以使用 AdSelectionManager.reportInteraction()
方法,將互動回報給先前已註冊的得標買方和賣方平台。如何回報廣告事件:
- 初始化
AdSelectionManager
物件。 - 使用廣告選擇 ID、互動鍵、互動資料和報表目的地,建構
ReportInteractionRequest
物件。 - 使用
request
物件和相關的Executor
及OutcomeReceiver
物件,呼叫非同步reportInteraction()
方法。
AdSelectionManager adSelectionManager =
context.getSystemService(AdSelectionManager.class);
// Initialize a ReportInteractionRequest
ReportInteractionRequest request =
new ReportInteractionRequest.Builder()
.setAdSelectionId(adSelectionId)
.setInteractionKey("view")
.setInteractionData("{ viewTimeInSeconds : 1 }") // Can be any string
.setReportingDestinations(
FLAG_REPORTING_DESTINATION_BUYER | FLAG_REPORTING_DESTINATION_SELLER
)
.build();
// Request to report the impression with the ReportImpressionRequest
adSelectionManager.reportInteraction(
reportImpressionRequest,
executor,
outcomeReceiver);
使用下列必要參數初始化 ReportInteractionRequest
:
- 廣告選擇 ID:從先前傳回的
AdSelectionOutcome
擷取的廣告選擇 ID。 - 互動鍵:由用戶端定義的字串鍵,用於說明回報的動作。這必須符合賣方或買方在報表 JavaScript 函式中註冊的鍵。
- 互動資料:包含要納入事件報表的字串,會以 POST 方式傳回報表伺服器。
- 報表目的地:指定是否應向買方和/或賣方回報事件的位元遮罩。這些標記是由平台提供,而系統可使用位元運算建立最終目的地遮罩。如要回報給單一目的地,可以直接使用平台提供的標記。如要回報給多個目的地,可以使用按位元或 (
|
) 合併標記值。
非同步 reportInteraction()
方法會使用 OutcomeReceiver
物件,指出 API 呼叫的結果。
onResult()
回呼代表回報互動呼叫有效。onError()
回呼代表可能發生下列情況:- 若是在應用程式於背景執行時發出呼叫,會傳回
IllegalStateException
和失敗說明。 - 如果用戶端因呼叫
reportInteraction()
而受到節流限制,會傳回LimitExceededException
。 - 如果未註冊套件就呼叫隱私權保護 API,會傳回
SecurityException()
。 - 如果回報互動的應用程式不同於呼叫
selectAds()
的應用程式,會傳回IllegalStateException
。
- 若是在應用程式於背景執行時發出呼叫,會傳回
- 如果使用者不同意啟用 Privacy Sandbox API,則呼叫會失敗,而且不會顯示相關通知。
互動報表端點
報表互動 API 會向賣方平台和得標買方平台提供的端點發出 HTTPS POST 要求。Protected Audience 會比對互動鍵和報表 JavaScript 中宣告的 URI,並針對每個回報的互動向每個端點發出 POST 要求。要求的內容類型為純文字,主體為互動資料。
最佳效果互動報表
reportInteraction()
的用意是透過 HTTP POST 盡可能提供最佳報表。
每日背景更新
建立自訂目標對象時,應用程式或 SDK 可以初始化自訂目標對象的中繼資料。此外,平台也可以透過每日背景更新程序,更新自訂目標對象的下列中繼資料內容。
- 使用者出價信號
- 受信任的出價資料
AdData
清單
這項程序會根據自訂目標對象中定義的每日更新網址進行查詢,而網址可能會傳回 JSON 回應。
- JSON 回應可能包含需要更新的任何受支援中繼資料欄位。
- 每個 JSON 欄位都會經過獨立驗證。用戶端會忽略任何格式錯誤的欄位,因此不會在回應中更新該特定欄位。
- 空白的 HTTP 回應或空白的 JSON 物件「
{}
」會導致無法更新中繼資料。 - 回應訊息的大小上限為 10 KB。
- 所有 URI 都必須使用 HTTPS。
trusted_bidding_uri
必須和買方使用相同的 ETLD+1。
範例:每日背景更新的 JSON 回應
{
"user_bidding_signals" : { ... }, // Valid JSON object
"trusted_bidding_data" : {
"trusted_bidding_uri" : 'example-dsp1-key-value-service.com',
"trusted_bidding_keys" : [ 'campaign123', 'campaign456', ... ]
},
'ads' : [
{
"render_uri" : 'www.example-dsp1.com/.../campaign123.html',
'metadata' : { ... } // Valid JSON object
},
{
"render_uri" : 'www.example-dsp1.com/.../campaign456.html',
'metadata' : { ... } // Valid JSON object
},
...
]
}
廣告選擇專用的 JavaScript
廣告選擇工作流程可自動化調度管理買家提供和賣家提供的 JavaScript。
買家提供的 JavaScript 是擷取自自訂目標對象指定的出價邏輯網址。傳回的 JavaScript 應包含下列函式:
賣家提供的 JavaScript 是擷取自廣告選擇 API 的 AdSelectionConfig
參數中指定的決策邏輯網址。傳回的 JavaScript 應包含下列函式:
generateBid()
function generateBid(
ad,
auction_signals,
per_buyer_signals,
trusted_bidding_signals,
contextual_signals,
user_signals,
custom_audience_bidding_signals) {
return {'status': 0, 'ad': ad, 'bid': ad.metadata.result };
}
輸入參數:
ad
:JSON 物件,格式為var ad = { 'render_url': url, 'metadata': json_metadata };
auction_signals, per_buyer_signals
:競價設定物件中指定的 JSON 物件custom_audience_bidding_signals
:平台產生的 JSON 物件。格式如下:var custom_audience_signals = { "owner":"ca_owner", "buyer":"ca_buyer", "name":"ca_name", "activation_time":"ca_activation_time_epoch_ms", "expiration_time":"ca_expiration_time_epoch_ms", "user_bidding_signals":"ca_user_bidding_signals" }
其中:
owner
、buyer
和name
是取自屬性的字串,名稱與參與廣告選擇的自訂目標對象相同activation_time
和expiration_time
是自訂目標對象啟用和到期的時間,以 Unix Epoch 時間起算的秒數表示。ca_user_bidding_signals
是CustomAudience
建立時在userBiddingSignals
欄位中指定的 JSON 字串trusted_bidding_signals, contextual_signals
和user_signals
是 JSON 物件。這些物件是以空白物件的形式傳遞,後續版本將填入資料。這種格式並非由平台強制執行,而是由廣告技術管理。
成果:
ad
:出價參考的廣告。允許使用指令碼以回傳有不同中繼資料的廣告複本。廣告的render_url
屬性應該不會改變。bid
:代表這則廣告出價的浮點值status
:整數值,可能如下:0
:成功執行1
:(或任何非零值) 有無效的輸入信號。如果產生的出價傳回非零值,則所有 自訂目標對象廣告的出價程序都會失效
scoreAd()
function scoreAd(
ad,
bid,
ad_selection_config,
seller_signals,
trusted_scoring_signals,
contextual_signal,
user_signal,
custom_audience_signal) {
return {'status': 0, 'score': score };
}
輸入參數:
ad
:請參閱generateBid
說明文件bid
:廣告出價的值ad_selection_config
:JSON 物件,代表selectAds
API 的AdSelectionConfig
參數。格式為:var ad_selection_config = { 'seller': 'seller', 'decision_logic_url': 'url_of_decision_logic', 'custom_audience_buyers': ['buyer1', 'buyer2'], 'auction_signals': auction_signals, 'per_buyer_signals': per_buyer_signals, 'contextual_ads': [ad1, ad2] }
seller_signals
:讀取自sellerSignals
AdSelectionConfig
API 參數的 JSON 物件trusted_scoring_signal
:讀取自AdSelectionConfig
API 參數中的adSelectionSignals
欄位contextual_signals, user_signals
:JSON 物件。目前這些物件是以空白物件的形式傳遞,後續版本將填入資料。這種格式並非由平台強制執行,而是由廣告技術管理per_buyer_signals
:讀取自AdSelectionConfig
API 參數中perBuyerSignal
對應讀取的 JSON 物件,做為目前自訂目標對象買家的索引鍵。如果對應內容未包含特定買家的任何項目,則為空白。
輸出內容:
score
:代表這則廣告評分值的浮點值status
:整數值,可能如下:- 0:成功執行
- 1:如果
customAudienceSignals
無效 - 2:如果
AdSelectionConfig
無效 - 3:如果上述信號以外的信號無效
- 零以外的值都會導致程序失敗,此值決定了擲回例外狀況的類型
selectOutcome()
function selectOutcome(
outcomes,
selection_signals) {
return {'status': 0, 'result': null};
}
輸入參數:
outcomes
:JSON 物件{"id": id_string, "bid": bid_double}
selection_signals
:競價設定物件中指定的 JSON 物件
輸出內容:
status
:0
為成功,其他為失敗result
:傳遞的結果之一或空值
reportResult()
function reportResult(ad_selection_config, render_url, bid, contextual_signals) {
return {
'status': status,
'results': {'signals_for_buyer': signals_for_buyer, 'reporting_url': reporting_url }
};
}
輸入參數:
ad_selection_config
:請參閱scoreAds
的說明文件render_url
:得標廣告的顯示網址bid
:得標廣告的出價contextual_signals
:請參閱generateBid
的說明文件
輸出內容:
status: 0
為成功,非零為失敗results
:JSON 物件,包含以下項目signals_for_buyer
:傳遞至reportWin
函式的 JSON 物件reporting_url
:平台向買方回報曝光所用的網址
reportWin()
function reportWin(
ad_selection_signals,
per_buyer_signals,
signals_for_buyer,
contextual_signals,
custom_audience_signals) {
return {'status': 0, 'results': {'reporting_url': reporting_url } };
}
輸入參數:
ad_selection_signals, per_buyer_signals
:請參閱scoreAd
的說明文件signals_for_buyer
:reportResult
傳回的 JSON 物件contextual_signals, custom_audience_signals
:請參閱generateBid
的說明文件
輸出內容:
status: 0
為成功,非零為失敗results
:包含以下項目的 JSON 物件:reporting_url
:平台向賣方回報曝光所用的網址
registerAdBeacon()
function registerAdBeacon(
interaction_key,
reporting_uri
)
輸入參數:
interaction_key
:代表事件的字串。平台稍後會使用這個參數回報事件互動,查詢應收到通知的reporting_uri
。這個鍵需符合買方或賣方註冊的項目,以及賣方回報的內容。reporting_uri
:用於接收事件報表的 URI。這應視回報的事件類型而定。這個參數必須接受 POST 要求,才能處理與事件一併回報的資料。
廣告選擇程序的預建 URI
預先建構的 URI 可讓廣告技術人員指定 JavaScript 函式,以用於 AdSelectionConfig
和 AdSelectionFromOutcomesConfig
類別中的廣告選擇決策邏輯。預先建構的 URI 無需網路呼叫即可下載對應的 JavaScript。廣告技術人員可以使用預先建構的 URI,不必設定註冊網域來代管 JavaScript。
預先建構的 URI 是以下列格式構建而成:
ad-selection-prebuilt:<use-case>/<name>?<required-script-generation-parameters>
Privacy Sandbox 平台會在執行階段使用這個 URI 的資訊提供 JavaScript。
如果發生下列情況,系統會擲回 IllegalArgumentException
:
- URI 中沒有任何必要參數
- URI 中有無法辨識的參數
支援的預建 URI 用途和名稱
用途 1:ad-selection
selectAds(AdSelectionConfig)
流程支援 ad-selection
用途下的預先建構 URI。
預先建構的 URI 名稱:highest-bid-wins
這個預先建構的 URI 會提供 JavaScript,可在出價後挑選出價最高的廣告。此外,此 URI 還提供基本報表功能,可回報勝出廣告的 render_uri
和 bid
。
必要參數
reportingUrl
:透過勝出廣告的 render_uri
和 bid
參數化的基本報表網址:
<reportingUrl>?render_uri=<renderUriOfWinnigAd>&bid=<bidOfWinningAd>
用法
如果基本報表網址為 https://www.ssp.com/reporting
,預先建構的 URI 會是:
`ad-selection-prebuilt://ad-selection/highest-bid-wins/?reportingUrl=https://www.ssp.com/reporting`
用途 2:ad-selection-from-outcomes
ad-selection-from-outcomes
用途下的預先建構 URI 可支援 selectAds(AdSelectionFromOutcomesConfig)
工作流程。
預先建構的 URI 名稱:waterfall-mediation-truncation
waterfall-mediation-truncation
的預先建構 URI 提供可實作刊登序列中介服務截斷邏輯的 JavaScript,如果 bid
大於或等於 bid floor
,JavaScript 就會傳回第一方廣告,在其他情況下則傳回 null
。
必要參數
bidFloor
:getSelectionSignals()
中傳遞的出價下限值鍵,用於與中介服務 SDK 的廣告比較。
用法
如果廣告選擇信號類似於 {"bid_floor": 10}
,那麼產生的預先建構 URI 會是:
`ad-selection-prebuilt://ad-selection-from-outcomes/waterfall-mediation-truncation/?bidFloor=bid_floor`
測試
為協助您開始使用 Protected Audience API,我們在 GitHub 上提供了 Kotlin 和 Java 的範例應用程式。
必要條件
在選擇廣告以及製作曝光報表時,Protected Audience API 需要一些 JavaScript。在測試環境中提供這個 JavaScript 的方法有兩種:
- 執行內含傳回 JavaScript 的必要 HTTP 端點的伺服器
- 提供來自本機來源的必要程式碼,以覆寫遠端擷取
無論採用哪一種方法,都需要設定 HTTPS 端點來處理曝光報表。
HTTPS 端點
如要測試廣告選擇和曝光回報程序,您必須設定 7 個可讓測試裝置或模擬器存取的 HTTPS 端點:
- 提供出價邏輯 JavaScript 的買方端點。
- 提供出價信號的端點。
- 提供決策邏輯 JavaScript 的賣家端點。
- 提供評分信號的端點。
- 得標買家曝光報表端點。
- 賣家曝光報表端點。
- 為自訂目標對象提供每日更新內容的端點。
為方便起見,GitHub 存放區提供基本的 JavaScript 程式碼供您進行測試。其中也包含 OpenAPI 服務定義,可部署至支援的模擬或微服務平台。如需瞭解詳情,請參考 README 專案。
覆寫遠端擷取 JavaScript
這項功能用於端對端測試。如要覆寫遠端擷取功能,應用程式必須在偵錯模式中執行,並啟用開發人員選項。
如要為您的應用程式啟用偵錯模式,請將以下程式碼新增至 AndroidManifest.xml 的應用程式屬性:
<application
android:debuggable="true">
如需覆寫機制的應用範例,請參考 GitHub 上的 Protected Audience API 範例應用程式。
您必須自行新增 JavaScript 來處理廣告選擇日常安排,例如出價、評分決策和報表。您可以在 GitHub 存放區中找到處理所有必要要求的基本 JavaScript 程式碼範例。Protected Audience API 範例應用程式展示了如何讀取該檔案的程式碼,以及如何準備用來覆寫的資料。
您可以單獨覆寫賣方或買方指定擷取的 JavaScript,但對於未覆寫的 JavaScript,您需要透過 HTTPS 端點來處理相關作業。如要瞭解如何設定伺服器來處理這些情況,請參閱 README。
您只能覆寫針對套件擁有的自訂目標對象進行擷取的 JavaScript。
覆寫賣方 JavaScript
如要設定賣方 JavaScript 的覆寫值,請按照下方程式碼範例操作:
- 初始化
AdSelectionManager
物件。 - 從
AdSelectionManager
物件取得TestAdSelectionManager
的參照。 - 建構
AdSelectionConfig
物件。 - 使用
AdSelectionConfig
物件和String
建構AddAdSelectionOverrideRequest
代表您打算當做覆寫使用的 JavaScript。 - 使用
AddAdSelectionOverrideRequest
物件和相關的Executor
及OutcomeReceiver
物件呼叫非同步overrideAdSelectionConfigRemoteInfo()
。
Kotlin
val testAdSelectionManager: TestAdSelectionManager =
context.getSystemService(AdSelectionManager::class.java).getTestAdSelectionManager()
// Initialize AdSelectionConfig =
val adSelectionConfig = new AdSelectionConfig.Builder()
.setSeller(seller)
.setDecisionLogicUrl(decisionLogicUrl)
.setCustomAudienceBuyers(customAudienceBuyers)
.setAdSelectionSignals(adSelectionSignals)
.setSellerSignals(sellerSignals)
.setPerBuyerSignals(perBuyerSignals)
.build()
// Initialize AddAddSelectionOverrideRequest
val request = AddAdSelectionOverrideRequest.Builder()
.setAdSelectionConfig(adSelectionConfig)
.setDecisionLogicJs(decisionLogicJS)
.build()
// Run the call to override the JavaScript for the given AdSelectionConfig
// Note that this only takes effect in apps marked as debuggable
testAdSelectionManager.overrideAdSelectionConfigRemoteInfo(
request,
executor,
outComeReceiver)
Java
TestAdSelectionManager testAdSelectionManager =
context.getSystemService(AdSelectionManager.class).getTestAdSelectionManager();
// Initialize AdSelectionConfig =
AdSelectionConfig adSelectionConfig = new AdSelectionConfig.Builder()
.setSeller(seller)
.setDecisionLogicUrl(decisionLogicUrl)
.setCustomAudienceBuyers(customAudienceBuyers)
.setAdSelectionSignals(adSelectionSignals)
.setSellerSignals(sellerSignals)
.setPerBuyerSignals(perBuyerSignals)
.build();
// Initialize AddAddSelectionOverrideRequest
AddAdSelectionOverrideRequest request = AddAdSelectionOverrideRequest.Builder()
.setAdSelectionConfig(adSelectionConfig)
.setDecisionLogicJs(decisionLogicJS)
.build();
// Run the call to override the JavaScript for the given AdSelectionConfig
// Note that this only takes effect in apps marked as debuggable
testAdSelectionManager.overrideAdSelectionConfigRemoteInfo(
request,
executor,
outComeReceiver);
如要進一步瞭解 AdSelectionConfig
中每個欄位代表的意義,請參閱「執行廣告選擇」一節。主要差異在於「decisionLogicUrl」可以設為預留位置值,系統會忽略該值。
如要覆寫廣告選擇期間使用的 JavaScript,decisionLogicJs
必須包含適當的賣方端函式簽章。如需如何以字串形式讀取 JavaScript 檔案的範例,請參閱 GitHub 上的「Protected Audience API 範例應用程式」。
非同步 overrideAdSelectionConfigRemoteInfo()
方法會使用 OutcomeReceiver
物件指出 API 呼叫的結果。
onResult()
回呼表示已成功套用覆寫值。日後對 selectAds()
的呼叫將使用您傳遞用於覆寫的判斷和回報邏輯。
onError()
回呼代表兩種可能情況:
- 如果嘗試使用無效引數進行覆寫,
AdServiceException
會指出IllegalArgumentException
是錯誤原因。 - 如果嘗試覆寫時,應用程式未執行偵錯模式,但已啟用開發人員選項,
AdServiceException
會指出IllegalStateException
是錯誤原因。
重設賣方覆寫值
本節假設您已覆寫賣方 JavaScript,並已取得上一節所用 TestAdSelectionManager
和 AdSelectionConfig
的參照。
如何重設所有 AdSelectionConfigs
的覆寫值:
- 使用相關的
OutcomeReceiver
物件呼叫非同步resetAllAdSelectionConfigRemoteOverrides()
方法。
Kotlin
// Resets overrides for all AdSelectionConfigs
testAadSelectionManager.resetAllAdSelectionConfigRemoteOverrides(
outComeReceiver)
Java
// Resets overrides for all AdSelectionConfigs
testAdSelectionManager.resetAllAdSelectionConfigRemoteOverrides(
outComeReceiver);
重設賣方覆寫值後,對 selectAds()
的呼叫就會使用 AdSelectionConfig
中儲存的 decisionLogicUrl 來嘗試擷取需要的 JavaScript。
如果呼叫 resetAllAdSelectionConfigRemoteOverrides()
失敗,OutComeReceiver.onError()
回呼會提供 AdServiceException
。若應用程式未執行偵錯模式,但已啟用開發人員選項,當系統嘗試移除覆寫資料時,AdServiceException
就會指出 IllegalStateException
是錯誤原因。
覆寫買方 JavaScript
- 請按照步驟加入自訂目標對象
- 根據要覆寫的自訂目標對象,使用相應的「買方」和「名稱」值建構
AddCustomAudienceOverrideRequest
,並建構用於覆寫的出價邏輯和資料 - 使用
AddCustomAudienceOverrideRequest
物件和相關的Executor
及OutcomeReceiver
物件呼叫非同步overrideCustomAudienceRemoteInfo()
。
Kotlin
val testCustomAudienceManager: TestCustomAudienceManager =
context.getSystemService(CustomAudienceManager::class.java).getTestCustomAudienceManager()
// Join custom audience
// Build the AddCustomAudienceOverrideRequest
val request = AddCustomAudienceOverrideRequest.Builder()
.setBuyer(buyer)
.setName(name)
.setBiddingLogicJs(biddingLogicJS)
.setTrustedBiddingSignals(trustedBiddingSignals)
.build()
// Run the call to override JavaScript for the given custom audience
testCustomAudienceManager.overrideCustomAudienceRemoteInfo(
request,
executor,
outComeReceiver)
Java
TestCustomAudienceManager testCustomAudienceManager =
context.getSystemService(CustomAudienceManager.class).getTestCustomAudienceManager();
// Join custom audience
// Build the AddCustomAudienceOverrideRequest
AddCustomAudienceOverrideRequest request =
AddCustomAudienceOverrideRequest.Builder()
.setBuyer(buyer)
.setName(name)
.setBiddingLogicJs(biddingLogicJS)
.setTrustedBiddingSignals(trustedBiddingSignals)
.build();
// Run the call to override JavaScript for the given custom audience
testCustomAudienceManager.overrideCustomAudienceRemoteInfo(
request,
executor,
outComeReceiver);
「買家」和「名字」的值與用來建立自訂目標對象的值相同。進一步瞭解這些欄位。
此外,您還可以指定兩個額外參數:
biddingLogicJs
:這個 JavaScript 包含在選擇廣告時使用的買方邏輯。請留意這個 JavaScript 必須包含的函式簽章。trustedBiddingSignals
:選擇廣告時使用的出價信號。如果是測試用途,這個值可以是空白字串。
非同步 overrideCustomAudienceRemoteInfo()
方法會使用 OutcomeReceiver
物件來指出 API 呼叫的結果。
onResult()
回呼表示已成功套用覆寫值。後續對 selectAds()
的呼叫將使用您傳遞用於覆寫的判斷和回報邏輯。
onError()
回呼代表兩種可能情況。
- 如果嘗試使用無效引數進行覆寫,
AdServiceException
會指出IllegalArgumentException
是錯誤原因。 - 如果嘗試覆寫時,應用程式未執行偵錯模式,但已啟用開發人員選項,
AdServiceException
會指出IllegalStateException
是錯誤原因。
重設買方覆寫值
本節假設您已覆寫買方 JavaScript,且已取得上一節中所用 TestCustomAudienceManager
的參照。
如要重設所有自訂目標對象的覆寫值,請按照下列步驟操作:
- 使用相關的
Executor
和OutcomeReceiver
物件呼叫非同步的resetAllCustomAudienceOverrides()
方法。
Kotlin
// Resets overrides for all custom audiences
testCustomAudienceManager.resetCustomAudienceRemoteInfoOverride(
executor,
outComeReceiver)
Java
// Resets overrides for all custom audiences
testCustomAudienceManager.resetCustomAudienceRemoteInfoOverride(
executor,
outComeReceiver)
重設買方覆寫值後,後續對 selectAds()
的呼叫就會使用 CustomAudience
中儲存的 biddingLogicUrl
和 trustedBiddingData
來嘗試擷取需要的 JavaScript。
如果呼叫 resetCustomAudienceRemoteInfoOverride()
失敗,OutComeReceiver.onError()
回呼會提供 AdServiceException
。若應用程式未執行偵錯模式,但已啟用開發人員選項,當系統嘗試移除覆寫資料時,AdServiceException
就會指出 IllegalStateException
是錯誤原因。
設定回報伺服器
使用遠端擷取覆寫功能時,您仍須設定伺服器,讓裝置或模擬器能存取該伺服器來回應回報事件。傳回 200 的簡單端點就足以進行測試。GitHub 存放區包含 OpenAPI 服務定義,您可以將這些定義部署至支援的模擬或微服務平台。如需瞭解詳情,請參考 README 專案。
尋找 OpenAPI 定義時,請搜尋 reporting-server.json。這個檔案含有會傳回 200 的簡易端點,代表 HTTP 回應代碼。這個端點會在 selectAds()
期間使用,並向 Protected Audience API 發出信號,表示曝光報表已順利完成。
要測試的功能
- 根據先前的使用者動作,加入/退出及設定自訂目標對象。
- 透過遠端代管的 JavaScript 在裝置上啟動廣告選擇程序。
- 觀察應用程式與自訂目標對象設定之間的關聯如何影響廣告選擇結果。
- 在廣告選擇完成後回報曝光。
限制
下表列出了 Protected Audience API 處理程序的限制。這些限制可能根據意見回饋有所調整。如要查看開發中的功能,請參閱版本資訊。
元件 | 限制說明 | 限制值 |
---|---|---|
自訂目標對象 (CA) | 每個自訂目標對象的廣告數量上限 | 100 |
每個應用程式的自訂目標對象數量上限 | 1000 | |
可建立自訂目標對象的應用程式數量上限 | 1000 | |
CA 的啟用時間與其建立時間的最長延遲 | 60 天 | |
自訂目標對象啟用期間上限 | 60 天 | |
裝置的自訂目標對象數量上限 | 4000 | |
自訂目標對象名稱大小上限 | 200 個位元組 | |
每日擷取 URI 的大小上限 | 400 個位元組 | |
出價邏輯 URI 的大小上限 | 400 個位元組 | |
受信任出價資料大小上限 | 10 KB | |
使用者出價信號大小上限 | 10 KB | |
每個買家的 leaveCustomAudience 呼叫頻率上限 |
每秒 1 次 | |
每個買家的 joinCustomAudience 呼叫頻率上限 |
每秒 1 次 | |
自訂目標對象背景擷取 | 連線逾時 | 5 秒 |
HTTP 讀取逾時 | 30 秒 | |
總下載大小上限 | 10 KB | |
擷取疊代時長上限 | 5 分鐘 | |
每項工作更新的 CA 數量上限 | 1000 | |
廣告選擇 | 買家人數上限 | 未定 |
每個買家的自訂目標對象數量上限 | 未定 | |
單次競價廣告數量上限 | 未定 | |
初始連線逾時 | 5 秒 | |
連線讀取逾時 | 5 秒 | |
整體 AdSelection 的執行時間上限 |
10 秒 | |
AdSelection 中每個自訂目標對象的出價執行時間上限 |
5 秒 | |
AdSelection 中的評分執行時間上限 |
5 秒 | |
AdSelection 中每個買家的執行時間上限 |
未定 | |
廣告選擇/賣方/每個買方信號的大小上限 | 未定 | |
賣方/買方指令碼的大小上限 | 未定 | |
selectAds 的呼叫頻率上限 |
1 QPS | |
曝光報表 | 廣告選擇至少保留多久才會移除 | 24 小時 |
儲存空間廣告選擇數量上限 | 未定 | |
報表輸出網址大小上限 | 未定 | |
曝光報表時間上限 | 未定 | |
通知呼叫的重試次數上限 | 未定 | |
連線逾時 | 5 秒 | |
reportImpression 的總執行時間上限 |
2 秒 | |
reportImpressions 的呼叫頻率上限 |
1 QPS | |
事件回報功能 | 每次競價的每個買家信標數量上限 | 10 |
每次競價的每個賣方信標數量上限 |
10 |
|
事件索引鍵大小上限 |
40 位元組 |
|
事件資料大小上限 |
64 KB |
|
廣告 | 廣告清單的大小上限 | 關聯單一 CA 中所有 AdData 共用 10 KB |
網址 | 接受輸入的任何網址字串長度上限 | 未定 |
JavaScript | 執行時間上限 | 出價及曝光報表的評分皆為 1 秒 |
耗用記憶體上限 | 10 MB |
回報錯誤和問題
您的意見回饋對 Android 版 Privacy Sandbox 至關重要!如果您發現了任何問題,或希望針對 Android 版 Privacy Sandbox 提出改進意見,請告訴我們。
為您推薦
- 注意:系統會在 JavaScript 關閉時顯示連結文字
- 使用 Protected Audience API 支援自訂指定目標對象
- 版本資訊
- Protected Audience:整合指南