add_to_cart הוא האירוע שהכי משתנה בין חנויות, ובדיוק לכן הוא מעניין. אין קוד אחד שמתאים לכל אתר, ולכן המדריך מתחיל בבחירת אסטרטגיית המדידה: איך מזהים איזה flow יש באתר, ואז מיישמים את השיטה ל-WooCommerce קלאסי עם AJAX עם קוד להעתקה.
add_to_cart, כי יש עשרות דרכים להוסיף לעגלה. קודם מזהים איזה אירוע החנות משדרת, ואז, למקרה הנפוץ (WooCommerce קלאסי עם AJAX בלולאה), משתמשים בפילטר woocommerce_loop_add_to_cart_args ובאירוע added_to_cart כדי לדחוף add_to_cart ל-dataLayer. ל-Blocks, בילדרים ו-Quick View נדרשות התאמות.בניגוד ל-purchase ול-begin_checkout, שקורים בטעינת עמוד ברורה, ל-add_to_cart אין דרך אחת. יש עשרות דרכים שבהן לקוח מוסיף מוצר לעגלה, וכל אחת עובדת אחרת. הנה מפה מהירה של איפה הקוד במדריך נתמך, ואיפה תידרש התאמה:
| סוג ההוספה לעגלה | נתמך במדריך | הערות |
|---|---|---|
| WooCommerce Classic (AJAX) | ✅ | נתמך במלואו |
| עמוד מוצר בודד | ⚠ | דורש מימוש אחר |
| Cart & Checkout Blocks | ❌ | דורש API אחר |
| Elementor / Bricks | ⚠ | תלוי במימוש |
| Flatsome / Woodmart | ⚠ | לבדוק אירועים |
| Quick View | ⚠ | מאזין ייעודי |
לפני שכותבים קוד, כדאי לוודא שהחנות באמת משדרת את האירוע added_to_cart. פותחים DevTools, עוברים ל-Console, ומריצים:
// DevTools -> Console
jQuery(document.body).on('added_to_cart', function () {
console.log('event fired');
});עכשיו מוסיפים מוצר לעגלה מעמוד קטגוריה. אם מודפס event fired, הקוד במדריך מתאים לחנות. אם לא הודפס כלום, החנות משתמשת ב-flow אחר, וצריך לחפש את האירוע הנכון לפי הטבלה למעלה.
added_to_cart כלל אינו קיים שם.שני חלקים: קודם מצמידים את פרטי המוצר לכפתור ההוספה בלולאה (דרך הפילטר הרשמי woocommerce_loop_add_to_cart_args), ואז מאזינים לאירוע added_to_cart ודוחפים את האירוע ל-dataLayer.
add_to_cart ל-dataLayer./**
* 1) Attach product data to the AJAX add-to-cart buttons in product loops
* (shop / category), so the browser can read it when the item is added.
* We attach the data to the button itself so that, on the added_to_cart
* event, we can read it WITHOUT making another AJAX request.
*/
add_filter( 'woocommerce_loop_add_to_cart_args', 'doffice_ga4_atc_button_data', 10, 2 );
function doffice_ga4_atc_button_data( $args, $product ) {
$categories = wp_get_post_terms( $product->get_id(), 'product_cat', array( 'fields' => 'names' ) );
$args['attributes']['data-ga4-id'] = $product->get_sku() ? $product->get_sku() : $product->get_id();
$args['attributes']['data-ga4-name'] = $product->get_name();
// The price the customer SAW at click time. Usually the right value for
// add_to_cart. If the price changes only AFTER adding (coupons, dynamic
// pricing, currency switchers), read the final price from the cart instead.
$args['attributes']['data-ga4-price'] = wc_get_price_to_display( $product );
$args['attributes']['data-ga4-category'] = ! empty( $categories ) ? $categories[0] : '';
return $args;
}
/**
* 2) When WooCommerce confirms the AJAX add (jQuery "added_to_cart" event),
* push a GA4 "add_to_cart" event to the dataLayer.
*/
add_action( 'wp_enqueue_scripts', 'doffice_ga4_atc_script' );
function doffice_ga4_atc_script() {
if ( is_admin() || ! function_exists( 'WC' ) ) {
return;
}
wp_register_script( 'doffice-ga4-atc', '', array( 'jquery' ), null, true );
wp_enqueue_script( 'doffice-ga4-atc' );
// Despite the name, wp_localize_script() is used here to pass data from PHP
// to JavaScript (the store currency), NOT for translation.
wp_localize_script( 'doffice-ga4-atc', 'dofficeGA4', array(
'currency' => get_woocommerce_currency(),
) );
$js = <<<'JS'
window.dataLayer = window.dataLayer || [];
jQuery(function ($) {
// Fires after a SUCCESSFUL AJAX add-to-cart from a product loop button.
$(document.body).on('added_to_cart', function (e, fragments, cart_hash, $button) {
if (!$button || !$button.data('ga4-name')) return;
var qty = parseInt($button.data('quantity'), 10) || 1;
var price = parseFloat($button.data('ga4-price')) || 0;
window.dataLayer.push({ ecommerce: null });
window.dataLayer.push({
event: 'add_to_cart',
ecommerce: {
currency: dofficeGA4.currency,
// add_to_cart represents the value of THIS action,
// NOT the current total cart value.
value: Math.round(price * qty * 100) / 100,
items: [{
item_id: String($button.data('ga4-id')),
item_name: $button.data('ga4-name'),
item_category: $button.data('ga4-category') || '',
price: price,
quantity: qty
}]
}
});
});
});
JS;
wp_add_inline_script( 'doffice-ga4-atc', $js );
}למה מצמידים נתונים לכפתור? כדי שברגע שאירוע added_to_cart נורה, נוכל לקרוא את שם המוצר, המחיר והמזהה ישירות מהכפתור, בלי לבצע קריאת AJAX נוספת לשרת. כך האירוע נשאר מיידי, בלי להמתין לתגובה נוספת מהשרת.
wp_localize_script() משמש כאן להעברת נתונים מ-PHP ל-JavaScript (המטבע), ולא לצורך תרגום.לגבי המחיר: GA4 מתאר את פעולת ההוספה לעגלה, ולכן ברוב החנויות נכון לשלוח את המחיר שהיה מוצג בזמן הלחיצה (wc_get_price_to_display). אם המחיר משתנה רק לאחר ההוספה (למשל קופונים או Dynamic Pricing), יש למדוד את המחיר הסופי מתוך העגלה.
אותה שיטה כמו בשאר האירועים: טריגר Custom Event בשם add_to_cart, ותגית GA4 Event עם אותו שם, Send Ecommerce data מ-Data Layer, מחוברת לטריגר. משתמשים באותו משתנה ecommerce מהמדריכים הקודמים. שומרים ו-Publish.
נכנסים לעמוד קטגוריה, מוסיפים מוצר, ובקונסול מסננים את האירוע:
window.dataLayer.filter(e => e.event === "add_to_cart")
// Expected after adding a product from the shop / category page:
[
{
event: "add_to_cart",
ecommerce: {
currency: "ILS",
value: 349.90,
items: [
{ item_id: "SKU-1", item_name: "...", item_category: "...", price: 349.90, quantity: 1 }
]
}
}
]ואז מוודאים ב-GA4 DebugView שהאירוע נכנס עם items, value ו-currency תקינים.
added_to_cart לא נורה, ונדרש מאזין אחר.add_to_cart פותח את משפך המסחר, ועכשיו שלושת השלבים מחוברים:
הצעדים הבאים באותה שיטה: אירוע view_item (צפייה במוצר) שפותח את המשפך אפילו מוקדם יותר, וחיבור Meta Pixel + CAPI לאותם אירועים עם event_id משותף לדדופליקציה.
נחבר את כל אירועי המסחר, מהוספה לעגלה ועד הרכישה, ל-GA4 ולמטא, בהתאמה לאיך שהחנות שלכם באמת עובדת (כולל Blocks ובילדרים), כדי שתראו בדיוק היכן הלקוחות נופלים.
בואו נדבר