WooCommerce GA4 Ecommerce dataLayer
WordPress + WooCommerce plugin: 8 GA4 ecommerce dataLayer events for GTM (view_item_list, select_item, add_to_cart, remove_from_cart, view_item, view_cart, begin_checkout, purchase) with Google Ads dynamic remarketing fields and Google Merchant Center gtin
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/hadomdev/woo-ga4-ecommerce/archive/refs/heads/main.zipA focused WordPress plugin that pushes 8 GA4 ecommerce events into window.dataLayer for GTM, with the exact item structure required by Google Ads dynamic remarketing and Google Merchant Center.
Events covered
| Event | Where it fires | Source |
|---|---|---|
view_item_list |
shop / category / search / homepage loop | server (PHP) |
view_item |
single product page | server (PHP) |
view_cart |
cart page + cart fragment refresh | server (PHP) |
begin_checkout |
checkout page (one-shot per cart hash) | server (PHP) |
purchase |
thank-you page (one-shot per order) | server (PHP) |
select_item |
click on product card link | client (JS) |
add_to_cart |
Woo added_to_cart event + single ATC |
client (JS) |
remove_from_cart |
cart row + mini-cart remove | client (JS) |
Item structure
Each items[] entry contains:
item_id, item_name, price, item_brand, item_category,
quantity, item_list_id, item_list_name (when known),
id (duplicate of item_id, for Google Ads dynamic remarketing),
google_business_vertical: 'retail',
gtin (only on purchase, when available)
Architecture
Helper— brand resolver (Woo product attribute), GTIN resolver, primary category, price float, dataLayer push helper.ItemBuilder::build($product, $context)— single source of truth for item objects across all events.ListContext— resolves the current list (category slug,tag_<slug>,search,shop,home) soselect_itemandadd_to_cartcarry consistentitem_list_id/item_list_name.ServerEvents— registers WC hooks for view_item_list, view_item, view_cart, begin_checkout, purchase. One-shot guards: WC session cart hash forbegin_checkout; order meta_sdm_ga4_purchase_pushedforpurchase.ClientEvents— server-side injectsdata-sdm-ga4-item="{...}"on add-to-cart buttons, single-product hidden marker, and cart-row remove links. The accompanying JS reads these attributes on click / Woo events.assets/js/sdm-ga4.js— listeners forselect_item,add_to_cart,remove_from_cart, plus a fragment-refresh listener that re-emitsview_cartafter Woo updates the cart, plus a Woodmart-compatibility helper that propagates the data attribute from the add-to-cart button up to the product card link (forselect_itemclicks on the card image / title).
Brand and GTIN sources
Helper::get_brand( $product ) checks attributes in this order: Виробник, виробник, Бренд, бренд, Brand, brand, pa_brand, pa_vyrobnyk. First match wins; missing brand → key omitted from the item.
Helper::get_gtin( $product ) checks: WC_Product::get_global_unique_id() (Woo 9.4+), then meta _global_unique_id, ACF field gtin, finally meta _gtin. Missing GTIN → key omitted.
Compatibility notes
- Woodmart and similar themes override
woocommerce_loop_product_link, so the corresponding PHP filter does not get the chance to inject thedata-sdm-ga4-role="select_item"attribute on product card permalinks. The bundled JS performs the propagation client-side after DOM ready and afterupdated_wc_div/wc_fragments_refreshedevents. - The category slug for
item_list_idisurldecode()-ed so non-Latin slugs land in GA4 as readable Cyrillic instead ofvag-volkswagen-upor%d1%8b-.... - The plugin only pushes; it does not load
gtag.js. A GTM container (or a Site Kit / standalone Google Tag) is responsible for forwarding the events to GA4. The recommended GTM setup is a single GA4 Event Tag with Event name ={{Event}}and Send Ecommerce data → On, Source → Data Layer, fired by a Custom Event trigger with the regex^(view_item_list|select_item|add_to_cart|remove_from_cart|view_item|view_cart|begin_checkout|purchase)$.
Requirements
- WordPress 6.0+
- WooCommerce 8.0+
- PHP 7.4+