בפוסט הזה אני אדבר על שליטה בסדר שליחת התגים בגוגל תג מנג’ר, ובגלל מורכבות העניין אני אנסה לכתוב את הפוסט בצורה פשוטה ככל האפשר.
ניגש לעניין –
גוגל תג מנג’ר היא פלטפורמה שמאפשרת לנו לשלוח תגים מסוגים שונים.
“תגים” (Tags) יכולים להיות קוד של גוגל אנליטיקס, איוונט של גוגל אנליטיקס, פיקסל המרות/רימרקטינג של פייסבוק, פיקסל המרות/רימרקטינג של אדוורדס ועוד ועוד פעולות (או יותר נכון קודים) שאנחנו רוצים להריץ באתר מבלי לגשת ולהטמיע אותם בקוד עצמו.
אחד היתרונות של גוגל תג מנג’ר הוא בכך שהוא שולח את כל התגים בצורה א-סינכרונית, כלומר הטעינה של התגים לא מעכבת את הטעינה של האתר, וטעינה איטית של תג אחד לא מעכבת את הטעינה של התג השני.
אבל היתרון הזה הוא גם חסרון, מכיוון שאם יש לנו 2 תגים שתלויים אחד בשני – האופן הא-סינכרוני הופך אותם ללא תלויים אחד בשני, מה שעלול ליצור שגיאות בקוד ולתקוע תהליכים.
על פי איזה סדר התגים נשלחים?
על פי הגדרות ברירת המחדל, תגים בתג מנג’ר בעלי אותו טריגר נשלחים על פי התאריך והשעה בהם הם נוצרו.
התג שנוצר הכי מוקדם נשלח ראשון ואחריו התגים שנוצרו אחריו.
זה לא כתוב בשום מקום בדוקומנטציה של גוגל, אבל אחרי הרבה ניסויים אני יכול להגיד לכם בוודאות שזה המצב.
ואיך אני יודע מתי התגים נשלחים אם יש להם את אותו טריגר?
נורא פשוט – הפעילו את הדיבאגר של תג מנג’ר, פתחו את ה-console בדפדפן ותוכלו לראות את סדר הפעולות שהתג מנג’ר מבצע.
בקונטיינר שלפניכם יש 3 תגים – שימו לב לזמן היצירה שלהם:
עכשיו אפתח את העמוד בו הטמעתי את הקונטיינר ואסתכל על כל הפעמים שמופיע TAG_STARTED בקונסול – זה מצביע על שליחת התגים השונים ותוכלו לראות שהסדר בו התגים נשלחים הוא אכן הסדר בו הם נוצרו:
זו היתה הקדמה קצרה ועכשיו ניגש לסיבה שבגללה החלטתי לכתוב את הפוסט הזה.
שליחה של קוד המרות פייסבוק בדף תודה
מדי פעם עולות שאלות בקבוצה של Google Tag Manager Israel בפייסבוק (מוזמנים להצטרף אגב) לגבי שליחה של קוד המרות פייסבוק בדפי תודה.
השאלות בד”כ מתארות סינריו של דף נחיתה עם טופס להשארת פרטים, ולאחר מילוי הפרטים הגולש מגיע לדף תודה שבו אתם רוצים לדווח לפייסבוק על המרה מסוג Lead (או Purchase במקרה של רכישה).
כדי לדווח על ההמרה הזו אתם צריכים לקרוא לפונקציה של פייסבוק בשם fbq, באופן הבא:
<script>fbq(‘track’,’Lead’)</script>
את הקוד הזה תשימו בתוך תג מסוג Custom HTML עם טריגר Page URL contains thanks (או משהו כזה), וזה יראה בערך כך:
הפונקציה הזו שולחת את המידע על ההמרה לפייסבוק, אבל באופן כללי כדי שפונקציה תעבוד צריך להגדיר אותה איפשהוא, ואת זה הפיקסל הגנרי של פייסבוק עושה.
המשמעות של זה היא שכדי שהפונקציה תעבוד וכדי שהדיווח שלנו לפייסבוק על ההמרה יישלח כמו שצריך, אנחנו חייבים לשלוח את הפיקסל הגנרי עוד לפני שאנחנו שולחים את הדיווח על ההמרה.
כלומר אם יש לנו 2 תגים, אחד לשליחת הפיקסל הגנרי בטריגר של All Pages, והשני לשליחת הדיווח על ההמרה (=Facebook Event) – אנחנו צריכים לוודא שהפיקסל של פייסבוק נשלח לפני האיוונט של פייסבוק.
אם לא נעשה את זה נקבל שגיאה בקונסול שהפונקציה fbq לא קיימת, וגם בתוסף Pixel Helper לכרום, שמדווח לנו על תקינותם של הפיקסלים השונים של פייסבוק שנשלחים בעמוד, נראה שהאיוונט לא נשלח.
פתרון #1: שימוש באיוונטים הבילטאין של גוגל תג מנג’ר
כדי להבין את זה אקדים ואסביר נקודה מאוד מאוד חשובה בתג מנג’ר:
תגים בגוגל תג מנג’ר יכולים להישלח רק כאשר קורה איוונט.
כשאני אומר איוונט אני לא מתכוון לאיוונט של גוגל אנליטיקס וגם לא לאיוונט של פייסבוק, אלא לאיוונט שנדחף לדטאלייר של התג מנג’ר והוא זה שגורם לו “להתעורר” ולבדוק האם יש איזה תג שהוא אמור לשלוח כאשר האיוונט הזה קורה.
בצד שמאל בתמונה שלפניכם תוכלו לראות את האיוונטים שנשלחים כאשר התג מנג’ר נטען בעמוד, על פי הסדר שבו הם נטענים.
האיוונט הראשון שקורה הוא gtm.js, לאחר מכן קורה איוונט בשם gtm.dom, ולבסוף איוונט בשם gtm.load.
כאשר אנחנו אומרים לתג מנג’ר לשלוח תג מסוים בטריגר All Pages זה כאילו אנחנו אומרים לו “שלח את התג בכל פעם שאיוונט gtm.js נשלח”:
הסיבה שאני אומר לכם את זה, היא קודם כל כדי שתבינו שהטריגר All Pages שווה בדיוק לטריגר Page URL contains thanks (או כל URL אחר), כי המשמעות של טריגר Page URL… זה “כאשר קורה אירוע gtm.js וגם ה-Page URL מכיל thanks”.
המשמעות של היא שכאשר אתם שמים תג אחד (הפיקסל הגנרי) על All Pages ותג אחד (האיוונט של ההמרה) על Page URL contains thanks זה אומר ששניהם יישלחו ביחד בהפרשים של אלפיות השנייה (בהתאם לזמן שבו הם נוצרו, כפי שהסברנו קודם) ואין לנו אפשרות לוודא שהפיקסל נטען לפני האיוונט.
בימים הראשונים של גוגל תג מנג’ר, מה שהיינו עושים במצב כזה זה לשים את התג הראשון (הפיקסל הגנרי) על טריגר All Pages (שהמשמעות שלו בעצם זה gtm.js), ואת האיוונט היינו שמים על gtm.dom:
בצורה כזו היינו יכולים לוודא שהאיוונט נשלח אחרי הפיקסל, אבל הבעיה עם זה היא שיש לנו רק 3 איוונטים בילטאין בגוגל תג מנג’ר, ולכן הפתרון הזה מאפשר לנו לשלוט בסדר של 3 תגים בלבד בכל עמוד.
בעיה נוספת היא שהפתרון הזה מחייב אותנו לשלוח את התג השני אחרי שה-DOM מסתיים להיטען, ולפעמים זה יכול ליצור discerpanies גדולים במקרים שהעמוד נטען לאט או שהגולש עזב את העמוד לפני שהדפדפן סיים לטעון אותו.
פתרון #2: Firing Priorities
ב-1 ליולי 2014 החבר’ה בתג מנג’ר הוסיפו לתגים פיצ’ר לשלוט על סדר השליחה שלהם.
הפיצ’ר נקרא Firing Priority והוא נמצא תחת Advanced Settings בכל אחד מסוגי התגים שקיימים במערכת. אתם יכולים להכניס שם כל מספר שתרצו, ומה שיקרה זה שתגים בעלי priority גבוה יישלחו ראשונים, ותגים בעלי priority נמוך יותר יישלחו אחריהם:
מכיוון שהתגים בגוגל תג מנג’ר נשלחים באופן א-סינכרוני, כלומר טעינה של תג אחד לא מושפעת מטעינה של תג אחר, האפשרות הזו שימושית במיוחד אם יש לכם כמות גדולה של פיקסלים שנשלחים באותו טריגר.
למשל אם יש לכם בדף תודה 10 פיקסלים של רימרקטינג ממערכות שונות, וגם קוד ששולח את הטרנזקציה לגוגל אנליטיקס – כולם נשלחים באותו טריגר (Thank you page) ולכן סביר להניח שתרצו לשים את הטרנזקציה בעדיפות גבוהה יותר למקרה שהיוזר יחליט לסגור את העמוד לפני שהתג מנג’ר יספיק לשלוח את כל התגים.
מתי זה לא יהיה יעיל?
כמו שראינו, העובדה שגוגל תג מנג’ר טען את התג לא אומרת שהתג סיים להיטען.
מחקרים שנעשו גילו שההשפעה של ה-priority על זמן הטעינה של התגים היא מינורית לחלוטין, והזמן שעובר בין טעינת תג בעל עדיפות גבוהה לבין תג בעל עדיפות נמוכה עומד על פחות מ-50ms.
בבדיקה שאני עשיתי יצרתי 3 תגי אנליטיקס – הראשון pageview, השני event A והשלישי event B. שלושתם על אותו טריגר של All Pages.
בבדיקה הראשונה נתתי להם לרוץ ללא priority, שזה אומר על פי הזמן שבו הם נוצרו, ואלו היו התוצאות:
בבדיקה השניה שיניתי את ה-priority שלהם וזה אכן השפיע על סדר הטעינה שלהם, אבל בהפרשי זמן מינורים לחלוטין:
מה שזה אומר מבחינתנו הוא, שבמקרים בהם טעינה של תג אחד תלויה בטעינה של תג אחר – ה-priority לא ממש יעזור לנו לוודא שהתג הראשון (=הפיקסל של פייסבוק במקרה שלנו) נטען לפני התג השני (=האיוונט של פייסבוק).
דוגמא נוספת לבעיתיות שיש בעניין אפשר למצוא בפונקציות jQuery למיניהן, שכדי שהם יפעלו אנחנו חייבים לוודא שהספריה של jQuery נטענת לפניהם.
ולכן אם יש לנו תג Custom HTML שטוען את הספריה, ואחריו יש לנו תג נוסף שמריץ פקודת jQuery מסויימת – אנחנו חייבים לוודא שהספריה נטענת לפני שהתג השני נורה.
הנה דוגמא למקרה כזה, שבו למרות שנתתי עדיפות גבוהה יותר ל-jQuery library – הקובץ שאמור להיטען גדול מדי (29KB) ולא מסתיים להיטען לפני שהתג השני נורה, ולכן אנחנו מקבלים שגיאה:
אז נכון שבמקרה של פייסבוק זה יהיה פחות נורא כי כל הסקריפט שוקל בסה”כ 3.6KB ולכן priority יעבוד ב-99% מהמקרים, אבל במקרים אחרים זה לא יעזור.
פתרון #3: Tag Sequencing
גם זה אחד הפיצ’רים הפחות מדוברים בתג מנג’ר, אבל הוא עובד בצורה מאוד פשוטה:
יש לנו תג עיקרי (Main Tag), תג מקדים (Setup Tag) ותג סוגר (Cleanup Tag).
1. התג העיקרי הוא בעצם הבסיס ל-sequence, ואנחנו נותנים לו טריגר כמו לכל תג רגיל.
2. התג המקדים הוא התג שאנחנו רוצים לשלוח לפני שהתג העיקרי נשלח.
3. התג הסוגר הוא התג שאנחנו רוצים לשלוח אחרי שהתג העיקרי נשלח.
נשמע מסובך? הנה דוגמא:
נגיד שיש לנו תג שהמטרה שלו היא לטעון את הספריה של jQuery, ובתג אחר אנחנו רוצים לעשות מניפולציה על ה-DOM (לשנות את הכותרת למשל) באמצעות פקודת jQuery.
התג השני (הפקודה) חייב את התג הראשון (הספריה) כדי לפעול, ולכן הוא יוגדר בצורה כזו:
מכיוון שזה ה-Main Tag שמתי לו טריגר של All Pages, אבל התניתי את השליחה של התג הזה בכך שהספריה של jQuery (שנמצאת בתג נפרד) תיטען קודם לכן בהצלחה (אחרת שלא יטען את הפקודה כי זה יתן לי JS error).
עכשיו ניצור את התג עם הספריה של jQuery, והוא יהיה ה-Setup Tag שלנו:
עכשיו שימו לב טוב – מכיוון שהתג הזה הוא תג Setup – אני לא צריך לשים לו שום טריגר, כי ברגע שיגיע זמנו של התג הראשי לרוץ הוא יחכה רגע, יפעיל את ה-Setup Tag ורק אז ימשיך לרוץ בעצמו.
במקרה שלנו מדובר בקוד HTML שעושה injection לספרייה של jQuery ולכן זה כתוב בצורה קצת מורכבת (שלא אכנס אליה כרגע), אבל אם אתם מגדירים כל תג אחר שהוא בילטאין במערכת אתם פשוט צריכים לסמן אותו בתור Setup Tag וזהו.
בכל אופן, אתם יכולים לשים לב שחסרה אות אחת בקוד שאני מנסה להריץ ולכן הספריה של jQuery לא תצליח להיטען בהצלחה, ולכן גם ה-Main Tag לא ירוץ למרות שיש לו טריגר של All Pages.
אם הייתי מוריד את הצ’קבוקס ליד Don’t fire… if… fails התג הראשי היה נשלח בטריגר הרגיל מבלי לחכות לתשובה אם ה-Setup Tag נשלח או לא, ואז היינו מקבלים את השגיאה הזו:
השורות באדום הם כתוצאה מהרצה של פקודת ה-jQuery (שלא מצליחה לרוץ כי אין את הספריה של jQuery ולכן התו $ לא מוגדר), והשורה השלישית היא כתוצאה מנסיון להריץ את ה-Setup Tag והיתקלות בשגיאה בגלל האות t שחסרה במילה document.
Cleanup Tag
מכיוון שהפוסט הזה כבר מתארך ואין לי כח להביא דוגמא לזה, אני רק אציין שזה פועל בדיוק כמו Setup Tag אבל הפוך – כלומר ב-Main Tag אתם מגדירים תג אחר שירוץ אחרי שהתג הראשי נשלח בהצלחה.
מתי זה יהיה מאוד שימושי? מתי שהגולש מגיע לעמוד תודה ואתם שולחים מידע על טרנזקציה ורוצים לנקות את סל הקניות (למקרה שהוא יחליט לרכוש עוד מוצר באותו סשן), אז ה-Main Tag שלכם יהיה התג ששולח את הטרנזקציה לגוגל אנליטיקס, וה-Cleanup Tag יהיה תג שמנקה את סל הקניות. כזה למשל:
[syntax type=”js”]dataLayer.push({
“ecommerce”: {
“checkout”: {
“products”: []
}
}
});[/syntax]
מתי לא יעזור לכם להשתמש ב-Sequence בגוגל תג מנג’ר?
האמת שאתם תצחקו, אבל sequence יכול לוודא שהתג נשלח בהצלחה, אבל במקרה שאנחנו טוענים ספריה חיצונית (כמו jQuery למשל) הוא לא יכול לדעת אם הספריה נטענה או לא.
אני אחדד כדי שתבינו את ההבדל: גם אם תגדירו את הספריית ה-jQuery בתור Setup Tag (כלומר התג שטוען את הספריה חייב להישלח לפני שהפקודה נשלחת) – זה אכן אומר שהתג יישלח, אבל זה לא אומר שהספריה תספיק להיטען לפני שה-Main Tag ירוץ.
נמחיש את זה באמצעות איור כדי שתבינו את זה בצורה טובה יותר:
אז מה אפשר לעשות כדי לפתור את זה?
הפתרון הכי פשוט לדעתי זה לשים את פקודת ה-jQuery בתור פונקציה של setTimeout עם דיליי של 0.5-1 שניות:
[syntax type=”js”]
<script>
setTimeout(function(){ $(‘h1’).text(‘The title has been changed’); }, 500)
</script>
[/syntax]
בצורה כזו התג עם הפקודה אכן יישלח רק אם התג של ספרית ה-jQuery יישלח בהצלחה, אבל הפקודה עצמה תרוץ רק אחרי חצי שניה כדי לוודא שהספריה אכן סיימה להיטען.
סיכום
בפוסט הזה ניסיתי להסביר על קצה המזלג את האפשרויות השונות שיש לנו כאשר אנחנו באים לשלוט על סדר שליחת התגים בגוגל תג מנג’ר.
הפוסט אמנם לווה בהרבה מאוד דוגמאות, אבל הם מאוד תיאורטיות ואין כמו המציאות כדי לפתור בעיות מורכבות כגון אלו.
יש כמובן דברים שלא נגעתי בהם (כמו דחיפת איוונטים לדטאלייר כדי לשלוח תגים אחרים) אבל היה חשוב לי לגעת דווקא בנקודות הפחות מוכרות, ולהסביר לכם לעומק את אופן הפעולה של המערכת.
אשמח מאוד אם תשתפו אותי בתגובות על אתגרים שנתקלתם בהם בעבר / בהווה בנוגע לשליטה על סדר הטעינה של תגים, ואשמח לנסות לסייע לכם לפתור אותם!