「比對使用者提供的資料」功能會彙整您收集的使用者第一方資料 (例如來自網站、應用程式或實體商店的資訊),以及該使用者在所有Google 廣告資料 (包括 Google 自有和經營的資料) 中的登入活動記錄。包括透過 Google Marketing Platform (GMP) 產品購買的資料,例如透過 Display & Video 360 購買的 YouTube 廣告。不支援其他非 Google 擁有及營運的 GMP 產品。
廣告事件必須連結到 Google 廣告資料中的登入使用者,才能比對使用者提供的資料。
本文將說明使用者提供的資料比對功能,並提供設定和使用指南。
私有雲比對總覽
如要取得實用的廣告洞察資料,通常需要整合多個來源的資料。自行建構解決方案來解決資料管道問題,需要投入大量時間和工程資源。廣告資料中心的私有雲比對功能提供廣告資料中心查詢範本,可在 BigQuery 中建立比對資料表,然後在廣告資料中心查詢中使用,比對廣告資料與第一方資料,簡化這個程序。使用第一方資料讓查詢內容更豐富,不僅可帶來更豐富的顧客體驗,也更能因應整個產業的廣告追蹤變化。
「比對使用者提供的資料」功能只會比對 Google 自有自營廣告空間的登入使用者,因此不會受到第三方 Cookie 淘汰影響。第一方資料比第三方資料更能適應業界變遷,因此能提供更詳盡的洞察資料,進而提高顧客參與度。
程序摘要
- 設定資料擷取和比對
- 請確認第一方資料位於 BigQuery 中,且服務帳戶具有讀取權限。請參閱設定資料擷取。
- 擷取及比對第一方資料
- 您將第一方資料格式化並上傳至 BigQuery 資料集。
- 您可以建立 Private Cloud Match 分析查詢並設定時間表,發起資料比對要求。
- Google 會彙整專案和 Google 自有資料中的資料,其中包含 Google 使用者 ID 和經雜湊處理的使用者提供資料,藉此建立及更新比對表格。
- 請參閱「擷取第一方資料」一文
- 廣告資料中心根據相符資料執行的持續查詢
- 您可以對照表執行查詢,方式與在廣告資料中心執行一般查詢相同。請參閱「查詢比對成功的資料」。
瞭解隱私權規定
收集顧客資料
使用「比對使用者提供的資料」功能時,您必須上傳第一方資料。這類資訊可能是您從網站、應用程式、實體商店收集的資訊,或是顧客直接提供給您的任何資訊。
須遵循的規定如下:
- 確實在隱私權政策中聲明您會與第三方共用顧客數位資料,以便第三方代為提供服務,且您已按法律規定取得分享資訊的同意聲明
- 僅使用 Google 核准的 API 或介面上傳顧客數位資料
- 遵守所有適用法律和法規 (包括任何適用的自我規範或業界準則)
確認已取得第一方同意聲明
為確保能在廣告資料中心使用第一方資料,請務必確認您已根據歐盟地區使用者同意授權政策和廣告資料中心政策,取得適當的同意聲明,能與 Google 分享歐洲經濟區使用者的資料。這項規定適用於每個廣告資料中心帳戶,且您每次上傳新的第一方資料時,都必須更新同意聲明。任一使用者都可代表整個帳戶確認已取得同意聲明。
請注意,適用於分析查詢的 Google 服務查詢規則,同樣也適用於 UPDM 查詢。例如,建立對照表時,您無法對歐洲經濟區使用者執行跨服務查詢。
請參閱歐洲經濟區同意聲明規定,瞭解如何在廣告資料中心確認已取得同意聲明。
資料大小
為保護使用者隱私,系統會對使用者提供的資料比對功能,強制執行下列資料大小規定:
- 使用者名單必須至少有 1,000 筆記錄。
設定資料擷取
開始前,請確認下列事項:
- 第一方資料必須位於 BigQuery 中。如果您有 VPC-SC 範圍,這類第一方資料必須位於 VPC-SC 內。
- 廣告資料中心服務帳戶必須具備第一方資料的讀取權限。
- 第一方資料必須格式正確且經過雜湊處理。詳情請參閱下一節。
除此之外,私有雲比對功能不需要額外導入。如果您可以執行分析查詢,就能執行 Private Cloud Match 查詢。
擷取及比對第一方資料
設定輸入資料的格式
資料必須符合下列格式規定,才能正確比對:
- 如以下輸入欄位說明所示,您必須使用 SHA256 雜湊演算法上傳。
- 輸入欄位必須採用字串格式。舉例來說,如果您使用 BigQuery 的 SHA256 雜湊函式搭配 Base64 編碼函式 (TO_BASE64),請使用以下轉換指令:
TO_BASE64(SHA256(user_data))
。 - UPDM 支援 Base64 編碼。您必須讓第一方資料的編碼與廣告資料中心查詢中使用的解碼方式一致。如果變更第一方資料編碼,請務必更新廣告資料中心查詢,從相同基底解碼。下列範例使用 Base64 編碼。
使用者 ID
- 純文字
- 雜湊:無
電子郵件
- 移除開頭和結尾的空白字元
- 全部使用小寫字元
- 為所有電子郵件地址加上網域名稱 (例如 gmail.com 或 hotmail.co.jp)
- 移除重音符號,例如將 è、é、ê 或 ë 改為 e
- 移除
gmail.com
和googlemail.com
電子郵件地址中網域名稱前的所有半形句號 (.) - 雜湊:Base64 編碼的 SHA256
有效: TO_BASE64(SHA256("jeffersonloveshiking@gmail.com"))
無效: TO_BASE64(SHA256(" Jéfferson.Lôves.Hiking@gmail.com "))
電話
- 除去空白字元
- 請使用 E.164 格式,例如美國:+14155552671,英國:+442071838750
- 移除所有特殊字元,國家/地區代碼前的「+」除外
- 雜湊:Base64 編碼的 SHA256
有效: TO_BASE64(SHA256("+18005550101"))
無效: TO_BASE64(SHA256("(800) 555-0101"))
名字
- 除去空白字元
- 全部使用小寫字元
- 移除所有前置字元,例如 Mrs.、先生,Ms.、博士
- 請勿移除重音符號,例如:è、é、ê 或 ë
- 雜湊:Base64 編碼的 SHA256
有效: TO_BASE64(SHA256("daní"))
無效: TO_BASE64(SHA256("Mrs. Daní"))
姓氏
- 除去空白字元
- 全部使用小寫字元
- 移除所有後置字元,例如 Jr.、Sr. 2nd、3rd、II、III、PHD、MD
- 請勿移除重音符號,例如:è、é、ê 或 ë
- 雜湊:Base64 編碼的 SHA256
有效: TO_BASE64(SHA256("délacruz"))
無效: TO_BASE64(SHA256("dé la Cruz, Jr."))
國家/地區
- 即使所有顧客數位資料的國家/地區代碼皆相同,仍須納入
- 請勿雜湊處理國家/地區資料
- 使用 ISO 3166-1 alpha-2 國家/地區代碼
- 雜湊:無
有效: US
無效: United States of America
或 USA
郵遞區號
- 請勿對郵遞區號資料進行雜湊處理
- 美國與國際郵遞區號皆可使用
- 美國:
- 可使用 5 碼郵遞區號,例如 94043
- 也可使用 5 碼後加 4 碼額外編碼的郵遞區號,例如 94043-1351 或 940431351
- 所有其他國家/地區:
- 不需要設定格式 (不需要改為小寫,或移除空格和特殊字元)
- 移除郵遞區號的額外編碼
- 雜湊:無
雜湊驗證和資料編碼
您可以使用下列雜湊驗證指令碼,確保資料格式正確無誤。
JavaScript
/**
* @fileoverview Provides the hashing algorithm, as well as some valid hashes of
* sample data for testing.
*/
async function hash(token) {
// Removes leading or trailing spaces and converts all characters to lowercase.
const formattedToken = token.trim().toLowerCase();
// Hashes the formatted string using the SHA-256 hashing algorithm.
const hashBuffer = await crypto.subtle.digest(
'SHA-256', (new TextEncoder()).encode(formattedToken));
// Converts the hash buffer to a base64-encoded string and returns it.
const base64Str = btoa(String.fromCharCode(...new Uint8Array(hashBuffer)));
return base64Str;
}
function main() {
// Expected hash for test@gmail.com:
// h5JGBrQTGorO7q6IaFMfu5cSqqB6XTp1aybOD11spnQ=
hash('test@gmail.com').then(result => console.log(result));
// Expected hash for +18005551212:
// YdkRG+0+bZz8G8O1yzWkAmh8TxVGvuBhor1ET73WTEQ=
hash('+18005551212').then(result => console.log(result));
// Expected hash for John: ltljLzY1ZMwwMlIUCc8iqFLyAy7sCZ7VlnwNAAzsYHo=
hash('John').then(result => console.log(result));
// Expected hash for Doe: eZ75KhGvkY4/t0HfQpNPO1aO0tk6wd908bjUGieTKm8=
hash('Doe').then(result => console.log(result));
}
main()
Python
"""Provides the hashing algorithm, as well as some valid hashes of sample data for testing.
Supports: Python 2, Python 3
Sample hashes:
- Email 'test@gmail.com': h5JGBrQTGorO7q6IaFMfu5cSqqB6XTp1aybOD11spnQ=
- Phone '+18005551212': YdkRG+0+bZz8G8O1yzWkAmh8TxVGvuBhor1ET73WTEQ=
- First name 'John': ltljLzY1ZMwwMlIUCc8iqFLyAy7sCZ7VlnwNAAzsYHo=
- Last name 'Doe': eZ75KhGvkY4/t0HfQpNPO1aO0tk6wd908bjUGieTKm8=
"""
import base64
import hashlib
def hash(token):
# Generates a base64-encoded SHA-256 hash of a normalized input string.
return base64.b64encode(
hashlib.sha256(
token.strip().lower().encode('utf-8')).digest()).decode('utf-8')
def print_hash(token, expected=None):
# Computes and displays the hash of a token, with optional validation.
hashed = hash(token)
if expected is not None and hashed != expected:
print(
'ERROR: Incorrect hash for token "{}". Expected "{}", got "{}"'.format(
token, expected, hashed))
return
print('Hash: "{}"\t(Token: {})'.format(hashed, token))
def main():
# Tests the hash function with sample tokens and expected results.
print_hash(
'test@gmail.com', expected='h5JGBrQTGorO7q6IaFMfu5cSqqB6XTp1aybOD11spnQ=')
print_hash(
'+18005551212', expected='YdkRG+0+bZz8G8O1yzWkAmh8TxVGvuBhor1ET73WTEQ=')
print_hash('John', expected='ltljLzY1ZMwwMlIUCc8iqFLyAy7sCZ7VlnwNAAzsYHo=')
print_hash('Doe', expected='eZ75KhGvkY4/t0HfQpNPO1aO0tk6wd908bjUGieTKm8=')
if __name__ == '__main__':
main()
Go
/*
Provides the hashing algorithm, as well as some valid hashes of sample data for testing.
Sample hashes:
- Email 'test@gmail.com': h5JGBrQTGorO7q6IaFMfu5cSqqB6XTp1aybOD11spnQ=
- Phone '+18005551212': YdkRG+0+bZz8G8O1yzWkAmh8TxVGvuBhor1ET73WTEQ=
- First name 'John': ltljLzY1ZMwwMlIUCc8iqFLyAy7sCZ7VlnwNAAzsYHo=
- Last name 'Doe': eZ75KhGvkY4/t0HfQpNPO1aO0tk6wd908bjUGieTKm8=
*/
package main
import (
"crypto/sha256"
"encoding/base64"
"fmt"
"strings"
)
// Hash hashes an email, phone, first name, or last name into the correct format.
func Hash(token string) string {
formatted := strings.TrimSpace(strings.ToLower(token))
hashed := sha256.Sum256([]byte(formatted))
encoded := base64.StdEncoding.EncodeToString(hashed[:])
return encoded
}
// PrintHash prints the hash for a token.
func PrintHash(token string) {
fmt.Printf("Hash: \"%s\"\t(Token: %s)\n", Hash(token), token)
}
func main() {
PrintHash("test@gmail.com")
PrintHash("+18005551212")
PrintHash("John")
PrintHash("Doe")
}
Java
package updm.hashing;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
/**
* Example of the hashing algorithm.
*
* <p>Sample hashes:
*
* <ul>
* <li>Email 'test@gmail.com': h5JGBrQTGorO7q6IaFMfu5cSqqB6XTp1aybOD11spnQ=
* <li>Phone '+18005551212': YdkRG+0+bZz8G8O1yzWkAmh8TxVGvuBhor1ET73WTEQ=
* <li>First name 'John': ltljLzY1ZMwwMlIUCc8iqFLyAy7sCZ7VlnwNAAzsYHo=
* <li>Last name 'Doe': eZ75KhGvkY4/t0HfQpNPO1aO0tk6wd908bjUGieTKm8=
* </ul>
*/
public final class HashExample {
private HashExample() {}
public static String hash(String token) {
// Normalizes and hashes the input token using SHA-256 and Base64 encoding.
String formattedToken = token.toLowerCase().strip();
byte[] hash;
try {
hash = MessageDigest.getInstance("SHA-256").digest(formattedToken.getBytes(UTF_8));
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("SHA-256 not supported", e);
}
return Base64.getEncoder().encodeToString(hash);
}
public static void printHash(String token) {
// Calculates and prints the hash for the given token.
System.out.printf("Hash: \"%s\"\t(Token: %s)\n", hash(token), token);
}
public static void main(String[] args) {
// Executes hash calculations and prints results for sample tokens.
printHash("test@gmail.com");
printHash("+18005551212");
printHash("John");
printHash("Doe");
}
}
SQL
/*
Provides the hashing algorithm, as well as some valid hashes of sample data for testing.
The following code uses Google Standard SQL and can be run on BigQuery to generate match tables from unhashed data.
Sample hashes:
- Email 'test@gmail.com': h5JGBrQTGorO7q6IaFMfu5cSqqB6XTp1aybOD11spnQ=
- Phone '+18005551212': YdkRG+0+bZz8G8O1yzWkAmh8TxVGvuBhor1ET73WTEQ=
- First name 'John': ltljLzY1ZMwwMlIUCc8iqFLyAy7sCZ7VlnwNAAzsYHo=
- Last name 'Doe': eZ75KhGvkY4/t0HfQpNPO1aO0tk6wd908bjUGieTKm8=
The unhashed input table schema is assumed to be:
- Column name: UserID, Type: String
- Column name: Email, Type: String
- Column name: Phone, Type: String
- Column name: FirstName, Type: String
- Column name: LastName, Type: String
- Column name: PostalCode, Type: String
- Column name: CountryCode, Type: String
*/
-- Creates a new table with Base64-encoded SHA-256 hashes of specified columns.
CREATE TABLE `your_project_name.your_dataset_name.output_hashed_table_name`
AS
SELECT
UserID,
TO_BASE64(SHA256(LOWER(Email))) AS Email,
TO_BASE64(SHA256(Phone)) AS Phone,
TO_BASE64(SHA256(LOWER(FirstName))) AS FirstName,
TO_BASE64(SHA256(LOWER(LastName))) AS LastName,
PostalCode,
CountryCode,
FROM
`your_project_name.your_dataset_name.input_unhashed_table_name`;
加入鍵值
有些使用者提供的資料組合比其他組合更有效。以下列出不同使用者提供資料的組合,並依相對強度排序。如果使用地址,必須包含:名字、姓氏、國家/地區和郵遞區號。
- 電子郵件、電話、地址 (最強)
- 電話、地址
- 電子郵件地址、地址
- 電子郵件、電話
- 地址
- 電話
- 電子郵件 (最弱)
建立對照表
依序點選「報表」>「建立報表」>「生成私有雲比對表」>「使用範本」 選用:如果資料尚未經過雜湊處理,可以選取「生成私有雲比對表 (進行雜湊處理)」。
// Create a new match table using your first party data with this template. /* Parameters: Manually remove all the parameters tagged with @ prefix and replace them with column names from your first party table: * @user_id * @email * @phone * @first_name * @last_name * @country_code * @postal_code And your BigQuery table information: * @my_project: Your BigQuery project where the first party table is. * @my_dataset: Your dataset where the first party table is. * @my_first_party_table: Your first party table. */ CREATE OR REPLACE TABLE adh.updm_match_table AS ( SELECT CAST(@user_id AS BYTES) AS user_id, @email AS email, @phone AS phone, @first_name AS first_name, @last_name AS last_name, @country_code AS country, @postal_code AS zip_code FROM `@my_project.@my_dataset.@my_first_party_table` );
將參數名稱替換為資料欄名稱,以提供適當的別名。
按一下「設定時間表」,設定要重新整理比對表的頻率。每次執行都會覆寫目前的相符資料表。
查詢相符資料
查詢對照表
如果對照表包含足夠的資料,可以滿足隱私權檢查的條件,您就能針對資料表執行查詢。
第一方資料 (1PD) 的原始資料表以 my_data
表示。
包括個人識別資訊 (PII) 和非 PII 資料。
與比對表相比,原始表格代表範圍內的所有第一方資料,因此使用原始表格可提供更多洞察資料,進而改善報表。
廣告資料中心結構定義中,每個包含 user_id
欄位的資料表,都會附帶一個對照表。以 adh.google_ads_impressions
資料表為例,廣告資料中心會產生名為 adh.google_ads_impressions_updm
的對照表,其中包含 User-ID。如果是政策排除聯播網資料表,系統會建立個別的對照表。舉例來說,廣告資料中心也會為 adh.google_ads_impressions_policy_isolated_network
資料表,產生名為 adh.google_ads_impressions_policy_isolated_network_updm
的對照表,其中包含 User-ID。
這些資料表包含原始資料表的一部分使用者,user_id
會有相符項目。舉例來說,如果原始資料表包含使用者 A 和使用者 B 的資料,但只有使用者 A 成功比對,那麼使用者 B 就不會出現在對照表。
對照表包含另一個名為 customer_data_user_id
的資料欄,該欄會以位元組形式儲存使用者 ID。
編寫查詢時,請務必考慮欄位的類型。SQL 比較運算子會認為您要比較的常值類型相同。視第一方資料表儲存 user_id
的方式而定,您可能需要先為資料表中的值編碼,才能比對資料。您必須將彙整鍵轉換為位元組,才能成功比對:
JOIN ON
adh.google_ads_impressions_updm.customer_data_user_id = CAST(my_data.user_id AS BYTES)
另外,在 SQL 中比較字串時會區分大小寫,因此您可能需要為比較兩方的字串編碼來提高比較準確度。
查詢範例
計算相符使用者數
這項查詢會計算 Google Ads 曝光次數表格中比對成功的使用者人數。
/* Count matched users in Google Ads impressions table */
SELECT COUNT(DISTINCT user_id)
FROM adh.google_ads_impressions_updm
計算媒合率
並非所有使用者都符合比對資格。舉例來說,系統不會透過 UPDM 比對已登出使用者、兒童和未同意的使用者。您可以使用 is_updm_eligible
欄位,計算更準確的「比對使用者提供的資料」媒合率。請注意,is_updm_eligible
欄位自 2024 年 10 月 1 日起開放使用。您無法使用這個欄位計算該日期前的比對率。
/* Calculate the UPDM match rate */
CREATE TEMP TABLE total_events OPTIONS(privacy_checked_export=TRUE) AS
SELECT
customer_id,
COUNT(*) AS n
FROM adh.google_ads_impressions
WHERE is_updm_eligible
GROUP BY 1;
CREATE TEMP TABLE matched_events OPTIONS(privacy_checked_export=TRUE) AS
SELECT
customer_id,
COUNT(*) AS n
FROM adh.google_ads_impressions_updm
GROUP BY 1;
SELECT
customer_id,
SAFE_DIVIDE(matched_events.n, total_events.n) AS match_rate
FROM total_events
LEFT JOIN matched_events
USING (customer_id)
彙整第一方資料和 Google Ads 資料
這項查詢會顯示如何彙整第一方資料與 Google Ads 資料:
/* Join first-party data with Google Ads data. The customer_data_user_id field
contains your ID as BYTES. You need to cast your join key into BYTES for
successful matches. */
SELECT
inventory_type,
COUNT(*) AS impressions
FROM
adh.yt_reserve_impressions_updm AS google_data_imp
LEFT JOIN
`my_data`
ON
google_data_imp.customer_data_user_id = CAST(my_data.user_id AS BYTES)
GROUP BY
inventory_type
UPDM 常見問題
如需 UPDM 相關常見問題清單,請參閱 UPDM 常見問題。