session ) { return; } $product = wc_get_product( $variation_id ? $variation_id : $product_id ); $parent = $variation_id ? wc_get_product( $product_id ) : $product; if ( ! $product || ! $parent ) { return; } $data = array( 'product_id' => (string) $product_id, 'product_title' => $parent->get_name(), 'variant_id' => $variation_id ? (string) $variation_id : '', 'variant_title' => $variation_id ? wc_get_formatted_variation( $product, true, false, false ) : '', 'variant_price' => (string) $product->get_price(), 'quantity' => (string) $quantity, ); $events = self::queued_events(); $events[] = array( 'name' => 'woocommerce_product_added_to_cart', 'data' => $data, ); WC()->session->set( self::SESSION_EVENTS, array_slice( $events, -self::MAX_QUEUED ) ); } /** * For AJAX add to cart, return the queued events with the cart fragments. * fullsession-woocommerce.js picks them up from the `added_to_cart` event. * * @param array $fragments Cart fragments. * @return array */ public static function add_fragment( $fragments ) { $is_add_to_cart = doing_action( 'wc_ajax_add_to_cart' ) || doing_action( 'wp_ajax_woocommerce_add_to_cart' ) || doing_action( 'wp_ajax_nopriv_woocommerce_add_to_cart' ); if ( ! $is_add_to_cart || ! self::is_enabled() ) { return $fragments; } $events = self::take_queued_events(); if ( $events ) { $fragments[ self::FRAGMENT_KEY ] = FullSession_Tracker::encode( $events ); } return $fragments; } /** * Events for the current page: queued add to cart, checkout started and order completed. * * @param array $events Events from other sources. * @return array */ public static function page_events( $events ) { if ( ! self::is_enabled() ) { return $events; } $events = array_merge( $events, self::take_queued_events() ); $checkout = self::checkout_started_event(); if ( $checkout ) { $events[] = $checkout; } $completed = self::checkout_completed_event(); if ( $completed ) { $events[] = $completed; } return $events; } /** * Load the add to cart listener. */ public static function enqueue() { if ( ! self::is_enabled() || ! wp_script_is( FullSession_Tracker::HANDLE, 'enqueued' ) ) { return; } wp_enqueue_script( 'fullsession-woocommerce', FULLSESSION_URL . 'assets/js/fullsession-woocommerce.js', array( 'jquery', FullSession_Tracker::HANDLE ), FULLSESSION_VERSION, true ); wp_add_inline_script( 'fullsession-woocommerce', 'window.fullsessionWooFragmentKey = ' . FullSession_Tracker::encode( self::FRAGMENT_KEY ) . ';', 'before' ); } /** * Checkout page opened. Sent once per cart, so reloading the page doesn't repeat it. * * @return array|null */ private static function checkout_started_event() { if ( ! is_checkout() || is_order_received_page() || ! WC()->cart || WC()->cart->is_empty() || ! WC()->session ) { return null; } $hash = WC()->cart->get_cart_hash(); if ( WC()->session->get( self::SESSION_CHECKOUT ) === $hash ) { return null; } WC()->session->set( self::SESSION_CHECKOUT, $hash ); return array( 'name' => 'woocommerce_checkout_started', 'data' => array( 'checkout_total' => (string) WC()->cart->get_total( 'edit' ), 'checkout_currency' => get_woocommerce_currency(), 'checkout_item_count' => (string) count( WC()->cart->get_cart() ), ), ); } /** * Thank-you page. Sent once per order. * * @return array|null */ private static function checkout_completed_event() { if ( ! is_order_received_page() ) { return null; } $order_id = absint( get_query_var( 'order-received' ) ); // The order key in the URL is what WooCommerce itself uses to show this page. $key = isset( $_GET['key'] ) ? sanitize_text_field( wp_unslash( $_GET['key'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended $order = $order_id ? wc_get_order( $order_id ) : false; if ( ! $order || '' === $key || ! hash_equals( $order->get_order_key(), $key ) || $order->get_meta( self::ORDER_META ) ) { return null; } $order->update_meta_data( self::ORDER_META, 1 ); $order->save(); return array( 'name' => 'woocommerce_checkout_completed', 'data' => array( 'order_id' => (string) $order->get_id(), 'checkout_total' => (string) $order->get_total(), 'checkout_currency' => $order->get_currency(), ), ); } /** * Events waiting in the session. * * @return array */ private static function queued_events() { if ( ! WC()->session ) { return array(); } $events = WC()->session->get( self::SESSION_EVENTS, array() ); return is_array( $events ) ? $events : array(); } /** * Events waiting in the session, removed from it. * * @return array */ private static function take_queued_events() { $events = self::queued_events(); if ( $events ) { WC()->session->set( self::SESSION_EVENTS, array() ); } return $events; } }