היסודות של API לצבירה פרטית

מושגי מפתח ב-Private Aggregation API

למי המסמך הזה מיועד?

באמצעות Private Aggregation API אפשר לאסוף נתונים נצברים מ-worklet עם גישה לנתונים מאתרים שונים. המושגים שישותפו כאן חשובים למפתחים שיוצרים פונקציות דיווח ב-Shared Storage וב-Protected Audience API.

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

מונחי מפתח

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

  • מפתח צבירה (נקרא גם קטגוריה) הוא אוסף מוגדר מראש של נקודות נתונים. לדוגמה, יכול להיות שתרצו לאסוף קטגוריה של נתוני מיקום שבה הדפדפן מדווח על שם המדינה. מפתח צבירה עשוי להכיל יותר ממאפיין אחד (לדוגמה, מדינה ומזהה של ווידג'ט התוכן).
  • ערך ניתן לצבירה הוא נקודה בודדת על הגרף שנאספת למפתח צבירה. אם אתם רוצים למדוד כמה משתמשים מצרפת ראו את התוכן שלכם, France הוא מאפיין במפתח הצבירה ו-viewCount של 1 הוא הערך המצטבר.
  • דוחות נצברים נוצרים ומוצפנים בתוך דפדפן. ב-Private Aggregation API, זה מכיל נתונים על אירוע יחיד.
  • ב-Aggregation Service מעבדים נתונים מדוחות נצברים כדי ליצור דוח סיכום.
  • דוח סיכום הוא הפלט הסופי של שירות הצבירה, והוא מכיל נתוני משתמשים נצברים רועשים ונתוני המרות מפורטים.
  • worklet הוא תשתית שמאפשרת להריץ פונקציות JavaScript ספציפיות ולהחזיר מידע למגיש הבקשה. בתוך worklet אפשר להפעיל JavaScript, אבל אי אפשר ליצור אינטראקציה עם הדף החיצוני או לתקשר איתו.

תהליך עבודה של צבירה פרטית

כשמפעילים את Private Aggregation API עם מפתח צבירה וערך מצטבר, הדפדפן יוצר דוח ניתן לצבירה. הדוחות נשלחים לשרת שלכם שמקבץ את הדוחות. הדוחות המקובעים מעובדים מאוחר יותר על ידי שירות הצבירה, ונוצר דוח סיכום.

הנתונים עוברים מהלקוח למאסוף, ואז לשירות הצבירה
    כדי ליצור דוח סיכום.
  1. כשמפעילים את Private Aggregation API, הלקוח (הדפדפן) יוצר ושולח את הדוח המצטבר לשרת שלכם לאיסוף.
  2. השרת אוסף את הדוחות מהלקוחות ומקבץ אותם כך שיישלחו אל שירות הצבירה.
  3. אחרי שאוספים מספיק דוחות, צריך לקבץ אותם ולשלוח אותם לשירות הצבירה, שפועל בסביבת ביצוע מהימנה, כדי ליצור דוח סיכום.

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

מפתח צבירה

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

לדוגמה, יכול להיות שיש לכם ווידג'ט שמוטמע בכמה אתרים ואתם רוצים לנתח את המדינה של המשתמשים שראו את הווידג'ט שלכם. ברצונך לענות על שאלות כמו "כמה מהמשתמשים שראו את הווידג'ט שלי הם ממדינה X?" כדי לדווח על השאלה הזו, תוכלו להגדיר מפתח צבירה שמקודד שני מאפיינים: מזהה ווידג'ט ומזהה מדינה.

המפתח שמסופק ל-Private Aggregation API הוא BigInt, שמורכב מכמה מאפיינים. בדוגמה זו, המאפיינים הם מזהה הווידג'ט ומזהה המדינה. נניח שמזהה הווידג'ט יכול להיות באורך של עד 4 ספרות, כמו 1234, וכל מדינה ממופה למספר בסדר אלפביתי כמו אפגניסטן הוא 1, צרפת היא 61 וזימבבואה היא '195'. לכן, המפתח המצטבר יהיה באורך 7 ספרות, כאשר 4 התווים הראשונים שמורים ל-WidgetID ו-3 התווים האחרונים שמורים ל-CountryID.

נניח שהמפתח מייצג את מספר המשתמשים מצרפת (מזהה מדינה 061) שראו את מזהה הווידג'ט 3276, מפתח הצבירה הוא 3276061.

מפתח צבירה
מזהה ווידג'ט מזהה מדינה
3276 061

אפשר ליצור את מפתח הצבירה גם באמצעות מנגנון גיבוב (hashing), כמו SHA-256. לדוגמה, אפשר לגבב את המחרוזת {"WidgetId":3276,"CountryID":67} ואז להמיר אותה לערך BigInt של 42943797454801331377966796057547478208888578253058197330928948081739249096287n. אם ערך הגיבוב כולל יותר מ-128 ביט, אפשר לחתוך אותו כדי להבטיח שהוא לא יחרוג מהערך המקסימלי המותר בקטגוריה 2^128−1.

ב-worklet של Shared Storage אפשר לגשת למודולים crypto ו-TextEncoder שיכולים לעזור לך ליצור גיבוב. מידע נוסף על יצירת גיבוב זמין במאמר SubtleCrypto.digest() ב-MDN.

בדוגמה הבאה מוסבר איך ליצור מפתח קטגוריה מערך מגובב:

async function convertToBucket(data) {
  // Encode as UTF-8 Uint8Array
  const encodedData = new TextEncoder().encode(data);

  // Generate SHA-256 hash
  const hashBuffer = await crypto.subtle.digest('SHA-256', encodedData);

  // Truncate the hash
  const truncatedHash = Array.from(new Uint8Array(hashBuffer, 0, 16));

  // Convert the byte sequence to a decimal
  return truncatedHash.reduce((acc, curr) => acc * 256n + BigInt(curr), 0n);
}

const data = {
  WidgetId: 3276,
  CountryID: 67
};

const dataString = JSON.stringify(data);
const bucket = await convertToBucket(dataString);

console.log(bucket); // 126200478277438733997751102134640640264n

ערך ניתן לצבירה

הערכים שנצברים מסוכמים לכל מפתח ממשתמשים רבים, כדי ליצור תובנות מצטברות בצורת ערכי סיכום בדוחות סיכום.

עכשיו נחזור לשאלה לדוגמה שהוצגה קודם: "כמה מהמשתמשים שראו את הווידג'ט שלי הם מצרפת?" התשובה לשאלה הזו תיראה בערך כך: "בערך 4881 משתמשים שראו את מזהה הווידג'ט שלי 3276 הם מצרפת". הערך המצטבר הוא 1 לכל משתמש, ו-'4881 משתמשים' הוא הערך הנצבר שהוא הסכום של כל הערכים המצטברים של מפתח הצבירה הזה.

מפתח צבירה ערך ניתן לצבירה
מזהה ווידג'ט מזהה מדינה ספירת צפיות
3276 061 1

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

תקציב התרומות

כל קריאה ל-Private Aggregation API נקראת contribution. כדי להגן על פרטיות המשתמשים, אנחנו מגבילים את מספר התכנים שאפשר לאסוף מאדם ספציפי.

כשמסכמים את כל הערכים הנצברים בכל מפתחות הצבירה, הסכום צריך להיות נמוך מהתקציב התרומה. התקציב הוא בהיקף לכל מקור של worklet, ליום, והוא נפרד ל-Protected Audience API ול-Shared Storage של worklet. במהלך היום נעשה שימוש בחלון נע של כ-24 השעות האחרונות. אם דוח מצטבר חדש גורם לחריגה מהתקציב, לא יוצרים אותו.

התקציב לתרומה מיוצג על ידי הפרמטר L1, ומוגדר כ-216 (65,536) לעשר דקות ביום עם סטופ-סטופ של 220

(1,048,576). למידע נוסף על הפרמטרים האלה, קראו את המסביר.

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

למידע נוסף על תקציבי תרומות, ראו הסבר. למידע נוסף, קראו את המאמר תקציב לתרומה.

דוחות נצברים

אחרי שהמשתמש מפעיל את Private Aggregation API, הדפדפן יוצר דוחות נצברים שיעברו עיבוד על ידי שירות הצבירה בשלב מאוחר יותר, כדי ליצור דוחות סיכום. הדוח המצטבר בפורמט JSON ומכיל רשימה מוצפנת של תכנים שנוספו, כאשר כל אחד מהם הוא צמד {aggregation key, aggregatable value}. הדוחות המצטברים נשלחים בעיכוב אקראי של עד שעה.

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

דוגמה לדוח מצטבר עם מצב ניפוי באגים מופעל:

  "aggregation_service_payloads": [
    {
      "debug_cleartext_payload": "omRkYXRhgaJldmFsdWVEAAAAgGZidWNrZXRQAAAAAAAAAAAAAAAAAAAE0mlvcGVyYXRpb25paGlzdG9ncmFt",
      "key_id": "2cc72b6a-b92f-4b78-b929-e3048294f4d6",
      "payload": "a9Mk3XxvnfX70FsKrzcLNZPy+00kWYnoXF23ZpNXPz/Htv1KCzl/exzplqVlM/wvXdKUXCCtiGrDEL7BQ6MCbQp1NxbWzdXfdsZHGkZaLS2eF+vXw2UmLFH+BUg/zYMu13CxHtlNSFcZQQTwnCHb"
    }
  ],
  "debug_key": "777",
  "shared_info": "{\"api\":\"shared-storage\",\"debug_mode\":\"enabled\",\"report_id\":\"5bc74ea5-7656-43da-9d76-5ea3ebb5fca5\",\"reporting_origin\":\"https://localhost:4437\",\"scheduled_report_time\":\"1664907229\",\"version\":\"0.1\"}"

אפשר לבדוק את הדוחות המצטברים מהדף chrome://private-aggregation-internals:

צילום מסך של דף ה-API הפנימי לצבירה פרטית

למטרות בדיקה, ניתן להשתמש בלחצן 'שליחת הדוחות שנבחרו' על מנת לשלוח את הדוח לשרת באופן מיידי.

איסוף ואצווה של דוחות נצברים

הדפדפן שולח את הדוחות המצטברים למקור של ה-worklet שמכיל את הקריאה ל-Private Aggregation API, באמצעות הנתיב הידוע שמופיע:

  • לנפח אחסון משותף: /.well-known/private-aggregation/report-shared-storage
  • לקהל מוגן: /.well-known/private-aggregation/report-protected-audience

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

לאחר מכן השרת צריך לקבץ דוחות ולשלוח את האצווה לשירות הצבירה. יצירת קבוצות על סמך המידע שזמין במטען הייעודי (payload) הלא מוצפן של הדוח הנצבר, כמו השדה shared_info. רצוי שהקבוצות יכללו 100 דוחות או יותר לכל אצווה.

אפשר להחליט לקבץ על בסיס יומי או שבועי. זו שיטה גמישה, ואפשר לשנות את אסטרטגיית הקיבוץ בהתאם לאירועים ספציפיים שבהם אתם מצפים לנפח גדול יותר – לדוגמה, ימים בשנה שבהם צפויות יותר חשיפות. האצווה צריכה לכלול דוחות מאותה גרסת API, מקור דיווח ושעת הדוח המתוזמנת.

שירות צבירה

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

ב-Aggregation Service מקבלים דוחות מוצפנים שנצברים מהאוסף, ויוצרים דוחות סיכום.

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

דוחות סיכום

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

דוח סיכום מכיל קבוצה של צמדי מפתח/ערך בסגנון מילון JSON. כל צמד מכיל:

  • bucket: מפתח הצבירה כמחרוזת של מספר בינארי. אם מפתח הצבירה שבו השתמשת הוא '123', הקטגוריה היא 1111011.
  • value: הערך הסיכום של יעד מדידה נתון, שמסכם מכל הדוחות הזמינים המצטברים עם רעשי רקע.

לדוגמה:

[
  {"bucket":` `"111001001",` `"value":` `"2558500"},
  {"bucket":` `"111101001",` `"value":` `"3256211"},
  {"bucket":` `"111101001",` `"value":` `"6536542"},
]

רעש וקנה מידה

כדי לשמור על פרטיות המשתמשים, שירות הצבירה מוסיף "רעש" פעם אחת לכל ערך סיכום בכל פעם שמוצגת בקשה לדוח סיכום. ערכי הרעש נגזרים באופן אקראי מהתפלגות ההסתברות של Laplace. אין לכם שליטה ישירה על הדרכים שבהן רעש נוסף, אבל אתם יכולים להשפיע על ההשפעה של הרעש על נתוני המדידה שלו.

התפלגות הרעש זהה, ללא קשר לסכום של כל הערכים המצטברים. לכן, ככל שהערכים המצטברים גבוהים יותר, כך ההשפעה של הרעש עשויה להיות נמוכה יותר.

לדוגמה, נניח שלהתפלגות הרעש יש סטיית תקן של 100 והיא ממורכזת באפס. אם הערך של הדוח המצטבר שנאסף (או 'הערך שנצבר') הוא רק 200, סטיית התקן של הרעש תהיה 50% מהערך המצטבר. אבל במקרה שהערך המצטבר הוא 20,000, סטיית התקן של הרעש תהיה רק 0.5% מהערך המצטבר. כלומר, לערך המצטבר של 20,000 יהיה יחס גבוה הרבה יותר בין אות לרעש.

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

הרעש קבוע בלי קשר לערך המצטבר.

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

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

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

למידע נוסף, קראו את מסמכי התיעוד בנושא תקציב התרומות.

יצירת מעורבות ושיתוף משוב

ה-Private Aggregation API נמצאת בדיון פעיל וכפוף לשינויים בעתיד. אם ניסית את ממשק ה-API הזה ויש לך משוב, נשמח לשמוע אותו.