בית › מרכז הידע › מדידה › מדריכי יישום
מדריך יישום · קודמתקדם

מעקב רכישות ב-WooCommerce: מ-dataLayer ל-GTM

מדריך יישום · לקהל טכני · 12 דקות

מדריך מעשי עם קוד אמיתי להעתקה, והסבר בעברית לכל שלב. נלמד לדחוף אירוע רכישה (purchase) מ-WooCommerce ל-dataLayer, לחבר אותו ב-GTM, ולאמת שהוא עובד, אחרי שנוודא שהאתר בכלל מתאים לזה.

חדש כאן? מומלץ להתחיל במפת הארכיטקטורה, שמציגה את כל שכבות המדידה במבט אחד לפני שנכנסים למימוש.
חשוב לדעת: הקוד במדריך נכתב לפי ה-API הרשמי של WordPress ו-WooCommerce, ונבדק על התקנה סטנדרטית. אתרים עם Checkout Blocks, תבניות מותאמות, הרחבות מסחר או תוספי צד שלישי עשויים לדרוש התאמות. השתמשו בקוד כבסיס ליישום, לא כהבטחה שהוא יתאים לכל אתר ללא שינויים. לפני הטמעה באתר חי, בדקו בסביבת פיתוח או ב-Staging.
איפה אנחנו נמצאים במערכת · פרק 14 מתוך 20
אתרמדידהניהול לידיםאוטומציהעסקהOffline Conversionלמידת האלגוריתם
מסלול קריאה מומלץ: Data LayerGTMרכישה (יישום) (כאן)
רמת קושיבינוני–מתקדם
זמן יישוםכ-20 דקות
נבדק עםWordPress 6.x · WooCommerce 9.x · PHP 8.2+
תואםWooCommerce Classic · עמוד Order Received
לא תואםזרימות שבהן הלקוח לא חוזר לאתר
ידע נדרשPHP בסיסי · GTM · GA4
עודכןאוגוסט 2026
בקצרה: WooCommerce דוחף אירוע purchase ל-dataLayer דרך ה-hook woocommerce_thankyou (עמוד אישור ההזמנה). GTM קורא אותו ושולח ל-GA4. ה-dataLayer הוא שכבת נתונים משותפת לכל מערכות המדידה. הקוד תואם HPOS, מונע ספירה כפולה, כולל event_id ניטרלי, ומהווה את שכבת ה-client-side שעליה בונים server-side ו-CAPI.

לפני שמתחילים: האם האתר שלכם בכלל מתאים?

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

  • האם נוצרת הזמנה? אם WooCommerce לא יוצר Order, אין מה למדוד.
  • האם הלקוח מגיע לעמוד אישור ההזמנה (Order Received)? יש שערי סליקה, וגם Apple Pay / Google Pay, שבהם הלקוח לא בהכרח חוזר לאתר. אם הוא לא חוזר, שום JavaScript לא ירוץ.
  • האם באמת נדחף dataLayer? לא מנחשים, פותחים GTM Preview או window.dataLayer ורואים שהאירוע קיים.
Checkout Blocks: בדקו באיזה Checkout החנות משתמשת. חנויות חדשות רבות עברו ל-WooCommerce Checkout Blocks, שבהם ייתכן שיידרשו Hooks שונים או התאמות נוספות.

האם האתר שלכם מתאים למדידת client-side?

  • ✓ הלקוח חוזר לעמוד אישור ההזמנה.
  • ✓ אפשר להוסיף קוד או GTM.
  • ✓ אירוע purchase מופיע ב-dataLayer.
אם אחת מהתשובות "לא", עדיף לתכנן מראש מדידה בצד השרת.

דרישות מקדימות

  • אתר WordPress + WooCommerce פעיל.
  • Google Tag Manager מותקן (GTM-XXXXXXX).
  • גישה ל-functions.php של Child Theme, או תוסף Code Snippets.
  • חשבון GA4 עם Measurement ID (G-XXXXXXXXXX).

למה dataLayer, ולא ישר ל-GA4?

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

Google AnalyticsGoogle AdsMeta PixelMeta CAPIServer GTMכל מערכת אחרת

ה-dataLayer הוא שכבת הנתונים המשותפת, ולא תלוי בפלטפורמת מדידה אחת. זו בדיוק הסיבה שמתחילים ממנו.

למה לא פשוט תוסף?

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

1איפה שמים את הקוד

שתי דרכים בטוחות, בחרו אחת:

  • Child Theme: מדביקים בסוף functions.php של תבנית הבת.
  • תוסף Code Snippets: יוצרים snippet מסוג PHP ומדביקים שם.
אל תדביקו ב-functions.php של התבנית הראשית, עדכון תבנית ימחק את השינוי.

2דחיפת אירוע ה-purchase

חשוב להבין נקודה אחת: אנחנו משתמשים ב-woocommerce_thankyou כי הוא פשוט ומתאים לרוב החנויות. אבל הוא מסמן שהלקוח הגיע לעמוד אישור ההזמנה, וזה לא בדיוק כמו "התשלום אושר". Payment Success ≠ woocommerce_thankyou. כשנדרשת מדידה מלאה, מודדים את אישור התשלום דרך Webhook או Server-side, שאינם תלויים בכך שהלקוח יחזור. כאן מתחילים מהבסיס.

הקוד נתלה על ה-hook, בונה את אובייקט ה-purchase בפורמט GA4, כולל מניעת כפילות ברענון, שמירה על ריצה רק בעמוד אישור ההזמנה, ו-event_id ניטרלי מבוסס-הזמנה (לא קשור לסוג האירוע, כדי שישרת בעתיד גם refund/renewal, ולדדופליקציה של Pixel ו-CAPI).

functions.php (Child Theme) או Code Snippet
add_action( 'woocommerce_thankyou', 'doffice_ga4_purchase_datalayer', 20, 1 );

/**
 * Pushes a GA4 "purchase" event to the dataLayer on the Order Received page.
 * Note: this fires when the customer REACHES the Order Received page,
 * which is not always the same as "payment confirmed" (see the guide).
 */
function doffice_ga4_purchase_datalayer( $order_id ) {
    if ( ! $order_id ) {
        return;
    }

    // Extra guard: run only on the Order Received page, in case the
    // hook is ever triggered in another context.
    if ( function_exists( 'is_order_received_page' ) && ! is_order_received_page() ) {
        return;
    }

    $order = wc_get_order( $order_id );
    if ( ! $order ) {
        return;
    }

    // Prevent a second push if the customer refreshes the page.
    // This is ONE simple option; larger setups may instead rely on GA4's
    // transaction_id deduplication, or keep this state outside the order.
    if ( 'yes' === $order->get_meta( '_doffice_ga4_tracked' ) ) {
        return;
    }
    $order->update_meta_data( '_doffice_ga4_tracked', 'yes' );
    $order->save();

    // Build the items array in GA4 format.
    $items = array();
    foreach ( $order->get_items() as $item ) {
        $product    = $item->get_product();
        $product_id = $item->get_product_id();
        $categories = wp_get_post_terms( $product_id, 'product_cat', array( 'fields' => 'names' ) );

        $items[] = array(
            'item_id'       => ( $product && $product->get_sku() ) ? $product->get_sku() : (string) $product_id,
            'item_name'     => $item->get_name(),
            'item_category' => ! empty( $categories ) ? $categories[0] : '',
            'price'         => $product ? (float) $product->get_price() : 0,
            'quantity'      => (int) $item->get_quantity(),
        );
    }

    $datalayer = array(
        'event'     => 'purchase',
        // Neutral, order-based ID (NOT tied to the event type), so the same
        // order can back future refund / renewal events too. Reused later
        // for Meta Pixel + CAPI deduplication.
        'event_id'  => 'order_' . $order->get_id(),
        'ecommerce' => array(
            'transaction_id' => $order->get_order_number(),
            'value'          => (float) $order->get_total(),
            'tax'            => (float) $order->get_total_tax(),
            'shipping'       => (float) $order->get_shipping_total(),
            'currency'       => $order->get_currency(),
            'items'          => $items,
        ),
    );

    // Reset the previous ecommerce object, then push the purchase.
    echo '<script>';
    echo 'window.dataLayer = window.dataLayer || [];';
    echo 'window.dataLayer.push({ ecommerce: null });';
    echo 'window.dataLayer.push(' . wp_json_encode( $datalayer ) . ');';
    echo '</script>';
}

תאימות HPOS: הקוד משתמש ב-API הרשמי של WooCommerce (wc_get_order() ומתודות האובייקט), בלי גישה ישירה לטבלאות או ל-post meta, ולכן תואם גם לאחסון ההזמנות החדש (HPOS).

למה מטא-שדה למניעת כפילות? רק כדי שהאירוע לא יירה שוב ברענון עמוד. זו אפשרות אחת ופשוטה, במערכות גדולות אפשר להישען על דדופליקציית transaction_id של GA4, או לשמור את המצב מחוץ להזמנה.

למה מאפסים את ecommerce ל-null? לפני כל אירוע Ecommerce ב-GA4 מאפסים את האובייקט, כדי שנתונים מאירוע קודם לא "ייגררו" לאירוע הבא. זה עיקרון, לא רק שורת קוד.

3לחבר את זה ב-GTM

עכשיו מגדירים ב-GTM שיקרא את האירוע וישלח אותו ל-GA4 (הכל בממשק, בלי קוד):

  • משתנה: Variables ← New ← Data Layer Variable, בשם ecommerce.
  • טריגר: Triggers ← New ← Custom Event, שם האירוע purchase.
  • תגית: Tags ← New ← GA4 Event, Measurement ID, שם האירוע purchase, מסמנים Send Ecommerce data עם Source = Data Layer, ומחברים לטריגר.

שומרים ולוחצים Submit / Publish.

4אימות ו-Debug

איך יודעים שזה באמת עובד? שלוש דרכים: GTM Preview (משלימים רכישת בדיקה ובודקים שהאירוע נורה), GA4 DebugView (Admin ← DebugView), ו-Console. בקונסול, במקום להסתכל על כל ה-dataLayer, סננו רק את אירוע הרכישה:

Console, בעמוד אישור ההזמנה
window.dataLayer.filter(e => e.event === "purchase")

// Expected output on the Order Received page:
[
  {
    event: "purchase",
    event_id: "order_1234",
    ecommerce: {
      transaction_id: "1234",
      value: 349.9,
      currency: "ILS",
      items: [
        { item_id: "SKU-1", item_name: "...", price: 349.9, quantity: 1 }
      ]
    }
  }
]

תקלות נפוצות

מלכודת קריטית, Page Cache: עמוד אישור ההזמנה אסור שיהיה במטמון. אם CDN או תוסף Cache מגיש עמוד ישן, לקוח אחד עלול לקבל את אירוע הרכישה של לקוח אחר (עם הסכום והפריטים שלו). ודאו שעמוד Order Received מוחרג ממנגנוני Cache.

האירוע לא מופיע? עברו על הרשימה:

  • ✓ ה-GTM נטען בעמוד.
  • ✓ הקוד רץ רק בעמוד אישור ההזמנה.
  • ✓ עמוד אישור ההזמנה מוחרג מ-Cache.
  • ✓ זה עמוד אישור אמיתי, ולא Checkout Blocks / עמוד מותאם ללא ה-hook.
  • ✓ בדקתם ב-GTM Preview וב-GA4 DebugView.

ביצועים

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

איפה זה במסלול הגדול

המדריך הזה הוא רק השלב הראשון בשרשרת מדידה מלאה:

WooCommerce
dataLayer
GTM Web
GA4
Server GTM
Meta CAPI

כרגע סיימנו עד GA4 (client-side). הקוד רץ בדפדפן, ולכן חשוף לחוסמי פרסום, iOS ומחיקת קוקיז, וגם תלוי בכך שהלקוח יחזור לעמוד אישור ההזמנה. במדריכים הבאים נעבור לאירועים שמבוססים על אישור התשלום ועל תהליכים בצד השרת (Server GTM, CAPI), שאינם תלויים בחזרת הלקוח. וזה גם ההבדל המהותי בין מדידה בצד הדפדפן (client-side) למדידה בצד השרת (server-side). הרחבנו על התפיסה במדריך המדידה server-side ובמדריך CAPI.

מה הלאה

אחרי ה-purchase, מרחיבים באותה שיטה. כל אחד מאלה יקבל מדריך נפרד:

  • אירועי add_to_cart ו-begin_checkout למשפך מלא.
  • חיבור Meta Pixel + CAPI עם ה-event_id שכבר הכנו, לדדופליקציה.
  • מדידת רכישה מבוססת-שרת (Webhook / CAPI), שלא תלויה בחזרת הלקוח.

מושגים שהוזכרו במדריך

dataLayerGTM (Google Tag Manager)Server-side GTMGA4woocommerce_thankyouOrder ReceivedCheckout BlocksHPOSevent_idtransaction_idPage CacheGA4 DebugView
שאלות נפוצות

שאלות ותשובות על היישום

צריך לדעת לתכנת בשביל זה?
עדיף. המדריך מיועד למפתחים ולאנשי יישום. אם אתם רק רוצים להבין את התמונה, התחילו במדריך המדידה server-side.
למה לא לשלוח ישר ל-GA4?
כי ברגע שהמידע ב-dataLayer, אפשר להשתמש בו גם ל-Google Ads, Meta Pixel, Meta CAPI, Server GTM וכל מערכת אחרת. ה-dataLayer הוא שכבת הנתונים המשותפת, ולא תלוי בפלטפורמה אחת.
woocommerce_thankyou זו הדרך הנכונה?
זו דרך פשוטה להתחיל, המתאימה לרוב החנויות. אבל היא מסמנת שהלקוח הגיע לעמוד אישור ההזמנה, לא בהכרח שהתשלום אושר. כשנדרשת מדידה מלאה, מודדים את אישור התשלום דרך Webhook או Server-side.
מה אם הלקוח לא חוזר לאתר אחרי התשלום?
אז שום JavaScript לא ירוץ וה-purchase לא יידחף. קורה בחלק משערי הסליקה, ב-Apple Pay/Google Pay, ובחלק מ-Checkout Blocks. במקרים כאלה מודדים דרך Webhook, API של הסליקה, או Server-side.
למה מוסיפים שדה מטא להזמנה?
רק כדי למנוע ירי חוזר במקרה של רענון עמוד. זו אפשרות אחת ופשוטה, בפרויקטים אחרים אפשר להישען על דדופליקציית transaction_id של GA4 או על מצב חיצוני.
הקוד מכביד על האתר?
לא. הוא רץ פעם אחת בלבד, אחרי השלמת ההזמנה, ומוסיף רק Script קטן ל-HTML של עמוד אחד.
למה מאפסים את ecommerce ל-null?
כדי למנוע שנתונים מאירוע Ecommerce קודם ייגררו לאירוע הבא. זו המלצת GA4 לפני כל אירוע Ecommerce.
האם הקוד תואם HPOS?
כן. הוא משתמש ב-API הרשמי של WooCommerce (wc_get_order ומתודות האובייקט), בלי גישה ישירה לטבלאות או ל-post meta, ולכן תואם גם לאחסון ההזמנות החדש.
הפרק הבא · פרק 15 מתוך 20begin_checkout (Woo)למדוד את הרגע שבו הלקוח מתחיל לשלם

רוצים שנקים לכם את המדידה נכון מהיסוד?

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

בואו נדבר
כולל dataLayer תקין, GTM, GA4, Meta Pixel + CAPI עם Event ID, ו-Server-side GTM.