PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.3-beta
16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 All 507 releases
jetpack / jetpack_vendor / automattic / woocommerce-analytics / src / class-my-account.php

class-my-account.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3-beta, at jetpack_vendor/automattic/woocommerce-analytics/src/class-my-account.php

253 lines 8.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Events tracked on the My Account page.
4 *
5 * @package automattic/woocommerce-analytics
6 */
7
8 namespace Automattic\Woocommerce_Analytics;
9
10 /**
11 * Filters and Actions added to My Account pages to perform analytics
12 */
13 class My_Account {
14
15 use Woo_Analytics_Trait;
16
17 /**
18 * Constructor.
19 */
20 public function init_hooks() {
21 add_action( 'woocommerce_account_content', array( $this, 'track_tabs' ) );
22 add_action( 'woocommerce_customer_save_address', array( $this, 'track_save_address' ), 10, 2 );
23 add_action( 'wp', array( $this, 'track_add_payment_method' ) );
24 add_action( 'wp', array( $this, 'track_delete_payment_method' ) );
25 add_action( 'woocommerce_save_account_details', array( $this, 'track_save_account_details' ) );
26 add_filter( 'woocommerce_my_account_my_orders_actions', array( $this, 'add_initiator_prop_to_my_account_action_links' ) );
27 add_action( 'woocommerce_cancelled_order', array( $this, 'track_order_cancel_event' ), 10, 0 );
28 add_action( 'before_woocommerce_pay', array( $this, 'track_order_pay_event' ) );
29 add_action( 'woocommerce_before_account_orders', array( $this, 'add_initiator_prop_to_order_urls' ), 9 );
30 add_filter( 'query_vars', array( $this, 'add_initiator_param_to_query_vars' ) );
31 }
32
33 /**
34 * Track my account tabs, we only trigger an event if a tab is viewed.
35 *
36 * We also track other events here, like order number clicks, order action clicks,
37 * address clicks, payment method add and delete.
38 */
39 public function track_tabs() {
40 global $wp;
41
42 // WooCommerce keeps a map of my-account endpoints keys and their custom permalinks.
43 $core_endpoints = WC()->query->get_query_vars();
44
45 if ( ! empty( $wp->query_vars ) ) {
46
47 foreach ( $wp->query_vars as $key => $value ) {
48 // we skip pagename.
49 if ( 'pagename' === $key ) {
50 continue;
51 }
52
53 // When no permalink is set, the first page is page_id, so we skip it.
54 if ( 'page_id' === $key ) {
55 continue;
56 }
57
58 // We don't want to track our own analytics params.
59 if ( '_wca_initiator' === $key ) {
60 continue;
61 }
62
63 if ( isset( $core_endpoints['view-order'] ) && $core_endpoints['view-order'] === $key && is_numeric( $value ) ) {
64 $initiator = get_query_var( '_wca_initiator' );
65 if ( 'number' === $initiator ) {
66 $this->enqueue_event( 'my_account_order_number_click' );
67 continue;
68 }
69 if ( 'action' === $initiator ) {
70 $this->enqueue_event( 'my_account_order_action_click', array( 'action' => 'view' ) );
71 continue;
72 }
73 }
74
75 if ( isset( $core_endpoints['edit-address'] ) && $core_endpoints['edit-address'] === $key && in_array( $value, array( 'billing', 'shipping' ), true ) ) {
76 $refer = wp_get_referer();
77 if ( $refer === wc_get_endpoint_url( 'edit-address', $value ) ) {
78 // It means we're likely coming from the same page after a failed save and don't want to retrigger the address click event.
79 continue;
80 }
81
82 $this->enqueue_event( 'my_account_address_click', array( 'address' => $value ) );
83 continue;
84 }
85
86 if ( isset( $core_endpoints['add-payment-method'] ) && $core_endpoints['add-payment-method'] === $key ) {
87 $this->enqueue_event( 'my_account_payment_add' );
88 continue;
89 }
90
91 if ( isset( $core_endpoints['edit-address'] ) && $core_endpoints['edit-address'] ) {
92 $refer = wp_get_referer();
93 if ( $refer === wc_get_endpoint_url( 'edit-address', 'billing' ) || $refer === wc_get_endpoint_url( 'edit-address', 'shipping' ) ) {
94 // It means we're likely coming from the edit page save and don't want to retrigger the page view event.
95 continue;
96 }
97 }
98 /**
99 * The main dashboard view has page as key, so we rename it.
100 */
101 if ( 'page' === $key ) {
102 $key = 'dashboard';
103 }
104
105 /**
106 * If a custom permalink is used for one of the pages, query_vars will have 2 keys, the custom permalink and the core endpoint key.
107 * To avoid triggering the event twice, we skip the core one and only track the custom one.
108 * Tracking the custom endpoint is safer than hoping the duplicated, redundant core endpoint is always present.
109 */
110 if ( isset( $core_endpoints[ $key ] ) && $core_endpoints[ $key ] !== $key ) {
111 continue;
112 }
113 /**
114 * $core_endpoints is an array of core_permalink => custom_permalink,
115 * query_vars gives us the custom_permalink, but we want to track it as core_permalink.
116 */
117 if ( array_search( $key, $core_endpoints, true ) ) {
118 $key = array_search( $key, $core_endpoints, true );
119 }
120
121 $this->enqueue_event( 'my_account_page_view', array( 'tab' => $key ) );
122 }
123 }
124 }
125
126 /**
127 * Track address save events, this can only come from the my account page.
128 *
129 * @param int $customer_id The customer id.
130 * @param string $load_address The address type (billing, shipping).
131 */
132 public function track_save_address( $customer_id, $load_address ) {
133 WC_Analytics_Tracking::record_event( 'my_account_address_save', array( 'address' => $load_address ) );
134 }
135
136 /**
137 * Track payment method add events, this can only come from the my account page.
138 */
139 public function track_add_payment_method() {
140 if ( isset( $_POST['woocommerce_add_payment_method'] ) && isset( $_POST['payment_method'] ) ) {
141
142 $nonce_value = wc_get_var( $_REQUEST['woocommerce-add-payment-method-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash
143
144 if ( ! wp_verify_nonce( $nonce_value, 'woocommerce-add-payment-method' ) ) {
145 return;
146 }
147
148 WC_Analytics_Tracking::record_event( 'my_account_payment_save' );
149 return;
150 }
151 }
152
153 /**
154 * Track payment method delete events.
155 */
156 public function track_delete_payment_method() {
157 global $wp;
158 if ( isset( $wp->query_vars['delete-payment-method'] ) ) {
159 WC_Analytics_Tracking::record_event( 'my_account_payment_delete' );
160 return;
161 }
162 }
163
164 /**
165 * Track order cancel events.
166 */
167 public function track_order_cancel_event() {
168 if ( isset( $_GET['_wca_initiator'] ) && ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'woocommerce-cancel_order' ) ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
169 WC_Analytics_Tracking::record_event( 'my_account_order_action_click', array( 'action' => 'cancel' ) );
170 }
171 }
172
173 /**
174 * Track order pay events.
175 */
176 public function track_order_pay_event() {
177 if ( isset( $_GET['_wca_initiator'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.NonceVerification.Recommended
178 WC_Analytics_Tracking::record_event( 'my_account_order_action_click', array( 'action' => 'pay' ) );
179 }
180 }
181
182 /**
183 * Track account details save events, this can only come from the my account page.
184 */
185 public function track_save_account_details() {
186 WC_Analytics_Tracking::record_event( 'my_account_details_save' );
187 }
188
189 /**
190 * Add referrer prop to my account action links
191 *
192 * @param array $actions My account action links.
193 * @return array
194 */
195 public function add_initiator_prop_to_my_account_action_links( $actions ) {
196 foreach ( $actions as $key => $action ) {
197 if ( ! isset( $action['url'] ) ) {
198 continue;
199 }
200
201 // Check if the action key is view, pay, or cancel.
202 if ( ! in_array( $key, array( 'view', 'pay', 'cancel' ), true ) ) {
203 continue;
204 }
205
206 $url = add_query_arg( array( '_wca_initiator' => 'action' ), $action['url'] );
207 $actions[ $key ]['url'] = $url;
208 }
209
210 return $actions;
211 }
212
213 /**
214 * Add an initiator prop to the order url.
215 *
216 * The get_view_order_url is used in a lot of places,
217 * so we want to limit it just to my account page.
218 */
219 public function add_initiator_prop_to_order_urls() {
220 add_filter(
221 'woocommerce_get_view_order_url',
222 function ( $url ) {
223 return add_query_arg( array( '_wca_initiator' => 'number' ), $url );
224 },
225 10,
226 1
227 );
228
229 add_filter(
230 'woocommerce_get_endpoint_url',
231 function ( $url, $endpoint ) {
232 if ( 'edit-address' === $endpoint ) {
233 return add_query_arg( array( '_wca_initiator' => 'action' ), $url );
234 }
235 return $url;
236 },
237 10,
238 2
239 );
240 }
241
242 /**
243 * Add initiator to query vars
244 *
245 * @param array $query_vars Query vars.
246 * @return array
247 */
248 public function add_initiator_param_to_query_vars( $query_vars ) {
249 $query_vars[] = '_wca_initiator';
250 return $query_vars;
251 }
252 }
253