למה בכלל יש הבדל בין תבנית ל-Custom HTML?
שני הסוגים נראים אותו דבר בתוצאה הסופית: בקשת רשת יוצאת מהדפדפן לשרתי הפלטפורמה. ההבדל הוא בדרך. תג Custom HTML מזריק לדף כל קוד שהודבק בו, בלי שום בדיקה, עם גישה מלאה ל-window, לעוגיות ולכל אובייקט בעמוד. GTM לא יודע מה הקוד עושה ולכן גם לא יכול להבטיח לו שום דבר: לא הסכמה, לא רצף, לא דיווח על כישלון.
תבנית תג (Custom Template) בנויה אחרת. הקוד שלה כתוב ב-JavaScript מוגבל שרץ בתוך ארגז חול של GTM. כל פעולה שיוצאת מהארגז דורשת הרשאה מוצהרת: טעינת סקריפט מכתובת מסוימת (inject_script), שליחת פיקסל לדומיין מסוים (send_pixel), קריאה או כתיבה למשתנה גלובלי ספציפי כמו fbq (access_globals), גישה למצב ההסכמה (access_consent). Google מתארת את התבניות בתיעוד הרשמי כחלופה בטוחה ויעילה יותר לתגי Custom HTML ולמשתני JavaScript, בדיוק מהסיבה הזו: ההרשאות גלויות למי שמייבא את התבנית ו-GTM אוכף אותן בזמן ריצה.
בפרויקטים שלנו הכלל פשוט. אם קיימת תבנית רשמית של הפלטפורמה או תבנית מוכרת בגלריה, היא זו שנכנסת לקונטיינר. Custom HTML מקבל מקום רק אחרי שהוכח שאין ברירה, עם התיעוד שמסביר למה.
מה ההבדלים המעשיים, ממד אחרי ממד?
הטבלה מסכמת את ההשוואה בשבעת הממדים שמשפיעים על איכות המדידה ביום-יום. השורות שמפתיעות לקוחות הן בדרך כלל Tag Sequencing ו-Consent, כי שם הבעיה לא נראית בעין: התג "נורה" ב-Preview, אבל לא עשה את מה שחשבתם.
| ממד | תבנית ייעודית מהגלריה | תג Custom HTML |
|---|---|---|
| Consent | תבנית יכולה לכלול בדיקת הסכמה מובנית (isConsentGranted, addConsentListener) ולהתנהג אחרת לפי ad_storage או ad_user_data. בתבנית Meta יש גם מצב Consent שמעביר fbq consent grant או revoke. | אין לוגיקת הסכמה בקוד עצמו. ההגנה היחידה היא "Additional consent checks" בהגדרות התג (Advanced, Consent Settings). אם שכחתם לסמן, הפיקסל נורה למי שסירב. |
| Tag Sequencing | הקוד קורא ל-gtmOnSuccess רק כשהפעולה הושלמה ול-gtmOnFailure כשנכשלה. תג שמוגדר "fire only if setup tag succeeds" מקבל מידע אמיתי. | GTM מדווח הצלחה ברגע שה-HTML הוזרק לדף, בלי קשר לשאלה אם הסקריפט החיצוני נטען או אם fbq מוגדר. רצף תגים שנשען על זה נשבר בשקט. |
| Event ID לדה-דופליקציה מול CAPI | שדה ייעודי (Event ID). מכניסים משתנה אחד, אותו משתנה נשלח גם לתג השרת והערך זהה בשני הצדדים. | צריך לשרשר את המשתנה לתוך מחרוזת הקוד ביד: fbq('track','Purchase',{…},{eventID:'{{Event ID}}'}). טעות בגרש או במיקום הפרמטר ואין דה-דופליקציה, בלי שגיאה גלויה. |
| Advanced Matching | טבלת שדות לפרמטרי לקוח (em, ph, fn, ln, ct, zp, external_id) שממופים למשתנים. הפורמט שהפלטפורמה דורשת מוסבר בשדה. | בניית אובייקט ביד בקריאת fbq('init'). קל לשלוח ערך לא מנורמל, לשלוח PII בטקסט גלוי לקונסול או לשכוח את הפרמטר באירועים הבאים. |
| הרשאות וביטחון | JavaScript מוגבל (sandboxed). רשימת הרשאות גלויה לפני הייבוא: לאילו דומיינים מותר לטעון סקריפט, לאילו משתנים גלובליים מותר לגשת. קוד שמנסה לחרוג נכשל. | גישה מלאה לדף. כל ספק שקיבל Custom HTML יכול להחליף את הסקריפט בצד שלו מחר בלי שתראו שינוי בקונטיינר. |
| תחזוקה | שינוי Pixel ID, הוספת אירוע או פרמטר הם שינוי בשדה, שנראה בהיסטוריית הגרסאות של GTM בצורה קריאה. התבנית מתעדכנת מהגלריה בלחיצה. | כל שינוי הוא עריכת קוד. שכפול תגים לכל אירוע מייצר עשרות בלוקים כמעט זהים שסוטים זה מזה עם הזמן. |
| בדיקות | ב-Preview רואים את ערכי השדות שנשלחו, את מצב ההסכמה ואת תוצאת ההרצה (הצלחה או כישלון) כנתונים מובנים. | ב-Preview רואים רק שהתג נורה. את מה שקרה בפועל צריך לחפש ב-Network, ב-Pixel Helper או בקונסול. |
נקודה אחת שחשוב להבין בשורת ה-Consent: גם לתבנית צריך להגדיר הסכמה. ההבדל הוא שלתבנית טובה יש שתי שכבות, הלוגיקה הפנימית שלה והבדיקה הנוספת בהגדרות התג, בעוד שלתג Custom HTML יש שכבה אחת בלבד שתלויה במי שיצר את התג.
איך Event ID אחד מגיע גם לפיקסל וגם ל-CAPI?
הדיאגרמה מתארת את זרימת אירוע purchase מה-dataLayer, דרך קונטיינר ה-Web של GTM, לשני יעדים: תבנית הפיקסל של Meta בדפדפן ותג Conversions API בקונטיינר השרת (sGTM). שניהם מקבלים את אותו event_id. בצד של Meta הכפילות מוסרת לפי השילוב של event_id ו-event_name.
דה-דופליקציה
אירוע purchase: event_id אחד, שני מסלולים, רכישה אחת ב-Meta
dataLayer.pushevent: purchase, transaction_idevent_id = T-1001מהיר, כפוף לחוסמים ולהסכמה
fbq track PurchaseeventID: T-1001עמיד יותר, דורש אותו מזהה
event_id בבקשהevent_id: T-1001event_id: T-1001event_id + event_nameשני אירועים נכנסים, הראשון נשמר, השני מושלך. נספרת רכישה אחתT-1001 הוא ערך דמו. בפועל משתמשים ב-transaction_id או במזהה ייחודי לכל אירוע.הכלל של Meta לדה-דופליקציה ברור בתיעוד הרשמי: ה-eventID של הפיקסל חייב להיות זהה ל-event_id של ה-Conversions API ושם האירוע חייב להיות זהה בשני הצדדים. האירוע השני שמגיע עם אותו צמד בחלון של 48 שעות מושלך. האירוע שנשמר הוא בדרך כלל זה שהתקבל קודם. יש גם מסלול חלופי לפי fbp או external_id, אבל הוא עובד רק כשאירוע הדפדפן מגיע לפני אירוע השרת. לכן אנחנו תמיד מעדיפים event_id מפורש.
איך מגדירים Meta Pixel מהגלריה עם Event ID משותף?
התהליך למטה מתאר הטמעה של התבנית הרשמית Facebook Pixel (המפרסם בגלריה: facebookincubator). התבנית תומכת באירועים סטנדרטיים ומותאמים, ב-Advanced Matching, במאפייני אירוע, ב-Data Processing Options, ב-Consent וב-Event ID לדה-דופליקציה מול השרת, כך שאין סיבה טכנית לחזור ל-Custom HTML.
- ייבוא התבנית. בקונטיינר ה-Web: Templates, Tag Templates, Search Gallery, חיפוש "Facebook Pixel". לפני ההוספה פותחים את לשונית ההרשאות ובודקים שהדומיינים לטעינת הסקריפט ולמשתנים הגלובליים (fbq, _fbq) הגיוניים. זה בדיוק היתרון של תבנית: אתם רואים מה היא מבקשת.
- משתנה Event ID. יוצרים משתנה אחד שישמש את כל האירועים. לרכישה, הערך הטבעי הוא transaction_id מה-dataLayer, כי הוא ייחודי לעסקה גם אם העמוד נטען פעמיים. לאירועים בלי מזהה עסקה (lead, add_to_cart) משתמשים במזהה ייחודי שהאתר דוחף ל-dataLayer עם האירוע, או במשתנה שמייצר מזהה פעם אחת לכל אירוע ושומר אותו לשימוש בשני התגים.
- תג הפיקסל. תג חדש מסוג Facebook Pixel: Pixel ID, Event Name (Purchase), מאפייני האירוע (value, currency, content_ids) ממופים למשתני dataLayer. בחלק Event ID מכניסים את המשתנה מהשלב הקודם. בטבלת Advanced Matching ממפים את שדות הלקוח שקיימים אצלכם בזמן האירוע. בחלק Consent בוחרים את ההתנהגות הרצויה. בהגדרות המתקדמות של התג מסמנים Additional consent checks עבור ad_storage ו-ad_user_data.
- תג GA4 לשרת. תג GA4 Event על אותו טריגר (purchase) שולח לקונטיינר השרת פרמטר נוסף, event_id, עם אותו משתנה. במדריך הרשמי של Meta ל-sGTM הפרמטר נקרא x-fb-event_id. העיקרון זהה: אותו טריגר, אותו שם אירוע, אותו ערך.
- תג CAPI בשרת. בקונטיינר השרת, התבנית Facebook Conversions API Tag מקבלת את האירוע מה-GA4 Client, ממפה את event_id, את נתוני המשתמש (אימייל, טלפון, עיר) ואת נתוני האירוע ושולחת ל-Meta עם Pixel ID, Access Token ו-Action Source שהוגדרו בתג.
- אימות. ב-Events Manager, בלשונית Test Events, מריצים רכישת דמו ומוודאים שנראים שני אירועי Purchase עם אותו Event ID, אחד מהדפדפן ואחד מהשרת, כשהעמודה Deduplicated מסומנת. רק אחר כך מפרסמים את שתי הגרסאות.
מתי בכל זאת Custom HTML ומה חובה לעשות אז?
יש שני מצבים לגיטימיים. הראשון: אין תבנית. פלטפורמה חדשה או ספק נישה ישראלי שמספק רק קטע קוד ואין לו תבנית בגלריה ואין תבנית קהילתית אמינה. השני: התבנית קיימת אבל לא תומכת במה שצריך, למשל קריאת API ספציפית של הפלטפורמה שהתבנית לא חשפה, או קוד של הספק שמשתנה לפי תנאים שהתבנית לא מכירה. בשני המצבים Custom HTML הוא זמני. בודקים מדי כמה חודשים אם נוספה תבנית.
כשכן משתמשים ב-Custom HTML, אלה הדברים שאנחנו לא מתפשרים עליהם. קודם כל, הסכמה: בהגדרות המתקדמות של התג מסמנים Additional consent checks עם סוגי ההסכמה הרלוונטיים, כי אין לקוד שום בדיקה פנימית. בלי זה הפיקסל נורה גם למי שסירב. זו בעיה משפטית, לא רק מדידתית. שנית, לא נשענים על Tag Sequencing מול Custom HTML: אם תג אחר צריך לרוץ אחרי שהסקריפט נטען, בודקים זאת בקוד עצמו (callback או בדיקה שהאובייקט הגלובלי קיים) ולא דרך "fire only if succeeds". שלישית, Event ID נכנס לקוד דרך משתנה GTM, אותו משתנה שמשמש את תג השרת. בודקים את המחרוזת שנוצרה בפועל ב-Preview ולא רק את הקוד שנכתב. רביעית, קוראים כל שורה בקוד שהספק שלח ומוודאים לאיזה דומיין הוא טוען משאבים, האם הוא כותב עוגיות ומה הוא קורא מהדף. חמישית, מסמנים את התג בשם ובהערה כ-Custom HTML עם הסיבה, כדי שמי שיפתח את הקונטיינר בעוד שנה ידע שזה לא היה חוסר ידע אלא החלטה. אם האתר עובד עם Content Security Policy, מתאמים עם המפתחים את הדומיינים, כי תג שנחסם על ידי CSP נראה ב-Preview כאילו נורה.
טעויות נפוצות
הטעות הראשונה היא Pixel ID עם קוד base מודבק ב-Custom HTML על All Pages. לידו תגי אירוע נפרדים, גם הם ב-Custom HTML, שכולם מכילים שוב את קוד ה-init. התוצאה היא אתחול כפול של הפיקסל וערבוב של Advanced Matching בין קריאות. בתבנית הבעיה לא קיימת: התבנית מאתחלת פעם אחת ושולחת אירועים אחר כך.
הטעות השנייה היא Event ID שנוצר בנפרד בכל תג. משתנה מסוג Random Number, למשל, מחזיר ערך אחר בכל קריאה, כך שהפיקסל והשרת מקבלים שני מזהים שונים ו-Meta סופרת שתי רכישות. ב-Events Manager זה נראה כעלייה חדה במספר הרכישות אחרי "שיפור" המדידה. המזהה חייב להיווצר פעם אחת לכל אירוע ולהישמר לשני התגים.
הטעות השלישית היא שם אירוע לא זהה: Purchase בפיקסל ו-purchase בשרת, או Lead מול lead. הדה-דופליקציה של Meta דורשת event_name זהה, כולל אותיות גדולות וקטנות. הטעות הרביעית היא תג תבנית עם Consent מוגדר בתוך התבנית אבל בלי Additional consent checks בהגדרות התג, או ההפך: מסתמכים על אחד משני המנגנונים ומניחים שהשני קיים. הטעות החמישית היא ייבוא תבנית מהגלריה בלי לקרוא את ההרשאות שלה. אחר כך לא ברור למה תבנית לפיקסל מבקשת לקרוא את כל העוגיות באתר. תבנית היא בטוחה יותר רק אם מישהו קרא מה היא מבקשת.
איך בודקים שזה עובד?
הבדיקה הראשונה היא ב-Preview של GTM. בוחרים את אירוע purchase בציר הזמן, פותחים את תג הפיקסל ובודקים בלשונית הערכים שה-Event ID מכיל ערך ממשי ולא undefined, שמאפייני האירוע מולאו ושמצב ההסכמה שהתג ראה תואם למה שהמשתמש בחר. אחר כך עוברים לתג GA4 ומוודאים שפרמטר event_id נשלח עם ערך זהה. אם יש קונטיינר שרת, מחברים גם אותו ל-Preview ובודקים שתג ה-CAPI נורה על אותו אירוע עם אותו מזהה.
הבדיקה השנייה היא בצד של Meta. ב-Events Manager, Test Events, מזינים את קוד הבדיקה בתג השרת, מבצעים רכישת דמו ובודקים שמגיעים שני אירועים עם אותו Event ID ושאחד מהם מסומן כמשוכפל. בלשונית Overview של אותו Pixel, בפירוט האירוע, יש גם מדד של אחוז האירועים שהתקבלו עם מזהה ושל כיסוי הדה-דופליקציה. שם רואים אם הבעיה היא בחלק מהאירועים בלבד.
הבדיקה השלישית היא תרחיש הסירוב. פותחים את האתר בחלון פרטי, דוחים את באנר ההסכמה ובודקים ב-Network שאין בקשה ל-facebook.com/tr ושאין בקשה מהשרת ל-Meta עבור אותו משתמש. תג שנורה למי שסירב הוא כשל גם אם המספרים ב-Events Manager נראים נהדר. הבדיקה הרביעית, שרוב הצוותים מדלגים עליה, היא בדיקה חוזרת שבוע אחרי הפרסום: משווים את מספר רכישות ה-Purchase ב-Meta למספר ההזמנות במערכת ההזמנות באותם ימים. פער של אחוזים בודדים הוא תקין, פער של כפול מעיד שהדה-דופליקציה לא עובדת.
מה לקחת מכאן?
תבנית ייעודית היא לא עניין של אסתטיקה בקונטיינר. היא ההבדל בין פיקסל שמכבד הסכמה, מדווח על כישלון ושולח Event ID תקין, לפיקסל שעובד עד שהוא מפסיק בלי שמישהו שם לב. Custom HTML נשאר כלי לגיטימי למקרה שאין תבנית, בתנאי שמבצעים את חובות ההסכמה, הבדיקה והתיעוד שתוארו למעלה. אם אתם רוצים שנעבור על הקונטיינר שלכם ונבדוק אילו פיקסלים יושבים בו ב-Custom HTML ומה המחיר של זה במדידה, אפשר לקרוא על שירות ה-Tag Manager שלנו, על מדידה מתקדמת עם Server-Side ו-Meta CAPI, או לפנות אלינו ישירות.
מדריכים קשורים
| LinkedIn Insight Tag ו-Conversions API: מדידת המרות ב-B2B |
| Google tag ותג אירוע GA4 ב-GTM: ההבדל, Event Settings והגדרות משותפות |
| Google tag gateway: טעינת תגי Google מהדומיין שלכם ואיך מקימים |
מקורות
Google Tag Manager: Custom templates overview, Google Tag Manager: Custom template APIs and permissions, Google Tag Manager Help: About consent mode (built-in and additional consent checks), Meta for Developers: Handling duplicate Pixel and Conversions API events, Meta for Developers: Conversions API with server-side Google Tag Manager
