---
title: 反詐欺 — 廣告反作弊
---
# 廣告反作弊
這是一份**場景指南**。核心接入不變——你照常載入 [Web SDK](../web-sdk)、讀取
[裁決](../verdict-reference),並從[資料 API](../data-api) 拉取資料,和那幾頁裡描述的
完全一樣。本頁只補充廣告反作弊場景特有的那一點內容。
廣告反作弊把機器人與無效流量擋在付費投放之外,讓廣告主與廣告平台為真實的點擊和曝光
付費——而非虛假量。它與其他使用場景的不同之處在於:**訪客由第三方送來**,且雙方需要
就一份獨立的、逐點擊的真人/機器人結論達成一致。
## 源頭即時攔截
反作弊在入口處 inline 執行、即時給出裁決——它不是事後報表。訪客著陸在誰的頁面上,誰就能立刻依裁決處置:
- **廣告主**在著陸頁跑 SDK:無效流量一到達就被識別——並可選觸發驗證碼——在它進入轉換漏斗、污染報表之前就攔住。
- **流量平台**在自己的 pre-lander 或跳轉頁跑 SDK:點擊在**被轉發之前**就先驗一道,機器人在入口就被攔下,根本不會變成已投遞流量。
唯一前提是要有一張能跑 SDK 的頁:裁決需要瀏覽器訊號,純伺服器端 302 跳轉沒有採集訊號的地方——加一個極輕的中間頁,同樣能即時攔截。
簽名 click token 與資料 API 在此之上做兩端對帳;即時 inline 攔截是主要機制,事後 API 清洗是沒有中間頁時的兜底。
## 兩端角色
- **廣告主(Advertiser)** —— 擁有訪客著陸的頁面。在該頁面上執行 Web SDK,為每次到達的
訪問拿一份裁決,並從資料 API 拉取裁決,以核對自己被計費的部分。
- **服務商(Provider,流量/廣告來源)** —— 投遞點擊。它需要**證明自己投遞的品質**,
因此為每次點擊簽發一個點擊 token,之後用獨立裁決去比對自己的投遞報表。
雙方都用各自的應用程式憑證向[資料 API](../data-api) 鑑權,並讀取同一份逐點擊裁決——正是
這一點讓他們無需互信對方的原始日誌即可對帳。
## 端到端流程
下面的時序圖展示了一次點擊如何從服務商的投遞,經訪客與廣告主著陸頁,最終落到同一份
裁決上——而**兩個帳號之後各自從自己一側讀到這同一列**。
```mermaid
sequenceDiagram
autonumber
participant P as 流量方(Provider / 帳號 B)
participant V as 訪客(Visitor)
participant A as 廣告主著陸頁 + SDK
participant F as 反詐欺後端(Fraud Prevention API)
P->>P: 用自己的 bot_kid + secret 簽 click_token(內含 pkid)
P->>V: 把 token 拼進投放連結 ?_ctk=click_token
V->>A: 點擊 → 落到廣告主著陸頁(URL 攜帶 _ctk)
A->>A: SDK 從 URL 讀取 _ctk
A->>F: 加密 POST /bot/verify
(app_key = 廣告主,click_token = 服務商所簽)
F->>F: app_key → advertiser_app_id,
驗簽 pkid → provider_app_id,出裁決,
一列寫入兩端 app_id
F-->>A: verdict → onVerdict
A->>A: 按 verdict.action 處理(記錄 / 攔截 / 彈驗證碼)
Note over P,F: 對帳(跨帳號)
A->>F: 廣告主用自己的 App-Key 查 GET /v1/bot
F-->>A: 讀到同一列(匹配 advertiser_app_id)
P->>F: 流量方用自己的 App-Key 查 GET /v1/bot
F-->>P: 讀到同一列(匹配 provider_app_id)
```
關鍵特性在於:**兩個 app_id 落在同一列上。** 廣告主按 `advertiser_app_id` 匹配讀到它,
流量方按 `provider_app_id` 匹配讀到它——兩個不同帳號,各用各自的 App-Key 查詢,各自
落到同一份獨立裁決上。雙方無需暴露或互信對方的原始日誌,即可就某次點擊發生了什麼
達成一致。
## 點擊 token
**點擊 token(click token)**把服務商投遞的某次點擊,與該次訪問最終收到的裁決關聯
起來。它是雙方據以結算的逐點擊識別碼。反詐欺的其他使用場景無需點擊 token——不用它也能
對帳裁決。
流程:
1. **簽發** —— 服務商在把訪客路由到廣告主著陸頁時,取得一個已簽名的點擊 token
(每次點擊一個)。
2. **拼接到目標 URL** —— 把簽發的 token 作為查詢參數拼到著陸 URL 上:
```
https://advertiser.example/lp?click_token=ct_xxxxxxxx
```
3. **在頁面讀取** —— [Web SDK](../web-sdk) 會自動從 URL 讀取該 token。若你使用不同的
參數名,設定 `tokenParam`:
```js
BotSignal.init({ appKey: 'YOUR_APP_KEY', tokenParam: 'click_token' });
```
4. **對帳** —— 之後透過資料 API 查回該點擊,並與服務商的投遞報表關聯。
::: info
該 token 在簽發給你時就已簽名——你只需把它**透傳到著陸 URL** 即可。你這邊無需做任何
簽名或計算。
:::
### `tokenParam` 選項
在這個場景下,Web SDK 多出一個選項:
| 選項 | 型別 | 預設值 | 說明 |
| --- | --- | --- | --- |
| `tokenParam` | string | 自動辨識 | URL 查詢參數名,用於攜帶服務商的點擊 token(如 `click_token`)。SDK 會從頁面 URL 中讀取它,並把裁決與該次點擊關聯。若不使用點擊 token,保持預設即可。 |
## 對帳與結算
一旦訪問攜帶了點擊 token,雙方就基於同一份獨立裁決結算:
- **取得單次點擊的裁決** —— 例如用於申訴或確認某次點擊:
```bash
GET /v1/bot/verdict?click_token=ct_xxx
X-App-Key: YOUR_APP_KEY
X-App-Secret: YOUR_APP_SECRET
```
- **匯出逐點擊列** —— 拉取一個時間範圍,把每列的 `click_token` 與你自己的點擊日誌關聯:
```bash
GET /v1/bot/export?from=2026-06-01&to=2026-06-30&format=csv
X-App-Key: YOUR_APP_KEY
X-App-Secret: YOUR_APP_SECRET
```
每一列攜帶該次訪問的 `click_token`(若存在)、時間戳記,以及裁決欄位
(`is_bot`、`score`、`level`、`action`)。
廣告主把被標記和機器人點擊從付費中剔除;服務商用同一份結論比對自己的投遞報表。因為
雙方讀取的是**同一份獨立裁決**,結算不依賴任何一方的原始日誌。
## 安全模型
`cid` 與 click token 走在 URL 裡,所以把它們當**識別碼**、而不是**憑證**:
- **讀裁決必須 App-Key + App-Secret。** Data API 每次呼叫都用你的 app secret 鑑權(常數時間比較),且只回傳「你是其中廣告主或流量方」的列。光有 `cid` 查不到任何東西——路人從 URL 抄走它,既沒有 secret、也不是這一列的任何一端。
- **流量方由簽章綁定。** click token 用流量方 secret 做 HMAC 簽章、帶流量方 `pkid`,無法偽造;同一個 `cid` 只能被認領一次(防重放)。
- **可選:把廣告主也綁上。** 把目標廣告主的 `app_key` 作為 `aud` 簽進 token。驗證時要求頁面的 app_key 與 `aud` 一致——這樣發給廣告主 A 的 token 就無法在廣告主 B 身上歸屬裁決。不簽 `aud` 則任意廣告主頁面都可承接。
最終效果:某個 `cid` 的裁決,只有釘在它上面的兩個 app 能讀——跑了 SDK 的那個廣告主、出示了 token 的那個流量方,各自用自己的 App-Secret 鑑權。
## 下一步
- [Web SDK](../web-sdk) —— 在著陸頁收集裁決
- [裁決欄位參考](../verdict-reference) —— 每個欄位及處理方式
- [資料 API](../data-api) —— 伺服器端拉取與對帳裁決