PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.7
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.7
16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 All 506 releases
jetpack / jetpack_vendor / automattic / woocommerce-analytics / src / class-universal.php

class-universal.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3-a.7, at jetpack_vendor/automattic/woocommerce-analytics/src/class-universal.php

726 lines 24.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * General store tracking actions.
4 *
5 * @package automattic/woocommerce-analytics
6 */
7
8 namespace Automattic\Woocommerce_Analytics;
9
10 use Automattic\Jetpack\Constants;
11 use WC_Order;
12 use WC_Product;
13
14 /**
15 * Filters and Actions added to Store pages to perform analytics.
16 */
17 class Universal {
18 /**
19 * Trait to handle common analytics functions.
20 */
21 use Woo_Analytics_Trait;
22
23 /**
24 * Constructor.
25 */
26 public function init_hooks() {
27 $this->find_cart_checkout_content_sources();
28 $this->additional_blocks_on_cart_page = $this->get_additional_blocks_on_page( 'cart' );
29 $this->additional_blocks_on_checkout_page = $this->get_additional_blocks_on_page( 'checkout' );
30
31 // Capture search
32 add_action( 'template_redirect', array( $this, 'capture_search_query' ), 11 );
33
34 // Capture cart events.
35 add_action( 'woocommerce_add_to_cart', array( $this, 'capture_add_to_cart' ), 10, 6 );
36 add_action( 'woocommerce_after_cart_item_quantity_update', array( $this, 'capture_cart_quantity_update' ), 10, 4 );
37 add_action( 'woocommerce_cart_item_removed', array( $this, 'capture_remove_from_cart' ), 10, 2 );
38 add_filter( 'woocommerce_cart_item_remove_link', array( $this, 'remove_from_cart_attributes' ), 10, 2 );
39
40 // Checkout.
41 // Send events after checkout template (shortcode).
42 add_action( 'woocommerce_after_checkout_form', array( $this, 'checkout_process' ) );
43 // Send events after checkout block.
44 add_action( 'woocommerce_blocks_enqueue_checkout_block_scripts_after', array( $this, 'checkout_process' ) );
45
46 // order processed.
47 add_action( 'woocommerce_checkout_order_processed', array( $this, 'order_process' ), 10, 1 );
48 add_action( 'woocommerce_store_api_checkout_order_processed', array( $this, 'order_process' ), 10, 1 );
49
50 add_filter( 'woocommerce_checkout_posted_data', array( $this, 'save_checkout_post_data' ), 10, 1 );
51
52 add_action( 'woocommerce_created_customer', array( $this, 'capture_created_customer' ), 10, 2 );
53
54 add_action( 'woocommerce_created_customer', array( $this, 'capture_post_checkout_created_customer' ), 10, 2 );
55
56 // single product page view.
57 add_action( 'woocommerce_after_single_product', array( $this, 'capture_product_view' ) );
58
59 // order confirmed page view
60 add_action( 'woocommerce_thankyou', array( $this, 'capture_order_confirmation_view' ), 10, 1 );
61
62 // checkout page view
63 add_action( 'wp_footer', array( $this, 'capture_checkout_view' ), 11 );
64
65 // cart page view
66 add_action( 'wp_footer', array( $this, 'capture_cart_view' ), 11 );
67
68 // Enqueue events to track.
69 add_action( 'wp_footer', array( $this, 'inject_analytics_data' ), 999 );
70 }
71
72 /**
73 * Inject analytics data into the window object
74 */
75 public function inject_analytics_data() {
76 $is_clickhouse_enabled = Features::is_clickhouse_enabled();
77 $is_proxy_tracking_enabled = Features::is_proxy_tracking_enabled();
78 // When proxy tracking is enabled, we don't need to send the common properties to the client.
79 // Otherwise send only the page-safe properties: this markup is cacheable, so nothing
80 // derived from the current request may go into it.
81 $common_properties = $is_proxy_tracking_enabled ? array() : $this->get_page_common_properties();
82 ?>
83 <script type="text/javascript">
84 (function() {
85 // Always start from a fresh object: a `||` fallback would keep a same-named DOM element alive.
86 window.wcAnalytics = {};
87 const wcAnalytics = window.wcAnalytics;
88
89 // Set the assets URL for webpack to find the split assets.
90 wcAnalytics.assets_url = '<?php echo esc_url( plugins_url( '../build/', __DIR__ . '/class-woocommerce-analytics.php' ) ); ?>';
91
92 // Set the REST API tracking endpoint URL.
93 <?php
94 $track_endpoint = rest_url( 'woocommerce-analytics/v1/track' );
95 // Include the WP REST nonce for logged-in users so WordPress can identify
96 // the current user via cookie auth. This is needed for the store_admin
97 // property detection, not for endpoint authorization.
98 if ( is_user_logged_in() ) {
99 $track_endpoint = add_query_arg( '_wpnonce', wp_create_nonce( 'wp_rest' ), $track_endpoint );
100 }
101 ?>
102 wcAnalytics.trackEndpoint = <?php echo wp_json_encode( esc_url_raw( $track_endpoint ), JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ); ?>;
103
104 // Set common properties for all events.
105 wcAnalytics.commonProps = <?php echo wp_json_encode( $common_properties, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ); ?>;
106
107 // Set the event queue.
108 wcAnalytics.eventQueue = <?php echo wp_json_encode( WC_Analytics_Tracking::get_event_queue(), JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ); ?>;
109
110 // Features.
111 wcAnalytics.features = {
112 ch: <?php echo $is_clickhouse_enabled ? 'true' : 'false'; ?>,
113 sessionTracking: <?php echo $is_clickhouse_enabled ? 'true' : 'false'; ?>,
114 proxy: <?php echo $is_proxy_tracking_enabled ? 'true' : 'false'; ?>,
115 };
116
117 wcAnalytics.breadcrumbs = <?php echo wp_json_encode( $this->get_breadcrumb_titles(), JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ); ?>;
118
119 // Page context flags.
120 wcAnalytics.pages = {
121 isAccountPage: <?php echo is_account_page() ? 'true' : 'false'; ?>,
122 isCart: <?php echo is_cart() ? 'true' : 'false'; ?>,
123 };
124 })();
125 </script>
126 <?php
127 }
128
129 /**
130 * Capture remove from cart events in mini-cart and cart blocks
131 *
132 * @param string $cart_item_key The cart item removed.
133 * @param \WC_Cart $cart The cart.
134 *
135 * @return void
136 */
137 public function capture_remove_from_cart( $cart_item_key, $cart ) {
138 $item = $cart->removed_cart_contents[ $cart_item_key ] ?? null;
139
140 if ( ! is_array( $item ) || ! isset( $item['product_id'], $item['quantity'] ) ) {
141 return;
142 }
143
144 WC_Analytics_Tracking::record_event(
145 'remove_from_cart',
146 $this->get_cart_checkout_event_properties(
147 array(
148 'pi' => (int) $item['product_id'],
149 'pq' => (int) $item['quantity'],
150 )
151 )
152 );
153 }
154
155 /**
156 * Capture remove/add from cart events using the Cart Controller
157 *
158 * @param string $cart_item_key The cart item updated.
159 * @param int $quantity Contains the new quantity of the item.
160 * @param int $old_quantity Contains the old quantity of the item.
161 * @param \WC_Cart $cart The cart.
162 *
163 * @return void
164 */
165 public function capture_cart_quantity_update( $cart_item_key, $quantity, $old_quantity, $cart ) {
166 if ( ! isset( $cart->cart_contents[ $cart_item_key ]['product_id'] ) ) {
167 return;
168 }
169
170 $product_id = $cart->cart_contents[ $cart_item_key ]['product_id'];
171 if ( $quantity > $old_quantity ) {
172 WC_Analytics_Tracking::record_event(
173 'add_to_cart',
174 $this->get_cart_checkout_event_properties(
175 array(
176 'pi' => $product_id,
177 'pq' => $quantity,
178 )
179 )
180 );
181 $this->lock_add_to_cart_events = true;
182 return;
183 }
184
185 if ( $quantity < $old_quantity ) {
186 WC_Analytics_Tracking::record_event(
187 'remove_from_cart',
188 $this->get_cart_checkout_event_properties(
189 array(
190 'pi' => $product_id,
191 'pq' => $quantity,
192 )
193 )
194 );
195 return;
196 }
197 }
198
199 /**
200 * Adds the product ID to the remove product link (for use by remove_from_cart above) if not present
201 *
202 * @param string $url Full HTML a tag of the link to remove an item from the cart.
203 * @param string $key Unique Key ID for a cart item.
204 *
205 * @return string
206 */
207 public function remove_from_cart_attributes( $url, $key ) {
208 if ( str_contains( $url, 'data-product_id' ) ) {
209 return $url;
210 }
211
212 $item = WC()->cart->get_cart_item( $key );
213 $product = $item['data'];
214
215 $new_attributes = sprintf(
216 '" data-product_id="%s">',
217 esc_attr( $product->get_id() )
218 );
219
220 $url = str_replace( '">', $new_attributes, $url );
221 return $url;
222 }
223
224 /**
225 * Get the selected shipping option for a cart item. If the name cannot be found in the options table, the method's
226 * ID will be used.
227 *
228 * @param string $cart_item_key the cart item key.
229 *
230 * @return mixed|bool
231 */
232 public function get_shipping_option_for_item( $cart_item_key ) {
233 $packages = wc()->shipping()->get_packages();
234 $selected_options = wc()->session->get( 'chosen_shipping_methods' );
235
236 if ( ! is_array( $packages ) || ! is_array( $selected_options ) ) {
237 return false;
238 }
239
240 foreach ( $packages as $package_id => $package ) {
241
242 if ( ! isset( $package['contents'] ) || ! is_array( $package['contents'] ) ) {
243 return false;
244 }
245
246 foreach ( $package['contents'] as $package_item ) {
247 if ( ! isset( $package_item['key'] ) || $package_item['key'] !== $cart_item_key || ! isset( $selected_options[ $package_id ] ) ) {
248 continue;
249 }
250 $selected_rate_id = $selected_options[ $package_id ];
251 $method_key_id = sanitize_text_field( str_replace( ':', '_', $selected_rate_id ) );
252 $option_name = 'woocommerce_' . $method_key_id . '_settings';
253 $option_value = get_option( $option_name );
254 $title = '';
255 if ( is_array( $option_value ) && isset( $option_value['title'] ) ) {
256 $title = $option_value['title'];
257 }
258 if ( ! $title ) {
259 return $selected_rate_id;
260 }
261 return $title;
262 }
263 }
264
265 return false;
266 }
267
268 /**
269 * On the Checkout page, trigger an event for each product in the cart
270 */
271 public function checkout_process() {
272 global $post;
273 $checkout_page_id = wc_get_page_id( 'checkout' );
274 $cart = WC()->cart->get_cart();
275 $is_in_checkout_page = isset( $post->ID ) && $checkout_page_id === $post->ID ? 'Yes' : 'No';
276 $session = WC()->session;
277 if ( is_object( $session ) ) {
278 $session->set( 'checkout_page_used', 'Yes' === $is_in_checkout_page );
279 $session->save_data();
280 }
281
282 foreach ( $cart as $cart_item_key => $cart_item ) {
283 /**
284 * This filter is already documented in woocommerce/templates/cart/cart.php
285 */
286 $product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
287
288 if ( ! $product || ! $product instanceof WC_Product ) {
289 continue;
290 }
291
292 $data = $this->get_cart_checkout_shared_data();
293
294 $data['from_checkout'] = $is_in_checkout_page;
295
296 if ( ! empty( $data['products'] ) ) {
297 unset( $data['products'] );
298 }
299
300 if ( ! empty( $data['shipping_options_count'] ) ) {
301 unset( $data['shipping_options_count'] );
302 }
303
304 $data['pq'] = $cart_item['quantity'];
305 $this->enqueue_event( 'product_checkout', $this->get_cart_checkout_event_properties( $data ), $product->get_id() );
306 }
307 }
308
309 /**
310 * After the order processed, fire an event for each item in the order
311 *
312 * @param int|string|WC_Order $order_id_or_order Order Id or Order object.
313 */
314 public function order_process( $order_id_or_order ) {
315 $order = wc_get_order( $order_id_or_order );
316
317 if ( ! $order ) {
318 return;
319 }
320
321 $payment_option = $order->get_payment_method();
322
323 if ( is_object( WC()->session ) ) {
324 $create_account = true === WC()->session->get( 'wc_checkout_createaccount_used' ) ? 'Yes' : 'No';
325 $checkout_page_used = true === WC()->session->get( 'checkout_page_used' ) ? 'Yes' : 'No';
326
327 } else {
328 $create_account = 'No';
329 $checkout_page_used = 'No';
330 }
331
332 $delayed_account_creation = ucfirst( get_option( 'woocommerce_enable_delayed_account_creation', 'Yes' ) );
333
334 $guest_checkout = $order->get_user() ? 'No' : 'Yes';
335
336 $express_checkout = 'null';
337 // When the payment option is woocommerce_payment
338 // See if Google Pay or Apple Pay was used.
339 if ( 'woocommerce_payments' === $payment_option ) {
340 $payment_option_title = $order->get_payment_method_title();
341 if ( 'Google Pay (WooCommerce Payments)' === $payment_option_title ) {
342 $express_checkout = array( 'google_pay' );
343 } elseif ( 'Apple Pay (WooCommerce Payments)' === $payment_option_title ) {
344 $express_checkout = array( 'apple_pay' );
345 }
346 }
347
348 $checkout_page_contains_checkout_block = '0';
349 $checkout_page_contains_checkout_shortcode = '0';
350
351 $order_source = $order->get_created_via();
352 if ( 'store-api' === $order_source ) {
353 $checkout_page_contains_checkout_block = '1';
354 } elseif ( 'checkout' === $order_source ) {
355 $checkout_page_contains_checkout_shortcode = '1';
356 }
357
358 // loop through products in the order and queue a purchase event.
359 foreach ( $order->get_items() as $order_item ) {
360 // @phan-suppress-next-line PhanUndeclaredMethod -- Checked before being called. See also https://github.com/phan/phan/issues/1204.
361 $product_id = is_callable( array( $order_item, 'get_product_id' ) ) ? $order_item->get_product_id() : -1;
362
363 $order_items = $order->get_items();
364 $order_items_count = 0;
365 if ( is_array( $order_items ) ) {
366 $order_items_count = count( $order_items );
367 }
368 $order_coupons = $order->get_coupons();
369 $order_coupons_count = 0;
370 if ( is_array( $order_coupons ) ) {
371 $order_coupons_count = count( $order_coupons );
372 }
373
374 WC_Analytics_Tracking::record_event(
375 'product_purchase',
376 $this->get_cart_checkout_event_properties(
377 array(
378 'oi' => $order->get_order_number(),
379 'pi' => $product_id,
380 'pq' => $order_item->get_quantity(),
381 'payment_option' => $payment_option,
382 'create_account' => $create_account,
383 'guest_checkout' => $guest_checkout,
384 'delayed_account_creation' => $delayed_account_creation,
385 'express_checkout' => $express_checkout,
386 'coupon_used' => $order_coupons_count,
387 'products_count' => $order_items_count,
388 'order_value' => $order->get_subtotal(),
389 'order_total' => $order->get_total(),
390 'total_discount' => $order->get_discount_total(),
391 'total_taxes' => $order->get_total_tax(),
392 'total_shipping' => $order->get_shipping_total(),
393 'from_checkout' => $checkout_page_used,
394 'checkout_page_contains_checkout_block' => $checkout_page_contains_checkout_block,
395 'checkout_page_contains_checkout_shortcode' => $checkout_page_contains_checkout_shortcode,
396 )
397 )
398 );
399 }
400 }
401 /**
402 * Gets the inner blocks of a block.
403 *
404 * @param array $inner_blocks The inner blocks.
405 *
406 * @return array
407 */
408 private function get_inner_blocks( $inner_blocks ) {
409 $block_names = array();
410 if ( ! empty( $inner_blocks['blockName'] ) ) {
411 $block_names[] = $inner_blocks['blockName'];
412 }
413 if ( isset( $inner_blocks['innerBlocks'] ) && is_array( $inner_blocks['innerBlocks'] ) ) {
414 $block_names = array_merge( $block_names, $this->get_inner_blocks( $inner_blocks['innerBlocks'] ) );
415 }
416 return $block_names;
417 }
418
419 /**
420 * Track adding items to the cart.
421 *
422 * @param string $cart_item_key Cart item key.
423 * @param int $product_id Product added to cart.
424 * @param int $quantity Quantity added to cart.
425 * @param int $variation_id Product variation.
426 * @param array $variation Variation attributes..
427 * @param array $cart_item_data Other cart data.
428 */
429 public function capture_add_to_cart( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
430 if ( $this->lock_add_to_cart_events ) {
431 return;
432 }
433 WC_Analytics_Tracking::record_event(
434 'add_to_cart',
435 $this->get_cart_checkout_event_properties(
436 array(
437 'pi' => $product_id,
438 'pq' => $quantity,
439 )
440 )
441 );
442 }
443
444 /**
445 * Get the event properties for the cart and checkout events.
446 *
447 * @param array $event_properties Event properties.
448 */
449 public function get_cart_checkout_event_properties( $event_properties = array() ) {
450 if ( isset( $event_properties['pq'] ) ) {
451 $event_properties['pq'] = 0 === $event_properties['pq'] ? 1 : $event_properties['pq'];
452 $event_properties['pq'] = (string) $event_properties['pq'];
453 }
454 $product = isset( $event_properties['pi'] ) ? wc_get_product( $event_properties['pi'] ) : null;
455 $product_details = $product instanceof WC_Product ? $this->get_product_details( $product ) : array();
456
457 $checkout_cart_details = array(
458 'template_used' => $this->cart_checkout_templates_in_use ? '1' : '0',
459 'additional_blocks_on_cart_page' => $this->additional_blocks_on_cart_page,
460 'additional_blocks_on_checkout_page' => $this->additional_blocks_on_checkout_page,
461 'order_value' => $this->get_cart_subtotal(),
462 'order_total' => $this->get_cart_total(),
463 'total_tax' => $this->get_cart_taxes(),
464 'total_discount' => $this->get_total_discounts(),
465 'total_shipping' => $this->get_cart_shipping_total(),
466 'products_count' => $this->get_cart_items_count(),
467 );
468 $cart_checkout_info = $this->get_cart_checkout_info();
469
470 $event_properties = array_merge( $product_details, $checkout_cart_details, $cart_checkout_info, $event_properties ); // event properties should be last to allow for overrides
471
472 return $event_properties;
473 }
474
475 /**
476 * Save create account post data to be used in $this->order_process.
477 *
478 * @param array|null $data Post data from the checkout page.
479 *
480 * @return array|null
481 */
482 public function save_checkout_post_data( ?array $data ) {
483 if ( is_object( WC()->session ) && ! empty( $data['createaccount'] ) ) {
484 WC()->session->set( 'wc_checkout_createaccount_used', true );
485 WC()->session->save_data();
486 }
487 return $data;
488 }
489
490 /**
491 * Capture the create account event. Similar to save_checkout_post_data but works with Store API.
492 *
493 * @param int $customer_id Customer ID.
494 * @param array $new_customer_data New customer data.
495 */
496 public function capture_created_customer( $customer_id, $new_customer_data ) {
497 $session = WC()->session;
498 if (
499 is_object( $session )
500 && is_array( $new_customer_data )
501 && ! empty( $new_customer_data['source'] )
502 ) {
503 if ( str_contains( $new_customer_data['source'], 'store-api' ) ) {
504 $session->set( 'wc_checkout_createaccount_used', true );
505 $session->save_data();
506 }
507 }
508 }
509
510 /**
511 * Capture the post checkout create account event.
512 *
513 * @param int $customer_id Customer ID.
514 * @param array $new_customer_data New customer data.
515 */
516 public function capture_post_checkout_created_customer( $customer_id, $new_customer_data ) {
517 if (
518 is_array( $new_customer_data )
519 && ! empty( $new_customer_data['source'] )
520 && str_contains( $new_customer_data['source'], 'delayed-account-creation' )
521 ) {
522
523 $checkout_page_used = true === WC()->session->get( 'checkout_page_used' ) ? 'Yes' : 'No';
524 $checkout_page_contains_checkout_block = '1';
525 $checkout_page_contains_checkout_shortcode = '0';
526
527 $this->enqueue_event(
528 'post_account_creation',
529 $this->get_cart_checkout_event_properties(
530 array(
531 'from_checkout' => $checkout_page_used,
532 'checkout_page_contains_checkout_block' => $checkout_page_contains_checkout_block,
533 'checkout_page_contains_checkout_shortcode' => $checkout_page_contains_checkout_shortcode,
534 )
535 )
536 );
537 }
538 }
539
540 /**
541 * Capture a search event.
542 *
543 * The term is capped because this event is assembled here but fired by the
544 * client, so it travels through the page markup and then reaches the pixel
545 * URL. See `cap_page_string()`.
546 */
547 public function capture_search_query() {
548 if ( is_search() ) {
549 global $wp_query;
550 $this->enqueue_event(
551 'search_performed',
552 array(
553 'search_query' => $this->cap_page_string( $wp_query->get( 's' ) ),
554 'qty' => $wp_query->found_posts,
555 )
556 );
557 }
558 }
559
560 /**
561 * Track the cart page view
562 */
563 public function capture_cart_view() {
564 global $post;
565 $cart_page_id = wc_get_page_id( 'cart' );
566
567 $is_cart = $cart_page_id && is_page( $cart_page_id )
568 || wc_post_content_has_shortcode( 'woocommerce_cart' )
569 || has_block( 'woocommerce/cart', $post )
570 || apply_filters( 'woocommerce_is_cart', false )
571 || Constants::is_defined( 'WOOCOMMERCE_CART' )
572 || is_cart();
573
574 if ( ! $is_cart ) {
575 return;
576 }
577
578 $this->enqueue_event(
579 'cart_view',
580 $this->get_cart_checkout_event_properties(
581 $this->get_cart_checkout_shared_data()
582 )
583 );
584 }
585
586 /**
587 * Track a product page view
588 */
589 public function capture_product_view() {
590 global $product;
591 if ( ! $product instanceof WC_Product ) {
592 return;
593 }
594
595 $this->enqueue_event(
596 'product_view',
597 array(),
598 $product->get_id()
599 );
600 }
601
602 /**
603 * Track the order confirmation page view
604 */
605 public function capture_order_confirmation_view() {
606 $order_id = absint( get_query_var( 'order-received' ) );
607 if ( ! $order_id ) {
608 return;
609 }
610
611 if ( ! is_order_received_page() ) {
612 return;
613 }
614
615 $order = wc_get_order( $order_id );
616
617 $order_source = $order->get_created_via();
618 $checkout_page_contains_checkout_block = '0';
619 $checkout_page_contains_checkout_shortcode = '0';
620
621 if ( 'store-api' === $order_source ) {
622 $checkout_page_contains_checkout_block = '1';
623 } elseif ( 'checkout' === $order_source ) {
624 $checkout_page_contains_checkout_shortcode = '1';
625 }
626
627 $coupons = $order->get_coupons();
628 $coupon_used = 0;
629 if ( is_countable( $coupons ) ) {
630 $coupon_used = count( $coupons ) ? 1 : 0;
631 }
632
633 if ( is_object( WC()->session ) ) {
634 $create_account = true === WC()->session->get( 'wc_checkout_createaccount_used' ) ? 'Yes' : 'No';
635 $checkout_page_used = true === WC()->session->get( 'checkout_page_used' ) ? 'Yes' : 'No';
636 } else {
637 $create_account = 'No';
638 $checkout_page_used = 'No';
639 }
640
641 $delayed_account_creation = ucfirst( get_option( 'woocommerce_enable_delayed_account_creation', 'Yes' ) );
642 $this->enqueue_event(
643 'order_confirmation_view',
644 $this->get_cart_checkout_event_properties(
645 array(
646 'coupon_used' => $coupon_used,
647 'create_account' => $create_account,
648 'express_checkout' => 'null', // TODO: not solved yet.
649 'guest_checkout' => $order->get_customer_id() ? 'No' : 'Yes',
650 'delayed_account_creation' => $delayed_account_creation,
651 'oi' => $order->get_id(),
652 'order_value' => $order->get_subtotal(),
653 'order_total' => $order->get_total(),
654 'products_count' => $order->get_item_count(),
655 'total_discount' => $order->get_discount_total(),
656 'total_shipping' => $order->get_shipping_total(),
657 'total_tax' => $order->get_total_tax(),
658 'payment_option' => $order->get_payment_method(),
659 'products' => $this->format_items_to_json( $order->get_items() ),
660 'order_note' => $order->get_customer_note(),
661 'shipping_option' => $order->get_shipping_method(),
662 'from_checkout' => $checkout_page_used,
663 'checkout_page_contains_checkout_block' => $checkout_page_contains_checkout_block,
664 'checkout_page_contains_checkout_shortcode' => $checkout_page_contains_checkout_shortcode,
665 )
666 )
667 );
668 }
669
670 /**
671 * Track the checkout page view
672 */
673 public function capture_checkout_view() {
674 global $post;
675 if ( ! $post instanceof \WP_Post ) {
676 return;
677 }
678
679 $checkout_page_id = wc_get_page_id( 'checkout' );
680
681 $is_checkout = $checkout_page_id && is_page( $checkout_page_id )
682 || wc_post_content_has_shortcode( 'woocommerce_checkout' )
683 || has_block( 'woocommerce/checkout', $post )
684 || apply_filters( 'woocommerce_is_checkout', false )
685 || Constants::is_defined( 'WOOCOMMERCE_CHECKOUT' );
686
687 if ( ! $is_checkout ) {
688 return;
689 }
690
691 $is_in_checkout_page = isset( $post->ID ) && $checkout_page_id === $post->ID ? 'Yes' : 'No';
692 $checkout_page_contains_checkout_block = '0';
693 $checkout_page_contains_checkout_shortcode = '1';
694
695 $session = WC()->session;
696 if ( is_object( $session ) ) {
697 $session->set( 'checkout_page_used', true );
698 $session->save_data();
699 $draft_order_id = $session->get( 'store_api_draft_order', 0 );
700 if ( $draft_order_id ) {
701 $checkout_page_contains_checkout_block = '1';
702 $checkout_page_contains_checkout_shortcode = '0';
703 }
704 }
705
706 // Order received page is also a checkout page, so we need to bail out if we are on that page.
707 if ( is_order_received_page() ) {
708 return;
709 }
710
711 $this->enqueue_event(
712 'checkout_view',
713 $this->get_cart_checkout_event_properties(
714 array_merge(
715 $this->get_cart_checkout_shared_data(),
716 array(
717 'from_checkout' => $is_in_checkout_page,
718 'checkout_page_contains_checkout_block' => $checkout_page_contains_checkout_block,
719 'checkout_page_contains_checkout_shortcode' => $checkout_page_contains_checkout_shortcode,
720 )
721 )
722 )
723 );
724 }
725 }
726