HEX
Server: Apache
System: Linux 4801f1b1.ptr.provps.com 6.17.8-1.el9.elrepo.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Nov 13 18:02:25 EST 2025 x86_64
User: nassaugo (1004)
PHP: 8.1.34
Disabled: exec,passthru,shell_exec,system
Upload Files
File: /home/nassaugo/www/wp-content/plugins/cartflows-pro/classes/class-cartflows-pro-tracking.php
<?php
/**
 * Cartflows Pro tracking.
 *
 * @package cartflows
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Class Cartflows_Pro_Tracking.
 */
class Cartflows_Pro_Tracking {

	/**
	 * Member Variable
	 *
	 * @var instance
	 */
	private static $instance;

	/**
	 * Member Variable
	 *
	 * @var fb_pixel_settings
	 */
	private static $fb_pixel_settings;

	/**
	 * Member Variable
	 *
	 * @var ga_settings
	 */
	private static $ga_settings;

	/**
	 *  Initiator
	 */
	public static function get_instance() {
		if ( ! isset( self::$instance ) ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor
	 */
	public function __construct() {

		self::$fb_pixel_settings = Cartflows_Helper::get_facebook_settings();

		self::$ga_settings = Cartflows_Helper::get_google_analytics_settings();

		if ( 'enable' === self::$fb_pixel_settings['facebook_pixel_tracking'] ) {
			/* Facebook Pixel */
			add_action( 'wcf_order_bump_item_added', array( $this, 'trigger_fb_event' ) );
			add_action( 'wcf_after_quantity_update', array( $this, 'trigger_fb_event' ) );
			add_action( 'wcf_after_force_all_selection', array( $this, 'trigger_fb_event' ) );
			add_action( 'wcf_after_multiple_selection', array( $this, 'trigger_fb_event' ) );
			add_action( 'wcf_after_single_selection', array( $this, 'trigger_fb_event' ) );

			add_action( 'cartflows_offer_product_processed', array( $this, 'save_offer_data_for_fb' ), 10, 3 );
			add_filter( 'cartflows_view_content_offer', array( $this, 'trigger_offer_viewcontent_event' ), 10, 2 );
			add_action( 'cartflows_facebook_pixel_events', array( $this, 'trigger_offer_purchase_event' ), 10 );

			add_action( 'wcf_order_bump_item_removed', array( $this, 'update_cart_data_for_fb_event' ) );
		}

		if ( 'enable' === self::$ga_settings['enable_google_analytics'] ) {
			/* Google analyics add to cart */
			add_action( 'wcf_order_bump_item_added', array( $this, 'trigger_ga_add_to_cart_event' ) );
			add_action( 'wcf_after_quantity_update', array( $this, 'trigger_ga_add_to_cart_event' ) );
			add_action( 'wcf_after_force_all_selection', array( $this, 'trigger_ga_add_to_cart_event' ) );
			add_action( 'wcf_after_multiple_selection', array( $this, 'trigger_ga_add_to_cart_event' ) );
			add_action( 'wcf_after_single_selection', array( $this, 'trigger_ga_add_to_cart_event' ) );

			/* Google analyics remove from cart */
			add_action( 'wcf_order_bump_item_removed', array( $this, 'trigger_ga_remove_from_cart_event' ) );

			add_action( 'cartflows_offer_product_processed', array( $this, 'save_offer_data_for_ga' ), 10, 3 );
			add_action( 'cartflows_google_analytics_events', array( $this, 'trigger_offer_purchase_event_for_ga' ), 10 );
		}
	}

	/**
	 * Update the cart data for add payment info event when order bump product is removed from cart.
	 */
	public function update_cart_data_for_fb_event() {

		add_filter(
			'woocommerce_update_order_review_fragments',
			function( $data ) {

				if ( 'enable' === self::$fb_pixel_settings['facebook_pixel_add_payment_info'] ) {
					$data['fb_add_payment_info_data'] = wp_json_encode( Cartflows_Tracking::get_instance()->prepare_cart_data_fb_response( 'add_payment_info' ) );
				}

				return $data;
			}
		);

	}

	/**
	 * Add updated cart and product in Ajax response.
	 *
	 * @param integer $product_id product id.
	 */
	public function trigger_fb_event( $product_id ) {

		add_filter(
			'woocommerce_update_order_review_fragments',
			function( $data ) use ( $product_id ) {
				$data['added_to_cart_data'] = $this->prepare_fb_response( $product_id );

				if ( 'enable' === self::$fb_pixel_settings['facebook_pixel_add_payment_info'] ) {
					$data['fb_add_payment_info_data'] = wp_json_encode( Cartflows_Tracking::get_instance()->prepare_cart_data_fb_response( 'add_payment_info' ) );
				}

				return $data;
			}
		);

	}

	/**
	 * Save the offer details in transient to use for facebook pixel.
	 *
	 * @param object $parent_order parent order id.
	 * @param array  $offer_data offer product data.
	 * @param object $child_order child order.
	 */
	public function save_offer_data_for_fb( $parent_order, $offer_data, $child_order = null ) {
		$order_id = null;
		$user_key = WC()->session->get_customer_id();

		if ( $child_order ) {
			$order_id = $child_order->get_id();
		} else {
			$order_id = $parent_order->get_id();
		}

		$data = array(
			'order_id'      => $order_id,
			'offer_product' => $offer_data,
		);

		set_transient( 'wcf-offer-details-for-fbp-' . $user_key, $data );
	}


	/**
	 * Save the offer details in transient to use for Google Analytics.
	 *
	 * @param object $parent_order parent order id.
	 * @param array  $offer_data offer product data.
	 * @param object $child_order child order.
	 */
	public function save_offer_data_for_ga( $parent_order, $offer_data, $child_order = null ) {

		$order_id = null;
		$user_key = WC()->session->get_customer_id();

		if ( $child_order ) {
			$order_id = $child_order->get_id();
		} else {
			$order_id = $parent_order->get_id();
		}

		$data = array(
			'order_id'      => $order_id,
			'offer_product' => $offer_data,
		);

		set_transient( 'wcf-offer-details-for-ga-' . $user_key, $data );
	}

	/**
	 * Trigger the purchase event for the upsell/downsell offer.
	 */
	public function trigger_offer_purchase_event() {

		if ( isset( $_GET['wcf-order'] ) && 'enable' === self::$fb_pixel_settings['facebook_pixel_purchase_complete'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended

			$order_id = intval( $_GET['wcf-order'] ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended

			$user_key = WC()->session->get_customer_id();

			$offer_data = get_transient( 'wcf-offer-details-for-fbp-' . $user_key );

			if ( empty( $offer_data ) ) {
				return;
			}

			$purchase_details = $this->prepare_offer_purchase_data_fb_response( $order_id, $offer_data );

			delete_transient( 'wcf-offer-details-for-fbp-' . $user_key );

			if ( ! empty( $purchase_details ) ) {

				$purchase_details = wp_json_encode( $purchase_details );
				$event_script     = "
					<script type='text/javascript'>
						fbq( 'track', 'Purchase', $purchase_details );
					</script>";

				// Reason for PHPCS ignore: Printing Google Analytics script. No input taken from the user except GA ID.
				echo html_entity_decode( $event_script ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
			}
		}
	}

	/**
	 * Trigger the view content event for the upsell/downsell offer.
	 *
	 * @param array $params Facebook event parameters array.
	 * @param int   $step_id current step ID.
	 *
	 * @return array
	 */
	public function trigger_offer_viewcontent_event( $params, $step_id ) {

		// Upsell/Downsell Page.
		if ( isset( $step_id ) && wcf()->utils->check_is_offer_page( $step_id ) ) {
			return $this->prepare_viewcontent_data_fb_response( $params, $step_id );
		}

		return $params;
	}

	/**
	 * Prepare view content data for fb response.
	 *
	 * @param array $params Facebook event parameters array.
	 * @param int   $step_id current step id.
	 *
	 * @return array
	 */
	public function prepare_viewcontent_data_fb_response( $params, $step_id ) {

		$product_data   = array();
		$content_ids    = array();
		$category_names = '';
		$product_names  = '';

		// Get offer page data.
		$offer_product = wcf_pro()->utils->get_offer_data( $step_id );

		// Add offer data only if the offer data is array and set.
		if ( ! empty( $offer_product ) && is_array( $offer_product ) ) {

			$content_ids[]  = $offer_product['id'];
			$category_names = wp_strip_all_tags( wc_get_product_category_list( $offer_product['id'] ) );

			$product_data = array(
				'cart_contents'  => array(
					'id'       => $offer_product['id'],
					'name'     => $offer_product['name'],
					'price'    => $offer_product['price'],
					'quantity' => $offer_product['qty'],
				),
				'content_ids'    => $offer_product['id'],
				'product_names'  => $offer_product['name'],
				'category_names' => $category_names,
			);

			$params['content_ids']  = $product_data['content_ids'];
			$params['currency']     = get_woocommerce_currency();
			$params['value']        = $offer_product['total'];
			$params['content_type'] = 'product';
			$params['contents']     = wp_json_encode( $product_data['cart_contents'] );
		}

		return $params;
	}

	/**
	 * Trigger the purchase event for the upsell/downsell offer.
	 */
	public function trigger_offer_purchase_event_for_ga() {

		if ( isset( $_GET['wcf-order'] ) && 'enable' === self::$ga_settings['enable_add_payment_info'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended

			$order_id = intval( $_GET['wcf-order'] ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended

			$user_key   = WC()->session->get_customer_id();
			$offer_data = get_transient( 'wcf-offer-details-for-ga-' . $user_key );

			if ( empty( $offer_data ) ) {
				return;
			}

			$purchase_details = $this->prepare_offer_purchase_data_ga_response( $order_id, $offer_data );
			delete_transient( 'wcf-offer-details-for-ga-' . $user_key );

			if ( ! empty( $purchase_details ) ) {

				$purchase_data = wp_json_encode( $purchase_details );

				$event_script = "
					<script type='text/javascript'>
						gtag( 'event', 'purchase', $purchase_data );
					</script>";

				// Reason for PHPCS ignore: Printing Google Analytics script. No input taken from the user except GA ID.
				echo html_entity_decode( $event_script ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
			}
		}
	}

	/**
	 * Prepare the purchase event data for the facebook pixel.
	 *
	 * @param integer $order_id order id.
	 * @param array   $offer_data offer data.
	 */
	public function prepare_offer_purchase_data_fb_response( $order_id, $offer_data ) {

		$purchase_data = array();

		$product_data = $offer_data['offer_product'];

		if ( empty( $product_data ) ) {
			return $purchase_data;
		}

		$purchase_data['content_type'] = 'product';
		$purchase_data['currency']     = wcf()->options->get_checkout_meta_value( $order_id, '_order_currency' );
		$purchase_data['userAgent']    = wcf()->options->get_checkout_meta_value( $order_id, '_customer_user_agent' );
		$purchase_data['plugin']       = 'CartFlows-Offer';

		$purchase_data['content_ids'][]      = (string) $product_data['id'];
		$purchase_data['content_names'][]    = $product_data['name'];
		$purchase_data['content_category'][] = wp_strip_all_tags( wc_get_product_category_list( $product_data['id'] ) );
		$purchase_data['value']              = $product_data['total'];
		$purchase_data['transaction_id']     = $offer_data['order_id'];

		if ( ! wcf_pro()->utils->is_separate_offer_order() ) {
			$purchase_data['transaction_id'] = $offer_data['order_id'] . '_' . $product_data['step_id'];
		}

		return $purchase_data;
	}

	/**
	 * Prepare the purchase event data for the google analytics.
	 *
	 * @param integer $order_id order id.
	 * @param array   $offer_data offer data.
	 */
	public function prepare_offer_purchase_data_ga_response( $order_id, $offer_data ) {

		$purchase_data = array();

		$product_data = $offer_data['offer_product'];

		if ( empty( $product_data ) ) {
			return $purchase_data;
		}

		$ga_tracking_id = esc_attr( self::$ga_settings['google_analytics_id'] );

		$shipping_tax = $product_data['shipping_fee_tax'] - $product_data['shipping_fee'];
		$products_tax = $product_data['qty'] * ( $product_data['unit_price_tax'] - intval( $product_data['unit_price'] ) );

		$purchase_data = array(
			'send_to'         => $ga_tracking_id,
			'event_category'  => 'Enhanced-Ecommerce',
			'transaction_id'  => $offer_data['order_id'],
			'affiliation'     => get_bloginfo( 'name' ),
			'value'           => $this->format_number( $product_data['total'] ),
			'currency'        => wcf()->options->get_checkout_meta_value( $order_id, '_order_currency' ),
			'shipping'        => $product_data['shipping_fee_tax'],
			'tax'             => $this->format_number( $shipping_tax + $products_tax ),
			'items'           => array(
				array(
					'id'       => $product_data['id'],
					'name'     => $product_data['name'],
					'quantity' => $product_data['qty'],
					'price'    => $this->format_number( $product_data['unit_price_tax'] ),
				),
			),
			'non_interaction' => true,
		);

		if ( ! wcf_pro()->utils->is_separate_offer_order() ) {
			$purchase_data['transaction_id'] = $offer_data['order_id'] . '_' . $product_data['step_id'];
		}

		return $purchase_data;
	}




	/**
	 * Add updated cart and product in Ajax response.
	 *
	 * @param integer $product_id product id.
	 */
	public function trigger_ga_add_to_cart_event( $product_id ) {

		add_filter(
			'woocommerce_update_order_review_fragments',
			function( $data ) use ( $product_id ) {
				$data['ga_added_to_cart_data'] = $this->prepare_ga_response( $product_id );

				if ( 'enable' === self::$ga_settings['enable_add_payment_info'] ) {
					$data['ga_add_payment_info_data'] = wp_json_encode( Cartflows_Tracking::get_instance()->prepare_cart_data_ga_response() );
				}

				return $data;
			}
		);

	}

	/**
	 * Add updated cart and product in Ajax response.
	 *
	 * @param integer $product_id product id.
	 */
	public function trigger_ga_remove_from_cart_event( $product_id ) {

		add_filter(
			'woocommerce_update_order_review_fragments',
			function( $data ) use ( $product_id ) {

				$product_data = array();
				if ( isset( $data['removed_order_bump_data'] ) ) {
					$product_data = $data['removed_order_bump_data'];
				}
				$data['ga_remove_to_cart_data'] = $this->prepare_ga_response( $product_id, $product_data );

				if ( 'enable' === self::$ga_settings['enable_add_payment_info'] ) {
					$data['ga_add_payment_info_data'] = wp_json_encode( Cartflows_Tracking::get_instance()->prepare_cart_data_ga_response() );
				}

				return $data;
			}
		);
	}

	/**
	 * Prepare response for facebook.
	 *
	 * @param integer $product_id product id.
	 * @return array
	 */
	public function prepare_fb_response( $product_id ) {

		$response     = array();
		$product_data = array();
		$product      = wc_get_product( $product_id );
		$items        = WC()->cart->get_cart();

		foreach ( $items as $index => $item ) {
			if ( $item['product_id'] === $product_id ) {
				$product_data = $item;
				break;
			}
		}

		if ( ! empty( $product_data ) ) {

			$add_to_cart['content_type']       = 'product';
			$add_to_cart['plugin']             = 'CartFlows-OrderBump';
			$add_to_cart['user_roles']         = implode( ', ', wp_get_current_user()->roles );
			$add_to_cart['content_category'][] = wp_strip_all_tags( wc_get_product_category_list( $product->get_id() ) );
			$add_to_cart['currency']           = get_woocommerce_currency();
			$add_to_cart['value']              = $this->format_number( $product_data['line_subtotal'] + $product_data['line_subtotal_tax'] );
			$add_to_cart['content_name']       = $product->get_title();
			$add_to_cart['content_ids'][]      = (string) $item['product_id'];

			$add_to_cart['contents'] = wp_json_encode(
				array(
					array(
						'id'         => $product_data['product_id'],
						'name'       => $product->get_title(),
						'quantity'   => $product_data['quantity'],
						'item_price' => $this->format_number( $product_data['line_subtotal'] + $product_data['line_subtotal_tax'] ),
					),
				)
			);

			// Put it in single variable.
			$response['added_to_cart'] = $add_to_cart;
		}

		return $response;

	}

	/**
	 * Prepare response for Google Analytics for Bump Order.
	 *
	 * @param integer $product_id product id.
	 * @param array   $product_data product data.
	 */
	public function prepare_ga_response( $product_id, $product_data = array() ) {

		$response = array();
		$data     = array(
			'quantity' => 1,
			'price'    => 0,
		);

		$product = wc_get_product( $product_id );

		if ( $product ) {

			$items = WC()->cart->get_cart();

			foreach ( $items as $index => $item ) {
				if ( $item['product_id'] === $product_id ) {
					$data['quantity'] = $item['quantity'];
					$data['price']    = $item['line_subtotal'] + $item['line_subtotal_tax'];
					break;
				}
			}

			// For remove from cart event of the order bump.
			if ( ! empty( $product_data ) ) {
				$data['quantity'] = $product_data['quantity'];
				$data['price']    = $product_data['line_subtotal'] + $product_data['line_subtotal_tax'];
			}

			$add_to_cart_ob = array(
				'send_to'         => self::$ga_settings['google_analytics_id'],
				'event_category'  => 'Enhanced-Ecommerce',
				'currency'        => get_woocommerce_currency(),
				'value'           => $this->format_number( $data['price'] ),
				'items'           => array(
					array(
						'id'       => $product_id,
						'name'     => $product->get_title(),
						'sku'      => $product->get_sku(),
						'category' => wp_strip_all_tags( wc_get_product_category_list( $product->get_id() ) ),
						'price'    => $this->format_number( $data['price'] ),
						'quantity' => $data['quantity'],
					),
				),
				'non_interaction' => true,
			);

			$response['add_to_cart']      = wp_json_encode( $add_to_cart_ob );
			$response['remove_from_cart'] = wp_json_encode( $add_to_cart_ob );
		}

		return $response;
	}

	/**
	 * Get decimal of price.
	 *
	 * @param integer $price price.
	 */
	public function format_number( $price ) {

		return number_format( floatval( $price ), wc_get_price_decimals(), '.', '' );
	}

}
/**
 *  Prepare if class 'Cartflows_Pro_Frontend' exist.
 *  Kicking this off by calling 'get_instance()' method
 */
Cartflows_Pro_Tracking::get_instance();