אחד הדברים שלא קיימים באנליטיקס 4 (נכון לזמן כתיבת שורות אלו) זה זמן שהייה ממוצע בעמוד, או Avg. time on page כמו שקראו לו ביוניברסל אנליטיקס.
ביוניברסל, המספר הזה חושב בצורה מאוד פשוטה ואולי אפילו לא חכמה –
נגיד שיש לי 2 עמודים – A ו-B.
גולש הגיע בשעה 9:00 לעמוד A, ובשעה 9:05 עבר לעמוד B, ולכן ה-avg. time on page של עמוד A יהיה 9:05 מינוס 9:00, כלומר 5 דקות.
ומה קורה אם הגולש לא עבר לעמוד B, או בכלל לא עבר לעמוד אחר אלא צפה רק בעמוד אחד במהלך הביקור?
נכון, זמן השהייה באותו עמוד יהיה 0.
הנה דוגמא – בחרתי סגמנט של Bounced Sessions. הגולשים הללו לא עברו לעמוד נוסף, ואתם יכולים לראות שה-Avg. time on page הוא 0 עבור כל הדפים.
אין את זה בכלל בגוגל אנליטיקס 4?!
אז זה לא נכון להגיד שהנתון הזה לא קיים בכלל בגוגל אנליטיקס 4, כי בדוח המובנה של Pages and screens אפשר למצוא אותו בצורה משודרגת תחת Avg. engagement time, שזה בעצם כמה זמן הגולש אשכרה היה אקטיבי בעמוד (איך גוגל יודעים? כתבתי על זה פוסט):
ואף על פי כן, באופן אישי אני לא ממש משתמש בדוחות הסטנדרטיים, אלא בעיקר בדוחות שאני בונה באופן אישי ב-Explore, בדאטה סטודיו, או ב-BigQuery.
בשניים הראשונים אין את המדד הזה:
ובביג קוורי אתם יודעים, צריך לבנות הכל בעצמנו.
מטרת הפוסט הזה היא להראות לכם איך אני יוצר את הנתון של Avg. time on page בביג קוורי בצורה קלה.
בואו נתחיל
סדר הפעולות שלנו הולך להיות כזה:
בתור שלב ראשון ניקח יוזר ספציפי, ונציג את כל העמודים בהם הוא צפה (event_name = page_view) לפי סדר עולה – מהראשון לאחרון.
לאחר מכן נוסיף עמודה שמציינת מתי קרה ה-page_view הבא. כלומר באיזה חותמת זמן – event_timestamp.
כמובן שנמיין אותם גם לפי ה-ga_session_id, כי לעמוד האחרון של הסשן תמיד יהיה זמן שהייה 0 (לכאורה) בגלל שאין אחריו עוד עמוד
(תזכורת: time on page A = page B timestamp minus page A timestamp, ואם אין page B timestamp אז time on page A יהיה 0).
אחרי זה ניקח את ה-event_timestamp של העמוד הבא, נחסיר ממנו את ה-event_timestamp של העמוד הנוכחי, ונעשה לזה ממוצע.
זה יהיה זמן השהייה הממוצע בכל עמוד.
שלב ראשון – הצגת העמודים של כל גולש
נכתוב את השאילתה הבאה. שימו לב שכרגע ביקשתי רק את הנתונים של יוזר מסוים, לצורך ההמחשה.
1 2 3 4 5 6 7 8 9 10 11 | SELECT event_timestamp, CONCAT(user_pseudo_id ,'-', (SELECT value.int_value FROM UNNEST(event_params) WHERE key = "ga_session_id")) AS session_id, (SELECT value.string_value FROM UNNEST(event_params) WHERE key = "page_location") AS page_url, FROM `[YOUR TABLE NAME]` WHERE event_name = "page_view" AND user_pseudo_id = "2045363820.1682425558" -- you can change to your client id just for the test ORDER BY event_timestamp ASC |
וזה יתן לנו את רשימת העמודים בהם צפיתי, לפי הסדר מהראשון לאחרון:
עכשיו נוסיף עוד עמודה, שבה נשתמש בפונקציה LEAD שתכיל את ה-event_timestamp של העמוד הבא.
ולמה זה טוב? כי אמרנו שזמן השהייה בעמוד מחושב על ידי הזמן של העמוד הבא, מינוס הזמן של העמוד הזה, ולכן אנחנו צריכים שבכל שורה יופיעו שני הזמנים הללו.
הנה השאילתה:
1 2 3 4 5 6 7 8 9 10 11 12 13 | SELECT event_timestamp, CONCAT(user_pseudo_id ,'-', (SELECT value.int_value FROM UNNEST(event_params) WHERE key = "ga_session_id")) AS session_id, (SELECT value.string_value FROM UNNEST(event_params) WHERE key = "page_location") AS page_url, LEAD(event_timestamp) OVER (PARTITION BY CONCAT(user_pseudo_id ,'-', (SELECT value.int_value FROM UNNEST(event_params) WHERE key = "ga_session_id")) ORDER BY event_timestamp ASC ) AS next_pv_timestamp, FROM `[YOUR TABLE NAME]` WHERE event_name = "page_view" AND user_pseudo_id = "2045363820.1682425558" -- you can change to your client id ORDER BY event_timestamp ASC |
והנה התוצאות של השאילתה:
מה קרה בעמוד האחרון? ניחשתם נכון – הוא מכיל null בגלל שאחריו אין עוד עמוד.
עכשיו אנחנו פשוט צריכים ליצור שאילתה נוספת שתיקח את התוצאות של השאילתה הקודמת, תחסיר את event_timestamp מ-next_pv_timestamp, ותציג את זה לצד ה-URL אחרי חישוב ממוצע.
עכשיו גם אפשר להוריד את התנאי של user_pseudo_id ולהציג את התוצאות עבור כל היוזרים.
זו תהיה השאילתה שלנו:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | SELECT page_url, COUNT(*) AS pageviews, ROUND(AVG(IFNULL((next_pv_timestamp - event_timestamp)/1000000,0)),2) AS avg_time_on_page_in_seconds FROM ( SELECT event_timestamp, CONCAT(user_pseudo_id ,'-', (SELECT value.int_value FROM UNNEST(event_params) WHERE key = "ga_session_id")) AS session_id, (SELECT value.string_value FROM UNNEST(event_params) WHERE key = "page_location") AS page_url, LEAD(event_timestamp) OVER (PARTITION BY CONCAT(user_pseudo_id ,'-', (SELECT value.int_value FROM UNNEST(event_params) WHERE key = "ga_session_id")) ORDER BY event_timestamp ASC ) AS next_pv_timestamp, FROM `[YOUR TABLE NAME]` WHERE event_name = "page_view" ORDER BY event_timestamp ASC ) GROUP BY page_url ORDER BY pageviews DESC |
ואלו יהיו התוצאות שלה:
עכשיו כמו שאמרתי בהתחלה, זה לא מושלם כי אם הדף היה האחרון בביקור – הזמן שלו יספר בתור 0.
שימו לב לסשן שאני ביצעתי ממוין לפי העמודים מהראשון לאחרון – הדף האחרון היה /contact ואחריו לא היה עוד דף, ולכן ה-avg_time_on_page מחושב בתור 0.
זה לא מושלם, אבל היי – יוניברסל אנליטיקס עבד ככה במשך כמעט שני עשורים, ולא אמרתם מילה 😉
סיכום
זמן שהייה בגוגל אנליטיקס 4 מחושב בצורה מאוד שונה, ואפשר לומר גם יותר מדוייקת, לעומת יוניברסל אנליטיקס.
מה שכן, לצערי עדיין אי אפשר להוסיף את המטריקה הזאת לדוחות ב-explore או בלוקר סטודיו, ולכן נאלצתי ליצור אותה בעצמי עם BigQuery.
כמובן המטרה היא לא להשאיר את המספר הזה בביג קוורי, אלא להוציא אותו החוצה ולבנות איתו דוחות בלוקר סטודיו או כל מקום אחר.
באחד הפוסטים הבאים אראה לכם איך להשתמש בפרמטר engagement_time_msec שמודד כמה זמן הגולש היה אקטיבי באתר, כדי ליצור מספר שתואם עד כמה שאפשר למה שמופיע בדוח Pages and screens ב-GA4.