איך משייכים את נתוני הביצועים למידע על תוצאות ניפוי הבאגים כדי לזהות ולפתור בעיות שמשפיעות על משתמשים אמיתיים באמצעות Analytics
Google מספקת שני סוגים של כלים למדידה ולניפוי באגים של ביצועים:
- כלים של Lab: כלים כמו Lighthouse, שבהם הדף נטען בסביבה מדומה שיכולה לחקות תנאים שונים (לדוגמה, רשת איטית ומכשיר נייד ברמה נמוכה).
- כלים של שדות: כלים כמו הדוח על חוויית המשתמש ב-Chrome (CrUX), שמבוסס על נתונים מצטברים של משתמשים אמיתיים מ-Chrome. (שימו לב שהנתונים מהשטח שמדווחים על ידי כלים כמו PageSpeed Insights ו-Search Console מגיעים מנתוני CrUX).
כלים למדידת נתוני שטח מספקים נתונים מדויקים יותר – נתונים שמייצגים את מה שמשתמשים אמיתיים חווים – אבל כלים למדידת נתוני מעבדה לרוב טובים יותר בזיהוי בעיות ובתיקון שלהן.
נתוני CrUX מייצגים בצורה טובה יותר את הביצועים האמיתיים של הדף, אבל סביר להניח שהידיעה מה הניקוד שלכם ב-CrUX לא תעזור לכם להבין איך לשפר את הביצועים.
לעומת זאת, Lighthouse יזהה בעיות ויציע הצעות ספציפיות לשיפור. עם זאת, Lighthouse יציג הצעות רק לבעיות בביצועים שהוא יזהה בזמן טעינה של דף. הכלי לא מזהה בעיות שמתרחשות רק כתוצאה מאינטראקציה של המשתמש, כמו גלילה או לחיצה על לחצנים בדף.
מכאן עולה שאלה חשובה: איך אפשר לתעד מידע לניפוי באגים לגבי מדדי הליבה לבדיקת חוויית המשתמש באתר או מדדים אחרים לבדיקת ביצועים ממשתמשים אמיתיים בשטח?
במאמר הזה נסביר בפירוט באילו ממשקי API אפשר להשתמש כדי לאסוף מידע על תוצאות ניפוי הבאגים לגבי כל אחד ממדדי Core Web Vitals הנוכחיים, וניתן לכם רעיונות לאיסוף הנתונים האלה בכלי הניתוח הקיים שלכם.
ממשקי API לשיוך ולניפוי באגים
Cumulative Layout Shift (CLS)
מבין כל ה-Core Web Vitals, CLS הוא אולי המדד שחשוב במיוחד לאסוף לגביו מידע על תוצאות ניפוי הבאגים בשטח. ה-CLS נמדד לאורך כל משך החיים של הדף, ולכן לאופן שבו משתמש מבצע אינטראקציה עם הדף – עד כמה הוא גולל, על מה הוא לוחץ וכו' – יכולה להיות השפעה משמעותית על קיומם של שינויי פריסה ועל האלמנטים שמשנים את הפריסה.
כדאי לעיין בדוח הבא מ-PageSpeed Insights:
הערך של CLS שמדווח מהמעבדה (Lighthouse) שונה מאוד מהערך של CLS מהשטח (נתוני CrUX). זה הגיוני אם לוקחים בחשבון שלדף יכול להיות הרבה תוכן אינטראקטיבי שלא נמצא בשימוש כשבודקים אותו ב-Lighthouse.
אבל גם אם אתם מבינים שהאינטראקציה של המשתמש משפיעה על נתוני השדה, אתם עדיין צריכים לדעת אילו רכיבים בדף משתנים כדי לקבל ציון של 0.28 באחוזון ה-75. הממשק LayoutShiftAttribution מאפשר לעשות את זה.
קבלת שיוך של שינוי פריסה
ממשק LayoutShiftAttribution נחשף בכל רשומה של layout-shift שמופקת על ידי Layout Instability API.
הסבר מפורט על שני הממשקים האלה מופיע במאמר בנושא ניפוי באגים של שינויים בפריסה. לצורך הפוסט הזה, הדבר העיקרי שחשוב לדעת הוא שבתור מפתחים, אתם יכולים לראות כל שינוי בפריסת הרכיבים שמתרחש בדף, וגם אילו רכיבים משתנים.
הנה קוד לדוגמה שמתעד כל שינוי פריסה וגם את הרכיבים שהשתנו:
new PerformanceObserver((list) => {
for (const {value, startTime, sources} of list.getEntries()) {
// Log the shift amount and other entry info.
console.log('Layout shift:', {value, startTime});
if (sources) {
for (const {node, curRect, prevRect} of sources) {
// Log the elements that shifted.
console.log(' Shift source:', node, {curRect, prevRect});
}
}
}
}).observe({type: 'layout-shift', buffered: true});
סביר להניח שלא כדאי למדוד ולשלוח נתונים לכלי הניתוח שלכם לגבי כל שינוי פריסה שמתרחש, אבל אם תעקבו אחרי כל השינויים, תוכלו לעקוב אחרי השינויים הכי גרועים ולדווח רק על המידע שקשור אליהם.
המטרה היא לא לזהות ולתקן כל תזוזת פריסה שמתרחשת אצל כל משתמש, אלא לזהות את התזוזות שמשפיעות על המספר הגדול ביותר של משתמשים, ולכן תורמות הכי הרבה ל-CLS של הדף באחוזון ה-75.
בנוסף, אתם לא צריכים לחשב את אלמנט המקור הגדול ביותר בכל פעם שיש שינוי, אלא רק כשאתם מוכנים לשלוח את ערך ה-CLS לכלי הניתוח שלכם.
הקוד הבא מקבל רשימה של רשומות layout-shift שתרמו ל-CLS ומחזיר את רכיב המקור הגדול ביותר מהשינוי הגדול ביותר:
function getCLSDebugTarget(entries) {
const largestEntry = entries.reduce((a, b) => {
return a && a.value > b.value ? a : b;
});
if (largestEntry && largestEntry.sources && largestEntry.sources.length) {
const largestSource = largestEntry.sources.reduce((a, b) => {
return a.node && a.previousRect.width * a.previousRect.height >
b.previousRect.width * b.previousRect.height ? a : b;
});
if (largestSource) {
return largestSource.node;
}
}
}
אחרי שמזהים את הרכיב הגדול ביותר שגורם לשינוי הגדול ביותר, אפשר לדווח על כך לכלי לניתוח הנתונים.
האלמנט שמשפיע הכי הרבה על ה-CLS בדף נתון משתנה כנראה ממשתמש למשתמש, אבל אם תצרפו את האלמנטים האלה לכל המשתמשים, תוכלו ליצור רשימה של אלמנטים שמשתנים ומשפיעים על מספר המשתמשים הגדול ביותר.
אחרי שתזהו ותתקנו את שורש הבעיה של השינויים באלמנטים האלה, קוד הניתוח יתחיל לדווח על שינויים קטנים יותר כשינויים ה'גרועים' ביותר בדפים. בסופו של דבר, כל השינויים המדווחים יהיו קטנים מספיק כדי שהדפים שלכם יהיו הרבה מתחת לסף ה "טוב" של 0.1.
מטא-נתונים נוספים שעשויים להיות שימושיים לתיעוד יחד עם רכיב המקור של השינוי הגדול ביותר:
- הזמן של השינוי הכי גדול
- נתיב כתובת ה-URL בזמן השינוי הגדול ביותר (באתרים שמעדכנים את כתובת ה-URL באופן דינמי, כמו אפליקציות של דף יחיד).
Largest Contentful Paint (LCP)
כדי לנפות באגים ב-LCP בשטח, המידע העיקרי שצריך הוא איזה רכיב ספציפי היה הרכיב הגדול ביותר (הרכיב המועמד ל-LCP) בטעינת הדף הספציפית הזו.
חשוב לציין שיכול להיות – ואפילו סביר מאוד – שהאלמנט המועמד ל-LCP יהיה שונה ממשתמש למשתמש, גם אם מדובר באותו דף בדיוק.
יכולות להיות לכך כמה סיבות:
- למכשירים של המשתמשים יש רזולוציות מסך שונות, ולכן פריסות הדפים שונות ורכיבים שונים גלויים באזור התצוגה.
- המשתמשים לא תמיד טוענים דפים שגוללים לחלק העליון. לעתים קרובות קישורים יכילו מזהי מקטעים או אפילו קטעי טקסט, מה שאומר שאפשר לטעון את הדפים ולהציג אותם בכל מיקום גלילה בדף.
- יכול להיות שהתוכן מותאם אישית למשתמש הנוכחי, ולכן רכיב ה-LCP הפוטנציאלי יכול להשתנות מאוד ממשתמש למשתמש.
כלומר, אי אפשר להניח איזה רכיב או קבוצת רכיבים יהיו הרכיבים הכי נפוצים שמועמדים ל-LCP בדף מסוים. צריך למדוד את המדד הזה על סמך התנהגות של משתמשים אמיתיים.
זיהוי רכיב מועמד ל-LCP
כדי לקבוע את רכיב ה-LCP הפוטנציאלי ב-JavaScript, אפשר להשתמש ב-Largest Contentful Paint API, אותו API שבו משתמשים כדי לקבוע את ערך הזמן של ה-LCP.
כשבודקים רשומות largest-contentful-paint, אפשר לקבוע את רכיב ה-LCP הנוכחי על ידי עיון במאפיין element של הרשומה האחרונה:
new PerformanceObserver((list) => {
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
console.log('LCP element:', lastEntry.element);
}).observe({type: 'largest-contentful-paint', buffered: true});
אחרי שמזהים את רכיב המועמד ל-LCP, אפשר לשלוח אותו לכלי הניתוח יחד עם ערך המדד. בדומה ל-CLS, המדד הזה יעזור לכם לזהות אילו רכיבים הכי חשובים לאופטימיזציה בשלב הראשון.
בנוסף לאלמנט המועמד ל-LCP, כדאי גם למדוד את הזמנים של חלקי המשנה של ה-LCP, שיכולים לעזור לכם לקבוע אילו שלבי אופטימיזציה ספציפיים רלוונטיים לאתר שלכם.
מהירות התגובה לאינטראקציה באתר (INP)
הפרטים הכי חשובים שצריך לתעד בשטח לגבי מדד INP הם:
- איזה רכיב היה מעורב באינטראקציה
- סוג האינטראקציה
- מתי האינטראקציה הזו התרחשה
אחת הסיבות העיקריות לאינטראקציות איטיות היא חסימה של ה-thread הראשי, שיכולה להיות נפוצה בזמן טעינת JavaScript. כדאי לדעת אם רוב האינטראקציות האיטיות מתרחשות במהלך טעינת הדף, כדי להבין מה צריך לעשות כדי לפתור את הבעיה.
המדד INP מתייחס לזמן האחזור המלא של אינטראקציה – כולל הזמן שנדרש להפעלת כל רכיבי event listener הרשומים, וגם הזמן שנדרש לציור הפריים הבא אחרי שכל רכיבי event listener הופעלו. כלומר, כשמדובר ב-INP, חשוב לדעת אילו רכיבי יעד נוטים להוביל לאינטראקציות איטיות, ואילו סוגים של אינטראקציות אלה.
הקוד הבא מתעד ביומן את רכיב היעד ואת הזמן של רשומת ה-INP.
function logINPDebugInfo(inpEntry) {
console.log('INP target element:', inpEntry.target);
console.log('INP interaction type:', inpEntry.name);
console.log('INP time:', inpEntry.startTime);
}
הערה: הקוד הזה לא מראה איך לקבוע איזו רשומה event היא רשומת ה-INP, כי הלוגיקה הזו מורכבת יותר. עם זאת, בקטע הבא מוסבר איך לקבל את המידע הזה באמצעות ספריית JavaScript web-vitals.
שימוש בספריית JavaScript web-vitals
בקטעים הקודמים מופיעות הצעות כלליות ודוגמאות לקוד שיעזרו לכם לתעד מידע על תוצאות ניפוי הבאגים כדי לכלול אותו בנתונים שאתם שולחים לכלי הניתוח.
החל מגרסה 3, ספריית ה-JavaScript web-vitals כוללת attribution build שמציג את כל המידע הזה, וגם כמה אותות נוספים.
בדוגמת הקוד הבאה אפשר לראות איך מגדירים פרמטר נוסף של אירוע (או מאפיין מותאם אישית) שמכיל מחרוזת ניפוי באגים שיכולה לעזור לזהות את שורש הבעיה בביצועים.
import {onCLS, onINP, onLCP} from 'web-vitals/attribution';
function sendToGoogleAnalytics({name, value, id, attribution}) {
const eventParams = {
metric_value: value,
metric_id: id,
}
switch (name) {
case 'CLS':
eventParams.debug_target = attribution.largestShiftTarget;
break;
case 'LCP':
eventParams.debug_target = attribution.element;
break;
case 'INP':
eventParams.debug_target = attribution.interactionTarget;
break;
}
// Assumes the global `gtag()` function exists, see:
// https://developers.google.com/analytics/devguides/collection/ga4
gtag('event', name, eventParams);
}
onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);
הקוד הזה ספציפי ל-Google Analytics, אבל הרעיון הכללי רלוונטי גם לכלים אחרים לניתוח נתונים.
הקוד הזה מראה גם איך לדווח על אות ניפוי באגים יחיד, אבל כדאי לאסוף ולדווח על כמה אותות שונים לכל מדד.
לדוגמה, כדי לנפות באגים ב-INP, יכול להיות שתרצו לאסוף את הרכיב שהמשתמש מקיים איתו אינטראקציה, את סוג האינטראקציה, את השעה, את loadState, את שלבי האינטראקציה ועוד (כמו נתונים של Long Animation Frame).
המאפיין web-vitals attribution build חושף מידע נוסף על שיוך,
כמו בדוגמה הבאה של INP:
import {onCLS, onINP, onLCP} from 'web-vitals/attribution';
function sendToGoogleAnalytics({name, value, id, attribution}) {
const eventParams = {
metric_value: value,
metric_id: id,
}
switch (name) {
case 'INP':
eventParams.debug_target = attribution.interactionTarget;
eventParams.debug_type = attribution.interactionType;
eventParams.debug_time = attribution.interactionTime;
eventParams.debug_load_state = attribution.loadState;
eventParams.debug_interaction_delay = Math.round(attribution.inputDelay);
eventParams.debug_processing_duration = Math.round(attribution.processingDuration);
eventParams.debug_presentation_delay = Math.round(attribution.presentationDelay);
break;
// Additional metric logic...
}
// Assumes the global `gtag()` function exists, see:
// https://developers.google.com/analytics/devguides/collection/ga4
gtag('event', name, eventParams);
}
onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);
רשימה מלאה של אותות ניפוי הבאגים שמוצגים מופיעה במאמר בנושא שיוך Web Vitals.
דיווח על הנתונים והמחשתם
אחרי שתתחילו לאסוף מידע על תוצאות ניפוי הבאגים יחד עם ערכי המדדים, השלב הבא הוא צבירת הנתונים של כל המשתמשים כדי להתחיל לחפש דפוסים ומגמות.
כמו שציינו קודם, לא צריך לטפל בכל בעיה שהמשתמשים נתקלים בה. כדאי לטפל – במיוחד בהתחלה – בבעיות שמשפיעות על מספר גדול של משתמשים, שהן גם הבעיות שמשפיעות הכי הרבה על הציונים של Core Web Vitals.
במאמר הייעודי בנושא איך שולחים שאילתות לגבי הנתונים ומציגים אותם באמצעות BigQuery מוסבר איך עושים את זה ב-GA4.
סיכום
אנחנו מקווים שהפוסט הזה עזר לכם להבין איך אפשר להשתמש בממשקי ה-API הקיימים של הביצועים ובספריית web-vitals כדי לקבל מידע על תוצאות ניפוי הבאגים שיעזור לכם לאבחן את הביצועים על סמך ביקורים של משתמשים אמיתיים בשטח. המדריך הזה מתמקד במדדי Core Web Vitals, אבל המושגים שמוסברים בו רלוונטיים גם לניפוי באגים של כל מדד ביצועים שאפשר למדוד ב-JavaScript.
אם אתם ספקי ניתוח נתונים ומחפשים דרכים לשפר את המוצרים שלכם ולספק למשתמשים מידע על תוצאות ניפוי הבאגים, כדאי לכם לשקול את הטכניקות שמתוארות כאן, אבל אל תגבילו את עצמכם רק לרעיונות שמוצגים כאן. הפוסט הזה רלוונטי באופן כללי לכל כלי הניתוח, אבל כלי ניתוח ספציפיים יכולים (וצריכים) לתעד ולדווח על עוד מידע על תוצאות ניפוי הבאגים.
לבסוף, אם לדעתכם יש פערים ביכולת שלכם לנפות באגים במדדים האלה בגלל תכונות או מידע חסרים בממשקי ה-API עצמם, אתם יכולים לשלוח משוב לכתובת web-vitals-feedback@googlegroups.com.