נכתב על ידי דני צ'רניאק, DigiKnowledge. נבדק לאחרונה: 24.10.2026

מסמך dataLayer שמפתח יכול ליישם בלי לשאול שאלות מגדיר לכל אירוע חמישה דברים: שם האירוע המדויק, הרגע הטכני שבו הוא נורה, רשימת הפרמטרים עם סוג הנתון של כל אחד, דוגמת קוד מלאה של dataLayer.push ובדיקת קבלה שמגדירה מה נחשב "עובד". כשאחד מהחמישה חסר, המפתח ממלא את החסר לפי הפרשנות שלו, הטריגרים ב-Google Tag Manager לא תואמים את מה שנשלח בפועל והנתונים ב-GA4 יוצאים חלקיים או כפולים. במדריך הזה אנחנו מראים את התבנית שאנחנו עובדים איתה, עם דוגמה מלאה לאירוע generate_lead ולאירוע purchase ואת הבדיקות שמאשרות שהיישום תקין.

למה מסמכי dataLayer נכשלים אצל המפתח?

רוב המסמכים שאנחנו רואים בפרויקטים נכתבים מנקודת המבט של האנליסט: "צריך לדעת כמה לידים הגיעו מהטופס". זו דרישה עסקית, לא מפרט טכני. המפתח צריך לדעת באיזה פונקציה בקוד לשים את ה-push, מה בדיוק לכתוב בתוכו, האם value הוא מספר או מחרוזת ומה לעשות כשהטופס נכשל בוולידציה. כל שאלה כזו שלא נענתה במסמך הופכת לסבב מיילים, או גרוע מזה, להחלטה שקטה של המפתח שמתגלה רק אחרי שבועיים של נתונים שגויים.

יש גם סיבה מבנית. dataLayer הוא מערך JavaScript שחי רק בעמוד הנוכחי. לפי התיעוד של Google, כל משתנה שנדחף אליו נשמר רק כל עוד המשתמש נמצא באותו עמוד. לכן מידע שצריך להיות זמין בכל העמודים חייב להידחף בכל עמוד מחדש. מפתח שלא קרא את התיעוד ידחוף את נתוני המשתמש פעם אחת בעמוד הראשון ויצפה שהם יישארו. המסמך צריך לסגור את הפער הזה מראש.

הכלל שאנחנו עובדים לפיו פשוט: אם המפתח צריך לפתוח את GA4 או את GTM כדי להבין מה לעשות, המסמך לא מספיק טוב. המסמך צריך לתאר רק את צד הקוד, בשפה של קוד, עם קריטריון הצלחה שהמפתח יכול לבדוק בעצמו בדפדפן.

מה חייב להופיע בכל שורה במסמך?

אנחנו בונים את המסמך כטבלה אחת, שורה לכל אירוע, עם חמש עמודות קבועות. העמודה הראשונה היא שם האירוע, באנגלית, באותיות קטנות, עם קו תחתון בין מילים, בדיוק כפי שהוא יופיע בטריגר ב-GTM. העמודה השנייה היא "מתי נורה": לא "כשמשתמש שולח טופס" אלא "בתוך ה-callback של תגובת 200 מהשרת, לפני הצגת הודעת ההצלחה, פעם אחת בלבד לכל שליחה". העמודה השלישית מפרטת את הפרמטרים עם סוג הנתון של כל אחד (string, number, boolean, array) ועם ציון מה חובה ומה אופציונלי. העמודה הרביעית היא דוגמת dataLayer.push שלמה שאפשר להעתיק. העמודה החמישית היא בדיקת הקבלה: מה המפתח אמור לראות בכלי הבדיקה כדי לסמן את המשימה כגמורה.

כך נראית התבנית, עם שני האירועים שנפרט בהמשך:

שם אירועמתי נורהפרמטרים וסוגי נתוניםדוגמת dataLayer.pushבדיקת קבלה
generate_lead אחרי תגובת הצלחה מהשרת (סטטוס 200 או אובייקט success), לפני הצגת הודעת התודה. לא בלחיצה על כפתור השליחה. פעם אחת לכל שליחה מוצלחת. event_params.form_id (string, חובה)
event_params.form_name (string, חובה)
event_params.lead_source (string, חובה)
event_params.currency (string, 3 אותיות ISO 4217, חובה אם יש value)
event_params.value (number, אופציונלי)
user_data.email (string, אופציונלי, רק עם הסכמה)
user_data.phone_number (string, פורמט E.164, אופציונלי)
ראו קוד מלא בסעיף הבא. מבנה: event, event_params, user_data. ב-Tag Assistant מופיע אירוע generate_lead בדיוק פעם אחת אחרי שליחה מוצלחת, לא מופיע כשהוולידציה נכשלת, form_id מגיע כמחרוזת. ב-DebugView האירוע מופיע עם הפרמטרים.
purchase בטעינת עמוד אישור ההזמנה, אחרי שההזמנה נוצרה במערכת ויש לה מספר. לפני קוד הקונטיינר של GTM. פעם אחת לכל transaction_id, גם אם המשתמש מרענן את העמוד. ecommerce.transaction_id (string, חובה)
ecommerce.value (number, חובה, ללא משלוח ומס)
ecommerce.currency (string, חובה)
ecommerce.tax (number, אופציונלי)
ecommerce.shipping (number, אופציונלי)
ecommerce.coupon (string, אופציונלי)
ecommerce.items (array, חובה, לפחות פריט אחד עם item_id או item_name)
ראו קוד מלא בסעיף purchase. חובה push של ecommerce: null לפני ה-push של האירוע. ב-Tag Assistant בלשונית Data Layer רואים ecommerce: null ואחריו purchase עם מערך items. סכום price כפול quantity של כל הפריטים שווה ל-value. ב-DebugView האירוע מופיע עם items. רענון העמוד לא יוצר אירוע נוסף.

על סוגי הנתונים אנחנו לא מתפשרים. value שנשלח כמחרוזת "150" במקום המספר 150 יגיע ל-GA4, אבל חישובי ההכנסה יהיו שגויים או ייעלמו. currency חייב להיות קוד ISO 4217 בן 3 אותיות (ILS, לא "שקל"). לפי מפרט האירועים של GA4, אם מגדירים value חובה להגדיר גם currency כדי שמדדי ההכנסה יחושבו נכון. את המשפט הזה אנחנו מעתיקים למסמך כפי שהוא.

איך נראית ארכיטקטורה של אירוע גנרי אחד עם שלושה מפתחות?

במקום להמציא מבנה שונה לכל אירוע, אנחנו עובדים עם מבנה אחיד: כל push מכיל שלושה מפתחות קבועים. המפתח event מחזיק את שם האירוע ומפעיל את הטריגר ב-GTM. המפתח event_params מחזיק את כל הפרמטרים של האירוע עצמו (מזהה טופס, מקור ליד, ערך). המפתח user_data מחזיק נתוני משתמש שמיועדים להמרות משופרות ב-Google Ads או למיפוי ב-Meta Conversions API. הוא נשלח רק כשיש הסכמה. אירועי מסחר הם היוצא מן הכלל: שם מוסיפים את המפתח ecommerce לפי המפרט של GA4, כי תג האירוע של GA4 ב-GTM קורא ממנו את מערך items באופן אוטומטי.

היתרון למפתח: הוא לומד תבנית אחת ומשכפל אותה. היתרון למי שמגדיר את GTM: טריגר אחד מסוג Custom Event לכל שם אירוע, משתני Data Layer Variable אחידים בפורמט event_params.form_id ועוד משתנה אחד מסוג User-Provided Data שקורא מ-user_data. הדיאגרמה מתארת את הזרימה:

ארכיטקטורה

push אחד עם שלושה מפתחות, שזורם לטריגר, למשתנים ולתגים

event"generate_lead"
טריגר Custom EventEvent name = generate_lead
GA4 Eventgenerate_lead + פרמטרים
event_paramsform_id, lead_source, value
Data Layer Variablesevent_params.form_id …
Google Ads Conversionvalue + המרות משופרות
user_dataemail, phone_number
User-Provided Dataקורא מ-user_data, עם הסכמה
Meta Pixel / CAPILead + user_data

push אחד, מבנה אחיד לכל אירוע

הטריגר מפעיל, המשתנים ממלאים

כל התגים נשענים על push אחד

קוד האתר דוחף אירוע אחד. GTM מזהה אותו בטריגר, שואב ערכים מהמשתנים ושולח לכל היעדים.

איך נראית דוגמה מלאה לאירוע generate_lead?

הטעות השכיחה ביותר בלידים היא לירות את האירוע בלחיצה על כפתור השליחה. לחיצה נרשמת גם כשהוולידציה נכשלת, גם כשהשרת מחזיר שגיאה וגם כשהמשתמש לוחץ פעמיים. התוצאה היא פער קבוע בין מספר הלידים ב-GA4 למספר הלידים במערכת ה-CRM. פער כזה הורס את האמון בדשבורד. לכן המסמך מגדיר במפורש: ה-push יושב בתוך ה-callback של תגובת ההצלחה מהשרת. בטפסים שמעבירים לעמוד תודה, ה-push יושב בעמוד התודה, לפני קוד הקונטיינר של GTM, עם מנגנון שמונע כפילות ברענון.

כך נראית הדוגמה שאנחנו מצרפים למסמך. הערכים הם נתוני דמו:

// generate_lead - נורה רק אחרי תגובת הצלחה מהשרת, לא בלחיצה
window.dataLayer = window.dataLayer || [];

function onLeadFormSuccess(response) {
  window.dataLayer.push({
    event: 'generate_lead',
    event_params: {
      form_id: 'contact_main',          // string, מזהה קבוע של הטופס
      form_name: 'צור קשר - עמוד הבית', // string, שם קריא
      lead_source: 'website_form',      // string
      currency: 'ILS',                  // string, ISO 4217
      value: 150                        // number, לא '150'
    },
    user_data: {
      email: response.email,            // string, רק אם המשתמש נתן הסכמה
      phone_number: response.phone      // string, פורמט E.164: +9725XXXXXXX
    }
  });
}

שימו לב לשורה הראשונה. התיעוד של Google מורה לאתחל את dataLayer פעם אחת בעמוד באמצעות window.dataLayer = window.dataLayer || [] ואף פעם לא להגדיר אותו מחדש אחרי שהקונטיינר נטען. הגדרה מחדש מוחקת את כל מה שנדחף קודם, כולל האירועים הפנימיים של GTM. התגים מפסיקים לעבוד בלי שום הודעת שגיאה.

הפרמטרים currency, value ו-lead_source הם הפרמטרים שמוגדרים במפרט של Google לאירוע generate_lead. form_id ו-form_name הם תוספת שלנו. הם מחייבים הגדרת מימדים מותאמים ב-GA4 כדי להופיע בדוחות. גם את זה כותבים במסמך, כדי שאף אחד לא יצפה לראות form_id בדוח סטנדרטי.

איך נראית דוגמה מלאה לאירוע purchase?

אירוע purchase הוא המקום שבו המפרט של GA4 מחייב מבנה מסוים. אין טעם להמציא מבנה אחר. תג האירוע של GA4 ב-GTM יודע לקרוא את נתוני המסחר ישירות מהמפתח ecommerce כשמסמנים את האפשרות "Read data from data layer". לכן השמות של כל השדות חייבים להיות בדיוק לפי המפרט. המסמך צריך לכלול שתי דחיפות: הראשונה מאפסת את אובייקט ecommerce והשנייה שולחת את האירוע.

// purchase - בעמוד אישור ההזמנה, לפני קוד הקונטיינר של GTM
window.dataLayer = window.dataLayer || [];

// שלב 1: איפוס אובייקט ecommerce קודם, כדי שפריטים מאירוע קודם לא יתערבבו
window.dataLayer.push({ ecommerce: null });

// שלב 2: האירוע עצמו (נתוני דמו)
window.dataLayer.push({
  event: 'purchase',
  ecommerce: {
    transaction_id: 'ORD-2026-48213', // string, חובה, ייחודי לכל הזמנה
    value: 540,                       // number, סכום price * quantity, ללא משלוח ומס
    tax: 91.8,                        // number
    shipping: 29.9,                   // number
    currency: 'ILS',                  // string
    coupon: 'WELCOME10',              // string, אופציונלי
    items: [
      {
        item_id: 'SKU-1001',          // string, חובה (או item_name)
        item_name: 'קרם לחות 50 מ"ל',  // string
        item_brand: 'DemoBrand',      // string
        item_category: 'טיפוח פנים',   // string
        item_variant: 'ללא ריח',       // string
        price: 180,                   // number, מחיר ליחידה אחרי הנחה
        quantity: 2,                  // number
        index: 0                      // number, מיקום ברשימה
      },
      {
        item_id: 'SKU-2044',
        item_name: 'סרום ויטמין C',
        item_brand: 'DemoBrand',
        item_category: 'טיפוח פנים',
        price: 180,
        quantity: 1,
        index: 1
      }
    ]
  },
  user_data: {
    email: 'customer@example.com',    // רק עם הסכמה, להמרות משופרות
    phone_number: '+972501234567'
  }
});

למה ecommerce: null? dataLayer ב-GTM עובד במיזוג רקורסיבי: כשדוחפים אובייקט חדש, GTM ממזג אותו עם מה שכבר קיים במודל הנתונים הפנימי. אם בעמוד הקודם היה view_item עם מערך items של שלושה פריטים ועכשיו דוחפים purchase עם פריט אחד, בלי האיפוס עלולים להגיע לתג פריטים שלא נקנו. התיעוד של Google כולל את שורת האיפוס בכל דוגמת קוד של אירוע מסחר, עם ההערה "Clear the previous ecommerce object". אנחנו דורשים אותה לפני כל push של ecommerce בלי יוצא מן הכלל.

שני פרטים מהמפרט שחשוב להעתיק למסמך כפי שהם: value הוא סכום price כפול quantity של כל הפריטים, בלי משלוח ובלי מס, שמדווחים בנפרד בשדות tax ו-shipping. transaction_id חייב להיות ייחודי, כי GA4 משתמש בו כדי למנוע ספירה כפולה של אותה רכישה. בדוגמה: 180 כפול 2 ועוד 180 כפול 1 שווה 540. זה בדיוק הערך של value.

איך בודקים שזה עובד?

בדיקת הקבלה היא העמודה שהופכת את המסמך מהנחיה לחוזה. בלי קריטריון הצלחה כתוב, "סיימתי" של המפתח ו"עובד" של האנליסט הם שני דברים שונים. אנחנו עובדים בשתי שכבות: Preview של GTM בודק שה-push הגיע ל-GTM במבנה הנכון ו-DebugView של GA4 בודק שהאירוע הגיע ל-GA4 עם הפרמטרים הנכונים.

  1. ב-GTM לוחצים על Preview, מכניסים את כתובת העמוד ומתחברים. Tag Assistant נפתח ומציג את רצף האירועים בעמוד.
  2. מבצעים את הפעולה: שולחים טופס או משלימים הזמנת דמו. בעמודה השמאלית של Tag Assistant אמור להופיע אירוע עם השם המדויק מהמסמך, פעם אחת בלבד.
  3. לוחצים על האירוע ועוברים ללשונית Data Layer. שם רואים את האובייקט כפי שנדחף בפועל, כולל ecommerce: null לפני purchase. בודקים שהמספרים הם מספרים (בלי מרכאות) ושכל שדות החובה קיימים.
  4. עוברים ללשונית Tags ומוודאים שתג GA4 Event נורה על האירוע ולא רק הטריגר. בלשונית Variables בודקים שמשתני Data Layer Variable מחזירים ערך ולא undefined.
  5. ב-GA4 נכנסים ל-Admin, תחת Data display בוחרים DebugView. מכיוון שה-Preview של GTM מפעיל debug mode למכשיר הנוכחי, המכשיר אמור להופיע ברשימה. לוחצים על האירוע בציר הזמן ובודקים את הפרמטרים ואת מערך items.
  6. חוזרים על הבדיקה השלילית: שולחים טופס עם שגיאת וולידציה ומוודאים שלא נורה generate_lead. מרעננים את עמוד התודה ומוודאים שלא נורה purchase נוסף.

שתי הערות מהתיעוד של Google שחשוב לדעת בזמן הבדיקה. אירועים לא מופיעים ב-DebugView אם מופעל Consent Mode והמשתמש לא נתן הסכמה לקוקיז של Analytics. לכן בבדיקה מאשרים את הבאנר קודם. בנוסף, ה-Preview של GTM זמין רק בדפדפן שהפעיל אותו. אם רוצים שהמפתח יבדוק בעצמו, משתפים איתו קישור Preview דרך Share ב-Tag Assistant במקום לתת לו הרשאות לקונטיינר.

מהן הטעויות הנפוצות במסמכי dataLayer?

הטעות הראשונה היא תיאור עסקי במקום רגע טכני. "כשמשתמש משלים רכישה" יכול להתפרש כלחיצה על "שלם", כחזרה מעמוד הסליקה או כטעינת עמוד התודה. במסמך טוב כתוב בדיוק איפה בקוד ובאיזה תנאי.

הטעות השנייה היא דחיפת האירוע אחרי טעינת GTM בעמוד תודה, אבל כאובייקט בלי מפתח event. אובייקט כזה מעדכן את המשתנים אך לא מפעיל שום טריגר. התג לא נורה. כל push שאמור להפעיל תג חייב לכלול את המפתח event.

הטעות השלישית היא סוגי נתונים לא עקביים: value כמחרוזת, quantity כמחרוזת, currency באותיות קטנות. GA4 לא תמיד יזרוק שגיאה, הוא פשוט יחשב לא נכון.

הטעות הרביעית היא שכחת ecommerce: null, שמביאה פריטים ישנים לאירוע חדש. הטעות החמישית היא שמות אירועים שונים בין המסמך לקוד, למשל generateLead בקוד מול generate_lead במסמך. הטריגר ב-GTM רגיש לאותיות גדולות וקטנות ולא יזהה את האירוע.

הטעות השישית היא נתוני משתמש בלי מדיניות. user_data נועד להמרות משופרות ולמיפוי שרת, לא לפרמטרים של GA4. המסמך צריך לציין שהשדות האלה לא נשלחים ל-GA4 כפרמטרי אירוע ושהם נדחפים רק בהתאם למצב ההסכמה של המשתמש.

איך ממשיכים מכאן?

מסמך dataLayer טוב חוסך סבבי תיקונים, מקצר את זמן הפיתוח ומייצר נתונים שאפשר להסתמך עליהם מהיום הראשון. אם אתם בונים אתר חדש, מחליפים פלטפורמת מסחר או פשוט לא בטוחים שהמדידה הנוכחית משקפת את מה שקורה באתר, אנחנו כותבים את מסמך ה-dataLayer, מגדירים את הקונטיינר ומבצעים את בדיקות הקבלה מול המפתחים. פרטים על השירות בעמוד הטמעת Google Tag Manager ובעמוד מדידה מתקדמת. אפשר גם לפנות אלינו דרך טופס הקשר.

מדריכים קשורים

אירועי איקומרס ב-GA4: מצפייה במוצר ועד רכישה, מה חובה לשלוח
משתנים ב-GTM: מובנים, Data Layer Variable, Lookup, RegEx ו-JavaScript
מילון אירועים לאפליקציה: איך מתכננים שמות, פרמטרים ומאפייני משתמש

מקורות

דני צ'רניאק
דני צ'רניאק
יועץ אנליטיקה דיגיטלית ומייסד DigiKnowledge. מרצה לאנליטיקה דיגיטלית באוניברסיטת תל אביב, באוניברסיטה הפתוחה ובאוניברסיטת אריאל. לעמוד האישי