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();