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

רכישות כפולות ב-GA4 נוצרות כשאירוע purchase נשלח יותר מפעם אחת עבור אותה הזמנה: רענון של עמוד התודה, תג purchase שמוטמע גם ב-Google Tag Manager וגם בקוד האתר, אירוע שרת ב-Measurement Protocol לצד האירוע מהדפדפן, או חזרה מדף סליקה חיצוני דרך עמוד ביניים. GA4 מאחד אירועי purchase שמגיעים עם אותו transaction_id, אבל רק בזרמי web, רק כשהמזהה קיים וזהה בכל השליחות, לפי התיעוד רק עבור אותו משתמש. הבדיקה הראשונה היא תמיד השוואה בין מספר אירועי purchase למספר ערכי Transaction ID ייחודיים ב-Exploration, מול מספר ההזמנות ששולמו במערכת הניהול.

איך מזהים שיש כפילות ברכישות ב-GA4?

הסימן הראשון הוא כמעט תמיד פער מול מערכת הניהול של החנות. GA4 מפספס רכישות בגלל חוסמי פרסומות, דחיית הסכמה ומשתמשים שסוגרים את העמוד לפני שהתג נשלח, אבל כל הגורמים האלה מורידים את המספר. כש-GA4 מציג יותר רכישות מהמערכת שסופרת כסף, ההסבר היחיד הוא שאירוע purchase נשלח יותר מפעם אחת להזמנה.

סימנים נוספים מופיעים בדוחות עצמם: ההכנסה קופצת ביום של עדכון באתר בלי שינוי בתנועה, שיעור ההמרה עולה בפתאומיות, או שב-Exploration עם המימד Transaction ID מופיעה שורה בשם "(not set)" עם עשרות אירועים לצד מזהים שמופיעים עם שני אירועי purchase.

חשוב להבין מה המדדים סופרים. לפי התיעוד של Google, המדד Ecommerce purchases סופר את מספר הפעמים שאירוע purchase הופעל. המדד Transactions סופר אירועים עם פרמטר value, כולל purchase, refund ורכישות בתוך אפליקציה. שני המדדים סופרים אירועים, לא הזמנות ייחודיות. אין ב-GA4 מדד מובנה של "מספר מזהי עסקה ייחודיים". את ההשוואה הזו עושים ידנית ב-Exploration.

איך GA4 מאחד כפילויות לפי transaction_id ומה המגבלות?

מה התיעוד הרשמי אומר

פרמטר transaction_id הוא פרמטר חובה באירוע purchase לפי מפרט האירועים המומלצים של GA4. התיעוד מגדיר אותו כמזהה הייחודי של העסקה שנועד למנוע אירועים כפולים לרכישה. במסמך "Minimize duplicate key events with transaction IDs" נכתב במפורש ש-Google Analytics מאחד אירועי purchase שמגיעים עם אותו transaction_id. המסמך גם קובע שצריך להוסיף את המזהה לכל אירוע מסחר כדי לאחד עסקאות מאותו משתמש ולעבד החזרים כספיים נכון. המזהה יכול להכיל ספרות, אותיות ותווים כמו מקף או רווח, אבל הוא חייב להיות ייחודי לכל הזמנה ואסור שיכיל מידע שמזהה את הלקוח.

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

איפה האיחוד לא מספיק

האיחוד עובד רק בזרמי web. לפי התיעוד הוא לא פועל בזרמי אפליקציה, שם כל שליחה כפולה נספרת. התיעוד גם מנסח את האיחוד כאיחוד "עסקאות מאותו משתמש" ומזהיר שאין להשתמש באותו מזהה אצל משתמשים שונים. Google לא מפרסמת חלון זמן לאיחוד ולא מפרטת מה קורה כש-client_id שונה בין שתי השליחות. בפרויקטים שלנו אנחנו רואים ב-Exploration מזהים עם שני אירועים גם בנכסים שהמזהה בהם תקין. המדיניות שלנו: האיחוד הוא רשת ביטחון, לא תיקון.

שלוש מגבלות נוספות חשובות מכולן. ראשית, האיחוד פועל רק כשהמזהה קיים: purchase בלי transaction_id מגיע לדוח כ-"(not set)" ושום דבר לא מאחד אותו. שנית, האיחוד דורש מזהה זהה: אם הדפדפן שולח את מספר ההזמנה של החנות והשרת שולח את מספר האישור של הסולק, GA4 רואה שתי עסקאות שונות. שלישית, מזהה ריק הוא הגרוע מכולם: התיעוד מזהיר שאסור לשלוח מחרוזת ריקה, כי GA4 יאחד את כל אירועי purchase עם transaction_id="" לעסקה אחת, ספירת חסר חמורה במקום ספירת יתר.

יש גם מה שהאיחוד לא נוגע בו. purchase שנוצר בתוך GA4 מכלל Create event על בסיס page_view מקבל את הפרמטרים של page_view, בלי מזהה עסקה. לתג ההמרה של Google Ads יש מנגנון transaction_id נפרד שתיקון ב-GA4 לא משפיע עליו. בייצוא ל-BigQuery סופרים מזהים ייחודיים מול אירועי purchase בשאילתה במקום להסתמך על האיחוד של ממשק הדוחות.

איפה במסע הרכישה נוצרת הכפילות?

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

איפה נוצרת כפילות

מסע הרכישה וחמש הנקודות שבהן purchase נשלח פעמיים

מסע הלקוח
תשלום באתרלחיצה על "לתשלום"
דף סליקה חיצונידומיין של חברת הסליקה
5כתובת החזרה (return)עמוד ביניים, redirect
1עמוד תודהdataLayer: purchase
שלושה מסלולי שליחה
4שרת: Measurement Protocolאחרי webhook אישור תשלום מהסולק
2תג GA4 ב-GTMטריגר על purchase ב-dataLayer
2gtag בקוד התבניתpurchase מוטבע בעמוד
3GA4: אירוע purchaseאיחוד לפי transaction_id
  1. 1רענון או חזרה לעמוד התודה, purchase בכל טעינה
  2. 2תג ב-GTM וגם בקוד, שתי בקשות להזמנה
  3. 3purchase מ-page_view בלי transaction_id
  4. 4Measurement Protocol מהשרת לצד הדפדפן, client_id שונה
  5. 5כתובת החזרה מהסולק שולחת ועמוד התודה שולח שוב
אירוע purchase אחד להזמנה אמור לצאת מנקודה אחת בלבד. כל נקודה כתומה היא מקום שבו הוא יוצא פעמיים, או יוצא בלי transaction_id. המסגרת המקווקוות היא מסלול השרת, שלא עובר דרך הדפדפן בכלל.

עץ אבחון: מהסימפטום בדוח לתיקון

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

#סימפטום בדוחסיבה סבירהאיך מאמתיםתיקון
1פער של כמה אחוזים מול מערכת ההזמנות שגדל בימי מבצעים. ב-Exploration אותו Transaction ID עם שני אירועים מאותו משתמש, בהפרש של שניות עד ימים (לקוח שחזר לעמוד התודה מהמייל)רענון עמוד התודה. הקוד דוחף purchase בכל טעינה של העמוד, בלי סימון שההזמנה כבר דווחה. כשהמזהה חסר, האיחוד לא עוזרב-DebugView מבצעים רכישת בדיקה, מרעננים את עמוד התודה ובודקים אם purchase מופיע שוב. משווים page_view בנתיב עמוד התודה לאירועי purchase באותו נתיבהשרת מרנדר את נתוני הרכישה רק בטעינה הראשונה ושומר על ההזמנה דגל "דווח". בלי גישה לשרת, דגל בצד הלקוח לפי מזהה ההזמנה (sessionStorage) שחוסם דחיפה חוזרת. transaction_id בכל שליחה
2רכישות והכנסה כפולות כמעט בדיוק (יחס 1.9 עד 2.0 מול ההזמנות) מתאריך מסוים, לרוב אחרי החלפת תבנית, תוסף או סוכנות. כשהמזהה זהה הדוח עלול להיראות תקין בזכות האיחוד, אבל Tag Assistant מראה שתי בקשותתג purchase גם ב-GTM וגם בקוד. תוסף המסחר או התבנית שולחים gtag('event','purchase') מהקוד, במקביל תג GA4 ב-GTM מאזין לאותה דחיפה ל-dataLayerב-Tag Assistant או בלשונית Network מסננים collect ובודקים כמה בקשות עם en=purchase יוצאות בטעינה אחת. מחפשים במקור העמוד את המחרוזת purchase. בודקים אם יש שני Measurement IDמקור אחד, בדרך כלל GTM. מבטלים את השליחה מהקוד או מהתוסף, או מוסיפים חריגה בטריגר של התג. מוודאים שהתג מוגדר Once per event
3שורת "(not set)" במימד Transaction ID עם עשרות אירועים, purchase בלי הכנסה ובלי פריטים, מספר רכישות שקרוב למספר הצפיות בעמוד התודה או גבוה ממנו. בולט באתרים שבנויים כאפליקציית עמוד יחידEnhanced Measurement וכלל Create event. כלל ב-GA4 מייצר purchase מ-page_view לפי כתובת עמוד התודה. Enhanced Measurement שולח page_view נוסף בכל שינוי היסטוריה (pushState, replaceState), למשל כשעמוד התודה מנקה פרמטרים מהכתובת. כל page_view כזה הופך לרכישה בלי מזההAdmin, Events, Create events: מחפשים כלל שיוצר purchase. בהגדרות הזרם בודקים אם page_view לפי אירועי היסטוריה פעיל. ב-DebugView רואים page_view ואחריו purchase בלי itemsמוחקים את הכלל. purchase מגיע רק מ-dataLayer עם transaction_id, value, currency ו-items. אירוע עזר על צפייה בעמוד התודה מקבל שם אחר (thank_you_view) ולא מסומן כרכישה
4אותו Transaction ID עם שני אירועים גם כשהמזהה תקין, לעיתים בהפרש של דקות. חלק מאירועי purchase בלי מקור ומדיום של סשן או עם מיקום "(not set)". בדוח לפי שעה יש רכישות בשעות בלי סשניםMeasurement Protocol לצד gtag. השרת שולח purchase אחרי webhook מהסולק, הדפדפן שולח purchase מעמוד התודה. אם client_id בשרת לא זהה לזה שבעוגיית _ga, GA4 רואה שני משתמשים. התיעוד מגדיר את MP כהשלמה לאיסוף מהדפדפן, לא כתחליףמשווים את ה-payload של השרת לבקשה מהדפדפן: client_id, transaction_id, שם האירוע. ב-Exploration מוסיפים Hour או Device category ובודקים אם לאותו מזהה יש שני ערכיםמסלול אחד לכל שם אירוע. אם השרת הוא מקור האמת, הדפדפן לא שולח purchase. אם רוצים את שניהם, השרת שולח שם אחר (purchase_server) שלא נספר במדדי המסחר. בכל מקרה אותו client_id ואותו transaction_id
5לאותה הזמנה שני מזהים שונים (מספר הזמנה של החנות ומספר אישור של הסולק), או purchase שיוצא משני נתיבים: כתובת החזרה ועמוד התודה. חלק מהרכישות מיוחסות לדומיין של הסולק כ-referralחזרה מדף סליקה חיצוני. כתובת ה-return דוחפת purchase לפי פרמטרים מהכתובת ואז מפנה לעמוד תודה שדוחף שוב. או ששתי מערכות (האתר ושרת התשלומים) שולחות כל אחת עם המזהה שלהב-Exploration מוסיפים ל-Transaction ID את המימד Page path and screen class ובודקים מאילו נתיבים יוצא purchase. משווים פורמט מזהים: חלק מספריים וחלק עם קידומת פירושו שני מקורותpurchase יוצא רק מעמוד התודה הסופי, אחרי שהשרת אישר את התשלום, עם מספר ההזמנה של החנות כמזהה יחיד. דומיין הסולק נכנס לרשימת unwanted referrals, אבל זה פותר ייחוס, לא כפילות

איך משווים purchase למזהי עסקה ייחודיים ב-Exploration? (נתוני דמו)

זו הבדיקה המרכזית של המדריך. היא עונה בדוח אחד על שלוש שאלות: כמה אירועי purchase נשלחו, כמה מזהי עסקה ייחודיים עומדים מאחוריהם וכמה מהם חסרי מזהה בכלל.

  1. פותחים Exploration חדש מסוג Free form ובוחרים טווח של 28 יום שהסתיים לפני לפחות יומיים, כדי שהעיבוד יושלם.
  2. מוסיפים את המימד Transaction ID לשורות ואת המדדים Ecommerce purchases ו-Purchase revenue לערכים. Ecommerce purchases סופר רק אירועי purchase, כך שאין צורך בפילטר לפי שם אירוע.
  3. מסדרים לפי Ecommerce purchases בסדר יורד ומגדילים את מספר השורות המוצגות למקסימום. בראש הטבלה תופיע שורת "(not set)" אם קיימת ואחריה כל מזהה שנספר יותר מפעם אחת.
  4. רושמים שלושה מספרים: סך Ecommerce purchases בשורת הסיכום, מספר השורות בטבלה (מספר המזהים הייחודיים, כולל not set) ומספר ההזמנות ששולמו באותו טווח במערכת הניהול.
  5. מוסיפים מימד שני לפי הצורך: Page path and screen class כדי לראות מאיזה נתיב יצא כל אירוע, או Hour ו-Device category כדי להפריד בין שליחה מהדפדפן לשליחה מהשרת.

הטבלה הבאה היא נתוני דמו, לא נתוני לקוח. היא בנויה כך שחודש עם 1,000 הזמנות ששולמו מציג ב-GA4 1,112 אירועי purchase. מוצגות רק השורות שמלמדות משהו.

Transaction IDEcommerce purchasesPurchase revenue (ש"ח)מה השורה אומרת
(not set)380אירועי purchase בלי מזהה ובלי הכנסה. בדמו זה כלל Create event על page_view של עמוד התודה (שורה 3 בעץ). שום איחוד לא חל עליהם
4821121,180אותו מזהה פעמיים, ההכנסה כפולה. השליחה השנייה הגיעה מהשרת עם client_id אחר (שורה 4). האיחוד לא תפס
PAY-7F3A911590מזהה בפורמט של חברת הסליקה, נשלח מכתובת החזרה (שורה 5)
482051590אותה הזמנה כמו השורה הקודמת, הפעם במספר ההזמנה של החנות מעמוד התודה. שתי עסקאות בדוח, הזמנה אחת במציאות
482041245שורה תקינה: מזהה אחד, אירוע אחד, הכנסה אחת
סיכום1,112603,6601,041 שורות (מזהים ייחודיים כולל not set) מול 1,000 הזמנות במערכת הניהול בהכנסה של 560,000

הקריאה של הדמו: 1,112 אירועים מול 1,000 הזמנות הם עודף של 112, 11.2 אחוז. העודף מתפרק לשלושה חלקים שכל אחד מצביע על שורה אחרת בעץ. 38 אירועים בלי מזהה הם שורה 3. 34 מזהים שמופיעים פעמיים (68 אירועים, עודף של 34) הם שורה 4. 40 מזהים בפורמט של הסולק שמכפילים הזמנות קיימות הם שורה 5. כשהפירוק סוגר את הפער עד האירוע האחרון, האבחון הושלם. כשנשארת שארית, חוזרים לשורות 1 ו-2 ובודקים אותן ב-Tag Assistant, כי כפילות עם מזהה זהה מאותו דפדפן יכולה להתאחד בדוח ולהישאר בלתי נראית בבדיקה הזו.

גם פער ההכנסה מלמד: 603,660 מול 560,000 הם עודף של 7.8 אחוז, פחות מהעודף בספירה, כי 38 האירועים חסרי המזהה הגיעו בלי value. כפילות מתג כפול מכפילה ספירה והכנסה באותו יחס. כפילות מכלל Create event מכפילה רק את הספירה.

אילו טעויות נפוצות חוזרות בתיקון כפילויות?

להסתמך על האיחוד במקום לתקן את המקור

האיחוד לפי transaction_id מסתיר את הבעיה בדוחות של GA4, אבל כל שליחה כפולה ממשיכה לצאת לכל שאר התגים שמאזינים לאותו טריגר: Meta, TikTok, Google Ads. המקור צריך לשלוח פעם אחת. האיחוד נשאר רשת ביטחון.

לשלוח מזהה ריק או קבוע

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

לתקן עם Once per page במקום לטפל ברענון

האפשרות Once per page ב-GTM מגבילה את התג לירייה אחת בטעינה אחת של העמוד. רענון הוא טעינה חדשה. האפשרות מתאימה למקרה שבו הקוד דוחף purchase פעמיים באותה טעינה, לא למקרה של רענון או חזרה לעמוד.

לייצר purchase מכלל בתוך GA4

Create event הוא כלי טוב לאירועי עזר, אבל purchase דורש transaction_id, value, currency ו-items. כלל שמייצר purchase מ-page_view מייצר אירוע עירום שמעלה את ספירת הרכישות ולא מוסיף הכנסה. לפי התיעוד, כללים כאלה גם לא חלים על אירועים שנשלחים ב-Measurement Protocol.

לבדוק רק ב-Preview של GTM

הכפילויות של שורות 4 ו-5 לא נראות ב-Preview, כי הן נוצרות בשרת או בכתובת החזרה של הסולק. בדיקה שלמה כוללת תשלום אמיתי בסכום נמוך דרך הסולק האמיתי ובדיקה של האירועים שהגיעו ל-GA4 מהדפדפן ומהשרת יחד.

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

אחרי התיקון מבצעים שלוש בדיקות בשלוש רמות זמן. מיד אחרי הפריסה, ב-DebugView, מבצעים רכישת בדיקה ועוקבים אחרי purchase אחד בלבד עם transaction_id, value ו-items. מרעננים את עמוד התודה, חוזרים אליו מההיסטוריה ובודקים שלא יוצא purchase נוסף. ב-Tag Assistant מוודאים שבכל טעינה יוצאת בקשה אחת עם en=purchase לכל Measurement ID.

אחרי שבוע חוזרים ל-Exploration מהסעיף הקודם. היחס בין Ecommerce purchases למספר השורות צריך להיות 1.00, שורת "(not set)" צריכה להיעלם ואף מזהה לא אמור להופיע פעמיים. היחס מול ההזמנות ששולמו צריך לרדת מתחת ל-1.00, בדרך כלל ל-0.85 עד 0.97, בגלל חוסמי פרסומות ודחיית הסכמה. יחס מעל 1.00 אחרי התיקון אומר שנותר מקור כפילות.

אחרי חודש מקבעים את ההשוואה כבדיקה חודשית: הזמנות ששולמו מול purchase ב-GA4 מול המרות הרכישה ב-Google Ads וב-Meta. אם יש ייצוא ל-BigQuery, שאילתה שסופרת אירועי purchase מול transaction_id ייחודיים לפי יום היא הבדיקה המדויקת ביותר. פער שנשאר קבוע מחודש לחודש הוא הסבר. פער שקופץ הוא תקלה חדשה.

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

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

Measurement Protocol של GA4: שליחת אירועים מהשרת, מה חובה ומה המגבלות
אירועי איקומרס ב-GA4: מצפייה במוצר ועד רכישה, מה חובה לשלוח
נטישת צ'קאאוט באיקומרס: איך מודדים כל שלב ומה בודקים קודם

מקורות

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