用户提供的数据匹配

用户提供的数据匹配 (UPDM) 功能会将您收集的关于用户的第一方数据(例如来自您的网站、应用或实体店的信息)与该用户在所有 Google 广告数据(包括 Google 自有自营数据)中的登录活动合并。这包括通过 Google Marketing Platform (GMP) 产品购买的数据,例如使用 Display & Video 360 购买的 YouTube 广告资源。不支持非 Google 自有自营的其他 GMP 产品。

若要使用用户提供的数据匹配这一功能,广告事件必须与 Google 广告数据涉及的已登录用户相关联。

本文档介绍了用户提供的数据匹配功能,并提供了设置和使用指南。

私有云匹配概览

若要获得有价值的广告数据洞见,通常需要将来自多个来源的数据拼接在一起。自行构建解决方案来解决此数据流水线问题需要投入大量时间和工程资源。广告数据中心内的 Private Cloud Match 简化了此流程,它提供了一个广告数据中心查询模板,用于在 BigQuery 中创建匹配表,然后您可以在广告数据中心查询中使用该表,将广告数据与第一方数据进行匹配。使用第一方数据丰富查询可以带来更丰富的客户体验,并且更能抵御整个行业的广告跟踪更改。

由于用户提供的数据匹配功能仅适用于 Google 自有自营广告资源中已登录的用户,因此不受即将弃用第三方 Cookie 的影响。由于第一方数据比第三方数据更能抵御行业变化,因此可以提供更丰富的洞见,从而提高客户互动度。

流程摘要

  1. 设置数据注入和匹配
    • 您:确保您的第一方数据位于 BigQuery 中,并且您的服务账号对其具有读取权限。请参阅设置数据注入。
  2. 第一方数据注入和匹配
    • 您设置第一方数据的格式,并将其上传到 BigQuery 数据集。
    • 您通过创建私有云 Match 分析查询 并设置时间表来发起数据匹配请求。
    • Google 会将您的项目中的数据与 Google 拥有的数据(包含 Google 的用户 ID 和经过哈希处理的用户提供的数据)进行联接,以构建和更新匹配表。
    • 请参阅注入第一方数据
  3. 在广告数据中心内基于匹配的数据持续运行查询
    • 您可以像在广告数据中心内运行常规查询一样,针对匹配表运行查询。请参阅查询匹配的数据。

了解隐私权要求

收集客户数据

使用用户提供的数据匹配功能时,您必须上传第一方数据。这些信息可能是您通过自己的网站、应用和实体店收集的信息,也可能是客户直接与您分享的任何信息。

您必须:

  • 确保您的隐私权政策如实披露:您会与第三方分享客户数据,以便第三方代您提供服务;在法律有相应要求的情况下,您会在进行此类分享前先征得客户同意
  • 仅使用 Google 批准的 API 或界面来上传客户数据
  • 遵守所有适用的法律法规,包括所有适用的自我监管条例或行业准则

确认第一方用户同意情况

为确保您能够在广告数据中心内使用第一方数据,您必须确认您已根据欧盟地区用户意见征求政策和广告数据中心政策征得用户同意,可以与 Google 共享 EEA 最终用户的数据。此要求适用于每个广告数据中心账号,且每次上传新的第一方数据时都必须更新意见征求结果。任何一个用户都可以代表整个账号进行这项确认。

请注意,适用于分析查询的 Google 服务查询规则,同样也适用于 UPDM 查询。例如,创建匹配表时,您不能对欧洲经济区 (EEA) 境内用户运行跨服务查询。

若要了解如何在广告数据中心内确认用户同意情况,请参阅欧洲经济区用户意见征求要求。

数据大小

为保护最终用户隐私,用户提供的数据匹配功能会强制执行以下有关数据大小的要求:

  • 您必须在用户名单中上传至少 1,000 条记录。

设置数据注入

开始之前,请确保:

  • 您的第一方数据必须位于 BigQuery 中。如果您有 VPC-SC 边界,则此第一方数据必须位于 VPC-SC 内。
  • 您的广告数据中心服务账号必须对第一方数据具有读取权限。
  • 您的第一方数据必须经过正确格式化和哈希处理。如需了解详情,请参阅下一部分。

除此之外,Private Cloud Match 无需进行其他初始配置。如果您可以运行分析查询,则可以运行 Private Cloud Match 查询。

提取和匹配第一方数据

源权限和连接要求

广告数据中心连接使用设置 > 详细信息 > 服务账号下显示的服务账号(通常为 service-<number>@gcp-sa-adsdatahub.iam.gserviceaccount.com)。请向其授予以下角色:

  • BigQuery 来源:针对源数据集或表的 roles/bigquery.dataViewer (BigQuery 数据视图)。
  • Cloud Storage 来源:来源存储桶或对象上的 roles/storage.objectViewer(Storage Object Viewer)。
  • 第一方数据导入目标位置:如果表不在默认数据集中,则需要目标数据集的 roles/bigquery.dataEditor(BigQuery Data Editor)角色。

字段和数据类型要求

  1. 用户提供的数据匹配 (UPDM):
    • 映射 user_id 以及至少一个 PII 字段(email、phone或完整地址:first_name、last_name、country、zip_code)。
    • user_id、country 和 zip_code:纯文本 STRING(未经过哈希处理)。 对于 BigQuery 来源,这些列必须已经是 STRING;其他类型(例如 INT64)在创建连接时会失败。Connections 会在匹配表中将 user_id 转换为 BYTES。country 必须是双字母 ISO 3166-1 alpha-2 代码。
    • email、phone、first_name 和 last_name:HASH - 必须已经过 SHA-256 哈希处理和 Base64 编码(也接受 64 个字符的十六进制 SHA-256 值)。Connections 不会对数据进行哈希处理。创建连接时,系统不会捕获纯文本值;然后,每次运行都会失败,并显示 ... must be encoded using TO_BASE64(SHA256(...))。
    • 用户提供的数据匹配连接没有目标表。账号中的所有这些查询以及手动运行的 UPDM 查询都会写入相同的匹配数据,因此每次运行都会替换上一次运行的结果。每个账号只需一个 UPDM 连接。
    • 如需了解每个字段的规则,请参阅设置输入数据的格式。
  2. 第一方数据导入:
    • 仅使用界面中提供的数据类型:INTEGER、STRING、HASH、DOUBLE、DATE 和 TIMESTAMP。不支持其他 BigQuery 类型。
    • BigQuery 来源:不应用映射的类型;每个目标列都会保留其来源列的类型。
    • Cloud Storage 来源:列会作为 STRING 读取,并转换为映射的类型。无法转换的值会变为 NULL,而不会导致运行失败。
    • 每次运行都会替换整个目标表,而不是附加数据。如果来源没有行,则目标位置将变为空。请勿将源表或需要保留其数据的表用作目标表。

Cloud Storage CSV 列要求

  • 添加标题行。第一行会被跳过,其列名称不会被使用。
  • 该文件必须恰好包含映射的源列,不能多也不能少。多余的列会导致运行失败。
  • 第一方数据导入:列的顺序必须与字段映射的顺序相同。
  • 用户提供的数据匹配:列必须按以下顺序排列,仅保留您映射的字段:user_id、email、phone、first_name、last_name、country、zip_code。映射行的顺序无关紧要。
  • 系统不会检测到列顺序不同:值会加载到错误的字段中(或匹配率下降),而不会报错。

支持的数据源和连接限制

  • 数据源:仅支持 BigQuery 和 Cloud Storage 来源。
  • BigQuery 表名称:源 BigQuery 表和目标 BigQuery 表需要完整的 project.dataset.table 名称。
  • Cloud Storage 文件路径:提供单个文件 URI(例如 gs://bucket/path/file.csv)。不支持包含 * 或 ? 的通配符路径。
  • 连接名称:账号中的每个连接都必须具有唯一的名称。

设置输入数据的格式

您的数据必须符合以下格式要求,才能正确匹配:

  • 在以下输入字段说明中指明的位置,您必须使用 SHA256 哈希算法进行上传。
  • UPDM 支持 Base64 编码。请参阅 TO_BASE64。
  • 输入字段必须采用字符串格式。例如,如果您使用的是 BigQuery SHA256 哈希函数,请使用以下转换:TO_BASE64(SHA256(user_data))。

用户 ID

  • 数据类型:BYTES
  • 哈希处理:无

电子邮件

  • 移除开头和结尾处的空格
  • 所有字符均须采用小写格式
  • 所有邮箱都必须包含域名,例如 gmail.com 或 hotmail.co.jp
  • 移除重音符号,例如将 è、é、ê 或 ë 更改为 e
  • 移除 gmail.com 和 googlemail.com 邮箱中域名前面的所有句点 (.)
  • 哈希处理:Base64 编码的 SHA256

有效期: TO_BASE64(SHA256("jeffersonloveshiking@gmail.com"))

无效: TO_BASE64(SHA256("JéffersonLôvesHiking@gmail.com"))

电话

  • 去除空格
  • 采用 E.164 格式,例如:美国示例:+14155552671,英国示例:+442071838750
  • 移除国家/地区代码前的所有特殊字符(“+”除外)
  • 哈希处理:Base64 编码的 SHA256

有效期: TO_BASE64(SHA256("+18005550101"))

无效: TO_BASE64(SHA256("(800) 555-0101"))

名字

  • 去除空格
  • 所有字符均须采用小写格式
  • 移除所有前缀,例如“Mrs.”、Mr., Ms., 博士
  • 请勿移除重音符号,例如 è、é、ê 或 ë
  • 哈希处理:Base64 编码的 SHA256

有效期: TO_BASE64(SHA256("daní"))

无效: TO_BASE64(SHA256("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`;

联接键

某些用户提供的数据组合比其他组合更有效。以下是不同用户提供的数据组合的列表,按相对强度排序。如果您使用地址,则必须包含:名字、姓氏、国家/地区和邮政编码。

  1. 邮箱、电话、地址(最强)
  2. 电话、地址
  3. 邮箱、地址
  4. 电子邮件、电话
  5. 地址
  6. 电话
  7. 电子邮件(最弱)

创建匹配表

  1. 点击 add 创建 > 查询。
  2. 复制生成私有云匹配表查询模板,并将其粘贴到查询编辑器中。可选:如果您的数据尚未经过哈希处理,您可以使用生成私有云匹配表(进行哈希处理)模板。

    /* Private cloud match table generation
    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`
    );
    
    /* Private cloud match table generation (with hashing)
    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,
          TO_BASE64(SHA256(LOWER(@email))) AS email,
          TO_BASE64(SHA256(@phone)) AS phone,
          TO_BASE64(SHA256(LOWER(@first_name))) AS first_name,
          TO_BASE64(SHA256(LOWER(@last_name))) AS last_name,
          @country_code AS country,
          @postal_code AS zip_code
    FROM `@my_project.@my_dataset.@my_first_party_table`
    );
    
  3. 将参数名称替换为您的列名称,以提供正确的别名。

  4. 点击保存

  5. 点击运行。您需要手动运行此查询来刷新匹配表。每次运行都会覆盖当前的匹配表。

迁移现有连接

连接标签页中的现有连接将迁移到直接内置于广告数据中心内的更新版连接体验。更新后的连接会使用设置 > 详细信息 > 服务账号下显示的服务账号(通常为 service-<number>@gcp-sa-adsdatahub.iam.gserviceaccount.com)读取来源和写入目标,而不是使用旧版 Data Fusion、Dataproc 和 UPDM 服务账号。

请在连接迁移之前完成以下待办项:

  1. 授予服务账号权限:向设置 > 详细信息 > 服务账号下显示的服务账号(通常为 service-<number>@gcp-sa-adsdatahub.iam.gserviceaccount.com)授予所需的来源和目标角色(roles/bigquery.dataViewer、roles/storage.objectViewer 和非默认目标数据集上的 roles/bigquery.dataEditor)。具有不可读、已删除或已更改来源的连接可能仍会移动(尤其是 Cloud Storage 来源,在移动时不会进行验证),但运行会失败,直到您授予访问权限或修复来源。
  2. 转换不受支持的连接:具有以下配置的连接不会迁移。请将其转换为受支持的 BigQuery 或 Cloud Storage 连接:
    • 其他数据源(Amazon S3、Snowflake、MySQL、PostgreSQL、Amazon Redshift、sFTP 或 Salesforce):先将数据暂存在 BigQuery 或 Cloud Storage 中,然后创建 BigQuery 或 Cloud Storage 连接。
    • 不支持的字段映射或数据类型:更新或重新创建连接,以满足字段和数据类型要求。
    • Cloud Storage 通配符路径(* 或 ?):将通配符 URI 替换为单个文件 URI,或先将文件加载到 BigQuery 中。
    • 连接名称重复:重命名或删除重复的连接,确保账号中的每个连接都有唯一的名称。
  3. 删除未使用的连接:删除您不再需要的过时连接。

查询匹配的数据

查询匹配表

如果匹配表包含的数据足以满足隐私权检查要求,就可以针对该表运行查询。

第一方数据 (1PD) 的原始表由 my_data 表示。 这包括个人身份信息 (PII) 和非 PII 数据。 与匹配表相比,使用原始表可以提供更多数据洞见,从而改进报告,因为它代表了范围内的所有第一方数据。

广告数据中心架构中包含 user_id 字段的每个表都附带一个匹配表。例如,对于 adh.google_ads_impressions 表,广告数据中心还会生成一个名为 adh.google_ads_impressions_updm 的匹配表,其中包含您的用户 ID。 对于因政策而隔离的网络表,系统会创建单独的匹配表。例如,对于 adh.google_ads_impressions_policy_isolated_network 表,广告数据中心还会生成一个名为 adh.google_ads_impressions_policy_isolated_network_updm 的匹配表,其中包含您的用户 ID。

这些表都包含原始表中在 user_id 方面匹配的一部分用户。例如,如果原始表包含用户 A 和用户 B 的数据,但只有用户 A 是匹配项,那么用户 B 将不会出现在匹配表中。

匹配表包含一个额外的列,名为 customer_data_user_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 字段来计算更准确的 UPDM 匹配率。请注意,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 常见问题解答。