התאמה לפרטים שהמשתמשים סיפקו (UPDM)

התכונה 'התאמה לפרטים שהמשתמשים סיפקו' (UPDM) מאפשרת לצרף את הנתונים מאינטראקציה ישירה (First-Party) שנאספו לגבי משתמש – כמו מידע מהאתרים, מהאפליקציות או מהחנויות הפיזיות – לפעילות של אותו המשתמש המחובר, שנאספה בנתוני מודעות ממוצרי Google, כולל נתונים ממוצרי Google בבעלותה ובניהולה. הנתונים האלה כוללים נתונים שנרכשו דרך מוצרי Google Marketing Platform‏ (GMP), לדוגמה, נתונים מ-YouTube שנרכשו באמצעות Display & Video 360. אין תמיכה במוצרים אחרים של GMP שלא נמצאים בבעלות של Google ולא מופעלים על ידה.

כדי שאפשר יהיה להשתמש בהתאמה לפרטים שהמשתמשים סיפקו (UPDM), אירוע המודעה חייב להיות מקושר למשתמש מחובר בנתוני מודעות ממוצרי Google.

במאמר הזה מתוארת התכונה 'התאמת נתונים שהמשתמשים סיפקו', ומוסבר איך להגדיר אותה ואיך להשתמש בה.

סקירה כללית של הכרטיסייה 'חיבורים'

כדי לקבל תובנות חשובות לגבי הפרסום, צריך לעיתים קרובות לשלב נתונים מכמה מקורות. כדי לבנות פתרון משלכם לבעיה הזו בצינור הנתונים, צריך להשקיע זמן רב ומשאבים הנדסיים רבים. הדף 'חיבורים' ב-Ads Data Hub מייעל את התהליך הזה. הוא מספק ממשק מודרך עם הוראות שלב אחר שלב לייבוא, לשינוי ולהתאמה של נתוני המודעות ב-BigQuery, כדי שתוכלו להשתמש בהם בשאילתות שלכם ב-Ads Data Hub או בכל מוצר אחר שקורא נתונים מ-BigQuery. העשרת השאילתות בנתונים מאינטראקציה ישירה (First-Party) יכולה לשפר את חוויית הלקוחות, והיא עמידה יותר לשינויים בתחום מעקב הפרסום.

הדף 'חיבורים' מבוסס על כלים שמאפשרים להצפין ולשתף פרטים אישיים מזהים (PII) עם שותפים באופן ששומר על הפרטיות. אחרי שבוחרים את העמודות שמכילות פרטים אישיים מזהים, מערכת Ads Data Hub מצפינה את הנתונים כדי להבטיח שאפשר יהיה לייצא את הנתונים מאינטראקציה ישירה (First-Party) או לקרוא אותם רק על ידי אנשים שיש להם הרשאה לעשות זאת. יכול להיות שיהיה לכם קשה לדעת אילו נתונים מאינטראקציה ישירה נדרשים לתרחיש השימוש שלכם במדידה או בהפעלה, ולכן מערכת Ads Data Hub מספקת רשימה מקיפה של תרחישי שימוש מוגדרים מראש, ואז מדריכה אתכם בכל התהליך של חילוץ, שינוי וטעינה של הנתונים. אפשר ליצור כמה סוגים של חיבורים, אבל במאמר הזה אנחנו מניחים שאתם משתמשים בדף 'חיבורים' להתאמת פרטים שהמשתמשים סיפקו.

מקורות נתונים מאינטראקציה ישירה (First-Party) נתמכים

אפשר לייבא נתונים ממקורות הנתונים הבאים:

  • BigQuery
  • Cloud Storage
  • פרוטוקול FTP מאובטח (sFTP)
  • פתית שלג
  • MySQL
  • PostgreSQL
  • Amazon Redshift
  • Amazon S3

התאמה לפרטים שהמשתמשים סיפקו (UPDM) זמינה רק במלאי שטחי פרסום שנמצא בבעלות ובהפעלה של Google, עבור משתמשים מחוברים, ולכן היא לא מושפעת מהוצאה משימוש בעתיד של קובצי Cookie של צד שלישי. התכונה עמידה יותר לשינויים בתחום בהשוואה לנתונים מצד שלישי, ולכן היא יכולה לספק תובנות מקיפות יותר, שיכולות להוביל למעורבות גבוהה יותר מצד הלקוחות.

לומדים את המונחים

  • קישור לפרטים שהמשתמשים סיפקו: הגדרת קישור לפרטים שהמשתמשים סיפקו כדי לייבא ולהתאים את הנתונים, לתזמן ייבוא נתונים, לשנות את הנתונים ולהתאים את נתוני המודעות באמצעות מזהה משתמש. אירוע המודעה חייב להיות מקושר למשתמש מחובר בנתוני מודעות ממוצרי Google. נדרשים כמה פרויקטים ב-Google Cloud.
  • חיבור לנתונים מאינטראקציה ישירה: אפשר להגדיר חיבור לנתונים מאינטראקציה ישירה ככלי להכנת נתונים, כדי לתזמן ייבוא נתונים ולשנות נתונים בלי התכונות המתקדמות של UPDM. סוג החיבור הזה דורש רק פרויקט אחד ב-Google Cloud.
  • מקור נתונים: מוצר מקושר, קובץ מיובא או שילוב עם צד שלישי. למשל: BigQuery.
  • יעד: תרחיש שימוש, בדרך כלל מוצר או תכונה במוצר של Google שמופעלים בהם נתונים מיובאים. למשל: התאמה לפרטים שהמשתמשים סיפקו ב-Ads Data Hub.
  • פרויקט אדמין: פרויקט ב-Google Cloud שמכיל את נתוני הפרסום הקנייניים שלכם בפורמט הגולמי שלהם.
  • מערך נתונים של פלט: מערך הנתונים ב-BigQuery שאליו נכתב מידע מ-Ads Data Hub. כברירת מחדל, זהו מערך נתונים בפרויקט הניהול. כדי לשנות את הפרויקט לפרויקט אחר ב-Google Cloud, אפשר לעיין במאמר בנושא הגדרת חשבונות שירות.

סיכום התהליך

  1. הגדרה של הטמעת נתונים והתאמה שלהם
    • אתם מעניקים לחשבונות השירות את ההרשאות הנדרשות בפרויקט האדמין. מידע נוסף זמין במאמר בנושא הגדרת הטמעת נתונים.
  2. הטמעה והתאמה של נתונים מאינטראקציה ישירה (First-Party)
    • אתם מעצבים ומעלים את הנתונים מאינטראקציה ישירה למערך הנתונים ב-BigQuery. כדי להקל על תהליך ההגדרה, כדאי להשתמש בפרויקט האדמין. עם זאת, אתם יכולים להשתמש בכל מערך נתונים ב-BigQuery שאתם הבעלים שלו.
    • אתם יוצרים חיבור ומגדירים לוח זמנים לייבוא כדי ליזום בקשה להתאמת נתונים.
    • Google מצטרפת לנתונים בין הפרויקט שלכם לבין נתונים בבעלות Google שכוללים את מזהה המשתמש של Google ונתונים מגובבים שהמשתמשים סיפקו, כדי ליצור ולעדכן טבלאות התאמה.
    • איך מעבירים נתונים מאינטראקציה ישירה
  3. שאילתות שמתבצעות באופן שוטף ב-Ads Data Hub, על סמך נתונים שתואמים

מידע על דרישות הפרטיות

איסוף נתוני לקוחות

כשמשתמשים בהתאמה לנתונים שהמשתמשים סיפקו, צריך להעלות נתונים מאינטראקציה ישירה (First-Party). למשל: מידע שאספתם מהאתרים, מהאפליקציות או מהחנויות הפיזיות שלכם, או מידע שהלקוחות שיתפו איתכם ישירות במצבים אחרים.

פעולות שצריך לבצע:

  • לוודא שמדיניות הפרטיות שלכם כוללת גילוי נאות על כך שאתם משתפים את נתוני הלקוחות עם צדדים שלישיים כדי שיספקו שירותים מטעמכם, ולבקש את הסכמת הלקוחות לשיתופים האלה כנדרש על פי חוק
  • להשתמש רק בממשק או ב-API שאושרו על ידי Google כדי להעלות נתוני לקוחות
  • לפעול בהתאם לכל התקנות והחוקים החלים, כולל כללים לרגולציה עצמית או כללים הנהוגים בתחום, אם חלים כאלו

אישור הסכמה מאינטראקציה ישירה

כדי לוודא שתוכלו להשתמש בנתונים מאינטראקציה ישירה (First-Party) ב-Ads Data Hub, אתם צריכים לאשר שקיבלתם הסכמה מתאימה לשיתוף נתונים ממשתמשי קצה באזור הכלכלי האירופי (EEA) עם Google בהתאם למדיניות Google בנושא הסכמת משתמשים באיחוד האירופי ולמדיניות של Ads Data Hub. הדרישה הזו חלה על כל חשבון ב-Ads Data Hub, וצריך לעדכן את ההסכמה בכל פעם שמעלים נתונים חדשים מאינטראקציה ישירה. כל משתמש יכול לאשר את ההסכמה הזו בשם כל החשבון.

שימו לב שכללי השאילתות של שירות Google שחלים על שאילתות ניתוח חלים גם על שאילתות של UPDM. לדוגמה, אי אפשר להריץ שאילתות בין שירותים על משתמשים באזור הכלכלי האירופי כשיוצרים טבלת התאמה.

במאמר דרישות לקבלת הסכמה באזור הכלכלי האירופי מוסבר איך לציין את הסכמת המשתמשים ב-Ads Data Hub.

גודל הנתונים

כדי להגן על פרטיות משתמשי הקצה, התאמה של פרטים שהמשתמשים סיפקו מחייבת אתכם לעמוד בדרישות הבאות לגבי גודל הנתונים:

  • צריך להעלות לפחות 1,000 רשומות לרשימת המשתמשים.
  • כל עדכון מוצלח של טבלת ההתאמות חייב לכלול מספר מינימלי של משתמשים חדשים שהותאמו. ההתנהגות הזו דומה לבדיקות של הבדלים.
  • המספר המקסימלי של רשומות ברשימה הוא 10,000. כדי לקבל מידע על מגבלת הנתונים המקסימלית, אפשר לפנות לנציג Google.

הגדרה של העברת נתונים

לפני שמתחילים, צריך להגדיר את חשבון Ads Data Hub כדי ליצור חיבורי נתונים. כך תוכלו ליצור את צינור הנתונים להתאמת נתונים. צריך לבצע את השלבים פעם אחת בלבד.

בדף חיבורים, לוחצים על התחלת ההגדרה כדי לפתוח את אשף הגדרת החשבון בשלב ההפעלה של UPDM.

כניסה אל חיבורים

אילו הרשאות ניתנות ל-BigQuery ול-Cloud Storage?

אם הגדרתם את UPDM לשימוש עם BigQuery או Cloud Storage, תוכלו להיעזר בהפניה הזו כדי להבין את ההרשאות שניתנות לחשבונות השירות של Ads Data Hub.

BigQuery

חשבון שירות Datafusion
מטרה חשבון השירות ב-Data Fusion משמש להצגת רשימה של שדות המקור בממשק המשתמש של Ads Data Hub.
פורמט service-some-number@gcp-sa-datafusion.iam.gserviceaccount.com
הגישה הנדרשת
BigQuery Data Viewer
roles/bigquery.dataViewer
למערכי נתונים ספציפיים בפרויקטים של מקור נתונים ויעד
Storage Admin
roles/storage.admin
בפרויקט מקור הנתונים, או בדלי אחסון ייעודי
חשבון שירות Dataproc
מטרה חשבון השירות ב-Dataproc אחראי להפעלת צינורות הנתונים ברקע.
פורמט some-number-compute@developer.gserviceaccount.com
הגישה הנדרשת
BigQuery Data Viewer
roles/bigquery.dataViewer
למערכי נתונים ספציפיים בפרויקטים של מקור נתונים ויעד
BigQuery Data Editor
roles/bigquery.dataEditor
למערכי נתונים ספציפיים בפרויקט יעד
BigQuery Job User
roles/bigquery.jobUser
גם בפרויקט מקור הנתונים וגם בפרויקט היעד
Storage Admin
roles/storage.admin
גם בפרויקט מקור הנתונים וגם בפרויקט היעד, או בקטגוריית אחסון ייעודית
חשבון שירות של UPDM
מטרה חשבון השירות של UPDM משמש להפעלת משימת ההתאמה.
פורמט service-some-number@gcp-sa-adsdataconnector.iam.gserviceaccount.com
הגישה הנדרשת
BigQuery Data Viewer
roles/bigquery.dataViewer
בפרויקט יעד
BigQuery Job User
roles/bigquery.jobUser
בפרויקט יעד

Cloud Storage

חשבון שירות Datafusion
מטרה חשבון השירות ב-Data Fusion משמש להצגת רשימה של שדות המקור בממשק המשתמש של Ads Data Hub.
פורמט service-some-number@gcp-sa-datafusion.iam.gserviceaccount.com
הגישה הנדרשת
Storage Object Viewer
roles/storage.objectViewer
למאגרי אחסון ספציפיים בפרויקט מקור הנתונים
BigQuery Data Viewer
roles/bigquery.dataViewer
בפרויקט מקור הנתונים, או בדלי אחסון ייעודי
Storage Admin
roles/storage.admin
בפרויקט מקור הנתונים, או בדלי אחסון ייעודי
חשבון שירות Dataproc
מטרה חשבון השירות ב-Dataproc אחראי להפעלת צינורות הנתונים ברקע.
פורמט some-number-compute@developer.gserviceaccount.com
הגישה הנדרשת
Storage Admin
roles/storage.admin
גם בפרויקט מקור הנתונים וגם בפרויקט היעד, או בקטגוריית אחסון ייעודית
BigQuery Job User
roles/bigquery.jobUser
בפרויקט יעד
חשבון שירות של UPDM
מטרה חשבון השירות של UPDM משמש להפעלת משימת ההתאמה.
פורמט service-some-number@gcp-sa-adsdataconnector.iam.gserviceaccount.com
הגישה הנדרשת
BigQuery Data Viewer
roles/bigquery.dataViewer
בפרויקט יעד
BigQuery Job User
roles/bigquery.jobUser
בפרויקט יעד

מקורות נתונים אחרים

לא נדרש למקורות נתונים אחרים

הטמעה והתאמה של נתונים מאינטראקציה ישירה (First-Party)

עיצוב נתונים לקלט

כדי שהנתונים יותאמו בצורה נכונה, הם צריכים לעמוד בדרישות הפורמט הבאות:

  • במקומות שבהם מצוין בתיאורים של שדות הקלט הבאים, צריך להעלות באמצעות גיבוב SHA256.
  • שדות הקלט צריכים להיות בפורמט של מחרוזות. לדוגמה, אם אתם משתמשים בפונקציית הגיבוב SHA256 של BigQuery עם פונקציית הקידוד Base16‏ (TO_HEX), אתם צריכים להשתמש בהמרה הבאה: TO_HEX(SHA256(user_data)).
  • ‫UPDM תומך בקידוד Base16 ובקידוד Base64. צריך להתאים את הקידוד של הנתונים מאינטראקציה ישירה (First-Party) לקידוד שמשמש בשאילתה שלכם ב-Ads Data Hub. אם משנים את הקידוד של הנתונים מאינטראקציה ישירה (First-Party), צריך לעדכן את השאילתה ב-Ads Data Hub כדי לפענח מאותו בסיס. בדוגמאות הבאות נעשה שימוש בקידוד Base16.

מזהה המשתמש

  • טקסט רגיל
  • גיבוב (hashing): ללא

אימייל

  • הסרת רווחים לבנים בתחילת הטקסט ובסופו
  • יש להשתמש באותיות קטנות בלבד
  • כל כתובות האימייל צריכות לכלול שמות דומיינים, כמו gmail.com או hotmail.co.jp
  • הסרת סימנים דיאקריטיים – לדוגמה, שינוי של è,‏ é,‏ ê או ë ל-e
  • מסירים את כל הנקודות (.) שלפני שם הדומיין בכתובות אימייל עם הסיומות gmail.com ו-googlemail.com.
  • גיבוב: SHA256 עם קידוד Base16

בתוקף: TO_HEX(SHA256("jeffersonloveshiking@gmail.com"))

לא תקין: TO_HEX(SHA256("JéffersonLôvesHiking@gmail.com"))

טלפון

  • הסרת רווחים לבנים
  • הפורמט צריך להיות E.164. לדוגמה, בארה"ב: ‎+14155552671, בבריטניה: ‎+442071838750
  • מסירים את כל התווים המיוחדים חוץ מהסימן '+' לפני קידומת המדינה
  • גיבוב: SHA256 עם קידוד Base16

בתוקף: TO_HEX(SHA256("+18005550101"))

לא תקין: TO_HEX(SHA256("(800) 555-0101"))

שם פרטי

  • הסרת רווחים לבנים
  • יש להשתמש באותיות קטנות בלבד
  • מסירים את כל התחיליות – למשל, Mrs., מר, גב', ד"ר
  • אל תסירו סימנים דיאקריטיים – לדוגמה, è,‏ é,‏ ê או ë
  • גיבוב: SHA256 עם קידוד Base16

בתוקף: TO_HEX(SHA256("daní"))

לא תקין: TO_HEX(SHA256("Daní"))

שם משפחה

  • הסרת רווחים לבנים
  • יש להשתמש באותיות קטנות בלבד
  • הסרת כל הסיומות – למשל Jr., Sr., ‫2nd, ‏ 3rd, ‏ II, ‏ III, ‏ PHD, ‏ MD
  • אל תסירו סימנים דיאקריטיים – לדוגמה, è,‏ é,‏ ê או ë
  • גיבוב: SHA256 עם קידוד Base16

בתוקף: TO_HEX(SHA256("delacruz"))

לא תקין: TO_HEX(SHA256("de la Cruz, Jr."))

מדינה

  • צריך לכלול את קוד המדינה גם אם כל נתוני הלקוחות הם מאותה מדינה.
  • אין לבצע גיבוב (hash) של נתוני המדינה
  • צריך להשתמש בקודי מדינה בפורמט ISO 3166-1 alpha-2
  • גיבוב (hashing): ללא

בתוקף: US

לא תקין: United States of America או USA

מיקוד

  • אין לבצע גיבוב של נתוני המיקוד
  • אפשר להזין מיקוד של ארה"ב וגם של מדינות אחרות
  • בארה"ב:
    • מותר להזין מיקוד בן 5 ספרות – לדוגמה, 94043
    • מותר גם להזין מיקוד בן 5 ספרות עם תוספת של 4 ספרות – לדוגמה, 94043-1351 או 940431351
  • בכל שאר המדינות:
    • אין צורך בפורמט (אין צורך להשתמש באותיות קטנות או להסיר רווחים ותווים מיוחדים)
    • אין לכלול תוספות למיקוד
  • גיבוב (hashing): ללא

אימות גיבוב וקידוד נתונים

אפשר להשתמש בסקריפטים הבאים לאימות גיבוב כדי לוודא שהפורמט של הנתונים נכון.

JavaScript

Base16

/**
 * @fileoverview Provides the hashing algorithm for User-Provided Data Match, 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 hashArrayBuffer = await crypto.subtle.digest(
      'SHA-256', (new TextEncoder()).encode(formattedToken));
  // Converts the hash buffer to a hexadecimal string.
  return Array.from(new Uint8Array(hashArrayBuffer))
      .map((b) => b.toString(16).padStart(2, '0'))
      .join('');
}

function main() {
  // Expected hash for test@gmail.com:
  // 87924606b4131a8aceeeae8868531fbb9712aaa07a5d3a756b26ce0f5d6ca674
  hash('test@gmail.com').then(result => console.log(result));

  // Expected hash for +18005551212:
  // 61d9111bed3e6d9cfc1bc3b5cb35a402687c4f1546bee061a2bd444fbdd64c44
  hash('+18005551212').then(result => console.log(result));

  // Expected hash for John:
  // 96d9632f363564cc3032521409cf22a852f2032eec099ed5967c0d000cec607a
  hash('John').then(result => console.log(result));

  // Expected hash for Doe:
  // 799ef92a11af918e3fb741df42934f3b568ed2d93ac1df74f1b8d41a27932a6f
  hash('Doe').then(result => console.log(result));
}

main()

Base64

/**
 * @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

Base16

"""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': 87924606b4131a8aceeeae8868531fbb9712aaa07a5d3a756b26ce0f5d6ca674
  - Phone '+18005551212':   61d9111bed3e6d9cfc1bc3b5cb35a402687c4f1546bee061a2bd444fbdd64c44
  - First name 'John':      96d9632f363564cc3032521409cf22a852f2032eec099ed5967c0d000cec607a
  - Last name 'Doe':        799ef92a11af918e3fb741df42934f3b568ed2d93ac1df74f1b8d41a27932a6f
"""

import base64
import hashlib

def updm_hash(token):
# Generates a SHA-256 hash of the input token after normalization.
  return hashlib.sha256(token.strip().lower().encode('utf-8')).hexdigest()

def print_updm_hash(token):
# Prints the SHA-256 hash and the original token.
  print('Hash: "{}"\t(Token: {})'.format(updm_hash(token), token))

def main():
# Hashes and prints sample tokens.
  print_updm_hash('test@gmail.com')
  print_updm_hash('+18005551212')
  print_updm_hash('John')
  print_updm_hash('Doe')

if __name__ == '__main__':
  main()

Base64

"""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

Base16

/*
Provides the hashing algorithm, as well as some valid hashes of sample data for testing.

Sample hashes:

  - Email 'test@gmail.com': 87924606b4131a8aceeeae8868531fbb9712aaa07a5d3a756b26ce0f5d6ca674
  - Phone '+18005551212':   61d9111bed3e6d9cfc1bc3b5cb35a402687c4f1546bee061a2bd444fbdd64c44
  - First name 'John':      96d9632f363564cc3032521409cf22a852f2032eec099ed5967c0d000cec607a
  - Last name 'Doe':        799ef92a11af918e3fb741df42934f3b568ed2d93ac1df74f1b8d41a27932a6f
*/
package main

import (
  "crypto/sha256"
  "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 := fmt.Sprintf("%x", 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")
}

Base64

/*
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

Base16

package updm.hashing;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.base.Ascii;
import com.google.common.hash.Hashing;

/**
 * Example of the UPDM hashing algorithm using hex-encoded SHA-256.
*
* <p>This uses the Guava Hashing to generate the hash: https://github.com/google/guava
*
* <p>Sample valid hashes:
*
* <ul>
*   <li>Email "test@gmail.com": "87924606b4131a8aceeeae8868531fbb9712aaa07a5d3a756b26ce0f5d6ca674"
*   <li>Phone "+18005551212": "61d9111bed3e6d9cfc1bc3b5cb35a402687c4f1546bee061a2bd444fbdd64c44"
*   <li>First name "John": "96d9632f363564cc3032521409cf22a852f2032eec099ed5967c0d000cec607a"
*   <li>Last name "Doe": "799ef92a11af918e3fb741df42934f3b568ed2d93ac1df74f1b8d41a27932a6f"
* </ul>
*/
public final class HashExample {

  private HashExample() {}

  public static String hash(String token) {
    // Normalizes and hashes the input token.
    String formattedToken = Ascii.toLowerCase(token).strip();
    return Hashing.sha256().hashString(formattedToken, UTF_8).toString();
  }

  public static void printHash(String token) {
    // Calculates and prints the token's hash.
    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");
  }
}

Base64

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

Base16

/*
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': 87924606b4131a8aceeeae8868531fbb9712aaa07a5d3a756b26ce0f5d6ca674
  - Phone '+18005551212':   61d9111bed3e6d9cfc1bc3b5cb35a402687c4f1546bee061a2bd444fbdd64c44
  - First name 'John':      96d9632f363564cc3032521409cf22a852f2032eec099ed5967c0d000cec607a
  - Last name 'Doe':        799ef92a11af918e3fb741df42934f3b568ed2d93ac1df74f1b8d41a27932a6f

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 hashed versions of specified columns from the input table.
CREATE TABLE `your_project_name.your_dataset_name.output_hashed_table_name`
AS
SELECT
  UserID,
  TO_HEX(SHA256(LOWER(Email))) AS Email,
  TO_HEX(SHA256(Phone)) AS Phone,
  TO_HEX(SHA256(LOWER(FirstName))) AS FirstName,
  TO_HEX(SHA256(LOWER(LastName))) AS LastName,
  PostalCode,
  CountryCode,
FROM
  `your_project_name.your_dataset_name.input_unhashed_table_name`;

Base64

/*
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. לוחצים על Connections (קישורים) > Create connection (יצירת קישור) > User-provided data matching (התאמה לפרטים שהמשתמשים סיפקו).
  2. בוחרים מקור נתונים ולוחצים על קישור.
  3. אם מוצגת בקשה לאימות, מבצעים את האימות ואז לוחצים על הבא:

    BigQuery

    לוחצים על 'החלה' כדי להעניק גישה ל-BigQuery.

    Cloud Storage

    לוחצים על 'אישור' כדי להעניק גישה ל-Cloud Storage.

    MySQL

    מזינים את המיקום של מסד הנתונים, היציאה, שם המשתמש והסיסמה ב-MySQL.

    S3

    מזינים את מפתח הגישה הסודי של Amazon S3.

    PostgreSQL

    מזינים את המיקום של מסד הנתונים, היציאה, שם המשתמש, הסיסמה ומסד הנתונים ב-PostgreSQL.

    Redshift

    מזינים את המיקום של מסד הנתונים, היציאה, שם המשתמש, הסיסמה ומסד הנתונים ב-Redshift.

    sFTP

    מזינים את המיקום של שרת ה-SFTP, את שם המשתמש ואת הסיסמה.

    פתית שלג

    מזינים את שם המשתמש, הסיסמה ומזהה החשבון ב-Snowflake.

  4. מגדירים את מקור הנתונים ולוחצים על הבא:

    BigQuery

    בוחרים את הטבלה ב-BigQuery לייבוא.

    Cloud Storage

    מזינים את הנתיב של gsutil, כמו gs://my-bucket/folder/ ובוחרים את הפורמט של הקובץ.

    בפעם הראשונה שמקשרים את מקור המידע, מופיעה התראה. לוחצים על 'אישור' כדי להעניק גישה, ולוחצים על 'הבא'. הערה: צריכה להיות לכם הרשאה לתת גישה ל-storage.buckets.setIamPolicy בקטגוריה הרלוונטית.

    MySQL

    בוחרים את הטבלה ומסד הנתונים ב-MySQL שבהם רוצים להשתמש.

    S3

    מזינים את ה-URI לקובץ שרוצים להעלות, ביחס לכתובת המארח.

    PostgreSQL

    מזינים את הסכימה ואת שם הטבלה (או התצוגה) מ-PostgreSQL.

    Redshift

    מזינים את שם הסכימה והטבלה (או התצוגה) ב-Redshift. כברירת מחדל, כתובות URL של מיקום מסד נתונים ב-Redshift בנויות כך: cluster-identifier.account-number.aws-region.redshift.amazonaws.com .

    sFTP

    מזינים את נתיב הקובץ והשם שלו בפורמט הבא: /PATH/FILENAME.csv

    פתית שלג

    מזינים את מסד הנתונים, הסכימה והטבלה (או התצוגה) שרוצים להשתמש בהם מ-Snowflake.

  5. בוחרים מערך נתונים ב-BigQuery שישמש כיעד ביניים ולוחצים על הבא. השלב הזה עוזר לוודא שהפורמט של הנתונים נכון.
  6. אופציונלי: משנים את הפורמט של הנתונים. טרנספורמציות כוללות חישוב גיבוב (hashing), שינוי אותיות קטנות/גדולות ומיזוג/פיצול של שדות.
    1. לוחצים על פעולה > > שינוי.
    2. בחלונית שקופצת, לוחצים על הוספת טרנספורמציה או על הוספת טרנספורמציה נוספת.
    3. בוחרים סוג טרנספורמציה מהתפריט הנפתח ומזינים את הדרישות.
    4. לוחצים על שמירה.
  7. בוחרים לפחות מפתח איחוד אחד וממפים את השדות שבהם תשתמשו. מערכת Ads Data Hub תמפה באופן אוטומטי שדות עם שמות זהים, שמסומנים ב. עורכים את השינויים הנדרשים ולוחצים על הבא.
  8. הגדרת לוח זמנים:
    1. נותנים שם לחיבור.
    2. מגדירים תדירות, שקובעת באיזו תדירות הנתונים ייובאו למערך הנתונים שבחרתם בשלב הקודם. בכל הפעלה, הנתונים בטבלת היעד יוחלפו.
    3. מציינים איך רוצים שהמערכת תטפל במקרים של התנגשויות בין מזהי משתמשים. אפשר לבחור אם לשמור את ההתאמה הקיימת או להחליף אותה בנתונים חדשים.
  9. לוחצים על סיום. בדרך כלל, אפשר להריץ שאילתות על טבלאות התאמה 12 שעות אחרי שהן נוצרות.

הצגת פרטי החיבור

בדף פרטי החיבור מוצג מידע על ההפעלות האחרונות של חיבור מסוים ועל השגיאות שקרו בו. כדי לראות את הפרטים של חיבור ספציפי:

  1. לוחצים על Connections (חיבורים).
  2. לוחצים על שם החיבור כדי לראות את הפרטים שלו.
  3. עכשיו אפשר לראות את פרטי החיבור ואת ההרצות האחרונות. בכל אחד מהם מוצגים שני סוגים אפשריים של שגיאות: שגיאות ברמת החיבור (החיבור לא פעל) ושגיאות ברמת השורה (שורה לא יובאה).
    1. הסטטוס נכשל מציין שהחיבור כולו לא הצליח לפעול (למשל, בעיה בהרשאות של חשבון שירות). לוחצים על סטטוס השגיאה כדי לראות אילו שגיאות השפיעו על החיבור.
    2. הסטטוס Completed (הושלם) מציין שהחיבור פעל בהצלחה. עם זאת, יכול להיות שעדיין יש שגיאות ברמת השורה – שמוצגות על ידי ערך שאינו אפס בעמודה 'שורות עם שגיאות'. כדי לקבל מידע נוסף על הרשומות שנכשלו, לוחצים על הערך.

עריכת חיבור

אפשר לערוך את הפרטים הבאים:

  • שם החיבור
  • תזמון
  • טבלת היעד
  • מיפוי שדות

אין תמיכה בעריכה של מקור נתונים. כדי לשנות מקור נתונים, צריך ליצור חיבור חדש ולמחוק את החיבור הישן.

כדי לערוך את פרטי החיבור:

  1. לוחצים על Connections (חיבורים).
  2. לוחצים על שם החיבור שרוצים לערוך.
  3. עורכים את הפרטים שרוצים לשנות:
    • שם החיבור: לוחצים על עריכה, מזינים את השם החדש ואז לוחצים על Enter.
    • לוח זמנים: לוחצים על עריכה, מגדירים את לוח הזמנים החדש ולוחצים על שמירה.
    • טבלת יעד: לוחצים על עריכה, מזינים את שם היעד החדש ולוחצים על שמירה.
    • מיפוי שדות: לוחצים על , מבצעים שינויים בשדות ואז לוחצים על שמירה.
  4. לוחצים על .

נתונים שתואמים לשאילתה

הרצת שאילתות על טבלאות של התאמות

אם טבלאות ההתאמה מכילות מספיק נתונים כדי לעבור את בדיקות הפרטיות, אפשר להריץ שאילתות על הטבלאות.

הטבלה המקורית של נתונים מאינטראקציה ישירה (1PD) מיוצגת על ידי my_data. הנתונים כוללים גם פרטים אישיים מזהים (PII) וגם נתונים שאינם פרטים אישיים מזהים. שימוש בטבלה המקורית יכול לשפר את הדוחות שלכם ולספק תובנות נוספות, כי היא מייצגת את כל נתוני הצד הראשון שכלולים בהיקף, בהשוואה לטבלת התאמה.

לכל טבלה בסכימה של Ads Data Hub שמכילה שדה user_id מצורפת טבלת התאמות. לדוגמה, עבור הטבלה adh.google_ads_impressions, מערכת Ads Data Hub יוצרת גם טבלת התאמה בשם adh.google_ads_impressions_updm שמכילה את מזהי המשתמשים שלכם. נוצרות טבלאות התאמה נפרדות לטבלאות רשת מבודדות לפי מדיניות. לדוגמה, עבור הטבלה adh.google_ads_impressions_policy_isolated_network, ‏ Ads Data Hub יוצר גם טבלת התאמה בשם adh.google_ads_impressions_policy_isolated_network_updm שמכילה את מזהי המשתמשים שלכם.

הטבלאות האלה מכילות קבוצת משנה של המשתמשים שזמינים בטבלאות המקוריות, שבהם יש התאמה ב-user_id. לדוגמה, אם הטבלה המקורית מכילה נתונים של משתמש א' ומשתמש ב', אבל רק משתמש א' תואם, משתמש ב' לא יופיע בטבלת ההתאמה.

טבלאות ההתאמה מכילות עמודה נוספת בשם customer_data_user_id, שבה מאוחסן מזהה המשתמש כ-BYTES.

כשכותבים שאילתות, חשוב להביא בחשבון את סוג השדה. אופרטורים להשוואה ב-SQL מצפים שהליטרלים שמשווים יהיו מאותו סוג. בהתאם לאופן שבו user_id מאוחסן בטבלה של נתונים מאינטראקציה ישירה, יכול להיות שתצטרכו לקודד את הערכים בטבלה לפני שתתאימו את הנתונים. כדי שההתאמות יתבצעו בהצלחה, צריך להמיר את מפתח ההצטרפות ל-BYTES:

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 יהיה זמין החל מ-1 באוקטובר 2024. אי אפשר להשתמש בשדה הזה כדי לחשב שיעורי התאמה לפני התאריך הזה.

/* 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)

איחוד נתונים מאינטראקציה ישירה (First-Party) ונתוני Google Ads

השאילתה הזו מדגימה איך לחבר בין נתונים מאינטראקציה ישירה (First-Party) לבין נתונים מ-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.