Created
August 18, 2025 19:12
-
-
Save mattpramschufer/1619723ef12a814790d6edeaa959aa49 to your computer and use it in GitHub Desktop.
Fires WooCommerce purchase event on thankyou page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Push GA4 purchase to dataLayer directly from WooCommerce thankyou hook. | |
* - Fires exactly when woocommerce_thankyou runs (confirmed on your site) | |
* - Includes a per-order/browser dedupe guard | |
* - Uses GA4-standard ecommerce payload (transaction_id, value, items, etc.) | |
*/ | |
add_action( 'woocommerce_thankyou', function ( $order_id ) { | |
if ( ! $order_id || ! function_exists( 'wc_get_order' ) ) { | |
return; | |
} | |
$order = wc_get_order( $order_id ); | |
if ( ! $order ) { | |
return; | |
} | |
// Only successful purchases (adjust if you also want 'on-hold' or 'completed' only) | |
if ( ! $order->has_status( array( 'processing', 'completed' ) ) ) { | |
return; | |
} | |
$currency = $order->get_currency(); | |
$value = (float) $order->get_total(); | |
$tax = (float) $order->get_total_tax(); | |
$shipping = (float) $order->get_shipping_total(); | |
$coupon = $order->get_coupon_codes() ? implode( ',', $order->get_coupon_codes() ) : ''; | |
$items = array(); | |
foreach ( $order->get_items() as $item_id => $item ) { | |
$product = $item->get_product(); | |
$sku_or_id = $product ? ( $product->get_sku() ?: $product->get_id() ) : $item_id; | |
$cat_path = ''; | |
if ( $product && function_exists( 'wc_get_product_category_list' ) ) { | |
$cat_path = wp_strip_all_tags( wc_get_product_category_list( $product->get_id(), ' / ' ) ); | |
} | |
$items[] = array( | |
'item_id' => (string) $sku_or_id, | |
'item_name' => (string) $item->get_name(), | |
'quantity' => (int) $item->get_quantity(), | |
'price' => (float) $order->get_item_total( $item, false, true ), // unit price ex tax | |
'item_category' => $cat_path ?: '', | |
); | |
} | |
$payload = array( | |
'transaction_id' => (string) $order->get_order_number(), | |
'value' => $value, | |
'currency' => $currency, | |
'tax' => $tax, | |
'shipping' => $shipping, | |
'coupon' => $coupon, | |
'items' => array_values( $items ), | |
); | |
// Print the push right where the hook runs (works even if wp_footer is missing) | |
// Includes a sessionStorage guard to avoid re-push on reload/back | |
echo '<script id="emx-purchase-' . (int) $order_id . '">'; | |
echo '(function(){try{'; | |
echo 'var k="emx_purchase_pushed_' . (int) $order_id . '";'; | |
echo 'if(sessionStorage.getItem(k))return;'; | |
echo 'window.dataLayer=window.dataLayer||[];'; | |
echo 'dataLayer.push({event:"purchase",ecommerce:' . wp_json_encode( $payload ) . '});'; | |
// Optional: also push GTM4WP legacy name in case your trigger listens for it | |
echo 'dataLayer.push({event:"gtm4wp.orderCompletedEEC",ecommerce:' . wp_json_encode( $payload ) . '});'; | |
// Clear ecommerce object to prevent accidental reuse | |
echo 'dataLayer.push({ecommerce:null});'; | |
echo 'sessionStorage.setItem(k,"1");'; | |
echo 'console.log("[emx] purchase pushed for order #' . (int) $order_id . '", ' . wp_json_encode( $payload ) . ');'; | |
echo '}catch(e){console&&console.warn&&console.warn("emx purchase push error",e);} })();'; | |
echo '</script>' . "\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
// Tiny HTML breadcrumb for quick view-source debugging | |
echo "\n<!-- emx: pushed GA4 purchase for order #{$order_id} -->\n"; | |
}, 20 ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment