PluginProbe
Elementor Website Builder – more than just a page builder / 3.2.5
Elementor Website Builder – more than just a page builder v3.2.5
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
← All changes | includes/tracker.php +15 -322 4.2.33.2.5 View file →
@@ -1,11 +1,7 @@
1 1 <?php
2 2 namespace Elementor;
3 3
4 -use Elementor\Core\Common\Modules\EventTracker\DB as Events_DB_Manager;
5 -use Elementor\Core\Experiments\Experiments_Reporter;
6 -use Elementor\Modules\System_Info\Module as System_Info_Module;
7 -
8 4 if ( ! defined( 'ABSPATH' ) ) {
9 5 exit; // Exit if accessed directly.
10 6 }
11 7
@@ -28,14 +24,12 @@
28 24 * @access private
29 25 *
30 26 * @var string API URL.
31 27 */
32 - private static $api_url = 'https://my.elementor.com/api/v1/tracker/';
28 + private static $_api_url = 'https://my.elementor.com/api/v1/tracker/';
33 29
34 30 private static $notice_shown = false;
35 31
36 - const LAST_TERMS_UPDATED = '2025-07-07';
37 -
38 32 /**
39 33 * Init.
40 34 *
41 35 * Initialize Elementor tracker.
@@ -46,10 +40,8 @@
46 40 */
47 41 public static function init() {
48 42 add_action( 'elementor/tracker/send_event', [ __CLASS__, 'send_tracking_data' ] );
49 43 add_action( 'admin_init', [ __CLASS__, 'handle_tracker_actions' ] );
50 -
51 - add_action( 'update_option_elementor_allow_tracking', [ __CLASS__, 'set_last_update_time' ] );
52 44 }
53 45
54 46 /**
55 47 * Check for settings opt-in.
@@ -66,20 +58,14 @@
66 58 */
67 59 public static function check_for_settings_optin( $new_value ) {
68 60 $old_value = get_option( 'elementor_allow_tracking', 'no' );
69 61 if ( $old_value !== $new_value && 'yes' === $new_value ) {
70 - Plugin::$instance->custom_tasks->add_tasks_requested_to_run( [
71 - 'opt_in_recalculate_usage',
72 - 'opt_in_send_tracking_data',
73 - ] );
62 + self::send_tracking_data( true );
74 63 }
75 64
76 - self::set_last_update_time();
77 -
78 65 if ( empty( $new_value ) ) {
79 66 $new_value = 'no';
80 67 }
81 -
82 68 return $new_value;
83 69 }
84 70
85 71 /**
@@ -133,10 +119,13 @@
133 119 // Send a maximum of once per week by default.
134 120 if ( $last_send && $last_send > $last_send_interval ) {
135 121 return;
136 122 }
137 - } elseif ( $last_send && $last_send > strtotime( '-1 hours' ) ) {
138 - return;
123 + } else {
124 + // Make sure there is at least a 1 hour delay between override sends, we dont want duplicate calls due to double clicking links.
125 + if ( $last_send && $last_send > strtotime( '-1 hours' ) ) {
126 + return;
127 + }
139 128 }
140 129
141 130 // Update time first before sending to ensure it is set.
142 131 update_option( 'elementor_tracker_last_send', time() );
@@ -142,27 +131,21 @@
142 131 update_option( 'elementor_tracker_last_send', time() );
143 132
144 133 $params = self::get_tracking_data( empty( $last_send ) );
145 134
146 - // Tracking data is used for System Info reports, and events should not be included in System Info reports,
147 - // so it is added here.
148 - $params['analytics_events'] = self::get_events();
149 -
150 135 add_filter( 'https_ssl_verify', '__return_false' );
151 136
152 137 wp_safe_remote_post(
153 - self::$api_url,
138 + self::$_api_url,
154 139 [
155 140 'timeout' => 25,
156 141 'blocking' => false,
142 + // 'sslverify' => false,
157 143 'body' => [
158 144 'data' => wp_json_encode( $params ),
159 145 ],
160 146 ]
161 147 );
162 -
163 - // After sending the event tracking data, we reset the events table.
164 - Events_DB_Manager::reset_table();
165 148 }
166 149
167 150 /**
168 151 * Is allow track.
@@ -176,31 +159,8 @@
176 159 public static function is_allow_track() {
177 160 return 'yes' === get_option( 'elementor_allow_tracking', 'no' );
178 161 }
179 162
180 - public static function get_last_update_time() {
181 - return get_option( 'elementor_allow_tracking_last_update', false );
182 - }
183 -
184 - public static function set_last_update_time(): void {
185 - update_option( 'elementor_allow_tracking_last_update', gmdate( 'U' ) );
186 - }
187 -
188 - public static function has_terms_changed( $terms_updated = self::LAST_TERMS_UPDATED ): bool {
189 - if ( ! self::is_allow_track() ) {
190 - return false;
191 - }
192 -
193 - $last_update_time = self::get_last_update_time();
194 - if ( $last_update_time ) {
195 - $terms_updated_timestamp = strtotime( $terms_updated . ' UTC' );
196 -
197 - return $last_update_time < $terms_updated_timestamp;
198 - }
199 -
200 - return true;
201 - }
202 -
203 163 /**
204 164 * Handle tracker actions.
205 165 *
206 166 * Check if the user opted-in or opted-out and update the database.
@@ -227,9 +187,9 @@
227 187
228 188 self::set_opt_in( false );
229 189 }
230 190
231 - wp_safe_redirect( remove_query_arg( 'elementor_tracker' ) );
191 + wp_redirect( remove_query_arg( 'elementor_tracker' ) );
232 192 exit;
233 193 }
234 194
235 195 /**
@@ -243,10 +203,8 @@
243 203
244 204 public static function set_opt_in( $value ) {
245 205 if ( $value ) {
246 206 update_option( 'elementor_allow_tracking', 'yes' );
247 - self::set_last_update_time();
248 -
249 207 self::send_tracking_data( true );
250 208 } else {
251 209 update_option( 'elementor_allow_tracking', 'no' );
252 210 update_option( 'elementor_tracker_notice', '1' );
@@ -264,19 +222,14 @@
264 222 *
265 223 * @return array The data from system reports.
266 224 */
267 225 private static function get_system_reports_data() {
268 - $reports = Plugin::$instance->system_info->load_reports( System_Info_Module::get_allowed_reports() );
226 + $reports = Plugin::$instance->system_info->load_reports( System_Info\Main::get_allowed_reports() );
269 227
270 - // The log report should not be sent with the usage data - it is not used and causes bloat.
271 - if ( isset( $reports['log'] ) ) {
272 - unset( $reports['log'] );
273 - }
274 -
275 228 $system_reports = [];
276 229 foreach ( $reports as $report_key => $report_details ) {
277 230 $system_reports[ $report_key ] = [];
278 - foreach ( $report_details['report']->get_report() as $sub_report_key => $sub_report_details ) {
231 + foreach ( $report_details['report'] as $sub_report_key => $sub_report_details ) {
279 232 $system_reports[ $report_key ][ $sub_report_key ] = $sub_report_details['value'];
280 233 }
281 234 }
282 235 return $system_reports;
@@ -312,39 +265,8 @@
312 265 return $last_send_time;
313 266 }
314 267
315 268 /**
316 - * Get non elementor post usages.
317 - *
318 - * Retrieve the number of posts that not using elementor.
319 -
320 - * @return array The number of posts using not used by Elementor grouped by post types
321 - * and post status.
322 - */
323 - public static function get_non_elementor_posts_usage() {
324 - global $wpdb;
325 -
326 - $usage = [];
327 -
328 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
329 - $results = $wpdb->get_results(
330 - "SELECT `post_type`, `post_status`, COUNT(`ID`) `hits`
331 - FROM {$wpdb->posts} `p`
332 - LEFT JOIN {$wpdb->postmeta} `pm` ON(`p`.`ID` = `pm`.`post_id` AND `meta_key` = '_elementor_edit_mode' )
333 - WHERE `post_type` != 'elementor_library' AND `meta_value` IS NULL
334 - GROUP BY `post_type`, `post_status`;"
335 - );
336 -
337 - if ( $results ) {
338 - foreach ( $results as $result ) {
339 - $usage[ $result->post_type ][ $result->post_status ] = $result->hits;
340 - }
341 - }
342 -
343 - return $usage;
344 - }
345 -
346 - /**
347 269 * Get posts usage.
348 270 *
349 271 * Retrieve the number of posts using Elementor.
350 272 *
@@ -359,9 +281,8 @@
359 281 global $wpdb;
360 282
361 283 $usage = [];
362 284
363 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
364 285 $results = $wpdb->get_results(
365 286 "SELECT `post_type`, `post_status`, COUNT(`ID`) `hits`
366 287 FROM {$wpdb->posts} `p`
367 288 LEFT JOIN {$wpdb->postmeta} `pm` ON(`p`.`ID` = `pm`.`post_id`)
@@ -371,13 +292,14 @@
371 292 );
372 293
373 294 if ( $results ) {
374 295 foreach ( $results as $result ) {
375 - $usage[ $result->post_type ][ $result->post_status ] = (int) $result->hits;
296 + $usage[ $result->post_type ][ $result->post_status ] = $result->hits;
376 297 }
377 298 }
378 299
379 300 return $usage;
301 +
380 302 }
381 303
382 304 /**
383 305 * Get library usage.
@@ -395,9 +317,8 @@
395 317 global $wpdb;
396 318
397 319 $usage = [];
398 320
399 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
400 321 $results = $wpdb->get_results(
401 322 "SELECT `meta_value`, COUNT(`ID`) `hits`
402 323 FROM {$wpdb->posts} `p`
403 324 LEFT JOIN {$wpdb->postmeta} `pm` ON(`p`.`ID` = `pm`.`post_id`)
@@ -412,149 +333,12 @@
412 333 }
413 334 }
414 335
415 336 return $usage;
416 - }
417 337
418 - /**
419 - * Get usage of general settings.
420 - * 'Elementor->Settings->General'.
421 - *
422 - * @return array
423 - */
424 - public static function get_settings_general_usage() {
425 - return self::get_tracking_data_from_settings( 'general' );
426 338 }
427 339
428 340 /**
429 - * Get usage of advanced settings.
430 - * 'Elementor->Settings->Advanced'.
431 - *
432 - * @return array
433 - */
434 - public static function get_settings_advanced_usage() {
435 - return self::get_tracking_data_from_settings( 'advanced' );
436 - }
437 -
438 - /**
439 - * Get usage of performance settings.
440 - * 'Elementor->Settings->Performance'.
441 - *
442 - * @return array
443 - */
444 - public static function get_settings_performance_usage() {
445 - return self::get_tracking_data_from_settings( 'performance' );
446 - }
447 -
448 - /**
449 - * Get usage of experiments settings.
450 - *
451 - * 'Elementor->Settings->Experiments'.
452 - *
453 - * @return array
454 - */
455 - public static function get_settings_experiments_usage() {
456 - $system_info = Plugin::$instance->system_info;
457 -
458 - /**
459 - * @var $experiments_report Experiments_Reporter
460 - */
461 - $experiments_report = $system_info->create_reporter( [
462 - 'class_name' => Experiments_Reporter::class,
463 - ] );
464 -
465 - return $experiments_report->get_experiments()['value'];
466 - }
467 -
468 - /**
469 - * Get usage of general tools.
470 - * 'Elementor->Tools->General'.
471 - *
472 - * @return array
473 - */
474 - public static function get_tools_general_usage() {
475 - return self::get_tracking_data_from_tools( 'general' );
476 - }
477 -
478 - /**
479 - * Get usage of 'version control' tools.
480 - * 'Elementor->Tools->Version Control'.
481 - *
482 - * @return array
483 - */
484 - public static function get_tools_version_control_usage() {
485 - return self::get_tracking_data_from_tools( 'versions' );
486 - }
487 -
488 - /**
489 - * Get usage of 'maintenance' tools.
490 - * 'Elementor->Tools->Maintenance'.
491 - *
492 - * @return array
493 - */
494 - public static function get_tools_maintenance_usage() {
495 - return self::get_tracking_data_from_tools( 'maintenance_mode' );
496 - }
497 -
498 - /**
499 - * Get library usage extend.
500 - *
501 - * Retrieve the number of Elementor library items saved.
502 - *
503 - * @return array The number of Elementor library items grouped by post types, post status
504 - * and meta value.
505 - */
506 - public static function get_library_usage_extend() {
507 - global $wpdb;
508 -
509 - $usage = [];
510 -
511 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
512 - $results = $wpdb->get_results(
513 - "SELECT `meta_value`, COUNT(`ID`) `hits`, `post_status`
514 - FROM {$wpdb->posts} `p`
515 - LEFT JOIN {$wpdb->postmeta} `pm` ON(`p`.`ID` = `pm`.`post_id`)
516 - WHERE `post_type` = 'elementor_library'
517 - AND `meta_key` = '_elementor_template_type'
518 - GROUP BY `post_type`, `meta_value`, `post_status`;"
519 - );
520 -
521 - if ( $results ) {
522 - foreach ( $results as $result ) {
523 - if ( empty( $usage[ $result->meta_value ] ) ) {
524 - $usage[ $result->meta_value ] = [];
525 - }
526 -
527 - if ( empty( $usage[ $result->meta_value ][ $result->post_status ] ) ) {
528 - $usage[ $result->meta_value ][ $result->post_status ] = 0;
529 - }
530 -
531 - $usage[ $result->meta_value ][ $result->post_status ] += $result->hits;
532 - }
533 - }
534 -
535 - return $usage;
536 - }
537 -
538 - public static function get_events() {
539 - global $wpdb;
540 - $table_name = $wpdb->prefix . Events_DB_Manager::TABLE_NAME;
541 -
542 - // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
543 - $results = $wpdb->get_results( "SELECT event_data FROM {$table_name}" );
544 -
545 - $events_data = [];
546 -
547 - foreach ( $results as $event ) {
548 - // Results are stored in the database as a JSON string. Since all tracking data is encoded right before
549 - // being sent, it is now decoded.
550 - $events_data[] = json_decode( $event->event_data, true );
551 - }
552 -
553 - return $events_data;
554 - }
555 -
556 - /**
557 341 * Get the tracking data
558 342 *
559 343 * Retrieve tracking data and apply filter
560 344 *
@@ -571,36 +355,13 @@
571 355 'site_lang' => get_bloginfo( 'language' ),
572 356 'email' => get_option( 'admin_email' ),
573 357 'usages' => [
574 358 'posts' => self::get_posts_usage(),
575 - 'non-elementor-posts' => self::get_non_elementor_posts_usage(),
576 359 'library' => self::get_library_usage(),
577 - 'settings' => [
578 - 'general' => self::get_settings_general_usage(),
579 - 'advanced' => self::get_settings_advanced_usage(),
580 - 'experiments' => self::get_settings_experiments_usage(),
581 - ],
582 - 'tools' => [
583 - 'general' => self::get_tools_general_usage(),
584 - 'version' => self::get_tools_version_control_usage(),
585 - 'maintenance' => self::get_tools_maintenance_usage(),
586 - ],
587 - 'library-details' => self::get_library_usage_extend(),
588 360 ],
589 361 'is_first_time' => $is_first_time,
590 - 'install_time' => Plugin::instance()->get_install_time(),
591 362 ];
592 363
593 - $site_key = Api::get_site_key();
594 - if ( ! empty( $site_key ) ) {
595 - $params['site_key'] = $site_key;
596 - }
597 -
598 - $allowed_usage_time = self::get_last_update_time();
599 - if ( ! empty( $allowed_usage_time ) ) {
600 - $params['allowed_usage_time'] = $allowed_usage_time;
601 - }
602 -
603 364 /**
604 365 * Tracker send tracking data params.
605 366 *
606 367 * Filters the data parameters when sending tracking request.
@@ -607,79 +368,11 @@
607 368 *
608 369 * @param array $params Variable to encode as JSON.
609 370 *
610 371 * @since 1.0.0
372 + *
611 373 */
612 374 $params = apply_filters( 'elementor/tracker/send_tracking_data_params', $params );
613 375
614 376 return $params;
615 - }
616 -
617 - /**
618 - * @param string $tab_name
619 - * @return array
620 - */
621 - private static function get_tracking_data_from_settings( $tab_name ) {
622 - return self::get_tracking_data_from_settings_page(
623 - Plugin::$instance->settings->get_tabs(),
624 - $tab_name
625 - );
626 - }
627 -
628 - /**
629 - * @param string $tab_name
630 - * @return array
631 - */
632 - private static function get_tracking_data_from_tools( $tab_name ) {
633 - return self::get_tracking_data_from_settings_page(
634 - Plugin::$instance->tools->get_tabs(),
635 - $tab_name
636 - );
637 - }
638 -
639 - private static function get_tracking_data_from_settings_page( $tabs, $tab_name ) {
640 - $result = [];
641 -
642 - if ( empty( $tabs[ $tab_name ] ) ) {
643 - return $result;
644 - }
645 -
646 - $tab = $tabs[ $tab_name ];
647 -
648 - foreach ( $tab['sections'] as $section_name => $section ) {
649 - foreach ( $section['fields'] as $field_name => $field ) {
650 - // Skips fields with '_' prefix.
651 - if ( '_' === $field_name[0] ) {
652 - continue;
653 - }
654 -
655 - $default_value = null;
656 - $args = $field['field_args'];
657 - switch ( $args['type'] ) {
658 - case 'checkbox':
659 - $default_value = $args['value'];
660 - break;
661 -
662 - case 'select':
663 - case 'checkbox_list_cpt':
664 - $default_value = $args['std'];
665 - break;
666 -
667 - case 'checkbox_list_roles':
668 - $default_value = null;
669 - break;
670 -
671 - // 'raw_html' is used as action and not as data.
672 - case 'raw_html':
673 - continue 2; // Skip fields loop.
674 -
675 - default:
676 - trigger_error( 'Invalid type: \'' . $args['type'] . '\'' ); // phpcs:ignore
677 - }
678 -
679 - $result[ $field_name ] = get_option( 'elementor_' . $field_name, $default_value );
680 - }
681 - }
682 -
683 - return $result;
684 377 }
685 378 }