Skip to content

Commit 949d7a8

Browse files
author
Eugene Manuilov
authored
Merge pull request #10727 from google/enhancement/10670-expand-woo-tracking-details
Enhancement/10670 expand woo tracking details
2 parents 4c7f1ff + dd0fdc1 commit 949d7a8

2 files changed

Lines changed: 203 additions & 0 deletions

File tree

  • includes/Core/Conversion_Tracking/Conversion_Event_Providers
  • tests/phpunit/integration/Core/Conversion_Tracking/Conversion_Event_Providers

includes/Core/Conversion_Tracking/Conversion_Event_Providers/WooCommerce.php

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,23 @@ class WooCommerce extends Conversion_Events_Provider {
2525

2626
const CONVERSION_EVENT_PROVIDER_SLUG = 'woocommerce';
2727

28+
/**
29+
* Avaialble products on the page.
30+
*
31+
* @var Array
32+
*
33+
* @since n.e.x.t
34+
*/
35+
protected $products = array();
36+
37+
/**
38+
* Current product added to the cart.
39+
*
40+
* @since n.e.x.t
41+
* @var WC_Product
42+
*/
43+
protected $add_to_cart;
44+
2845
/**
2946
* Checks if the WooCommerce plugin is active.
3047
*
@@ -77,6 +94,31 @@ public function register_script() {
7794
public function register_hooks() {
7895
$input = $this->context->input();
7996

97+
add_filter(
98+
'woocommerce_loop_add_to_cart_link',
99+
function ( $button, $product ) {
100+
$this->products[] = $this->get_formatted_product( $product );
101+
102+
return $button;
103+
},
104+
10,
105+
2
106+
);
107+
108+
add_action(
109+
'woocommerce_add_to_cart',
110+
function ( $cart_item_key, $product_id, $quantity, $variation_id, $variation ) {
111+
$this->add_to_cart = $this->get_formatted_product(
112+
wc_get_product( $product_id ),
113+
$variation_id,
114+
$variation,
115+
$quantity
116+
);
117+
},
118+
10,
119+
5
120+
);
121+
80122
add_action(
81123
'woocommerce_thankyou',
82124
function ( $order_id ) use ( $input ) {
@@ -102,12 +144,168 @@ function ( $order_id ) use ( $input ) {
102144
$order->update_meta_data( '_googlesitekit_ga_purchase_event_tracked', 1 );
103145
$order->save();
104146

147+
wp_add_inline_script(
148+
'googlesitekit-events-provider-' . self::CONVERSION_EVENT_PROVIDER_SLUG,
149+
join(
150+
"\n",
151+
array(
152+
'window._googlesitekit.wcdata = window._googlesitekit.wcdata || {};',
153+
sprintf( 'window._googlesitekit.wcdata.purchase = %s;', wp_json_encode( $this->get_formatted_order( $order ) ) ),
154+
)
155+
),
156+
'before'
157+
);
158+
105159
// Output the script tag to track the purchase event in
106160
// Analytics.
107161
BC_Functions::wp_print_inline_script_tag( "window?._googlesitekit?.gtagEvent?.( 'purchase' );" );
108162
},
109163
10,
110164
1
111165
);
166+
167+
add_action(
168+
'wp_footer',
169+
function () {
170+
$script_slug = 'googlesitekit-events-provider-' . self::CONVERSION_EVENT_PROVIDER_SLUG;
171+
172+
$inline_script = join(
173+
"\n",
174+
array(
175+
'window._googlesitekit.wcdata = window._googlesitekit.wcdata || {};',
176+
sprintf( 'window._googlesitekit.wcdata.products = %s;', wp_json_encode( $this->products ) ),
177+
sprintf( 'window._googlesitekit.wcdata.add_to_cart = %s;', wp_json_encode( $this->add_to_cart ) ),
178+
sprintf( 'window._googlesitekit.wcdata.currency = "%s";', esc_js( get_woocommerce_currency() ) ),
179+
)
180+
);
181+
182+
wp_add_inline_script( $script_slug, $inline_script, 'before' );
183+
}
184+
);
185+
}
186+
187+
/**
188+
* Returns an array of product data in the required format.
189+
* Adapted from https://github.com/woocommerce/woocommerce-google-analytics-integration
190+
*
191+
* @since n.e.x.t
192+
*
193+
* @param WC_Product $product The product to format.
194+
* @param int $variation_id Variation product ID.
195+
* @param array|bool $variation An array containing product variation attributes to include in the product data.
196+
* For the "variation" type products, we'll use product->get_attributes.
197+
* @param bool|int $quantity Quantity to include in the formatted product object.
198+
*
199+
* @return array
200+
*/
201+
public function get_formatted_product( $product, $variation_id = 0, $variation = false, $quantity = false ) {
202+
$product_id = $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id();
203+
$price = $product->get_price();
204+
205+
// Get product price from chosen variation if set.
206+
if ( $variation_id ) {
207+
$variation_product = wc_get_product( $variation_id );
208+
if ( $variation_product ) {
209+
$price = $variation_product->get_price();
210+
}
211+
}
212+
213+
// Integration with Product Bundles.
214+
// Get the minimum price, as `get_price` may return 0 if the product is a bundle and the price is potentially a range.
215+
// Even a range containing a single value.
216+
if ( $product->is_type( 'bundle' ) && is_callable( array( $product, 'get_bundle_price' ) ) ) {
217+
$price = $product->get_bundle_price( 'min' );
218+
}
219+
220+
$formatted = array(
221+
'id' => $product_id,
222+
'name' => $product->get_title(),
223+
'categories' => array_map(
224+
fn( $category ) => array( 'name' => $category->name ),
225+
wc_get_product_terms( $product_id, 'product_cat', array( 'number' => 5 ) )
226+
),
227+
'price' => $this->get_formatted_price( $price ),
228+
);
229+
230+
if ( $quantity ) {
231+
$formatted['quantity'] = (int) $quantity;
232+
}
233+
234+
if ( $product->is_type( 'variation' ) ) {
235+
$variation = $product->get_attributes();
236+
}
237+
238+
if ( is_array( $variation ) ) {
239+
$formatted['variation'] = implode(
240+
', ',
241+
array_map(
242+
function ( $attribute, $value ) {
243+
return sprintf(
244+
'%s: %s',
245+
str_replace( 'attribute_', '', $attribute ),
246+
$value
247+
);
248+
},
249+
array_keys( $variation ),
250+
array_values( $variation )
251+
)
252+
);
253+
}
254+
255+
return $formatted;
256+
}
257+
258+
/**
259+
* Returns an array of order data in the required format.
260+
* Adapted from https://github.com/woocommerce/woocommerce-google-analytics-integration
261+
*
262+
* @since n.e.x.t
263+
*
264+
* @param WC_Abstract_Order $order An instance of the WooCommerce Order object.
265+
*
266+
* @return array
267+
*/
268+
public function get_formatted_order( $order ) {
269+
return array(
270+
'id' => $order->get_id(),
271+
'affiliation' => get_bloginfo( 'name' ),
272+
'totals' => array(
273+
'currency_code' => $order->get_currency(),
274+
'tax_total' => $this->get_formatted_price( $order->get_total_tax() ),
275+
'shipping_total' => $this->get_formatted_price( $order->get_total_shipping() ),
276+
'total_price' => $this->get_formatted_price( $order->get_total() ),
277+
),
278+
'items' => array_map(
279+
function ( $item ) {
280+
return array_merge(
281+
$this->get_formatted_product( $item->get_product() ),
282+
array(
283+
'quantity' => $item->get_quantity(),
284+
'price_after_coupon_discount' => $this->get_formatted_price( $item->get_total() ),
285+
)
286+
);
287+
},
288+
array_values( $order->get_items() ),
289+
),
290+
);
291+
}
292+
293+
/**
294+
* Formats a price the same way WooCommerce Blocks does.
295+
* Taken from https://github.com/woocommerce/woocommerce-google-analytics-integration
296+
*
297+
* @since n.e.x.t
298+
*
299+
* @param mixed $value The price value for format.
300+
*
301+
* @return int
302+
*/
303+
public function get_formatted_price( $value ) {
304+
return intval(
305+
round(
306+
( (float) wc_format_decimal( $value ) ) * ( 10 ** absint( wc_get_price_decimals() ) ),
307+
0
308+
)
309+
);
112310
}
113311
}

tests/phpunit/integration/Core/Conversion_Tracking/Conversion_Event_Providers/WooCommerceTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,12 @@ public function test_register_script() {
5757

5858
public function test_register_hooks() {
5959
$this->assertFalse( has_action( 'woocommerce_thankyou' ) );
60+
$this->assertFalse( has_action( 'woocommerce_add_to_cart' ) );
61+
$this->assertFalse( has_filter( 'woocommerce_loop_add_to_cart_link' ) );
62+
6063
$this->woocommerce->register_hooks();
6164
$this->assertTrue( has_action( 'woocommerce_thankyou' ) );
65+
$this->assertTrue( has_action( 'woocommerce_add_to_cart' ) );
66+
$this->assertTrue( has_filter( 'woocommerce_loop_add_to_cart_link' ) );
6267
}
6368
}

0 commit comments

Comments
 (0)