Pixel Manager for WooCommerce – Track Google Analytics, Google Ads, Facebook and more - Version 1.24.0

Version Description

06.10.2022

  • New: The Pixel Manager has been refactored to be ready for the upcoming WooCommerce High Performance Orders Storage
  • Tweak: Some UI improvements
  • Tweak: Added GAds Conversion Adjustments feed URL to debug info
  • Tweak: Refactor for HPOS
Download this release

Release Info

Developer alekv
Plugin Icon 128x128 Pixel Manager for WooCommerce – Track Google Analytics, Google Ads, Facebook and more
Version 1.24.0
Comparing to
See all releases

Code changes from version 1.23.0 to 1.24.0

classes/admin/class-admin.php CHANGED
@@ -3,6 +3,7 @@
3
  // TODO move script for copying debug info into a proper .js enqueued file, or switch tabs to JavaScript switching and always save all settings at the same time
4
  namespace WCPM\Classes\Admin;
5
 
 
6
  use WCPM\Classes\Pixels\Google\Google ;
7
  use WCPM\Classes\Pixels\Trait_Shop ;
8
 
@@ -50,7 +51,7 @@ class Admin
50
 
51
  protected function if_is_wpm_admin_page()
52
  {
53
- $_get = $this->get_input_vars( INPUT_GET );
54
 
55
  if ( !empty($_get['page']) && 'wpm' === $_get['page'] ) {
56
  return true;
@@ -90,7 +91,7 @@ class Admin
90
  public function wpm_admin_css( $hook_suffix )
91
  {
92
  // Only output the css on PMW pages and the order page
93
- if ( !(strpos( $hook_suffix, 'page_wpm' ) || $this->is_orders_page()) ) {
94
  return;
95
  }
96
  wp_enqueue_style(
@@ -101,13 +102,6 @@ class Admin
101
  );
102
  }
103
 
104
- private function is_orders_page()
105
- {
106
- global $pagenow ;
107
- $_get = $this->get_input_vars( INPUT_GET );
108
- return 'edit.php' === $pagenow && isset( $_get['post_type'] ) && 'shop_order' === $_get['post_type'];
109
- }
110
-
111
  public function wpm_admin_scripts( $hook_suffix )
112
  {
113
  // Only output the remaining scripts on PMW settings page
@@ -348,7 +342,7 @@ class Admin
348
  // add the field for the TikTok pixel
349
  add_settings_field(
350
  'wpm_plugin_tiktok_pixel_id',
351
- esc_html__( 'TikTok pixel ID', 'woocommerce-google-adwords-conversion-tracking-tag' ) . $this->html_beta(),
352
  [ $this, 'wpm_option_html_tiktok_pixel_id' ],
353
  'wpm_plugin_options_page',
354
  $section_ids['settings_name']
@@ -2254,13 +2248,13 @@ class Admin
2254
  // feedUrlElement.setSelectionRange(0, 99999)
2255
  navigator.clipboard.writeText(document.getElementById("pmw_plugin_google_ads_conversion_adjustments_feed").value)
2256
 
2257
- const pmwCaFeedTooltip = document.getElementById("myPmwCaTooltip");
2258
- pmwCaFeedTooltip.innerHTML = "Copied feed URL to clipboard";
2259
  }
2260
 
2261
  const resetCaCopyButton = () => {
2262
- const pmwCaFeedTooltip = document.getElementById("myPmwCaTooltip");
2263
- pmwCaFeedTooltip.innerHTML = "Copy to clipboard";
2264
  }
2265
  </script>
2266
  <div class="pmwCaTooltip">
@@ -2649,7 +2643,7 @@ class Admin
2649
  ?>'
2650
  />
2651
  <?php
2652
- $this->get_status_icon( !empty($this->options['general']['scroll_tracker_thresholds']) );
2653
  ?>
2654
  <?php
2655
  $this->get_documentation_html_by_key( 'scroll_tracker_threshold' );
3
  // TODO move script for copying debug info into a proper .js enqueued file, or switch tabs to JavaScript switching and always save all settings at the same time
4
  namespace WCPM\Classes\Admin;
5
 
6
+ use WCPM\Classes\Helpers ;
7
  use WCPM\Classes\Pixels\Google\Google ;
8
  use WCPM\Classes\Pixels\Trait_Shop ;
9
 
51
 
52
  protected function if_is_wpm_admin_page()
53
  {
54
+ $_get = Helpers::get_input_vars( INPUT_GET );
55
 
56
  if ( !empty($_get['page']) && 'wpm' === $_get['page'] ) {
57
  return true;
91
  public function wpm_admin_css( $hook_suffix )
92
  {
93
  // Only output the css on PMW pages and the order page
94
+ if ( !(strpos( $hook_suffix, 'page_wpm' ) || Helpers::is_orders_page()) ) {
95
  return;
96
  }
97
  wp_enqueue_style(
102
  );
103
  }
104
 
 
 
 
 
 
 
 
105
  public function wpm_admin_scripts( $hook_suffix )
106
  {
107
  // Only output the remaining scripts on PMW settings page
342
  // add the field for the TikTok pixel
343
  add_settings_field(
344
  'wpm_plugin_tiktok_pixel_id',
345
+ esc_html__( 'TikTok pixel ID', 'woocommerce-google-adwords-conversion-tracking-tag' ),
346
  [ $this, 'wpm_option_html_tiktok_pixel_id' ],
347
  'wpm_plugin_options_page',
348
  $section_ids['settings_name']
2248
  // feedUrlElement.setSelectionRange(0, 99999)
2249
  navigator.clipboard.writeText(document.getElementById("pmw_plugin_google_ads_conversion_adjustments_feed").value)
2250
 
2251
+ const pmwCaFeedTooltip = document.getElementById("myPmwCaTooltip")
2252
+ pmwCaFeedTooltip.innerHTML = "Copied feed URL to clipboard"
2253
  }
2254
 
2255
  const resetCaCopyButton = () => {
2256
+ const pmwCaFeedTooltip = document.getElementById("myPmwCaTooltip")
2257
+ pmwCaFeedTooltip.innerHTML = "Copy to clipboard"
2258
  }
2259
  </script>
2260
  <div class="pmwCaTooltip">
2643
  ?>'
2644
  />
2645
  <?php
2646
+ $this->get_status_icon( !empty($this->options['general']['scroll_tracker_thresholds']), true, true );
2647
  ?>
2648
  <?php
2649
  $this->get_documentation_html_by_key( 'scroll_tracker_threshold' );
classes/admin/class-ask-for-rating.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  namespace WCPM\Classes\Admin;
4
 
 
5
  use WCPM\Classes\Pixels\Trait_Shop;
6
 
7
  if (!defined('ABSPATH')) {
@@ -51,7 +52,7 @@ class Ask_For_Rating {
51
  // server side php ajax handler for the admin rating notice
52
  public function ajax_rating_notice_handler() {
53
 
54
- $_post = $this->get_input_vars(INPUT_POST);
55
 
56
  $set = $_post['set'];
57
 
2
 
3
  namespace WCPM\Classes\Admin;
4
 
5
+ use WCPM\Classes\Helpers;
6
  use WCPM\Classes\Pixels\Trait_Shop;
7
 
8
  if (!defined('ABSPATH')) {
52
  // server side php ajax handler for the admin rating notice
53
  public function ajax_rating_notice_handler() {
54
 
55
+ $_post = Helpers::get_input_vars(INPUT_POST);
56
 
57
  $set = $_post['set'];
58
 
classes/admin/class-debug-info.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  namespace WCPM\Classes\Admin;
4
 
 
 
5
  use WCPM\Classes\Pixels\Trait_Shop ;
6
  use WP_Query ;
7
 
@@ -346,7 +348,7 @@ class Debug_Info
346
 
347
  if ( in_array( $order->get_payment_method(), $gateway_ids ) ) {
348
  $analysis[$order->get_payment_method()]['order_count_total']++;
349
- if ( get_post_meta( $order->get_id(), '_wpm_conversion_pixel_fired', true ) ) {
350
  $analysis[$order->get_payment_method()]['order_count_measured']++;
351
  }
352
  }
@@ -367,8 +369,9 @@ class Debug_Info
367
  {
368
  $count = 0;
369
  foreach ( $orders as $order_id ) {
 
370
  // Get meta data for post id and meta key _wpm_conversion_pixel_fired
371
- if ( get_post_meta( $order_id, '_wpm_conversion_pixel_fired', true ) ) {
372
  $count++;
373
  }
374
  }
@@ -586,7 +589,15 @@ class Debug_Info
586
  private function generate_pmw_tracked_payment_methods()
587
  {
588
  global $wpdb ;
589
- $tracked_payment_methods = $wpdb->get_col( "SELECT DISTINCT meta_value FROM {$wpdb->prefix}postmeta WHERE `meta_key` = '_payment_method' AND meta_value != ''" );
 
 
 
 
 
 
 
 
590
  set_transient( 'pmw_tracked_payment_methods', $tracked_payment_methods, MONTH_IN_SECONDS );
591
  }
592
 
2
 
3
  namespace WCPM\Classes\Admin;
4
 
5
+ use Automattic\WooCommerce\Utilities\OrderUtil ;
6
+ use WCPM\Classes\Pixels\Pixel_Manager ;
7
  use WCPM\Classes\Pixels\Trait_Shop ;
8
  use WP_Query ;
9
 
348
 
349
  if ( in_array( $order->get_payment_method(), $gateway_ids ) ) {
350
  $analysis[$order->get_payment_method()]['order_count_total']++;
351
+ if ( $order->meta_exists( '_wpm_conversion_pixel_fired' ) ) {
352
  $analysis[$order->get_payment_method()]['order_count_measured']++;
353
  }
354
  }
369
  {
370
  $count = 0;
371
  foreach ( $orders as $order_id ) {
372
+ $order = wc_get_order( $order_id );
373
  // Get meta data for post id and meta key _wpm_conversion_pixel_fired
374
+ if ( $order->meta_exists( '_wpm_conversion_pixel_fired' ) ) {
375
  $count++;
376
  }
377
  }
589
  private function generate_pmw_tracked_payment_methods()
590
  {
591
  global $wpdb ;
592
+
593
+ if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
594
+ // HPOS tables in use
595
+ $tracked_payment_methods = $wpdb->get_col( "SELECT DISTINCT payment_method FROM {$wpdb->prefix}wc_orders WHERE payment_method <> ''" );
596
+ } else {
597
+ // Traditional post tables are in use.
598
+ $tracked_payment_methods = $wpdb->get_col( "SELECT DISTINCT meta_value FROM {$wpdb->prefix}postmeta WHERE `meta_key` = '_payment_method' AND meta_value != ''" );
599
+ }
600
+
601
  set_transient( 'pmw_tracked_payment_methods', $tracked_payment_methods, MONTH_IN_SECONDS );
602
  }
603
 
classes/admin/class-environment-check.php CHANGED
@@ -142,7 +142,7 @@ class Environment_Check {
142
  'plugin' === $options['type'] &&
143
  isset($options['plugins']) &&
144
  is_array($options['plugins']) &&
145
- in_array(WPM_PLUGIN_BASE_NAME, $options['plugins'], true)
146
  ) {
147
  $this->flush_cache_of_all_cache_plugins();
148
  }
@@ -399,7 +399,7 @@ class Environment_Check {
399
 
400
  public function ajax_environment_check_handler() {
401
 
402
- $_post = $this->get_input_vars(INPUT_POST);
403
 
404
  if (isset($_post['set'])) {
405
 
@@ -655,7 +655,7 @@ class Environment_Check {
655
 
656
  public function is_hosting_cloudways() {
657
 
658
- $_server = $this->get_input_vars(INPUT_SERVER);
659
 
660
  if ($_server && array_key_exists('cw_allowed_ip', $_server)) {
661
  return true;
142
  'plugin' === $options['type'] &&
143
  isset($options['plugins']) &&
144
  is_array($options['plugins']) &&
145
+ in_array(WPM_PLUGIN_BASENAME, $options['plugins'], true)
146
  ) {
147
  $this->flush_cache_of_all_cache_plugins();
148
  }
399
 
400
  public function ajax_environment_check_handler() {
401
 
402
+ $_post = Helpers::get_input_vars(INPUT_POST);
403
 
404
  if (isset($_post['set'])) {
405
 
655
 
656
  public function is_hosting_cloudways() {
657
 
658
+ $_server = Helpers::get_input_vars(INPUT_SERVER);
659
 
660
  if ($_server && array_key_exists('cw_allowed_ip', $_server)) {
661
  return true;
classes/admin/class-order-columns.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  namespace WCPM\Classes\Admin;
4
 
 
5
  use WCPM\Classes\Helpers;
6
 
7
  if (!defined('ABSPATH')) {
@@ -22,30 +23,115 @@ class Order_Columns {
22
 
23
  private function __construct() {
24
 
25
- add_filter('manage_edit-shop_order_columns', [$this, 'custom_shop_order_column'], 20);
26
- add_action('manage_shop_order_posts_custom_column', [$this, 'custom_orders_list_column_content'], 20, 2);
27
  add_action('pre_get_posts', [$this, 'view_pixels_not_fired'], 1000, 1);
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  }
30
 
31
  public function view_pixels_not_fired( $query ) {
32
- global $pagenow;
33
 
34
- // Only run on WooCommerce orders page
35
- if (!( isset($query->query_vars['post_type']) && 'shop_order' === $query->query_vars['post_type'] && ( 'edit.php' === $pagenow ) )) {
36
  return;
37
  }
38
 
39
- if (!$query->is_main_query()) {
40
  return;
41
  }
42
 
43
- $_get = Helpers::get_input_vars_sanitized(INPUT_GET);
44
- $pmw_pixels_not_fired_query = isset($_get['pmw-pixels-not-fired']);
 
45
 
 
46
 
47
  // Set additional filters for the view
48
- if ($pmw_pixels_not_fired_query) {
49
 
50
  $query->set('post_status', ['wc-completed', 'wc-processing', 'wc-on-hold', 'wc-pending']);
51
 
@@ -100,22 +186,24 @@ class Order_Columns {
100
  ]
101
  ]));
102
 
103
-
104
  // Add new view with all orders where the conversion pixels have not been fired
105
- add_filter('views_edit-shop_order', function ( $views ) use ( $count_missing_pixel_fires, $pmw_pixels_not_fired_query ) {
106
-
107
- $query_string = admin_url('edit.php?post_type=shop_order');
108
- $query_string = add_query_arg('pmw-pixels-not-fired', '', $query_string);
109
 
110
- $class = $pmw_pixels_not_fired_query ? 'current' : '';
 
 
111
 
112
- $views['pmw-pixels-not-fired'] = sprintf('<a href="%s" class="%s">%s <span class="count">(%s)</span></a>', $query_string, $class, esc_html__('PMW pixels not fired - 30d', 'woocommerce-google-adwords-conversion-tracking-tag'), $count_missing_pixel_fires);
113
 
114
- return $views;
115
 
116
- });
117
  }
118
 
 
119
  public function pmw_order_table_styles() {
120
  wp_add_inline_style(
121
  'woocommerce_admin_styles',
@@ -125,6 +213,8 @@ class Order_Columns {
125
 
126
  public function custom_shop_order_column( $columns ) {
127
 
 
 
128
  function get_list_order_parameter( $list_order ) {
129
  if (is_null($list_order)) {
130
  return '';
@@ -135,7 +225,6 @@ class Order_Columns {
135
 
136
  $_get = Helpers::get_input_vars_sanitized(INPUT_GET);
137
 
138
-
139
  if (!isset($_get['order'])) {
140
  $list_order = 'dsc';
141
  } elseif ('dsc' === $_get['order']) {
@@ -159,12 +248,20 @@ class Order_Columns {
159
  return $reordered_columns;
160
  }
161
 
 
 
 
 
 
 
 
 
 
162
 
163
- public function custom_orders_list_column_content( $column, $post_id ) {
164
- switch ($column) {
165
  case 'pmw-monitored':
166
  // Get custom post meta data
167
- if (get_post_meta($post_id, '_wpm_process_through_wpm', true)) {
168
  $text = __('PMW monitored order', 'woocommerce-google-adwords-conversion-tracking-tag');
169
  ?>
170
  <div aria-hidden="true" title="<?php esc_html_e($text); ?>" class="pmw-monitored-icon good">
@@ -184,7 +281,7 @@ class Order_Columns {
184
 
185
  case 'pmw-pixels-fired':
186
  // Get custom post meta data
187
- if (!get_post_meta($post_id, '_wpm_process_through_wpm', true)) {
188
  $text = __('Order not tracked by PMW', 'woocommerce-google-adwords-conversion-tracking-tag');
189
  ?>
190
  <div aria-hidden="true" title="<?php esc_html_e($text); ?>" class="pmw-monitored-icon none">
@@ -192,7 +289,7 @@ class Order_Columns {
192
  </div>
193
  <?php
194
 
195
- } elseif (get_post_meta($post_id, '_created_via', true) !== 'checkout') {
196
  $text = __('This order was created by a shop manager. Only orders created by customers are analysed.', 'woocommerce-google-adwords-conversion-tracking-tag');
197
  ?>
198
  <div aria-hidden="true" title="<?php esc_html_e($text); ?>" class="pmw-monitored-icon none">
@@ -200,7 +297,7 @@ class Order_Columns {
200
  </div>
201
  <?php
202
 
203
- } elseif (get_post_meta($post_id, '_wpm_conversion_pixel_fired', true)) {
204
  $text = __('Conversion pixels fired', 'woocommerce-google-adwords-conversion-tracking-tag');
205
  ?>
206
  <div aria-hidden="true" title="<?php esc_html_e($text); ?>" class="pmw-monitored-icon good">
2
 
3
  namespace WCPM\Classes\Admin;
4
 
5
+ use WC_Order_Query;
6
  use WCPM\Classes\Helpers;
7
 
8
  if (!defined('ABSPATH')) {
23
 
24
  private function __construct() {
25
 
26
+ // pre HPOS
 
27
  add_action('pre_get_posts', [$this, 'view_pixels_not_fired'], 1000, 1);
28
 
29
+ // pre HPOS and HPOS
30
+ add_action('manage_shop_order_posts_custom_column', [$this, 'custom_orders_list_column_content'], 20, 2);
31
+ add_filter('manage_edit-shop_order_columns', [$this, 'custom_shop_order_column'], 20);
32
+ add_filter('manage_woocommerce_page_wc-orders_columns', [$this, 'custom_shop_order_column'], 20);
33
+
34
+ // HPOS only
35
+ add_action('manage_woocommerce_page_wc-orders_custom_column', [$this, 'custom_orders_list_column_content_order'], 20, 2);
36
+ add_action('woocommerce_order_list_table_prepare_items_query_args', [$this, 'hpos_view_query_adjustment'], 20);
37
+ add_filter('views_woocommerce_page_wc-orders', [$this, 'hpos_menu_view'], 20);
38
+ }
39
+
40
+ public function hpos_menu_view( $views ) {
41
+
42
+ $count_missing_pixel_fires = count(wc_get_orders([
43
+ 'return' => 'ids',
44
+ 'status' => ['wc-completed', 'wc-processing', 'wc-on-hold', 'wc-pending'],
45
+ 'posts_per_page' => -1,
46
+ 'date_created' => '>' . ( time() - MONTH_IN_SECONDS ),
47
+ 'meta_query' => [
48
+ [
49
+ 'key' => '_wpm_process_through_wpm',
50
+ 'compare' => 'EXISTS',
51
+ ],
52
+ [
53
+ 'key' => '_wpm_conversion_pixel_fired',
54
+ 'compare' => 'NOT EXISTS'
55
+ ],
56
+ ],
57
+ 'field_query' => [
58
+ [
59
+ 'field' => 'created_via',
60
+ 'value' => 'checkout',
61
+ 'compare' => '='
62
+ ]
63
+ ]
64
+ ]));
65
+
66
+
67
+ return $this->get_updated_views_hpos($views, $count_missing_pixel_fires, $this->is_pmw_pixels_not_fired_view());
68
+ }
69
+
70
+ public function get_updated_views_hpos( $views, $count_missing_pixel_fires, $pmw_pixels_not_fired_query ) {
71
+
72
+ $query_string = admin_url('admin.php?page=wc-orders');
73
+ $query_string = add_query_arg('pmw-pixels-not-fired', '', $query_string);
74
+
75
+ $class = $pmw_pixels_not_fired_query ? 'current' : '';
76
+
77
+ $views['pmw-pixels-not-fired'] = $this->get_pmw_no_pixels_fired_view_html($query_string, $class, $count_missing_pixel_fires);
78
+
79
+ return $views;
80
+ }
81
+
82
+ private function get_pmw_no_pixels_fired_view_html( $query_string, $class, $count_missing_pixel_fires ) {
83
+ return sprintf('<a href="%s" class="%s">%s <span class="count">(%s)</span></a>', $query_string, $class, esc_html__('PMW pixels not fired - 30d', 'woocommerce-google-adwords-conversion-tracking-tag'), $count_missing_pixel_fires);
84
+ }
85
+
86
+ public function hpos_view_query_adjustment( $query_args ) {
87
+
88
+ if (!$this->is_pmw_pixels_not_fired_view()) {
89
+ return $query_args;
90
+ }
91
+
92
+ // checkout, admin, subscription, Vipps Express Checkout
93
+ $query_args['created_via'] = 'checkout';
94
+
95
+ $query_args['status'] = ['wc-completed', 'wc-processing', 'wc-on-hold', 'wc-pending'];
96
+ $query_args['date_created'] = '>' . ( time() - MONTH_IN_SECONDS );
97
+
98
+ $query_args['meta_query'][] = [
99
+ 'key' => '_wpm_process_through_wpm',
100
+ 'compare' => 'EXISTS',
101
+ ];
102
+
103
+ $query_args['meta_query'][] = [
104
+ 'key' => '_wpm_conversion_pixel_fired',
105
+ 'compare' => 'NOT EXISTS',
106
+ ];
107
+
108
+ return $query_args;
109
+ }
110
+
111
+
112
+ private function is_pmw_pixels_not_fired_view() {
113
+ $_get = Helpers::get_input_vars_sanitized(INPUT_GET);
114
+ return isset($_get['pmw-pixels-not-fired']);
115
  }
116
 
117
  public function view_pixels_not_fired( $query ) {
 
118
 
119
+ if (!Helpers::is_orders_page()) {
 
120
  return;
121
  }
122
 
123
+ if (Helpers::is_wc_hpos_enabled()) {
124
  return;
125
  }
126
 
127
+ if (!$query->is_main_query()) {
128
+ return;
129
+ }
130
 
131
+ $is_pmw_pixels_not_fired_view = $this->is_pmw_pixels_not_fired_view();
132
 
133
  // Set additional filters for the view
134
+ if ($is_pmw_pixels_not_fired_view) {
135
 
136
  $query->set('post_status', ['wc-completed', 'wc-processing', 'wc-on-hold', 'wc-pending']);
137
 
186
  ]
187
  ]));
188
 
 
189
  // Add new view with all orders where the conversion pixels have not been fired
190
+ add_filter('views_edit-shop_order', function ( $views ) use ( $count_missing_pixel_fires, $is_pmw_pixels_not_fired_view ) {
191
+ return $this->get_updated_views($views, $count_missing_pixel_fires, $is_pmw_pixels_not_fired_view);
192
+ });
193
+ }
194
 
195
+ public function get_updated_views( $views, $count_missing_pixel_fires, $pmw_pixels_not_fired_query ) {
196
+ $query_string = admin_url('edit.php?post_type=shop_order');
197
+ $query_string = add_query_arg('pmw-pixels-not-fired', '', $query_string);
198
 
199
+ $class = $pmw_pixels_not_fired_query ? 'current' : '';
200
 
201
+ $views['pmw-pixels-not-fired'] = $this->get_pmw_no_pixels_fired_view_html($query_string, $class, $count_missing_pixel_fires);
202
 
203
+ return $views;
204
  }
205
 
206
+
207
  public function pmw_order_table_styles() {
208
  wp_add_inline_style(
209
  'woocommerce_admin_styles',
213
 
214
  public function custom_shop_order_column( $columns ) {
215
 
216
+ // error_log('columns: ' . print_r($columns, true));
217
+
218
  function get_list_order_parameter( $list_order ) {
219
  if (is_null($list_order)) {
220
  return '';
225
 
226
  $_get = Helpers::get_input_vars_sanitized(INPUT_GET);
227
 
 
228
  if (!isset($_get['order'])) {
229
  $list_order = 'dsc';
230
  } elseif ('dsc' === $_get['order']) {
248
  return $reordered_columns;
249
  }
250
 
251
+ public function custom_orders_list_column_content( $column_name, $post_id ) {
252
+
253
+ $order = wc_get_order($post_id);
254
+
255
+ $this->custom_orders_list_column_content_order($column_name, $order);
256
+ }
257
+
258
+ public function custom_orders_list_column_content_order( $column_name, $order ) {
259
+
260
 
261
+ switch ($column_name) {
 
262
  case 'pmw-monitored':
263
  // Get custom post meta data
264
+ if ($order->get_meta('_wpm_process_through_wpm', true)) {
265
  $text = __('PMW monitored order', 'woocommerce-google-adwords-conversion-tracking-tag');
266
  ?>
267
  <div aria-hidden="true" title="<?php esc_html_e($text); ?>" class="pmw-monitored-icon good">
281
 
282
  case 'pmw-pixels-fired':
283
  // Get custom post meta data
284
+ if (!$order->get_meta('_wpm_process_through_wpm', true)) {
285
  $text = __('Order not tracked by PMW', 'woocommerce-google-adwords-conversion-tracking-tag');
286
  ?>
287
  <div aria-hidden="true" title="<?php esc_html_e($text); ?>" class="pmw-monitored-icon none">
289
  </div>
290
  <?php
291
 
292
+ } elseif ($order->get_created_via() !== 'checkout') {
293
  $text = __('This order was created by a shop manager. Only orders created by customers are analysed.', 'woocommerce-google-adwords-conversion-tracking-tag');
294
  ?>
295
  <div aria-hidden="true" title="<?php esc_html_e($text); ?>" class="pmw-monitored-icon none">
297
  </div>
298
  <?php
299
 
300
+ } elseif ($order->get_meta('_wpm_conversion_pixel_fired', true)) {
301
  $text = __('Conversion pixels fired', 'woocommerce-google-adwords-conversion-tracking-tag');
302
  ?>
303
  <div aria-hidden="true" title="<?php esc_html_e($text); ?>" class="pmw-monitored-icon good">
classes/class-helpers.php CHANGED
@@ -15,7 +15,7 @@ class Helpers {
15
  return self::generic_sanitization($input_vars);
16
  }
17
 
18
- private static function generic_sanitization( $input ) {
19
 
20
  if (is_array($input)) {
21
  array_walk_recursive($input, function ( &$value, $key ) {
@@ -40,4 +40,23 @@ class Helpers {
40
 
41
  return false;
42
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  }
15
  return self::generic_sanitization($input_vars);
16
  }
17
 
18
+ public static function generic_sanitization( $input ) {
19
 
20
  if (is_array($input)) {
21
  array_walk_recursive($input, function ( &$value, $key ) {
40
 
41
  return false;
42
  }
43
+
44
+ public static function is_wc_hpos_enabled() {
45
+ return class_exists('Automattic\WooCommerce\Utilities\OrderUtil') && \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled();
46
+ }
47
+
48
+ public static function is_orders_page() {
49
+ global $pagenow;
50
+
51
+ $_get = self::get_input_vars(INPUT_GET);
52
+
53
+ return ( 'edit.php' === $pagenow && isset($_get['post_type']) && 'shop_order' === $_get['post_type'] ) || ( isset($_get['page']) && 'wc-orders' === $_get['page'] );
54
+ }
55
+
56
+ public static function get_input_vars( $type ) {
57
+
58
+ $input_vars = filter_input_array($type, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
59
+
60
+ return self::generic_sanitization($input_vars);
61
+ }
62
  }
classes/class-profit-margin.php CHANGED
@@ -112,17 +112,25 @@ class Profit_Margin {
112
 
113
  // Add Stripe fees
114
  // because Stripe doesn't save the fee on the order fees
115
- $order_fees += self::get_fee_by_postmeta_key($order->get_id(), '_stripe_fee');
116
 
117
  // Add _paypal_transaction_fee
118
  // because PayPal doesn't save the fee on the order fees
119
  // https://stackoverflow.com/a/56129332/4688612
120
- $order_fees += self::get_fee_by_postmeta_key($order->get_id(), '_paypal_transaction_fee');
121
 
122
  // Add ppcp_paypal_fees
123
  // because PayPal doesn't save the fee on the order fees
124
- if (get_post_meta($order->get_id(), '_ppcp_paypal_fees', true)) {
125
- $ppcp_paypal_fees = get_post_meta($order->get_id(), '_ppcp_paypal_fees', true);
 
 
 
 
 
 
 
 
126
 
127
  if (!empty($ppcp_paypal_fees['paypal_fee']['value'])) {
128
  $order_fees += $ppcp_paypal_fees['paypal_fee']['value'];
@@ -132,9 +140,9 @@ class Profit_Margin {
132
  return $order_fees;
133
  }
134
 
135
- private static function get_fee_by_postmeta_key( $order_id, $postmeta_key ) {
136
 
137
- $fee = get_post_meta($order_id, $postmeta_key, true);
138
 
139
  if (empty($fee)) {
140
  return 0;
112
 
113
  // Add Stripe fees
114
  // because Stripe doesn't save the fee on the order fees
115
+ $order_fees += self::get_fee_by_postmeta_key($order, '_stripe_fee');
116
 
117
  // Add _paypal_transaction_fee
118
  // because PayPal doesn't save the fee on the order fees
119
  // https://stackoverflow.com/a/56129332/4688612
120
+ $order_fees += self::get_fee_by_postmeta_key($order, '_paypal_transaction_fee');
121
 
122
  // Add ppcp_paypal_fees
123
  // because PayPal doesn't save the fee on the order fees
124
+ // if (get_post_meta($order->get_id(), '_ppcp_paypal_fees', true)) {
125
+ // $ppcp_paypal_fees = get_post_meta($order->get_id(), '_ppcp_paypal_fees', true);
126
+ //
127
+ // if (!empty($ppcp_paypal_fees['paypal_fee']['value'])) {
128
+ // $order_fees += $ppcp_paypal_fees['paypal_fee']['value'];
129
+ // }
130
+ // }
131
+
132
+ if ($order->meta_exists('_ppcp_paypal_fees')) {
133
+ $ppcp_paypal_fees = $order->get_meta('_ppcp_paypal_fees', true);
134
 
135
  if (!empty($ppcp_paypal_fees['paypal_fee']['value'])) {
136
  $order_fees += $ppcp_paypal_fees['paypal_fee']['value'];
140
  return $order_fees;
141
  }
142
 
143
+ private static function get_fee_by_postmeta_key( $order, $postmeta_key ) {
144
 
145
+ $fee = $order->get_meta( $postmeta_key, true);
146
 
147
  if (empty($fee)) {
148
  return 0;
classes/pixels/class-pixel-manager.php CHANGED
@@ -4,6 +4,7 @@ namespace WCPM\Classes\Pixels;
4
 
5
  use WCPM\Classes\Admin\Environment_Check ;
6
  use WCPM\Classes\Admin\Validations ;
 
7
  use WCPM\Classes\Http\Facebook_CAPI ;
8
  use WCPM\Classes\Http\Google_MP ;
9
  use WCPM\Classes\Pixels\Facebook\Facebook_Microdata ;
@@ -27,8 +28,10 @@ class Pixel_Manager
27
  protected $google_active ;
28
  protected $google ;
29
  protected $microdata_product_id ;
30
- protected $position = 1 ;
31
  protected $order ;
 
 
 
32
  private static $instance ;
33
  public static function get_instance()
34
  {
@@ -167,6 +170,11 @@ class Pixel_Manager
167
  return $this->order;
168
  }
169
 
 
 
 
 
 
170
  // https://wordpress.stackexchange.com/a/377954/68337
171
  public function prepare_custom_rest_handlers(
172
  $served,
@@ -179,13 +187,12 @@ class Pixel_Manager
179
  // error log $request->get_route();
180
  // error_log($request->get_route());
181
  // If $request->get_route() is not /pmw/v1/google-ads/conversion-adjustments then return $served
182
- if ( strpos( $request->get_route(), 'pmw/v1/google-ads/conversion-adjustments.csv' ) === false ) {
183
  return $served;
184
  }
185
  // if (strpos($request->get_route(), '/google-ads/conversion-adjustments/') !== 0) {
186
  // return $served;
187
  // }
188
- // error_log('prepare_custom_rest_responses - 2');
189
  // Send headers.
190
  // $server->send_header( 'Content-Type', 'text/xml' );
191
  // $server->send_header( 'Content-Type', 'application/xml' );
@@ -193,15 +200,14 @@ class Pixel_Manager
193
  // $server->send_header('Content-Type', 'text/html');
194
  // Echo the XML that's returned by smg_feed().
195
  // Turn off phpcs because we're echoing the XML.
196
- // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
197
- echo $result->get_data() ;
198
  // And then exit.
199
  exit;
200
  }
201
 
202
  public function register_rest_routes()
203
  {
204
- register_rest_route( 'pmw/v1', '/test/', [
205
  'methods' => 'POST',
206
  'callback' => function () {
207
  wp_send_json_success();
@@ -210,7 +216,7 @@ class Pixel_Manager
210
  return true;
211
  },
212
  ] );
213
- register_rest_route( 'pmw/v1', '/test/', [
214
  'methods' => 'GET',
215
  'callback' => function () {
216
  wp_send_json_success();
@@ -219,18 +225,18 @@ class Pixel_Manager
219
  return true;
220
  },
221
  ] );
222
- register_rest_route( 'pmw/v1', '/settings/', [
223
  'methods' => 'POST',
224
  'callback' => [ $this, 'wpm_save_imported_settings' ],
225
  'permission_callback' => function () {
226
  return current_user_can( 'manage_options' );
227
  },
228
  ] );
229
- register_rest_route( 'pmw/v1', '/products/', [
230
  'methods' => 'POST',
231
  'callback' => function ( $request ) {
232
  $product_ids = $request->get_json_params();
233
- $product_ids = $this->generic_sanitization( $product_ids );
234
 
235
  if ( !$product_ids ) {
236
  wp_send_json_error( 'No product ids provided' );
@@ -243,7 +249,7 @@ class Pixel_Manager
243
  return true;
244
  },
245
  ] );
246
- register_rest_route( 'pmw/v1', '/pixels-fired/', [
247
  'methods' => 'POST',
248
  'callback' => function ( $request ) {
249
  $data = $request->get_json_params();
@@ -285,12 +291,46 @@ class Pixel_Manager
285
  'Adjusted Value Currency'
286
  ];
287
  $csv = implode( ',', $title_row ) . PHP_EOL;
288
- // Get all refunds from 2 up to 3 days ago
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  $refunds = wc_get_orders( [
290
  'type' => 'shop_order_refund',
291
  'status' => 'completed',
292
- 'date_after' => gmdate( 'Y-m-d H:i:s', strtotime( '-4 days' ) ),
293
- 'date_before' => gmdate( 'Y-m-d H:i:s', strtotime( '-2 days' ) ),
294
  ] );
295
  // error_log('refunds: ' . print_r($refunds, true));
296
  foreach ( $refunds as $refund ) {
@@ -386,7 +426,7 @@ class Pixel_Manager
386
 
387
  public function capture_ajax_server_to_server_event()
388
  {
389
- $_post = $this->get_input_vars( INPUT_POST );
390
  $this->process_server_to_server_event( $_post['data'] );
391
  wp_send_json_success();
392
  }
@@ -403,7 +443,7 @@ class Pixel_Manager
403
  {
404
  $options = $request->get_params();
405
  // Sanitize nested array $options
406
- $options = $this->generic_sanitization( $options );
407
  // Validate imported options
408
 
409
  if ( Validations::validate_imported_options( $options ) ) {
@@ -445,18 +485,14 @@ class Pixel_Manager
445
 
446
  public function wpm_woocommerce_new_order( $order_id )
447
  {
 
448
  /**
449
  * All new orders should be marked as long WPM is active,
450
  * so that we know we can process them later through WPM,
451
  * and so that we know we should not touch orders that were
452
  * placed before WPM was active.
453
  */
454
- add_post_meta(
455
- $order_id,
456
- '_wpm_process_through_wpm',
457
- true,
458
- true
459
- );
460
  /**
461
  * Set a custom user ID on the order
462
  * because WC sets 0 on all order created
@@ -466,12 +502,8 @@ class Pixel_Manager
466
  if ( is_user_logged_in() ) {
467
  $user_id = get_current_user_id();
468
  }
469
- add_post_meta(
470
- $order_id,
471
- '_wpm_customer_user',
472
- $user_id,
473
- true
474
- );
475
  }
476
 
477
  // Thanks to: https://gist.github.com/mishterk/6b7a4d6e5a91086a5a9b05ace304b5ce#file-mark-wordpress-scripts-as-async-or-defer-php
@@ -1110,7 +1142,7 @@ class Pixel_Manager
1110
 
1111
  public function ajax_pmw_get_product_ids()
1112
  {
1113
- $_post = $this->get_input_vars( INPUT_POST );
1114
  $product_ids = explode( ',', $_post['productIds'] );
1115
 
1116
  if ( !$product_ids ) {
@@ -1145,7 +1177,7 @@ class Pixel_Manager
1145
 
1146
  public function ajax_purchase_pixels_fired_handler()
1147
  {
1148
- $_post = $this->get_input_vars( INPUT_POST );
1149
 
1150
  if ( isset( $_post['order_id'] ) && isset( $_post['source'] ) ) {
1151
  $this->save_conversion_pixels_fired_status( $_post['order_id'], $_post['source'] );
@@ -1158,12 +1190,13 @@ class Pixel_Manager
1158
 
1159
  public function save_conversion_pixels_fired_status( $order_id, $source = 'thankyou_page' )
1160
  {
1161
- update_post_meta( $order_id, '_wpm_conversion_pixel_trigger', $source );
1162
- update_post_meta( $order_id, '_wpm_conversion_pixel_fired', true );
1163
- // Get the time between when the order was created and now and save it in _wpm_conversion_pixel_fired_delay
1164
  $order = wc_get_order( $order_id );
 
 
 
1165
  $time_diff = time() - strtotime( $order->get_date_created() );
1166
- update_post_meta( $order_id, '_wpm_conversion_pixel_fired_delay', $time_diff );
 
1167
  }
1168
 
1169
  public function wpm_front_end_scripts()
4
 
5
  use WCPM\Classes\Admin\Environment_Check ;
6
  use WCPM\Classes\Admin\Validations ;
7
+ use WCPM\Classes\Helpers ;
8
  use WCPM\Classes\Http\Facebook_CAPI ;
9
  use WCPM\Classes\Http\Google_MP ;
10
  use WCPM\Classes\Pixels\Facebook\Facebook_Microdata ;
28
  protected $google_active ;
29
  protected $google ;
30
  protected $microdata_product_id ;
 
31
  protected $order ;
32
+ protected $position = 1 ;
33
+ protected $rest_namespace = 'pmw/v1' ;
34
+ protected $gads_conversion_adjustments_route = '/google-ads/conversion-adjustments.csv' ;
35
  private static $instance ;
36
  public static function get_instance()
37
  {
170
  return $this->order;
171
  }
172
 
173
+ public function get_google_ads_conversion_adjustments_endpoint()
174
+ {
175
+ return '/wp-json/' . $this->rest_namespace . $this->gads_conversion_adjustments_route;
176
+ }
177
+
178
  // https://wordpress.stackexchange.com/a/377954/68337
179
  public function prepare_custom_rest_handlers(
180
  $served,
187
  // error log $request->get_route();
188
  // error_log($request->get_route());
189
  // If $request->get_route() is not /pmw/v1/google-ads/conversion-adjustments then return $served
190
+ if ( strpos( $request->get_route(), $this->rest_namespace . $this->gads_conversion_adjustments_route ) === false ) {
191
  return $served;
192
  }
193
  // if (strpos($request->get_route(), '/google-ads/conversion-adjustments/') !== 0) {
194
  // return $served;
195
  // }
 
196
  // Send headers.
197
  // $server->send_header( 'Content-Type', 'text/xml' );
198
  // $server->send_header( 'Content-Type', 'application/xml' );
200
  // $server->send_header('Content-Type', 'text/html');
201
  // Echo the XML that's returned by smg_feed().
202
  // Turn off phpcs because we're echoing the XML.
203
+ esc_html_e( $result->get_data() );
 
204
  // And then exit.
205
  exit;
206
  }
207
 
208
  public function register_rest_routes()
209
  {
210
+ register_rest_route( $this->rest_namespace, '/test/', [
211
  'methods' => 'POST',
212
  'callback' => function () {
213
  wp_send_json_success();
216
  return true;
217
  },
218
  ] );
219
+ register_rest_route( $this->rest_namespace, '/test/', [
220
  'methods' => 'GET',
221
  'callback' => function () {
222
  wp_send_json_success();
225
  return true;
226
  },
227
  ] );
228
+ register_rest_route( $this->rest_namespace, '/settings/', [
229
  'methods' => 'POST',
230
  'callback' => [ $this, 'wpm_save_imported_settings' ],
231
  'permission_callback' => function () {
232
  return current_user_can( 'manage_options' );
233
  },
234
  ] );
235
+ register_rest_route( $this->rest_namespace, '/products/', [
236
  'methods' => 'POST',
237
  'callback' => function ( $request ) {
238
  $product_ids = $request->get_json_params();
239
+ $product_ids = Helpers::generic_sanitization( $product_ids );
240
 
241
  if ( !$product_ids ) {
242
  wp_send_json_error( 'No product ids provided' );
249
  return true;
250
  },
251
  ] );
252
+ register_rest_route( $this->rest_namespace, '/pixels-fired/', [
253
  'methods' => 'POST',
254
  'callback' => function ( $request ) {
255
  $data = $request->get_json_params();
291
  'Adjusted Value Currency'
292
  ];
293
  $csv = implode( ',', $title_row ) . PHP_EOL;
294
+ $date_before = gmdate( 'Y-m-d H:i:s', strtotime( '-2 days' ) );
295
+ $date_after = gmdate( 'Y-m-d H:i:s', strtotime( '-4 days' ) );
296
+ /**
297
+ * Get all cancelled orders that were cancelled within the last 2 and 4 days
298
+ * and retract them
299
+ */
300
+ $orders = wc_get_orders( [
301
+ 'limit' => -1,
302
+ 'status' => 'cancelled',
303
+ 'date_modified' => $date_after . '...' . $date_before,
304
+ ] );
305
+ foreach ( $orders as $order ) {
306
+ // Get the order ID
307
+ $order_id = $order->get_id();
308
+ // Get the modified date
309
+ $adjustment_time = $order->get_date_modified();
310
+ $adjustment_time = $adjustment_time->format( 'Y-m-d H:i:s' ) . ' ' . $timezone;
311
+ // Set adjustment type
312
+ $adjustment_type = 'RETRACT';
313
+ $adjusted_value = null;
314
+ $adjusted_value_currency = null;
315
+ // Compile new row
316
+ $row = [
317
+ $order_id,
318
+ $conversion_name,
319
+ $adjustment_time,
320
+ $adjustment_type,
321
+ $adjusted_value,
322
+ $adjusted_value_currency
323
+ ];
324
+ $csv .= implode( ',', $row ) . PHP_EOL;
325
+ }
326
+ /**
327
+ * Get all refunds from 2 up to 3 days ago
328
+ */
329
  $refunds = wc_get_orders( [
330
  'type' => 'shop_order_refund',
331
  'status' => 'completed',
332
+ 'date_after' => $date_after,
333
+ 'date_before' => $date_before,
334
  ] );
335
  // error_log('refunds: ' . print_r($refunds, true));
336
  foreach ( $refunds as $refund ) {
426
 
427
  public function capture_ajax_server_to_server_event()
428
  {
429
+ $_post = Helpers::get_input_vars( INPUT_POST );
430
  $this->process_server_to_server_event( $_post['data'] );
431
  wp_send_json_success();
432
  }
443
  {
444
  $options = $request->get_params();
445
  // Sanitize nested array $options
446
+ $options = Helpers::generic_sanitization( $options );
447
  // Validate imported options
448
 
449
  if ( Validations::validate_imported_options( $options ) ) {
485
 
486
  public function wpm_woocommerce_new_order( $order_id )
487
  {
488
+ $order = wc_get_order( $order_id );
489
  /**
490
  * All new orders should be marked as long WPM is active,
491
  * so that we know we can process them later through WPM,
492
  * and so that we know we should not touch orders that were
493
  * placed before WPM was active.
494
  */
495
+ $order->add_meta_data( '_wpm_process_through_wpm', true, true );
 
 
 
 
 
496
  /**
497
  * Set a custom user ID on the order
498
  * because WC sets 0 on all order created
502
  if ( is_user_logged_in() ) {
503
  $user_id = get_current_user_id();
504
  }
505
+ $order->add_meta_data( '_wpm_customer_user', $user_id, true );
506
+ $order->save();
 
 
 
 
507
  }
508
 
509
  // Thanks to: https://gist.github.com/mishterk/6b7a4d6e5a91086a5a9b05ace304b5ce#file-mark-wordpress-scripts-as-async-or-defer-php
1142
 
1143
  public function ajax_pmw_get_product_ids()
1144
  {
1145
+ $_post = Helpers::get_input_vars( INPUT_POST );
1146
  $product_ids = explode( ',', $_post['productIds'] );
1147
 
1148
  if ( !$product_ids ) {
1177
 
1178
  public function ajax_purchase_pixels_fired_handler()
1179
  {
1180
+ $_post = Helpers::get_input_vars( INPUT_POST );
1181
 
1182
  if ( isset( $_post['order_id'] ) && isset( $_post['source'] ) ) {
1183
  $this->save_conversion_pixels_fired_status( $_post['order_id'], $_post['source'] );
1190
 
1191
  public function save_conversion_pixels_fired_status( $order_id, $source = 'thankyou_page' )
1192
  {
 
 
 
1193
  $order = wc_get_order( $order_id );
1194
+ $order->update_meta_data( '_wpm_conversion_pixel_trigger', $source );
1195
+ $order->update_meta_data( '_wpm_conversion_pixel_fired', true );
1196
+ // Get the time between when the order was created and now and save it in _wpm_conversion_pixel_fired_delay
1197
  $time_diff = time() - strtotime( $order->get_date_created() );
1198
+ $order->update_meta_data( '_wpm_conversion_pixel_fired_delay', $time_diff );
1199
+ $order->save();
1200
  }
1201
 
1202
  public function wpm_front_end_scripts()
classes/pixels/facebook/class-facebook-pixel-manager.php CHANGED
@@ -44,7 +44,7 @@ class Facebook_Pixel_Manager
44
  add_action( 'woocommerce_subscription_status_cancelled', [ $this, 'facebook_capi_report_subscription_cancellation__premium_only' ] );
45
  add_action(
46
  'woocommerce_subscription_status_updated',
47
- [ $this, 'facebook_capi_report_subscription_reactivation__premium_only' ],
48
  10,
49
  3
50
  );
44
  add_action( 'woocommerce_subscription_status_cancelled', [ $this, 'facebook_capi_report_subscription_cancellation__premium_only' ] );
45
  add_action(
46
  'woocommerce_subscription_status_updated',
47
+ [ $this, 'facebook_capi_report_subscription_update__premium_only' ],
48
  10,
49
  3
50
  );
classes/pixels/google/class-google-pixel-manager.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  namespace WCPM\Classes\Pixels\Google;
4
 
 
5
  use WCPM\Classes\Http\Google_MP_GA4 ;
6
  use WCPM\Classes\Http\Google_MP_UA ;
7
  use WCPM\Classes\Pixels\Script_Manager ;
@@ -47,7 +48,7 @@ class Google_Pixel_Manager
47
  {
48
 
49
  if ( is_user_logged_in() ) {
50
- $user_info = get_user_by( 'id', $this->wpm_get_order_user_id( $order->get_id() ) );
51
  if ( is_object( $user_info ) ) {
52
  wc_get_logger()->debug( 'Prevented order ID ' . $order->get_id() . ' to be reported through the Measurement Protocol for user ' . $user_info->user_login . ' (roles: ' . implode( ', ', $user_info->roles ) . ')', [
53
  'source' => 'wpm',
2
 
3
  namespace WCPM\Classes\Pixels\Google;
4
 
5
+ use WCPM\Classes\Helpers ;
6
  use WCPM\Classes\Http\Google_MP_GA4 ;
7
  use WCPM\Classes\Http\Google_MP_UA ;
8
  use WCPM\Classes\Pixels\Script_Manager ;
48
  {
49
 
50
  if ( is_user_logged_in() ) {
51
+ $user_info = get_user_by( 'id', $this->wpm_get_order_user_id( $order ) );
52
  if ( is_object( $user_info ) ) {
53
  wc_get_logger()->debug( 'Prevented order ID ' . $order->get_id() . ' to be reported through the Measurement Protocol for user ' . $user_info->user_login . ' (roles: ' . implode( ', ', $user_info->roles ) . ')', [
54
  'source' => 'wpm',
classes/pixels/trait-shop.php CHANGED
@@ -8,6 +8,7 @@ use libphonenumber\PhoneNumberUtil ;
8
  use WC_Geolocation ;
9
  use WCPM\Classes\Admin\Documentation ;
10
  use WCPM\Classes\Admin\Environment_Check ;
 
11
  use WCPM\Classes\Profit_Margin ;
12
 
13
  if ( !defined( 'ABSPATH' ) ) {
@@ -84,7 +85,7 @@ trait Trait_Shop
84
 
85
  protected function is_valid_order_key_in_url()
86
  {
87
- $_get = $this->get_input_vars( INPUT_GET );
88
  $order_key = null;
89
  // key is for WooCommerce
90
  // wcf-key is for CartFlows
@@ -160,7 +161,7 @@ trait Trait_Shop
160
 
161
  protected function get_order_with_url_order_key()
162
  {
163
- $_get = $this->get_input_vars( INPUT_GET );
164
  // key is for WooCommerce
165
  // wcf-key is for CartFlows
166
 
@@ -409,11 +410,11 @@ trait Trait_Shop
409
  return wp_specialchars_decode( $title );
410
  }
411
 
412
- protected function is_backend_manual_order( $post_id )
413
  {
414
  // Only continue if this is a back-end order
415
 
416
- if ( metadata_exists( 'post', $post_id, '_created_via' ) && 'admin' === get_post_meta( $post_id, '_created_via', true ) ) {
417
  return true;
418
  } else {
419
  return false;
@@ -421,11 +422,11 @@ trait Trait_Shop
421
 
422
  }
423
 
424
- protected function is_backend_subscription_renewal_order( $post_id )
425
  {
426
  // Only continue if this is a back-end order
427
 
428
- if ( metadata_exists( 'post', $post_id, '_created_via' ) && 'subscription' === get_post_meta( $post_id, '_created_via', true ) ) {
429
  return true;
430
  } else {
431
  return false;
@@ -433,10 +434,10 @@ trait Trait_Shop
433
 
434
  }
435
 
436
- protected function was_order_created_while_wpm_was_active( $order_id )
437
  {
438
 
439
- if ( get_post_meta( $order_id, '_wpm_process_through_wpm', true ) ) {
440
  return true;
441
  } else {
442
  return false;
@@ -444,10 +445,10 @@ trait Trait_Shop
444
 
445
  }
446
 
447
- protected function was_order_created_while_wpm_premium_was_active( $order_id )
448
  {
449
 
450
- if ( get_post_meta( $order_id, '_wpm_premium_active', true ) ) {
451
  return true;
452
  } else {
453
  return false;
@@ -455,20 +456,20 @@ trait Trait_Shop
455
 
456
  }
457
 
458
- protected function wpm_get_order_user_id( $order_id )
459
  {
460
 
461
- if ( metadata_exists( 'post', $order_id, '_wpm_customer_user' ) ) {
462
- return (int) get_post_meta( $order_id, '_wpm_customer_user', true );
463
  } else {
464
- return (int) get_post_meta( $order_id, '_customer_user', true );
465
  }
466
 
467
  }
468
 
469
  protected function is_browser_on_shop()
470
  {
471
- $_server = $this->get_input_vars( INPUT_SERVER );
472
  // error_log(print_r($_server, true));
473
  // error_log(print_r($_server['HTTP_HOST'], true));
474
  // error_log('get_site_url(): ' . parse_url(get_site_url(), PHP_URL_HOST));
@@ -544,7 +545,7 @@ trait Trait_Shop
544
 
545
  protected function is_nodedupe_parameter_set()
546
  {
547
- $_get = $this->get_input_vars( INPUT_GET );
548
 
549
  if ( isset( $_get['nodedupe'] ) ) {
550
  return true;
@@ -593,26 +594,6 @@ trait Trait_Shop
593
  return filter_var( $email, FILTER_VALIDATE_EMAIL );
594
  }
595
 
596
- protected function get_input_vars( $type )
597
- {
598
- $input_vars = filter_input_array( $type, FILTER_SANITIZE_FULL_SPECIAL_CHARS );
599
- return $this->generic_sanitization( $input_vars );
600
- }
601
-
602
- protected function generic_sanitization( $input )
603
- {
604
-
605
- if ( is_array( $input ) ) {
606
- array_walk_recursive( $input, function ( &$value, $key ) {
607
- $value = filter_var( $value, FILTER_SANITIZE_FULL_SPECIAL_CHARS );
608
- } );
609
- } else {
610
- $input = filter_var( $input, FILTER_SANITIZE_FULL_SPECIAL_CHARS );
611
- }
612
-
613
- return $input;
614
- }
615
-
616
  private function get_percentage( $counter, $denominator )
617
  {
618
  return ( $denominator > 0 ? round( $counter / $denominator * 100 ) : 0 );
8
  use WC_Geolocation ;
9
  use WCPM\Classes\Admin\Documentation ;
10
  use WCPM\Classes\Admin\Environment_Check ;
11
+ use WCPM\Classes\Helpers ;
12
  use WCPM\Classes\Profit_Margin ;
13
 
14
  if ( !defined( 'ABSPATH' ) ) {
85
 
86
  protected function is_valid_order_key_in_url()
87
  {
88
+ $_get = Helpers::get_input_vars( INPUT_GET );
89
  $order_key = null;
90
  // key is for WooCommerce
91
  // wcf-key is for CartFlows
161
 
162
  protected function get_order_with_url_order_key()
163
  {
164
+ $_get = Helpers::get_input_vars( INPUT_GET );
165
  // key is for WooCommerce
166
  // wcf-key is for CartFlows
167
 
410
  return wp_specialchars_decode( $title );
411
  }
412
 
413
+ protected function is_backend_manual_order( $order )
414
  {
415
  // Only continue if this is a back-end order
416
 
417
+ if ( $order->meta_exists( '_created_via' ) && 'admin' === $order->get_meta( '_created_via', true ) ) {
418
  return true;
419
  } else {
420
  return false;
422
 
423
  }
424
 
425
+ protected function is_backend_subscription_renewal_order( $order )
426
  {
427
  // Only continue if this is a back-end order
428
 
429
+ if ( $order->meta_exists( '_created_via' ) && 'subscription' === $order->get_meta( '_created_via', true ) ) {
430
  return true;
431
  } else {
432
  return false;
434
 
435
  }
436
 
437
+ protected function was_order_created_while_wpm_was_active( $order )
438
  {
439
 
440
+ if ( $order->meta_exists( '_wpm_process_through_wpm' ) ) {
441
  return true;
442
  } else {
443
  return false;
445
 
446
  }
447
 
448
+ protected function was_order_created_while_wpm_premium_was_active( $order )
449
  {
450
 
451
+ if ( $order->meta_exists( '_wpm_premium_active' ) ) {
452
  return true;
453
  } else {
454
  return false;
456
 
457
  }
458
 
459
+ protected function wpm_get_order_user_id( $order )
460
  {
461
 
462
+ if ( $order->meta_exists( '_wpm_customer_user' ) ) {
463
+ return (int) $order->get_meta( '_wpm_customer_user', true );
464
  } else {
465
+ return (int) $order->get_meta( '_customer_user', true );
466
  }
467
 
468
  }
469
 
470
  protected function is_browser_on_shop()
471
  {
472
+ $_server = Helpers::get_input_vars( INPUT_SERVER );
473
  // error_log(print_r($_server, true));
474
  // error_log(print_r($_server['HTTP_HOST'], true));
475
  // error_log('get_site_url(): ' . parse_url(get_site_url(), PHP_URL_HOST));
545
 
546
  protected function is_nodedupe_parameter_set()
547
  {
548
+ $_get = Helpers::get_input_vars( INPUT_GET );
549
 
550
  if ( isset( $_get['nodedupe'] ) ) {
551
  return true;
594
  return filter_var( $email, FILTER_VALIDATE_EMAIL );
595
  }
596
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
597
  private function get_percentage( $counter, $denominator )
598
  {
599
  return ( $denominator > 0 ? round( $counter / $denominator * 100 ) : 0 );
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: woocommerce, google analytics, google ads, facebook, conversion tracking,
4
  Requires at least: 3.7
5
  Tested up to: 6.0
6
  Requires PHP: 7.3
7
- Stable tag: 1.23.0
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
@@ -86,6 +86,7 @@ Have a look at the full feature list over [here](https://sweetcode.com/docs/wpm/
86
  <strong>Premium Features</strong>
87
 
88
  * [Automatic Conversion Recovery (ACR)](https://sweetcode.com/docs/wpm/features/acr?utm_source=wordpress.org&utm_medium=wpm-plugin-page&utm_campaign=pixel-manager-for-woocommerce-docs&utm_content=acr)
 
89
  * Meta CAPI (Facebook CAPI)
90
  * Meta Microdata Output (Facebook Microdata Output)
91
  * Google Analytics Universal and Google Analytics 4 Enhanced E-Commerce
@@ -214,11 +215,19 @@ You can send the link to the front page of your shop too if you think it would b
214
 
215
  == Changelog ==
216
 
 
 
 
 
 
 
 
 
217
  = 1.23.0 = 30.09.2022
218
 
219
 
220
 
221
- * Tweak: Few styling fixes on the settings page.
222
 
223
  = 1.22.1 = 26.09.2022
224
 
4
  Requires at least: 3.7
5
  Tested up to: 6.0
6
  Requires PHP: 7.3
7
+ Stable tag: 1.24.0
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
86
  <strong>Premium Features</strong>
87
 
88
  * [Automatic Conversion Recovery (ACR)](https://sweetcode.com/docs/wpm/features/acr?utm_source=wordpress.org&utm_medium=wpm-plugin-page&utm_campaign=pixel-manager-for-woocommerce-docs&utm_content=acr)
89
+ * Google Ads Conversion Adjustments
90
  * Meta CAPI (Facebook CAPI)
91
  * Meta Microdata Output (Facebook Microdata Output)
92
  * Google Analytics Universal and Google Analytics 4 Enhanced E-Commerce
215
 
216
  == Changelog ==
217
 
218
+ = 1.24.0 = 06.10.2022
219
+
220
+ * New: The Pixel Manager has been refactored to be ready for the upcoming WooCommerce High Performance Orders Storage
221
+ * Tweak: Some UI improvements
222
+ * Tweak: Added GAds Conversion Adjustments feed URL to debug info
223
+ * Tweak: Refactor for HPOS
224
+
225
+
226
  = 1.23.0 = 30.09.2022
227
 
228
 
229
 
230
+ * Tweak: Few styling fixes in the settings page.
231
 
232
  = 1.22.1 = 26.09.2022
233
 
wgact.php CHANGED
@@ -10,16 +10,16 @@
10
  * Developer URI: https://sweetcode.com
11
  * Text Domain: woocommerce-google-adwords-conversion-tracking-tag
12
  * Domain path: /languages
13
- * * Version: 1.23.0
14
  *
15
  * WC requires at least: 3.7
16
- * WC tested up to: 6.8
17
  *
18
  * License: GNU General Public License v3.0
19
  * License URI: http://www.gnu.org/licenses/gpl-3.0.html
20
  *
21
  **/
22
- const WPM_CURRENT_VERSION = '1.23.0' ;
23
  // TODO add option checkbox on uninstall and ask if user wants to delete options from db
24
 
25
  if ( !defined( 'ABSPATH' ) ) {
@@ -35,6 +35,7 @@ use WCPM\Classes\Admin\Order_Columns ;
35
  use WCPM\Classes\Db_Upgrade ;
36
  use WCPM\Classes\Default_Options ;
37
  use WCPM\Classes\Deprecated_Filters ;
 
38
  use WCPM\Classes\Pixels\Pixel_Manager ;
39
  use WCPM\Classes\Admin\Ask_For_Rating ;
40
 
@@ -119,7 +120,7 @@ if ( function_exists( 'wpm_fs' ) ) {
119
  define( 'WPM_DB_OPTIONS_NAME', 'wgact_plugin_options' );
120
  define( 'WPM_DB_NOTIFICATIONS_NAME', 'wgact_notifications' );
121
  define( 'WPM_PLUGIN_DIR_PATH', plugin_dir_url( __FILE__ ) );
122
- define( 'WPM_PLUGIN_BASE_NAME', plugin_basename( __FILE__ ) );
123
  define( 'WPM_DB_RATINGS', 'wgact_ratings' );
124
  require_once dirname( __FILE__ ) . '/vendor/woocommerce/action-scheduler/action-scheduler.php';
125
  // check if WooCommerce is running
@@ -154,6 +155,12 @@ if ( function_exists( 'wpm_fs' ) ) {
154
  } );
155
 
156
  if ( $this->is_woocommerce_active() ) {
 
 
 
 
 
 
157
  add_action( 'woocommerce_init', [ $this, 'init' ] );
158
  add_action(
159
  'init',
10
  * Developer URI: https://sweetcode.com
11
  * Text Domain: woocommerce-google-adwords-conversion-tracking-tag
12
  * Domain path: /languages
13
+ * * Version: 1.24.0
14
  *
15
  * WC requires at least: 3.7
16
+ * WC tested up to: 6.9
17
  *
18
  * License: GNU General Public License v3.0
19
  * License URI: http://www.gnu.org/licenses/gpl-3.0.html
20
  *
21
  **/
22
+ const WPM_CURRENT_VERSION = '1.24.0' ;
23
  // TODO add option checkbox on uninstall and ask if user wants to delete options from db
24
 
25
  if ( !defined( 'ABSPATH' ) ) {
35
  use WCPM\Classes\Db_Upgrade ;
36
  use WCPM\Classes\Default_Options ;
37
  use WCPM\Classes\Deprecated_Filters ;
38
+ use WCPM\Classes\Helpers ;
39
  use WCPM\Classes\Pixels\Pixel_Manager ;
40
  use WCPM\Classes\Admin\Ask_For_Rating ;
41
 
120
  define( 'WPM_DB_OPTIONS_NAME', 'wgact_plugin_options' );
121
  define( 'WPM_DB_NOTIFICATIONS_NAME', 'wgact_notifications' );
122
  define( 'WPM_PLUGIN_DIR_PATH', plugin_dir_url( __FILE__ ) );
123
+ define( 'WPM_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
124
  define( 'WPM_DB_RATINGS', 'wgact_ratings' );
125
  require_once dirname( __FILE__ ) . '/vendor/woocommerce/action-scheduler/action-scheduler.php';
126
  // check if WooCommerce is running
155
  } );
156
 
157
  if ( $this->is_woocommerce_active() ) {
158
+ add_action( 'before_woocommerce_init', function () {
159
+ if ( Helpers::is_wc_hpos_enabled() && class_exists( 'Automattic\\WooCommerce\\Utilities\\FeaturesUtil' ) ) {
160
+ // TODO: https://app.asana.com/0/1110999795232049/1203086190142026
161
+ \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', WPM_PLUGIN_BASENAME, true );
162
+ }
163
+ } );
164
  add_action( 'woocommerce_init', [ $this, 'init' ] );
165
  add_action(
166
  'init',