I want to exclude WooCommerce revenue from the Google Analytics purchase event when the Product ID is 224112 or 159324.
I tried to find solutions to exclude sending the data to GA4 through GMT exclusion triggers or filters directly in the GA4 interface, but it seems the best way to accomplish this is to exclude the data from arriving into the datalayer in the first place.
I use the GTM4WP plugin to send the website data (WordPress, WooCommerce) to the GTM datalayer.
In the plugin, I found the part of the code that sends the purchase data to the datalayer. I'm not very familiar with this code and I dont want to mess things up on my site. Since the Google Analytics give the results only after 24 hours I want to make sure that I do the right thing right away.
This is the original plugin code:
function gtm4wp_get_purchase_datalayer( $order, $order_items ) {
global $gtm4wp_options, $gtm4wp_is_woocommerce3_7;
$dataLayer = array();
if ( $order instanceof WC_Order ) {
$woo = WC();
// variable for Google Smart Shopping campaign new customer reporting
// https://support.google.com/google-ads/answer/9917012?hl=en-AU#zippy=%2Cinstall-with-google-tag-manager
if ( $woo->customer instanceof WC_Customer ) {
// we need to use this instead of $woo->customer as this will load proper total order number and value from the database instead of the session
$woo_customer = new WC_Customer( $woo->customer->get_id() );
$dataLayer['new_customer'] = $woo_customer->get_order_count() === 1;
}
if ( $gtm4wp_options[ GTM4WP_OPTION_INTEGRATE_WCEXCLUDETAX ] ) {
$order_revenue = (float)( $order->get_total() - $order->get_total_tax() );
} else {
$order_revenue = (float) $order->get_total();
}
$order_shipping_cost = (float) $order->get_shipping_total();
if ( $gtm4wp_options[ GTM4WP_OPTION_INTEGRATE_WCEXCLUDESHIPPING ] ) {
$order_revenue -= $order_shipping_cost;
}
$order_currency = $order->get_currency();
if ( true === $gtm4wp_options[ GTM4WP_OPTION_INTEGRATE_WCTRACKCLASSICEC ] ) {
$dataLayer['event'] = 'gtm4wp.orderCompleted';
$dataLayer['transactionId'] = $order->get_order_number();
$dataLayer['transactionAffiliation'] = '';
$dataLayer['transactionTotal'] = $order_revenue;
$dataLayer['transactionShipping'] = $order_shipping_cost;
$dataLayer['transactionTax'] = (float) $order->get_total_tax();
$dataLayer['transactionCurrency'] = $order_currency;
}
if ( true === $gtm4wp_options[ GTM4WP_OPTION_INTEGRATE_WCTRACKENHANCEDEC ] ) {
$dataLayer['event'] = 'gtm4wp.orderCompletedEEC';
$dataLayer['ecommerce'] = array(
'currencyCode' => $order_currency,
'purchase' => array(
'actionField' => array(
'id' => $order->get_order_number(),
'affiliation' => '',
'revenue' => $order_revenue,
'tax' => (float) $order->get_total_tax(),
'shipping' => (float)( $order->get_shipping_total() ),
'coupon' => implode( ', ', ( $gtm4wp_is_woocommerce3_7 ? $order->get_coupon_codes() : $order->get_used_coupons() ) ),
)
)
);
}
if ( isset( $order_items ) ) {
$_order_items = $order_items;
} else {
$_order_items = gtm4wp_process_order_items( $order );
}
if ( true === $gtm4wp_options[ GTM4WP_OPTION_INTEGRATE_WCTRACKCLASSICEC ] ) {
$dataLayer['transactionProducts'] = $_order_items['products'];
}
if ( true === $gtm4wp_options[ GTM4WP_OPTION_INTEGRATE_WCTRACKENHANCEDEC ] ) {
$dataLayer['ecommerce']['purchase']['products'] = $_order_items['products'];
}
if ( $gtm4wp_options[ GTM4WP_OPTION_INTEGRATE_WCREMARKETING ] ) {
$dataLayer['ecomm_prodid'] = $_order_items['product_ids'];
$dataLayer['ecomm_pagetype'] = 'purchase';
$dataLayer['ecomm_totalvalue'] = (float) $_order_items['sumprice'];
}
}
return $dataLayer;
}
I think I could add an if statement just before the excludeTAX option. It would be something like this:
If ($productID = array (224112, 159324)) {
$order_revenue = 0;
} else {
$order_revenue = (float) $order->get_total();
}
I don't know what would be the correct variable for $productID and I am not sure that this would work.
Any help is appreciated.
$order_product_ids = array();
foreach ($order->get_items() as $item_key => $item) {
$product = $item->get_product();
$order_product_ids[] = $product->get_id();
}
$checklist_product_ids = array(224112, 159324);
$is_product_in_order = (count(array_intersect($order_product_ids, $checklist_product_ids))) ? true : false;
If ($is_product_in_order) {
$order_revenue = 0;
} else {
$order_revenue = (float) $order->get_total();
}
Related
I need to interact with a third party plugin to send SMS. The plugin is Bookly, which is for making appointments. I edited the Ajax.php that Bookly uses for saving the appointment. I've sent the SMS succesfully on Ajax.php. However, I want to code an external plugin to make the process controllable on admin panel.
I use a custom hook named "bookly_appointment_saved" and send an array with that. And in my new plugin I catch the hook succesfully. The SMS is always sent but the Ajax.php of Bookly doesn't send the response to the frontend. It keeps showing the page as loading.
Please see the codes below and help.
Ajax.php (Bookly) - Only related method is included.
/**
* Save cart appointments.
*/
public static function saveAppointment()
{
$userData = new Lib\UserBookingData( self::parameter( 'form_id' ) );
if ( $userData->load() ) {
$failed_cart_key = $userData->cart->getFailedKey();
if ( $failed_cart_key === null ) {
$cart_info = $userData->cart->getInfo();
$is_payment_disabled = Lib\Config::paymentStepDisabled();
$skip_payment = BookingProxy\CustomerGroups::getSkipPayment( $userData->getCustomer() );
$gateways = self::getGateways( $userData, clone $cart_info );
if ( $is_payment_disabled || isset( $gateways['local'] ) || $cart_info->getPayNow() <= 0 || $skip_payment ) {
// Handle coupon.
$coupon = $userData->getCoupon();
if ( $coupon ) {
$coupon->claim()->save();
}
// Handle payment.
$payment = null;
if ( ! $is_payment_disabled && ! $skip_payment ) {
if ( $cart_info->getTotal() <= 0 ) {
if ( $cart_info->withDiscount() ) {
$payment = new Lib\Entities\Payment();
$payment
->setType( Lib\Entities\Payment::TYPE_FREE )
->setStatus( Lib\Entities\Payment::STATUS_COMPLETED )
->setPaidType( Lib\Entities\Payment::PAY_IN_FULL )
->setTotal( 0 )
->setPaid( 0 )
->save();
}
} else {
$payment = new Lib\Entities\Payment();
$status = Lib\Entities\Payment::STATUS_PENDING;
$type = Lib\Entities\Payment::TYPE_LOCAL;
$paid = 0;
foreach ( $gateways as $gateway => $data ) {
if ( $data['pay'] == 0 ) {
$status = Lib\Entities\Payment::STATUS_COMPLETED;
$type = Lib\Entities\Payment::TYPE_FREE;
$cart_info->setGateway( $gateway );
$payment->setGatewayPriceCorrection( $cart_info->getPriceCorrection() );
break;
}
}
if ( $status !== Lib\Entities\Payment::STATUS_COMPLETED ) {
$gift_card = $userData->getGiftCard();
if ( $gift_card ) {
$type = Lib\Entities\Payment::TYPE_CLOUD_GIFT;
$cart_info->setGateway( $type );
if ( $gift_card->getBalance() >= $cart_info->getPayNow() ) {
$status = Lib\Entities\Payment::STATUS_COMPLETED;
$paid = $cart_info->getPayNow();
$gift_card->charge( $paid )->save();
$payment->setGatewayPriceCorrection( $cart_info->getPriceCorrection() );
}
}
}
$payment
->setType( $type )
->setStatus( $status )
->setPaidType( Lib\Entities\Payment::PAY_IN_FULL )
->setTotal( $cart_info->getTotal() )
->setTax( $cart_info->getTotalTax() )
->setPaid( $paid )
->save();
}
}
// Save cart.
$order = $userData->save( $payment );
if ( $payment !== null ) {
$payment->setDetailsFromOrder( $order, $cart_info )->save();
}
// Send notifications.
Lib\Notifications\Cart\Sender::send( $order );
$response = array(
'success' => true,
);
} else {
$response = array(
'success' => false,
'error' => Errors::PAY_LOCALLY_NOT_AVAILABLE,
);
}
} else {
$response = array(
'success' => false,
'failed_cart_key' => $failed_cart_key,
'error' => Errors::CART_ITEM_NOT_AVAILABLE,
);
}
//Custom hook
$user_appointed=$userData->getData();
do_action('bookly_appointment_saved',
$appointment=[
'date'=>date("d/m/Y", strtotime($user_appointed['slots'][0][2]) ),
'time'=>date("H:i", strtotime($user_appointed['slots'][0][2]) ),
'full_name'=>$user_appointed['full_name']=''?$user_appointed['first_name'].' '.$user_appointed['last_name']:$user_appointed['full_name'],
'service_name'=>$userData->cart->getItemsTitle(),
]
);
// end of hook
$userData->sessionSave();
wp_send_json( $response );
}
Errors::sendSessionError();
}
custom-sms-sender-plugin.php (My plugin)
add_action('bookly_appointment_saved','send_sms');
function send_sms($appointment){
$phone = "66666666666";
$message="New appointment - ".$appointment['full_name']." Service: ".$appointment['service_name']." Date: ".$appointment['date']." Time:".$appointment['time'];
$message = urlencode($message);
$url= "//request url with parameters";
$request = wp_remote_get($url);
if ($request['body'] !=30 || $request['body'] !=20 || $request['body'] !=40 || $request['body'] !=50 || $request['body'] != 51 || $request['body'] != 70 || $request['body'] != 85) {
write_log("SENT - SMS Code : ".explode(" ",$request['body'])[1]);
} else {
write_log("ERROR - Code : ".$request['body']);
}
}
I've solved the problem. It is caused by the "write_log" commands as the command doesn't exist. After changing the log method, it worked like a charm. Thanks for all comments.
I am not that proficient at coding so please bear with me.
I have this custom add to cart code:
public static function add_to_cart( $params, $uid ) {
$data = self::get_calc_data($uid);
foreach ($data as $calc_id => $calc_data) {
$product_id = isset($calc_data['woo_info']['product_id']) ? $calc_data['woo_info']['product_id'] : null;
if ( $product_id && intval($product_id) === intval($params['woo_info']['product_id']) ) {
$meta = [
'product_id' => $product_id,
'item_name' => isset($calc_data['item_name']) ? $calc_data['item_name'] : '',
];
if(!empty($calc_data['descriptions']) && is_array($calc_data['descriptions'])) {
foreach ($calc_data['descriptions'] as $calc_item) {
if ( $calc_item['hidden'] === true ){
continue;
}
if ( strpos($calc_item['alias'], 'datePicker_field_id_') !== false ) {
$val = $calc_item['converted'] ? ' ('. $calc_item['converted'] . ') ' . $calc_item['value'] : $calc_item['value'];
}else{
$labels = isset($calc_item['extra']) ? $calc_item['extra']: '';
if ( (strpos($calc_item['alias'], 'radio_field_id_') !== false
|| strpos($calc_item['alias'], 'dropDown_field_id_') !== false)
&& key_exists('options', $calc_item) ) {
$labels = CCBWooCheckout::getLabels($calc_item['options']);
}
if ( strpos($calc_item['alias'], 'multi_range_field_id_') !== false
&& key_exists('options', $calc_item) && count($calc_item['options']) > 0 ) {
$labels = key_exists('label', $calc_item['options'][0]) ?
$calc_item['options'][0]['label']: '';
}
$val = isset($labels) ? $labels . ' ' . $calc_item['converted'] : $calc_item['converted'];
}
$meta['calc_data'][$calc_item['label']] = $val;
}
}
/** add totals data */
if( !empty($calc_data['ccb_total_and_label']) && is_array($calc_data['ccb_total_and_label']) ) {
$meta['ccb_total'] = $calc_data['ccb_total_and_label']['total'];
}
WC()->cart->add_to_cart($product_id, 1, '', array(), array('ccb_calculator' => $meta));
}
}
}
It adds simple item from a plugin into Woocommerce Cart. I am trying to add a unique ID for every added item so that I can add multiples of the same item and they would show as unique items in the cart.
I was trying to create the unique ID with
public static function add_custom_cart_item_data( $cart_item_data, $cart_item_key ) {
$cart_item_data[custom_data]['unique_key'] = md5( microtime().rand() );
return $cart_item_data;
}
and then use the $cart_item_data; changing the 'product_id' => $product_id, to 'product_id' => $cart_item_data, but sadly this doesn't seem to work. What am I doing wrong?
Really appreciate all your help!
I Hope are you okay.
Today I have problems with I open order invoice pdf in admin after products list have components.
I Remove all components as well
I am using woocommerce-pdf-invoices-packing-slips plugin.
Below is my product URL :
https://www.pcguru.lt/produktas/amd-home-guru/
My Invoice PDF screenshot as well.
How can I remove it?
I Searching Google but couldn't Found Anything.
After Code Debugging Step by Step, That's are Found Successfully.
File Path:
/wp-content/plugins/woocommerce-pdf-invoices-packing-slips/includes/documents/abstract-wcpdf-order-document-methods.php
public function get_order_items() {
$items = $this->order->get_items();
$data_list = array();
if( sizeof( $items ) > 0 ) {
foreach ( $items as $item_id => $item ) {
//Find Child Product Of Composite Product
global $wpdb;
$post_id = $wpdb->get_row("SELECT meta_value FROM pcg_woocommerce_order_itemmeta WHERE (meta_key = 'wooco_ids' AND order_item_id = '". $item_id ."')");
if($post_id->meta_value !=''){
$main_id = str_replace('/1/', '', $post_id->meta_value);
$data_ids = explode(",",$main_id);
}
//END Custom Code
$data = array();
// Set the item_id
$data['item_id'] = $item_id;
// Set the id
$data['product_id'] = $item['product_id'];
$data['variation_id'] = $item['variation_id'];
// Compatibility: WooCommerce Composit Products uses a workaround for
// setting the order before the item name filter, so we run this first
if ( class_exists('WC_Composite_Products') ) {
$order_item_class = apply_filters( 'woocommerce_order_item_class', '', $item, $this->order );
}
// Set item name
$data['name'] = apply_filters( 'woocommerce_order_item_name', $item['name'], $item, false );
// Set item quantity
$data['quantity'] = $item['qty'];
//$data['product_desc'] = $item->get_product(); // Get the WC_Product objec
//echo '<pre>'; print_r($product); echo '</pre>'; die;
// Set the line total (=after discount)
$data['line_total'] = $this->format_price( $item['line_total'] );
$data['single_line_total'] = $this->format_price( $item['line_total'] / max( 1, abs( $item['qty'] ) ) );
$data['line_tax'] = $this->format_price( $item['line_tax'] );
$data['single_line_tax'] = $this->format_price( $item['line_tax'] / max( 1, abs( $item['qty'] ) ) );
$data['tax_rates'] = $this->get_tax_rate( $item, $this->order, false );
$data['calculated_tax_rates'] = $this->get_tax_rate( $item, $this->order, true );
// Set the line subtotal (=before discount)
$data['line_subtotal'] = $this->format_price( $item['line_subtotal'] );
$data['line_subtotal_tax'] = $this->format_price( $item['line_subtotal_tax'] );
$data['ex_price'] = $this->get_formatted_item_price( $item, 'total', 'excl' );
$data['price'] = $this->get_formatted_item_price( $item, 'total' );
$data['order_price'] = $this->order->get_formatted_line_subtotal( $item ); // formatted according to WC settings
// Calculate the single price with the same rules as the formatted line subtotal (!)
// = before discount
$data['ex_single_price'] = $this->get_formatted_item_price( $item, 'single', 'excl' );
$data['single_price'] = $this->get_formatted_item_price( $item, 'single' );
// Pass complete item array
$data['item'] = $item;
// Get the product to add more info
if ( is_callable( array( $item, 'get_product' ) ) ) {
$product = $item->get_product();
} else {
$product = $this->order->get_product_from_item( $item );
}
// Checking fo existance, thanks to MDesigner0
if( !empty( $product ) ) {
// Thumbnail (full img tag)
$data['thumbnail'] = $this->get_thumbnail( $product );
$data['get_parent_id'] = is_callable( array( $product, 'get_parent_id' ) ) ? $product->get_parent_id() : '';
// Set item SKU
$data['sku'] = is_callable( array( $product, 'get_sku' ) ) ? $product->get_sku() : '';
// Set item weight
$data['weight'] = is_callable( array( $product, 'get_weight' ) ) ? $product->get_weight() : '';
// Set item dimensions
$data['dimensions'] = $product instanceof \WC_Product ? WCX_Product::get_dimensions( $product ) : '';
// Pass complete product object
$data['product'] = $product;
} else {
$data['product'] = null;
}
// Set item meta
if (function_exists('wc_display_item_meta')) { // WC3.0+
$data['meta'] = wc_display_item_meta( $item, array(
'echo' => false,
) );
} else {
if ( version_compare( WOOCOMMERCE_VERSION, '2.4', '<' ) ) {
$meta = new \WC_Order_Item_Meta( $item['item_meta'], $product );
} else { // pass complete item for WC2.4+
$meta = new \WC_Order_Item_Meta( $item, $product );
}
$data['meta'] = $meta->display( false, true );
}
if (!in_array($data['product_id'], $data_ids)) {
$data_list[$item_id] = apply_filters( 'wpo_wcpdf_order_item_data', $data, $this->order, $this->get_type());
}
}
}
//echo '<pre>'; print_r($data_list); echo '</pre>'; die;
return apply_filters( 'wpo_wcpdf_order_items_data', $data_list, $this->order, $this->get_type() );
}
Solution Screenshot:
I am very happy because solution are completed.
Also Thanks to all helping guys
I would like to reconstruct the code by working with the names of the product attributes instead of the id variations.
From this code:
function action_woocommerce_thankyou( $order_id ) {
// Get $order object
$order = wc_get_order( $order_id );
// Get items
$items = $order->get_items();
// Set variable
$found = false;
// Set variable
$output = '';
// Loop
foreach ( $items as $item ) {
// Add whatever variation id you want below here.
if ( isset( $item[ 'variation_id' ] ) && $item[ 'variation_id' ] == 9647 ) {
$output = 'Thank you for buy VARIABLE A-9647';
$found = true;
break;
}
if ( isset( $item[ 'variation_id' ] ) && $item[ 'variation_id' ] == 9648 ) {
$output = 'Thank you for buy VARIABLE B-9648';
$found = true;
break;
}
}
// Get payment method
$payment_method = $order->get_payment_method();
// Payment method = basc & found = true
if ( $payment_method == 'bacs' && $found ) {
$output .= ' YOUR PAYMENT IS BACS';
}
// Print result
echo $output;
}
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );
I would like to reconstruct the code by working with the names of the product attributes instead of the id variations
How to change this code
from
variation_id
to
product name attribute
more exactly these lines:
if ( isset( $item[ 'variation_id' ] ) && $item[ 'variation_id' ] == 9647 )
if ( isset( $item[ 'variation_id' ] ) && $item[ 'variation_id' ] == 9648 )
Thanks in advance!
Assuming you mean this?
function action_woocommerce_thankyou( $order_id ) {
// Get $order object
$order = wc_get_order( $order_id );
// Get items
$items = $order->get_items();
// Set variable
$found = false;
// Set variable
$output = '';
// Loop
foreach ( $items as $item ) {
// The WC_Product object
$product = $item->get_product();
// Add whatever attribute you want below here.
if ( !empty( $product->get_attribute( 'pa_kleur' ) ) ) {
$output = 'Thank you...1';
$found = true;
break;
}
if ( !empty( $product->get_attribute( 'pa_jaar' ) ) ) {
$output = 'Thank you...2';
$found = true;
break;
}
}
// Get payment method
$payment_method = $order->get_payment_method();
// Payment method = basc & found = true
if ( $payment_method == 'bacs' && $found ) {
$output .= ' YOUR PAYMENT IS BACS';
}
// Print result
echo $output;
}
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );
How can I get, on Woocommerce, the date an order had its status changed to paid/complete?
I saw something about getting the orders from a costumer, but this would be just the first step of my algorithm. Then I would need to know when it changed to complete.
The idea is to make a membership area: a payment lasts 3 months. So I will count the days passed since it was bought
Something related
https://www.skyverge.com/blog/get-all-woocommerce-orders-for-a-customer/
And this is what I use to know if a product was bought by the costumer
if (wc_customer_bought_product($customer_email, $user_id,$loop->post->ID)){
$courses[] = $this->find($loop->post->ID);
}
I think you should look into:
/mySite/wp-content/plugins/woocommerce/includes/abstracts/abstract-wc-order.php
There is a __get function:
public function __get( $key ) {
// Get values or default if not set.
if ( 'completed_date' === $key ) {
$value = ( $value = get_post_meta( $this->id, '_completed_date', true ) ) ? $value : $this->modified_date;
} elseif ( 'user_id' === $key ) {
$value = ( $value = get_post_meta( $this->id, '_customer_user', true ) ) ? absint( $value ) : '';
} elseif ( 'status' === $key ) {
$value = $this->get_status();
} else {
$value = get_post_meta( $this->id, '_' . $key, true );
}
return $value;
}
So my understanding is that if you pass 'completed date' as the argument then it will return the completed_date.
It also gives you a hint where this date is i.e.
get_post_meta
Well, at least that's where I would start.
Probably the "most correct" way is:
$order = new WC_Order($order_id);
$date_obj = $order->get_date_paid();
echo $date_obj->date('d/m/Y');
This should to the job on recente WP/WooCommerce.
$order = new WC_Order($sale_id);
echo $order->get_date_paid();