אסטרטגיות להעברת האתר מהסתמכות על מחרוזת סוכן המשתמש לטיפים החדשים של לקוחות סוכן משתמש.
המחרוזת של סוכן המשתמש היא שטח משמעותי ליצירת טביעות אצבע פסיביות בדפדפנים, וגם קשה לעבד אותה. עם זאת, יש כל מיני סיבות לגיטימיות לאיסוף ולעיבוד של נתוני סוכן משתמש, ולכן מה שדרוש הוא דרך לפתרון טוב יותר. טיפים ללקוח של סוכן משתמש מספקים דרך מפורשת להצהיר על הצורך בנתוני סוכן המשתמש, וגם שיטות להחזרת הנתונים בפורמט קל לשימוש.
במאמר הזה נסביר איך מבצעים ביקורת על הגישה לנתוני סוכן המשתמש ומעבירים את השימוש במחרוזת של סוכן המשתמש לרמזים על הלקוח (Client Hints) לגבי סוכן המשתמש.
איסוף נתוני סוכן משתמש ושימוש בהם
כמו בכל סוג של איסוף נתונים, תמיד חשוב להבין למה אתם אוספים אותם. השלב הראשון, לא משנה אם תבצעו פעולה כלשהי או לא, הוא להבין איפה אתם משתמשים בנתוני סוכן המשתמש ולמה.
אם אתם לא יודעים אם נעשה שימוש בנתוני סוכן המשתמש או איפה, כדאי לחפש בקוד הקצה הקדמי שימוש ב-navigator.userAgent
ובקוד הקצה העורפי שימוש בכותרת ה-HTTP User-Agent
. כדאי גם לבדוק את הקוד של הקצה הקדמי כדי לראות אם יש בו שימוש בתכונות שכבר הוצאו משימוש, כמו navigator.platform
ו-navigator.appVersion
.
מנקודת מבט פונקציונלית, כדאי לחשוב על כל מקום בקוד שבו אתם מקליטים או מעבדים:
- השם או הגרסה של הדפדפן
- השם או הגרסה של מערכת ההפעלה
- היצרן או הדגם של המכשיר
- סוג המעבד, הארכיטקטורה או רמת הביטים (לדוגמה, 64 ביט)
סביר להניח שאתם משתמשים גם בספרייה או בשירות של צד שלישי כדי לעבד את סוכן המשתמש. במקרה כזה, כדאי לבדוק אם הם מעדכנים את הקוד כדי לתמוך ברמזים על הלקוח (Client Hints) לגבי סוכן המשתמש.
האם אתם משתמשים רק בנתונים בסיסיים של סוכן משתמש?
קבוצת ברירת המחדל של רמזים על הלקוח (Client Hints) לגבי הסוכן המשתמש כוללת:
Sec-CH-UA
: שם הדפדפן וגרסה ראשית/משמעותיתSec-CH-UA-Mobile
: ערך בוליאני שמציין מכשיר ניידSec-CH-UA-Platform
: שם מערכת ההפעלה- הערה: השינוי הזה עודכן במפרט, והוא יבוצע בקרוב ב-Chrome ובדפדפנים אחרים המבוססים על Chromium.
גם בגרסה המקוצרת של המחרוזת של סוכן המשתמש שתוצג, המידע הבסיסי הזה יישמר באופן תואם לאחור. לדוגמה, במקום Chrome/90.0.4430.85
, המחרוזת תכלול את Chrome/90.0.0.0
.
אם אתם בודקים את מחרוזת סוכן המשתמש רק כדי לזהות את שם הדפדפן, את הגרסה הראשית או את מערכת ההפעלה, הקוד ימשיך לפעול, אבל סביר להניח שתראו אזהרות על הוצאה משימוש.
אפשר ורצוי לעבור לרמזים על הלקוח (Client Hints) לגבי הסוכן המשתמש, אבל יכול להיות שיש לכם קודים מדור קודם או מגבלות משאבים שמונעים זאת. הפחתת המידע במחרוזת של סוכן המשתמש באופן תואם לאחור נועדה להבטיח שלמרות שהקוד הקיים יקבל מידע פחות מפורט, הוא עדיין ישמור על הפונקציונליות הבסיסית.
אסטרטגיה: JavaScript API על פי דרישה בצד הלקוח
אם אתם משתמשים כרגע ב-navigator.userAgent
, כדאי לעבור להעדפת navigator.userAgentData
לפני שתחזרו לנתח את מחרוזת סוכן המשתמש.
if (navigator.userAgentData) {
// use new hints
} else {
// fall back to user-agent string parsing
}
אם אתם בודקים את הגרסה לנייד או למחשב, צריך להשתמש בערך הבוליאני mobile
:
const isMobile = navigator.userAgentData.mobile;
userAgentData.brands
הוא מערך של אובייקטים עם המאפיינים brand
ו-version
, שבהם הדפדפן יכול לרשום את התאימות שלו למותגים האלה. אפשר לגשת אליו ישירות כמערך, או להשתמש בקריאה some()
כדי לבדוק אם יש רשומה ספציפית:
function isCompatible(item) {
// In real life you most likely have more complex rules here
return ['Chromium', 'Google Chrome', 'NewBrowser'].includes(item.brand);
}
if (navigator.userAgentData.brands.some(isCompatible)) {
// browser reports as compatible
}
אם אתם צריכים אחד מהערכים המפורטים יותר של סוכן המשתמש עם אנטרופי גבוה, תצטרכו לציין אותו ולבדוק את התוצאה ב-Promise
המוחזר:
navigator.userAgentData.getHighEntropyValues(['model'])
.then(ua => {
// requested hints available as attributes
const model = ua.model
});
כדאי להשתמש באסטרטגיה הזו גם אם רוצים לעבור מעיבוד בצד השרת לעיבוד בצד הלקוח. ל-JavaScript API לא נדרשת גישה לכותרות של בקשות HTTP, לכן אפשר לבקש ערכי סוכן משתמש בכל שלב.
אסטרטגיה: כותרת סטטית בצד השרת
אם אתם משתמשים בכותרת הבקשה User-Agent
בשרת והצרכים שלכם לגבי הנתונים האלה עקביים יחסית בכל האתר, תוכלו לציין את הטיפים הרצויים ללקוח כקבוצה סטטית בתשובות שלכם. זוהי גישה פשוטה יחסית, כי בדרך כלל צריך להגדיר אותה רק במיקום אחד. לדוגמה, יכול להיות שהיא תופיע בהגדרות של שרת האינטרנט אם כבר הוספתם כותרות, בהגדרות האירוח או בהגדרות ברמה העליונה של המסגרת או הפלטפורמה שבהם אתם משתמשים באתר.
כדאי להשתמש באסטרטגיה הזו אם אתם מבצעים טרנספורמציה או התאמה אישית של התשובות שמוצגות על סמך נתוני סוכן המשתמש.
דפדפנים ולקוחות אחרים עשויים לבחור לספק רמזים שונים לברירת מחדל, לכן מומלץ לציין את כל מה שאתם צריכים, גם אם הוא בדרך כלל זמין כברירת מחדל.
לדוגמה, הגדרות ברירת המחדל הנוכחיות של Chrome יוצגו כך:
⬇️ כותרות התגובה
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA
אם רוצים לקבל גם את דגם המכשיר בתשובות, צריך לשלוח:
❌️ כותרות של תשובות
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA
כשמעובדים את הבקשה בצד השרת, צריך קודם לבדוק אם הכותרת Sec-CH-UA
הרצויה נשלחה, ואז לעבור לניתוח הכותרת User-Agent
אם היא לא זמינה.
אסטרטגיה: הענקת הרשאות לקבלת רמזים לבקשות מ-origin שונים
אם אתם מבקשים משאבים משניים ממקורות שונים או מאתרים שונים, שדורשים שליחת רמזים על הלקוח (Client Hints) לגבי סוכן המשתמשים בבקשות שלהם, תצטרכו לציין במפורש את הרמזים הרצויים באמצעות מדיניות הרשאות.
לדוגמה, נניח ש-https://blog.site
מארח משאבים ב-https://cdn.site
שיכולים להחזיר משאבים שעברו אופטימיזציה למכשיר ספציפי.
https://blog.site
יכול לבקש את ההצעה Sec-CH-UA-Model
, אבל צריך להעניק אותה ל-https://cdn.site
באופן מפורש באמצעות הכותרת Permissions-Policy
. רשימת הרמזים בשליטת המדיניות זמינה ב-Clients Hints Hints Infrastructure
⬇️ התשובה מ-blog.site
שמעבירה את ההצעה
Accept-CH: Sec-CH-UA-Model
Permissions-Policy: ch-ua-model=(self "https://cdn.site")
⬆️ בקשה למשאבי משנה ב-cdn.site
כוללת את ההנחיה שהועברה
Sec-CH-UA-Model: "Pixel 5"
אפשר לציין כמה רמזים למקורות מרובים, ולא רק מטווח ch-ua
:
🎶️ תשובה שהתקבלה על ידי blog.site
מהאצלת רמזים לכמה מקורות
Accept-CH: Sec-CH-UA-Model, DPR
Permissions-Policy: ch-ua-model=(self "https://cdn.site"),
ch-dpr=(self "https://cdn.site" "https://img.site")
שיטה: הענקת הרשאות ל-hints למסגרות iframe
תגי iframe ממקורות שונים פועלים באופן דומה למשאבים ממקורות שונים, אבל צריך לציין את הטיפים שרוצים להעניק בסמכות במאפיין allow
.
⬇️ התשובה של blog.site
Accept-CH: Sec-CH-UA-Model
↪️ HTML עבור blog.site
<iframe src="https://widget.site" allow="ch-ua-model"></iframe>
⬆️ בקשה אל widget.site
Sec-CH-UA-Model: "Pixel 5"
המאפיין allow
ב-iframe יגביל כל כותרת Accept-CH
ש-widget.site
עשויה לשלוח בעצמה, לכן חשוב לוודא שציינתם את כל מה שנחוץ לאתר שמוטמע ב-iframe.
אסטרטגיה: רמזים דינמיים בצד השרת
אם יש חלקים ספציפיים בתהליך השימוש שבהם אתם צריכים מבחר גדול יותר של טיפים מאשר בשאר האתר, תוכלו לבקש את הטיפים האלה על פי דרישה במקום להציג אותם באופן סטטי בכל האתר. ניהול האפשרות הזו מורכב יותר, אבל אם כבר הגדרתם כותרות שונות לכל מסלול, יכול להיות שזה אפשרי.
חשוב לזכור שכל מופע של הכותרת Accept-CH
יחליף למעשה את הקבוצה הקיימת. לכן, אם מגדירים את הכותרת באופן דינמי, כל דף צריך לבקש את הקבוצה המלאה של ההנחיות הנדרשות.
לדוגמה, יכול להיות שיש קטע באתר שבו רוצים לספק סמלים ופקדים שתואמים למערכת ההפעלה של המשתמש. לשם כך, מומלץ גם לשלוח משיכה של Sec-CH-UA-Platform-Version
כדי להציג משאבי משנה מתאימים.
⬇️ כותרות התגובה של /blog
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA
六️ כותרות התגובה של /app
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA
אסטרטגיה: נדרשות רמזים מצד השרת בבקשה הראשונה
יכול להיות שבמקרים מסוימים תצטרכו יותר מקבוצת ההנחיות שמוגדרת כברירת מחדל בבקשה הראשונה, אבל סביר להניח שזה יקרה לעיתים רחוקות, לכן חשוב לבדוק את הסיבה לכך.
הבקשה הראשונה היא למעשה הבקשה הראשונה ברמת העליונה של המקור שנשלחה בסשן הגלישה הזה. קבוצת ההנחיות שמוגדרת כברירת מחדל כוללת את שם הדפדפן עם הגרסה הראשית, הפלטפורמה וסממן הניידות. לכן, השאלה היא: האם אתם זקוקים לנתונים מורחבים בטעינת הדף הראשונית?
לרמזים נוספים לגבי הבקשה הראשונה, יש שתי אפשרויות. קודם כול אפשר להשתמש בכותרת Critical-CH
. הפורמט של השדה הזה זהה לפורמט של Accept-CH
, אבל הוא מורה לדפדפן לנסות שוב את הבקשה באופן מיידי אם הבקשה הראשונה נשלחה בלי ההנחיה הקריטית.
⬆️ הבקשה הראשונית
[With default headers]
⬇️ כותרות התגובה
Accept-CH: Sec-CH-UA-Model
Critical-CH: Sec-CH-UA-Model
🔃 הדפדפן מנסה שוב את הבקשה הראשונית עם הכותרת הנוספת
[With default headers + …]
Sec-CH-UA-Model: Pixel 5
כתוצאה מכך עולה התקורה של הניסיון החוזר כבר בבקשה הראשונה, אבל עלות ההטמעה נמוכה יחסית. שולחים את הכותרת הנוספת והדפדפן יטפל בשאר.
במצבים שבהם אתם באמת זקוקים להנחיות נוספות בעומס הדף הראשון, הצעה לשיפור האמינות של הנחיות לקוח מציגה דרך לציין את ההנחיות בהגדרות ברמת החיבור. לשם כך, נעשה שימוש בתוסף Application-Layer Protocol Settings(ALPS) ל-TLS 1.3 כדי לאפשר העברה מוקדמת של רמזים בחיבורי HTTP/2 ו-HTTP/3. התהליך עדיין נמצא בשלב מוקדם מאוד, אבל אם אתם מנהלים באופן פעיל את הגדרות ה-TLS והחיבור שלכם, זה הזמן האידיאלי לתרום.
אסטרטגיה: תמיכה בגרסאות קודמות
יכול להיות שיש באתר קוד מדור קודם או קוד של צד שלישי שתלוי ב-navigator.userAgent
, כולל חלקים ממחרוזת ה-User-agent שיופחתו. לטווח ארוך, כדאי לתכנן מעבר לשיחות navigator.userAgentData
המקבילות, אבל יש פתרון ביניים.
מילוי מחדש של UA-CH הוא ספרייה קטנה שמאפשרת להחליף את navigator.userAgent
במחרוזת חדשה שנוצרה על סמך הערכים המבוקשים של navigator.userAgentData
.
לדוגמה, הקוד הזה יוצר מחרוזת של סוכן משתמש שכוללת גם את ההצעה 'model':
import { overrideUserAgentUsingClientHints } from './uach-retrofill.js';
overrideUserAgentUsingClientHints(['model'])
.then(() => { console.log(navigator.userAgent); });
המחרוזת שמתקבלת תציג את המודל Pixel 5
, אבל עדיין תציג את הערך המוקטן של 92.0.0.0
כי לא נשלחה בקשה לרמז uaFullVersion
:
Mozilla/5.0 (Linux; Android 10.0; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.0.0 Mobile Safari/537.36
תמיכה נוספת
אם השיטות האלה לא רלוונטיות לתרחיש לדוגמה שלכם, תוכלו להתחיל דיון ב-repo של privacy-sandbox-dev-support ונוכל לבדוק את הבעיה ביחד.
תמונה של Ricardo Rocha ב-Unsplash