PluginProbe
Elementor Website Builder – more than just a page builder / 3.4.1
Elementor Website Builder – more than just a page builder v3.4.1
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / includes / tracker.php

tracker.php in Elementor Website Builder – more than just a page builder 3.4.1, at includes/tracker.php

573 lines 13.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor;
3
4 use Elementor\Modules\System_Info\Module as System_Info_Module;
5
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit; // Exit if accessed directly.
8 }
9
10 /**
11 * Elementor tracker.
12 *
13 * Elementor tracker handler class is responsible for sending non-sensitive plugin
14 * data to Elementor servers for users that actively allowed data tracking.
15 *
16 * @since 1.0.0
17 */
18 class Tracker {
19
20 /**
21 * API URL.
22 *
23 * Holds the URL of the Tracker API.
24 *
25 * @since 1.0.0
26 * @access private
27 *
28 * @var string API URL.
29 */
30 private static $_api_url = 'https://my.elementor.com/api/v1/tracker/';
31
32 private static $notice_shown = false;
33
34 /**
35 * Init.
36 *
37 * Initialize Elementor tracker.
38 *
39 * @since 1.0.0
40 * @access public
41 * @static
42 */
43 public static function init() {
44 add_action( 'elementor/tracker/send_event', [ __CLASS__, 'send_tracking_data' ] );
45 add_action( 'admin_init', [ __CLASS__, 'handle_tracker_actions' ] );
46 }
47
48 /**
49 * Check for settings opt-in.
50 *
51 * Checks whether the site admin has opted-in for data tracking, or not.
52 *
53 * @since 1.0.0
54 * @access public
55 * @static
56 *
57 * @param string $new_value Allowed tracking value.
58 *
59 * @return string Return `yes` if tracking allowed, `no` otherwise.
60 */
61 public static function check_for_settings_optin( $new_value ) {
62 $old_value = get_option( 'elementor_allow_tracking', 'no' );
63 if ( $old_value !== $new_value && 'yes' === $new_value ) {
64 self::send_tracking_data( true );
65 }
66
67 if ( empty( $new_value ) ) {
68 $new_value = 'no';
69 }
70 return $new_value;
71 }
72
73 /**
74 * Send tracking data.
75 *
76 * Decide whether to send tracking data, or not.
77 *
78 * @since 1.0.0
79 * @access public
80 * @static
81 *
82 * @param bool $override
83 */
84 public static function send_tracking_data( $override = false ) {
85 // Don't trigger this on AJAX Requests.
86 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
87 return;
88 }
89
90 if ( ! self::is_allow_track() ) {
91 return;
92 }
93
94 $last_send = self::get_last_send_time();
95
96 /**
97 * Tracker override send.
98 *
99 * Filters whether to override sending tracking data or not.
100 *
101 * @since 1.0.0
102 *
103 * @param bool $override Whether to override default setting or not.
104 */
105 $override = apply_filters( 'elementor/tracker/send_override', $override );
106
107 if ( ! $override ) {
108 $last_send_interval = strtotime( '-1 week' );
109
110 /**
111 * Tracker last send interval.
112 *
113 * Filters the interval of between two tracking requests.
114 *
115 * @since 1.0.0
116 *
117 * @param int $last_send_interval A date/time string. Default is `strtotime( '-1 week' )`.
118 */
119 $last_send_interval = apply_filters( 'elementor/tracker/last_send_interval', $last_send_interval );
120
121 // Send a maximum of once per week by default.
122 if ( $last_send && $last_send > $last_send_interval ) {
123 return;
124 }
125 } else {
126 // Make sure there is at least a 1 hour delay between override sends, we dont want duplicate calls due to double clicking links.
127 if ( $last_send && $last_send > strtotime( '-1 hours' ) ) {
128 return;
129 }
130 }
131
132 // Update time first before sending to ensure it is set.
133 update_option( 'elementor_tracker_last_send', time() );
134
135 $params = self::get_tracking_data( empty( $last_send ) );
136
137 add_filter( 'https_ssl_verify', '__return_false' );
138
139 wp_safe_remote_post(
140 self::$_api_url,
141 [
142 'timeout' => 25,
143 'blocking' => false,
144 // 'sslverify' => false,
145 'body' => [
146 'data' => wp_json_encode( $params ),
147 ],
148 ]
149 );
150 }
151
152 /**
153 * Is allow track.
154 *
155 * Checks whether the site admin has opted-in for data tracking, or not.
156 *
157 * @since 1.0.0
158 * @access public
159 * @static
160 */
161 public static function is_allow_track() {
162 return 'yes' === get_option( 'elementor_allow_tracking', 'no' );
163 }
164
165 /**
166 * Handle tracker actions.
167 *
168 * Check if the user opted-in or opted-out and update the database.
169 *
170 * Fired by `admin_init` action.
171 *
172 * @since 1.0.0
173 * @access public
174 * @static
175 */
176 public static function handle_tracker_actions() {
177 if ( ! isset( $_GET['elementor_tracker'] ) ) {
178 return;
179 }
180
181 if ( 'opt_into' === $_GET['elementor_tracker'] ) {
182 check_admin_referer( 'opt_into' );
183
184 self::set_opt_in( true );
185 }
186
187 if ( 'opt_out' === $_GET['elementor_tracker'] ) {
188 check_admin_referer( 'opt_out' );
189
190 self::set_opt_in( false );
191 }
192
193 wp_redirect( remove_query_arg( 'elementor_tracker' ) );
194 exit;
195 }
196
197 /**
198 * @since 2.2.0
199 * @access public
200 * @static
201 */
202 public static function is_notice_shown() {
203 return self::$notice_shown;
204 }
205
206 public static function set_opt_in( $value ) {
207 if ( $value ) {
208 update_option( 'elementor_allow_tracking', 'yes' );
209 self::send_tracking_data( true );
210 } else {
211 update_option( 'elementor_allow_tracking', 'no' );
212 update_option( 'elementor_tracker_notice', '1' );
213 }
214 }
215
216 /**
217 * Get system reports data.
218 *
219 * Retrieve the data from system reports.
220 *
221 * @since 2.0.0
222 * @access private
223 * @static
224 *
225 * @return array The data from system reports.
226 */
227 private static function get_system_reports_data() {
228 $reports = Plugin::$instance->system_info->load_reports( System_Info_Module::get_allowed_reports() );
229
230 $system_reports = [];
231 foreach ( $reports as $report_key => $report_details ) {
232 $system_reports[ $report_key ] = [];
233 foreach ( $report_details['report'] as $sub_report_key => $sub_report_details ) {
234 $system_reports[ $report_key ][ $sub_report_key ] = $sub_report_details['value'];
235 }
236 }
237 return $system_reports;
238 }
239
240 /**
241 * Get last send time.
242 *
243 * Retrieve the last time tracking data was sent.
244 *
245 * @since 2.0.0
246 * @access private
247 * @static
248 *
249 * @return int|false The last time tracking data was sent, or false if
250 * tracking data never sent.
251 */
252 private static function get_last_send_time() {
253 $last_send_time = get_option( 'elementor_tracker_last_send', false );
254
255 /**
256 * Tracker last send time.
257 *
258 * Filters the last time tracking data was sent.
259 *
260 * @since 1.0.0
261 *
262 * @param int|false $last_send_time The last time tracking data was sent,
263 * or false if tracking data never sent.
264 */
265 $last_send_time = apply_filters( 'elementor/tracker/last_send_time', $last_send_time );
266
267 return $last_send_time;
268 }
269
270 /**
271 * Get non elementor post usages.
272 *
273 * Retrieve the number of posts that not using elementor.
274
275 * @return array The number of posts using not used by Elementor grouped by post types
276 * and post status.
277 */
278 public static function get_non_elementor_posts_usage() {
279 global $wpdb;
280
281 $usage = [];
282
283 $results = $wpdb->get_results(
284 "SELECT `post_type`, `post_status`, COUNT(`ID`) `hits`
285 FROM {$wpdb->posts} `p`
286 LEFT JOIN {$wpdb->postmeta} `pm` ON(`p`.`ID` = `pm`.`post_id` AND `meta_key` = '_elementor_edit_mode' )
287 WHERE `post_type` != 'elementor_library' AND `meta_value` IS NULL
288 GROUP BY `post_type`, `post_status`;"
289 );
290
291 if ( $results ) {
292 foreach ( $results as $result ) {
293 $usage[ $result->post_type ][ $result->post_status ] = $result->hits;
294 }
295 }
296
297 return $usage;
298 }
299
300 /**
301 * Get posts usage.
302 *
303 * Retrieve the number of posts using Elementor.
304 *
305 * @since 2.0.0
306 * @access public
307 * @static
308 *
309 * @return array The number of posts using Elementor grouped by post types
310 * and post status.
311 */
312 public static function get_posts_usage() {
313 global $wpdb;
314
315 $usage = [];
316
317 $results = $wpdb->get_results(
318 "SELECT `post_type`, `post_status`, COUNT(`ID`) `hits`
319 FROM {$wpdb->posts} `p`
320 LEFT JOIN {$wpdb->postmeta} `pm` ON(`p`.`ID` = `pm`.`post_id`)
321 WHERE `post_type` != 'elementor_library'
322 AND `meta_key` = '_elementor_edit_mode' AND `meta_value` = 'builder'
323 GROUP BY `post_type`, `post_status`;"
324 );
325
326 if ( $results ) {
327 foreach ( $results as $result ) {
328 $usage[ $result->post_type ][ $result->post_status ] = $result->hits;
329 }
330 }
331
332 return $usage;
333 }
334
335 /**
336 * Get library usage.
337 *
338 * Retrieve the number of Elementor library items saved.
339 *
340 * @since 2.0.0
341 * @access public
342 * @static
343 *
344 * @return array The number of Elementor library items grouped by post types
345 * and meta value.
346 */
347 public static function get_library_usage() {
348 global $wpdb;
349
350 $usage = [];
351
352 $results = $wpdb->get_results(
353 "SELECT `meta_value`, COUNT(`ID`) `hits`
354 FROM {$wpdb->posts} `p`
355 LEFT JOIN {$wpdb->postmeta} `pm` ON(`p`.`ID` = `pm`.`post_id`)
356 WHERE `post_type` = 'elementor_library'
357 AND `meta_key` = '_elementor_template_type'
358 GROUP BY `post_type`, `meta_value`;"
359 );
360
361 if ( $results ) {
362 foreach ( $results as $result ) {
363 $usage[ $result->meta_value ] = $result->hits;
364 }
365 }
366
367 return $usage;
368
369 }
370
371 /**
372 * Get usage of general settings.
373 * 'Elementor->Settings->General'.
374 *
375 * @return array
376 */
377 public static function get_settings_general_usage() {
378 return self::get_tracking_data_from_settings( 'general' );
379 }
380
381 /**
382 * Get usage of advanced settings.
383 * 'Elementor->Settings->Advanced'.
384 *
385 * @return array
386 */
387 public static function get_settings_advanced_usage() {
388 return self::get_tracking_data_from_settings( 'advanced' );
389 }
390
391 /**
392 * Get usage of experiments settings.
393 *
394 * 'Elementor->Settings->Experiments'.
395 *
396 * @return array
397 */
398 public static function get_settings_experiments_usage() {
399 $result = [];
400
401 $experiments_manager = Plugin::$instance->experiments;
402
403 // TODO: Those keys should be at `$experiments_manager`.
404 $tracking_keys = [
405 'default',
406 'state',
407 ];
408
409 foreach ( $experiments_manager->get_features() as $feature_name => $feature_data ) {
410 $data_to_collect = [];
411
412 // Extract only tracking keys.
413 foreach ( $tracking_keys as $tracking_key ) {
414 $data_to_collect[ $tracking_key ] = $feature_data[ $tracking_key ];
415 }
416
417 $result[ $feature_name ] = $data_to_collect;
418 }
419
420 return $result;
421 }
422
423 /**
424 * Get usage of general tools.
425 * 'Elementor->Tools->General'.
426 *
427 * @return array
428 */
429 public static function get_tools_general_usage() {
430 return self::get_tracking_data_from_tools( 'general' );
431 }
432
433 /**
434 * Get usage of 'version control' tools.
435 * 'Elementor->Tools->Version Control'.
436 *
437 * @return array
438 */
439 public static function get_tools_version_control_usage() {
440 return self::get_tracking_data_from_tools( 'versions' );
441 }
442
443 /**
444 * Get usage of 'maintenance' tools.
445 * 'Elementor->Tools->Maintenance'.
446 *
447 * @return array
448 */
449 public static function get_tools_maintenance_usage() {
450 return self::get_tracking_data_from_tools( 'maintenance_mode' );
451 }
452
453 /**
454 * Get the tracking data
455 *
456 * Retrieve tracking data and apply filter
457 *
458 * @access public
459 * @static
460 *
461 * @param bool $is_first_time
462 *
463 * @return array
464 */
465 public static function get_tracking_data( $is_first_time = false ) {
466 $params = [
467 'system' => self::get_system_reports_data(),
468 'site_lang' => get_bloginfo( 'language' ),
469 'email' => get_option( 'admin_email' ),
470 'usages' => [
471 'posts' => self::get_posts_usage(),
472 'non-elementor-posts' => self::get_non_elementor_posts_usage(),
473 'library' => self::get_library_usage(),
474 'settings' => [
475 'general' => self::get_settings_general_usage(),
476 'advanced' => self::get_settings_advanced_usage(),
477 'experiments' => self::get_settings_experiments_usage(),
478 ],
479 'tools' => [
480 'general' => self::get_tools_general_usage(),
481 'version' => self::get_tools_version_control_usage(),
482 'maintenance' => self::get_tools_maintenance_usage(),
483 ],
484 ],
485 'is_first_time' => $is_first_time,
486 'install_time' => Plugin::instance()->get_install_time(),
487 ];
488
489 /**
490 * Tracker send tracking data params.
491 *
492 * Filters the data parameters when sending tracking request.
493 *
494 * @param array $params Variable to encode as JSON.
495 *
496 * @since 1.0.0
497 *
498 */
499 $params = apply_filters( 'elementor/tracker/send_tracking_data_params', $params );
500
501 return $params;
502 }
503
504 /**
505 * @param string $tab_name
506 * @return array
507 */
508 private static function get_tracking_data_from_settings( $tab_name ) {
509 return self::get_tracking_data_from_settings_page(
510 Plugin::$instance->settings->get_tabs(),
511 $tab_name
512 );
513 }
514
515 /**
516 * @param string $tab_name
517 * @return array
518 */
519 private static function get_tracking_data_from_tools( $tab_name ) {
520 return self::get_tracking_data_from_settings_page(
521 Plugin::$instance->tools->get_tabs(),
522 $tab_name
523 );
524 }
525
526 private static function get_tracking_data_from_settings_page( $tabs, $tab_name ) {
527 $result = [];
528
529 if ( empty( $tabs[ $tab_name ] ) ) {
530 return $result;
531 }
532
533 $tab = $tabs[ $tab_name ];
534
535 foreach ( $tab['sections'] as $section_name => $section ) {
536 foreach ( $section['fields'] as $field_name => $field ) {
537 // Skips fields with '_' prefix.
538 if ( '_' === $field_name[0] ) {
539 continue;
540 }
541
542 $default_value = null;
543 $args = $field['field_args'];
544 switch ( $args['type'] ) {
545 case 'checkbox':
546 $default_value = $args['value'];
547 break;
548
549 case 'select':
550 case 'checkbox_list_cpt':
551 $default_value = $args['std'];
552 break;
553
554 case 'checkbox_list_roles':
555 $default_value = null;
556 break;
557
558 // 'raw_html' is used as action and not as data.
559 case 'raw_html':
560 continue 2; // Skip fields loop.
561
562 default:
563 trigger_error( 'Invalid type: \'' . $args['type'] . '\'' ); // phpcs:ignore
564 }
565
566 $result[ $field_name ] = get_option( 'elementor_' . $field_name, $default_value );
567 }
568 }
569
570 return $result;
571 }
572 }
573