PluginProbe
Analytify – Google Analytics Dashboard For WordPress (GA4 analytics tracking) / 8.1.3
Analytify – Google Analytics Dashboard For WordPress (GA4 analytics tracking) v8.1.3
9.1.2 9.1.1 9.1.0 9.0.2 9.0.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.1.0 1.1.1 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 All 153 releases
wp-analytify / wp-analytify.php

wp-analytify.php in Analytify – Google Analytics Dashboard For WordPress (GA4 analytics tracking) 8.1.3, at wp-analytify.php

1,558 lines 49.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 /**
3 * Plugin Name: Analytify Dashboard
4 * Plugin URI: https://analytify.io/?ref=27&utm_source=wp-org&utm_medium=plugin-header&utm_campaign=pro-upgrade&utm_content=plugin-uri
5 * Description: Analytify brings a brand new and modern feeling of Google Analytics superbly integrated within the WordPress.
6 * Version: 8.1.3
7 * Author: Analytify
8 * Author URI: https://analytify.io/?ref=27&utm_source=wp-org&utm_medium=plugin-header&utm_campaign=pro-upgrade&utm_content=author-uri
9 * License: GPLv3
10 * Text Domain: wp-analytify
11 * Requires at least: 4.0
12 * Tested up to: 6.9
13 * Domain Path: /languages
14 * GitHub Plugin URI: https://github.com/WPBrigade/wp-analytify
15 *
16 * @package WP_ANALYTIFY
17 */
18
19
20 // ========================================.
21 // TELEMETRY SDK INITIALIZATION START.
22 // ========================================.
23
24 if ( ! function_exists( 'wa_wpb78834179' ) ) {
25
26 /**
27 * Telemetry function.
28 *
29 * @return mixed
30 */
31 function wa_wpb78834179() {
32 global $wa_wpb78834179;
33
34 if ( ! isset( $wa_wpb78834179 ) ) {
35
36 require_once __DIR__ . '/lib/wpb-sdk/start.php';
37
38 $wa_wpb78834179 = wpb_dynamic_init(
39 array(
40 'id' => '7',
41 'slug' => 'wp-analytify',
42 'type' => 'plugin',
43 'public_key' => '1|4aOA8EuyIN4pi2miMvC23LLpnHbBZFNki9R9pVmwd673d3c8',
44 'secret_key' => 'sk_b36c525848fee035',
45 'is_premium' => false,
46 'has_addons' => false,
47 'has_paid_plans' => false,
48 'menu' => array(
49 'slug' => 'wp-analytify',
50 'account' => false,
51 'support' => false,
52 ),
53 'settings' => array(
54 'wp_analytify_modules' => '',
55 'wp-analytify-tracking' => '',
56 'wp-analytify-email' => '',
57 'wp-analytify-events-tracking' => '',
58 'wp-analytify-front' => '',
59 'wp-analytify-custom-dimensions' => '',
60 'wp-analytify-forms' => '',
61 'analytify_widget_date_differ' => '',
62 'wp-analytify-profile' => '',
63 'wp-analytify-admin' => '',
64 'wp-analytify-dashboard' => '',
65 'wp-analytify-advanced' => '',
66 'analytify_ua_code' => '',
67 'analytify_date_differ' => '',
68 'wp_analytify_review_dismiss_4_1_8' => '',
69 'wpanalytify_settings' => '',
70 'analytify_license_key' => '',
71 'analytify_license_status' => '',
72 'analytify_campaigns_license_status' => '',
73 'analytify_campaigns_license_key' => '',
74 'analytify_goals_license_status' => '',
75 'analytify_goals_license_key' => '',
76 'Analytify_Addon_Forms_license_status' => '',
77 'analytify_forms_license_key' => '',
78 'analytify_authors_license_status' => '',
79 'analytify_authors_license_key' => '',
80 'analytify_woo_license_status' => '',
81 'analytify_woo_license_key' => '',
82 'analytify_email_license_status' => '',
83 'analytify_email_license_key' => '',
84 'analytify-google-ads-tracking' => '',
85 '_analytify_optin' => '',
86 'analytify_cache_timeout' => '',
87 'analytify_csv_data' => '',
88 'analytify_active_date' => '',
89 'analytify_edd_license_status' => '',
90 'analytify_edd_license_key' => '',
91 '_transient_timeout_analytify_api_addons' => '',
92 '_transient_analytify_api_addons' => '',
93 'analytify_ga4_exceptions' => '',
94 'analytify-ga-properties-summery' => '',
95 'analytify_ga4-streams' => '',
96 'analytify_tracking_property_info' => '',
97 'analytify_reporting_property_info' => '',
98 'analytify_gtag_move_to_notice' => '',
99 'analytify_current_version' => '',
100 'analytify_logs_setup' => '',
101 'analytify_pro_default_settings' => '',
102 'analytify_pro_active_date' => '',
103 'analytify_pro_upgrade_routine' => '',
104 'analytify_pro_current_version' => '',
105 'WP_ANALYTIFY_PRO_PLUGIN_VERSION' => '',
106 'wp-analytify-license' => '',
107 'analytify_authentication_date' => '',
108 'WP_ANALYTIFY_PLUGIN_VERSION_OLD' => '',
109 'WP_ANALYTIFY_PRO_PLUGIN_VERSION_OLD' => '',
110 'analytify_default_settings' => '',
111 'analytify_free_upgrade_routine' => '',
112 'WP_ANALYTIFY_PLUGIN_VERSION' => '',
113 'wp_analytify_active_time' => '',
114 'wp-analytify-authentication' => '',
115 'wp-analytify-help' => '',
116 'WP_ANALYTIFY_NEW_LOGIN' => '',
117 'profiles_list_summary' => '',
118 'pa_google_token' => '',
119 'post_analytics_token' => '',
120 ),
121 )
122 );
123 }
124
125 return $wa_wpb78834179;
126 }
127
128
129 wa_wpb78834179();
130
131 do_action( 'wa_wpb78834179_loaded' );
132 }
133
134 // ========================================.
135 // TELEMETRY SDK INITIALIZATION END.
136 // ========================================.
137
138 if ( ! defined( 'ABSPATH' ) ) {
139 exit;
140 }
141
142
143
144
145 require_once __DIR__ . '/inc/analytify-constants.php';
146
147 if ( ! class_exists( 'Analytify_General' ) ) {
148 require_once 'analytify-general.php';
149 }
150
151
152
153 // ========================================.
154 // MAIN PLUGIN CLASS DEFINITION START.
155 // ========================================.
156
157 if ( ! class_exists( 'WP_Analytify' ) ) {
158 /**
159 * Main WP_Analytify class.
160 *
161 * @since 1.0.0
162 */
163 // phpcs:ignore Universal.Files.SeparateFunctionsFromOO.Mixed,Squiz.Commenting.ClassComment.Missing
164 class WP_Analytify extends Analytify_General {
165
166 /**
167 * Plugin instance.
168 *
169 * @var WP_Analytify $instance The one true WP_Analytify
170 * @since 1.2.2
171 */
172 private static $instance = null;
173
174 /**
175 * Token data.
176 *
177 * @var mixed
178 */
179 public $token = false;
180 /**
181 * Client instance.
182 *
183 * @var mixed
184 */
185 public $client = null;
186
187 /**
188 * Post stats disable flag.
189 *
190 * @var mixed
191 */
192 protected $disable_post_stats;
193
194 /**
195 * Settings data.
196 *
197 * @var mixed
198 */
199 public $settings;
200
201 /**
202 * Component loader instance
203 *
204 * @var Analytify_Loader
205 */
206 private $loader;
207
208 // ========================================.
209 // CONSTRUCTOR & CORE METHODS START.
210 // ========================================.
211
212 /**
213 * Constructor.
214 *
215 * @since 1.2.2
216 */
217 public function __construct() {
218 parent::__construct();
219 $this->setup_constants();
220 $this->includes();
221 $this->disable_post_stats = $this->settings->get_option( 'enable_back_end', 'wp-analytify-admin' );
222 $this->hooks();
223 }
224
225 /**
226 * Get active instance.
227 *
228 * @access public
229 * @since 1.2.2
230 * @return object self::$instance The one true WP_Analytify
231 */
232 public static function get_instance() {
233 if ( ! self::$instance ) {
234 self::$instance = new WP_Analytify();
235 }
236
237 return self::$instance;
238 }
239
240 /**
241 * Setup plugin constants
242 *
243 * @access private
244 * @since 1.2.2
245 * @return void
246 */
247 private function setup_constants() {
248
249 $upload_dir = wp_upload_dir( null, false );
250 }
251
252 /**
253 * Define constant if not already set
254 *
255 * @since 1.2.4
256 * @param string $name contanst name.
257 * @param string|bool $value constant value.
258 * @return void
259 */
260 private function define( $name, $value ) {
261 if ( ! defined( $name ) ) {
262 define( $name, $value );
263 }
264 }
265
266 /**
267 * What type of request is this?
268 *
269 * @since 1.2.4
270 * @param string $type ajax, frontend or admin.
271 * @return bool
272 */
273 private function is_request( $type ) {
274 switch ( $type ) {
275 case 'admin':
276 return is_admin();
277 case 'ajax':
278 return defined( 'DOING_AJAX' );
279 case 'cron':
280 return defined( 'DOING_CRON' );
281 case 'frontend':
282 return ( ! is_admin() || defined( 'DOING_AJAX' ) ) && ! defined( 'DOING_CRON' );
283 default:
284 return false;
285 }
286 }
287
288
289 /**
290 * Include necessary files
291 *
292 * @access private
293 * @since 1.2.2
294 * @return void
295 */
296 private function includes() {
297 $files = array(
298 WP_ANALYTIFY_LIB_PATH . 'logs/class-analytify-log-handler-interface.php',
299 WP_ANALYTIFY_LIB_PATH . 'logs/class-analytify-logger-interface.php',
300 WP_ANALYTIFY_LIB_PATH . 'logs/class-analytify-log-levels.php',
301 WP_ANALYTIFY_LIB_PATH . 'logs/class-analytify-logger.php',
302 WP_ANALYTIFY_LIB_PATH . 'logs/abstract-analytify-log-handler.php',
303 WP_ANALYTIFY_LIB_PATH . 'logs/class-analytify-log-handler-file.php',
304 WP_ANALYTIFY_PLUGIN_DIR . '/classes/analytify-logs.php',
305 WP_ANALYTIFY_PLUGIN_DIR . '/classes/analytify-sanitize.php',
306 WP_ANALYTIFY_PLUGIN_DIR . '/inc/analytify-core-functions.php',
307 WP_ANALYTIFY_PLUGIN_DIR . '/inc/class-analytify-adminbar.php',
308 WP_ANALYTIFY_PLUGIN_DIR . '/classes/abstracts/analytify-report-abstract.php',
309 WP_ANALYTIFY_PLUGIN_DIR . '/classes/abstracts/analytify-host-analytics-abstract.php',
310 WP_ANALYTIFY_PLUGIN_DIR . '/classes/analytify-host-analytics.php',
311 WP_ANALYTIFY_PLUGIN_DIR . '/classes/analytify-report-core.php',
312 WP_ANALYTIFY_PLUGIN_DIR . '/classes/analytify-rest-api.php',
313 WP_ANALYTIFY_PLUGIN_DIR . '/inc/class-analytify-ajax.php',
314 WP_ANALYTIFY_PLUGIN_DIR . '/inc/class-analytify-post-columns.php',
315 WP_ANALYTIFY_PLUGIN_DIR . '/classes/class-wp-analytify-compatibility-upgrade.php',
316 WP_ANALYTIFY_PLUGIN_DIR . '/classes/analytify-dashboard-widget.php',
317 WP_ANALYTIFY_PLUGIN_DIR . '/classes/class-analytify-user-optout.php',
318 WP_ANALYTIFY_PLUGIN_DIR . '/classes/class-analytify-gdpr-compliance.php',
319 WP_ANALYTIFY_PLUGIN_DIR . '/classes/analytify-email.php',
320 WP_ANALYTIFY_PLUGIN_DIR . '/classes/analytify-settings.php',
321 );
322
323 foreach ( $files as $file ) {
324 if ( file_exists( $file ) ) {
325 include_once $file;
326 } else {
327
328 echo '<div class="notice notice-error"><p>' . esc_html__( 'A critical file is missing:', 'wp-analytify' ) . ' ' . esc_html( $file ) . '. ' . esc_html__( 'The Analytify plugin needs to be deactivated && re-installed.', 'wp-analytify' ) . '</p></div>';
329 return;
330 }
331 }
332
333 if ( file_exists( WP_ANALYTIFY_PLUGIN_DIR . '/inc/class-analytify-loader.php' ) ) {
334 require_once WP_ANALYTIFY_PLUGIN_DIR . '/inc/class-analytify-loader.php';
335 if ( class_exists( 'Analytify_Loader' ) ) {
336 $this->loader = new Analytify_Loader( $this );
337 }
338 }
339 }
340
341 // ========================================.
342 // CONSTRUCTOR & CORE METHODS END.
343 // ========================================.
344
345 // ========================================.
346 // WordPress HOOKS & ACTIONS START.
347 // ========================================.
348
349 /**
350 * Run action && filter hooks
351 *
352 * @access private
353 * @since 1.2.2
354 * @return void
355 */
356 private function hooks() {
357
358 add_action( 'init', array( $this, 'load_textdomain' ) ); // Hook load_textdomain.
359 add_action( 'admin_init', array( $this, '_save_core_version' ) );
360 add_action( 'admin_init', array( $this, 'wpa_check_authentication' ) );
361 add_action( 'admin_init', array( $this, 'logout' ), 1 );
362 add_filter( 'removable_query_args', array( $this, 'Analytify_remove_query' ) );
363 add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
364
365 add_action( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 4 );
366 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'wp_analytify_plugin_action_links' ), 10, 1 );
367 add_filter( 'network_admin_plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'wp_analytify_plugin_action_links' ), 10, 1 );
368
369 add_action( 'wp_head', array( $this, 'analytify_add_analytics_code' ) );
370 add_action( 'wp_head', array( $this, 'analytify_add_manual_analytics_code' ) );
371
372 add_filter( 'admin_footer_text', 'wpa_admin_rate_footer_text', 1 );
373 add_action( 'admin_footer', 'wpa_print_js', 25 );
374 add_action( 'admin_footer', array( $this, 'wp_analytify_maybe_render_sdk_optout_form' ), 5 );
375
376 add_action( 'admin_init', array( $this, 'redirect_optin' ) );
377
378 add_action( 'analytify_cleanup_logs', array( $this, 'analytify_cleanup_logs' ) );
379
380 add_action(
381 'init',
382 function () {
383 if ( WPANALYTIFY_Utils::get_option( 'locally_host_analytics', 'wp-analytify-advanced', false ) && ! wp_next_scheduled( 'analytify_analytics_lib_cron' ) ) {
384 wp_schedule_event( time(), 'daily', 'analytify_analytics_lib_cron' );
385 }
386 }
387 );
388
389 add_action(
390 'analytify_analytics_lib_cron',
391 function () {
392 if ( class_exists( 'Analytify_Host_Analytics' ) ) {
393 new Analytify_Host_Analytics( 'gtag', true );
394 }
395 }
396 );
397 }
398
399 // ========================================.
400 // WordPress HOOKS & ACTIONS END.
401 // ========================================.
402
403
404 // ========================================.
405 // ADMIN NOTICES & PROMOTIONS START.
406 // ========================================.
407
408
409
410 /**
411 * Redirect to Welcome page.
412 *
413 * @since 2.0.14
414 * @return void
415 */
416 public function redirect_optin() {
417 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading URL parameter for display purposes
418 $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
419 if ( $page && ( 'analytify-settings' === $page || 'analytify-dashboard' === $page || 'analytify-woocommerce' === $page || 'analytify-addons' === $page ) ) {
420 if ( ! get_site_option( '_analytify_optin' ) ) {
421 wp_safe_redirect( admin_url( 'admin.php?page=analytify-optin' ) );
422 exit;
423 }
424 }
425 }
426
427
428 /**
429 * Internationalization.
430 *
431 * @access public
432 * @since 1.2.2
433 * @return void
434 */
435 public function load_textdomain() {
436 $plugin_dir = basename( __DIR__ );
437 load_plugin_textdomain( 'wp-analytify', false, $plugin_dir . '/languages/' );
438 }
439
440
441 /**
442 *
443 * Save Authentication code on return
444 * && nonce verification
445 *
446 * @return void
447 */
448 public function wpa_check_authentication() {
449
450 $state = isset( $_GET['state'] ) ? json_decode( urldecode( sanitize_text_field( wp_unslash( $_GET['state'] ) ) ), true ) : null;
451
452 if ( isset( $_GET['code'] ) && isset( $_GET['page'] ) && 'analytify-settings' === sanitize_text_field( wp_unslash( $_GET['page'] ) ) ) {
453 $get_nonce = isset( $_GET['nonce'] ) ? sanitize_text_field( wp_unslash( $_GET['nonce'] ) ) : null;
454 $nonce = isset( $state['nonce'] ) ? $state['nonce'] : $get_nonce;
455
456 if ( wp_verify_nonce( $nonce, 'analytify_analytics_login' ) ) {
457
458 $key_google_token = sanitize_text_field( wp_unslash( $_GET['code'] ) );
459 update_option( 'WP_ANALYTIFY_NEW_LOGIN', 'yes' );
460 self::pt_save_data( $key_google_token );
461 wp_safe_redirect( admin_url( 'admin.php?page=analytify-settings' ) . '#wp-analytify-profile' );
462 exit;
463
464 } else {
465 $plugin_page_url = admin_url( 'plugins.php' );
466 wp_die(
467 sprintf( // translators: Nonce verification failed.
468 esc_html__( 'Sorry, you are not allowed as nonce verification failed. %1$sClick here to return to the Dashboard%2$s.', 'wp-analytify' ),
469 '<a href="' . esc_url( $plugin_page_url ) . '">',
470 '</a>'
471 )
472 );
473 }
474 }
475 }
476
477 /**
478 * Save version number of the plugin && show a custom message for users
479 *
480 * @since 1.3
481 * @return void
482 */
483 public function _save_core_version() { // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore -- Underscore prefix is intentional for internal method
484 if ( ANALYTIFY_VERSION !== get_option( 'WP_ANALYTIFY_PLUGIN_VERSION' ) ) {
485 update_option( 'WP_ANALYTIFY_PLUGIN_VERSION_OLD', get_option( 'WP_ANALYTIFY_PLUGIN_VERSION' ), true ); // saving old plugin version.
486 update_option( 'WP_ANALYTIFY_PLUGIN_VERSION', ANALYTIFY_VERSION );
487 }
488 }
489
490
491
492
493
494 // ========================================.
495 // GOOGLE ANALYTICS TRACKING CODE START.
496 // ========================================.
497
498 /**
499 * Add Google Analytics JS code
500 *
501 * @since 1.0.0
502 * @version 7.0.4
503 * @return bool|void Returns false if tracking is blocked/skipped, true if code is output, void otherwise.
504 */
505 public function analytify_add_analytics_code() {
506 if ( WPANALYTIFY_Utils::skip_page_tracking() ) {
507 return false;
508 }
509
510 // Check for GDPR compliance.
511 if ( Analytify_GDPR_Compliance::is_gdpr_compliance_blocking() ) {
512 return false;
513 }
514
515 if ( 'on' === $this->settings->get_option( 'install_ga_code', 'wp-analytify-profile', 'off' ) ) {
516 global $current_user;
517
518 $roles = $current_user->roles;
519
520 if ( isset( $roles[0] ) && in_array( $roles[0], $this->settings->get_option( 'exclude_users_tracking', 'wp-analytify-profile', array() ), true ) ) {
521 echo '<!-- This user is disabled from tracking by Analytify !-->';
522 return false;
523 } else {
524 if ( ! $this->settings->get_option( 'profile_for_posts', 'wp-analytify-profile' ) ) {
525 return false;
526 }
527
528 $ua_code = WP_ANALYTIFY_FUNCTIONS::get_UA_code();
529
530 // Validate UA code before outputting tracking code.
531 if ( empty( $ua_code ) ) {
532 // Add a comment in HTML for debugging.
533 echo '<!-- Analytify: No tracking code - check profile selection or OAuth connection -->';
534 return false;
535 }
536
537 if ( 'gtag' === WP_ANALYTIFY_TRACKING_MODE ) {
538 $ga_code = $this->output_gtag_code( $ua_code );
539 } else {
540 $ga_code = $this->output_ga_code( $ua_code );
541 }
542
543 echo apply_filters( 'analytify_ga_script', $ga_code ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JavaScript code needs to be output directly
544 return true;
545 }
546 }
547 }
548
549 /**
550 * Add Google Manual Analytics JS code
551 *
552 * @return void
553 */
554 public function analytify_add_manual_analytics_code() {
555 if ( get_option( 'pa_google_token' ) ) {
556 return;
557 }
558
559 $manual_ua_code = $this->settings->get_option( 'manual_ua_code', 'wp-analytify-authentication', false );
560
561 if ( ! $manual_ua_code ) {
562 return;
563 }
564
565 global $current_user;
566 $roles = $current_user->roles;
567
568 if ( in_array( 'administrator', $roles, true ) ) {
569 echo '<!-- This user is disabled from tracking by Analytify !-->';
570 } elseif ( apply_filters( 'analytify_manaul_ga_script', false ) ) {
571 echo apply_filters( 'analytify_ga_script', $this->output_ga_code( $manual_ua_code ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JavaScript code needs to be output directly
572 } else {
573 echo apply_filters( 'analytify_gtag_script', $this->output_gtag_code( $manual_ua_code ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JavaScript code needs to be output directly
574 }
575 }
576
577 /**
578 * Generate gtag code.
579 *
580 * @param string $ua_code Google Analytics UA code.
581 * @since 3.0
582 * @version 7.0.4
583 * @return $gtag_code
584 */
585 private function output_gtag_code( $ua_code ) {
586 ob_start();
587
588 $local_analytics_file = class_exists( 'Analytify_Host_Analytics' ) ? ( new Analytify_Host_Analytics( 'gtag', false ) )->local_analytics_file_url() : false;
589
590 if ( false !== apply_filters( 'analytify_tracking_code_comments', true ) ) {
591 printf( // translators: Tracking code comments.
592 esc_html__( '%2$s This code is added by Analytify (%1$s) %4$s %3$s', 'wp-analytify' ),
593 esc_html( ANALYTIFY_VERSION ),
594 '<!--',
595 '!-->',
596 'https://analytify.io/'
597 );
598 }
599
600 $allow_display_features = ( 'on' === $this->settings->get_option( 'demographic_interest_tracking', 'wp-analytify-advanced' ) ) ? 'true' : 'false';
601 $linker_cross_domain_tracking = ( 'on' === $this->settings->get_option( 'linker_cross_domain_tracking', 'wp-analytify-advanced' ) ) ? true : false;
602 $linked_domains = array();
603
604 if ( $linker_cross_domain_tracking ) {
605 $all_linked_domains = $this->settings->get_option( 'linked_domain', 'wp-analytify-advanced' );
606 $all_linked_domains = trim( $all_linked_domains ? $all_linked_domains : '' );
607
608 if ( ! empty( $all_linked_domains ) ) {
609 $all_linked_domains = str_replace( "'", '', $all_linked_domains );
610 $all_linked_domains = str_replace( '"', '', $all_linked_domains );
611
612 $all_linked_domains = preg_replace( '/\s+/', '', $all_linked_domains );
613
614 $list_linked_domains = explode( ',', $all_linked_domains );
615 $number_of_linked_domains = count( $list_linked_domains );
616
617 if ( $number_of_linked_domains > 0 ) {
618 $linked_domains = array_filter(
619 (array) $list_linked_domains,
620 function ( $value ) {
621 return strlen( $value ) > 0;
622 }
623 );
624 } else {
625 $linked_domains = (array) $all_linked_domains;
626 }
627 } else {
628 $linker_cross_domain_tracking = false;
629 }
630 }
631
632 $configuration = array(
633
634 'allow_display_features' => $allow_display_features,
635 );
636
637 if ( $linker_cross_domain_tracking ) {
638 $configuration['linker'] = array(
639 'domains' => $linked_domains,
640 );
641 }
642
643 $debug_mode = apply_filters( 'analytify_debug_mode', true );
644
645 if ( $debug_mode ) {
646 $configuration['debug_mode'] = true;
647 }
648
649 if ( 'on' === $this->settings->get_option( 'track_user_id', 'wp-analytify-advanced' ) && is_user_logged_in() ) {
650 $configuration['user_id'] = esc_html( (string) get_current_user_id() );
651 }
652
653 $configuration = apply_filters( 'analytify_gtag_configuration', $configuration );
654 $configuration_json = wp_json_encode( $configuration, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT );
655
656 // Build the script src URL correctly.
657 $script_src = $local_analytics_file ?? 'https://www.googletagmanager.com/gtag/js';
658 $script_src .= ( strpos( $script_src, '?' ) !== false ? '&' : '?' ) . 'id=' . esc_attr( $ua_code );
659
660 ?>
661
662 <?php // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript -- Inline gtag script must be output directly in the page head. ?>
663 <script async src="<?php echo esc_url( $script_src ); ?>"></script>
664 <script>
665 window.dataLayer = window.dataLayer || [];
666 function gtag(){dataLayer.push(arguments);}
667 gtag('js', new Date());
668
669 const configuration = <?php echo $configuration_json; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- wp_json_encode() with JSON_HEX flags already escapes JSON safely for JavaScript context. ?>;
670 const gaID = '<?php echo esc_js( $ua_code ); ?>';
671
672 <?php do_action( 'analytify_tracking_code_before_pageview' ); ?>
673
674 gtag('config', gaID, configuration);
675
676 <?php
677 if ( $this->settings->get_option( 'custom_js_code', 'wp-analytify-advanced' ) ) {
678 $custom_js = $this->settings->get_option( 'custom_js_code', 'wp-analytify-advanced' );
679
680 if ( ! empty( $custom_js ) ) {
681 echo wp_kses_post( $custom_js );
682 }
683 }
684
685 do_action( 'ga_ecommerce_js' );
686 do_action( 'analytify_tracking_code_after_pageview' );
687 ?>
688
689 </script>
690
691 <?php
692 if ( false !== apply_filters( 'analytify_tracking_code_comments', true ) ) {
693 printf( // translators: Tracking code comments.
694 esc_html__( '%2$s This code is added by Analytify (%1$s) %3$s', 'wp-analytify' ),
695 esc_html( ANALYTIFY_VERSION ),
696 '<!--',
697 '!-->'
698 );
699 }
700
701 $gtag_code = ob_get_contents();
702 ob_end_clean();
703 return $gtag_code ? $gtag_code : '';
704 }
705
706 /**
707 * Generate gtag code.
708 *
709 * @param string $ua_code Google Analytics UA code.
710 * @since 3.0
711 * @return string
712 */
713 public function output_ga_code( $ua_code ) {
714 ob_start();
715
716 $src = apply_filters( 'analytify_output_ga_js_src', '//www.google-analytics.com/analytics.js' );
717
718 if ( false !== apply_filters( 'analytify_tracking_code_comments', true ) ) {
719 printf( // translators: Tracking code comments.
720 esc_html__( '%2$s This code is added by Analytify (%1$s) %4$s %3$s', 'wp-analytify' ),
721 esc_html( ANALYTIFY_VERSION ),
722 '<!--',
723 '!-->',
724 'https://analytify.io/'
725 );
726 }
727 ?>
728
729 <script>
730 (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
731 (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
732 m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
733 })
734
735 (window,document,'script','<?php echo esc_url( $src ); ?>','ga');
736
737 <?php
738 if ( 'on' === $this->settings->get_option( 'linker_cross_domain_tracking', 'wp-analytify-advanced' ) ) {
739 echo " ga('create', '" . esc_js( $ua_code ) . "', 'auto', {'allowLinker': true});";
740 echo "ga('require', 'linker');";
741 } else {
742 echo " ga('create', '" . esc_js( $ua_code ) . "', 'auto');";
743 }
744
745 if ( 'on' === $this->settings->get_option( 'track_user_id', 'wp-analytify-advanced' ) && is_user_logged_in() ) {
746 echo "ga('set', 'userId', " . esc_html( (string) get_current_user_id() ) . ');';
747 }
748
749 if ( 'on' === $this->settings->get_option( 'demographic_interest_tracking', 'wp-analytify-advanced' ) ) {
750 echo "ga('require', 'displayfeatures');";
751 }
752
753 if ( $this->settings->get_option( 'custom_js_code', 'wp-analytify-advanced' ) ) {
754
755 $custom_js = $this->settings->get_option( 'custom_js_code', 'wp-analytify-advanced' );
756
757 if ( $custom_js && false !== $custom_js ) {
758 $custom_js = wp_kses(
759 $custom_js,
760 array(
761 'script' => array(),
762 'noscript' => array(),
763 'div' => array(
764 'id' => array(),
765 'class' => array(),
766 ),
767 'span' => array(
768 'id' => array(),
769 'class' => array(),
770 ),
771 )
772 );
773 echo '<script type="text/javascript">' . esc_js( wp_strip_all_tags( $custom_js ) ) . '</script>';
774 }
775 }
776
777 do_action( 'ga_ecommerce_js' );
778 do_action( 'analytify_tracking_code_before_pageview' );
779 echo "ga('send', 'pageview');";
780 ?>
781
782 </script>
783
784 <?php
785 if ( false !== apply_filters( 'analytify_tracking_code_comments', true ) ) {
786 printf( // translators: Tracking code comments.
787 esc_html__( '%2$s This code is added by Analytify (%1$s) %3$s', 'wp-analytify' ),
788 esc_html( ANALYTIFY_VERSION ),
789 '<!--',
790 '!-->'
791 );
792 }
793
794 $ga_code = ob_get_contents();
795 ob_end_clean();
796 return $ga_code ? $ga_code : '';
797 }
798
799 // ========================================.
800 // GOOGLE ANALYTICS TRACKING CODE END.
801 // ========================================.
802
803
804 /**
805 * Adds action links to the plugin on the Plugins screen (e.g. Opt In / Opt Out, Settings).
806 *
807 * @param array<int|string, string> $links Default action links.
808 * @return array<int|string, string>
809 */
810 public function wp_analytify_plugin_action_links( $links ) {
811 $settings_link = '';
812
813 $sdk_data = json_decode( get_option( 'wpb_sdk_wp-analytify' ), true );
814 $sdk_data = is_array( $sdk_data ) ? $sdk_data : array();
815 $communication = isset( $sdk_data['communication'] ) ? $sdk_data['communication'] : false;
816 $diagnostic_info = isset( $sdk_data['diagnostic_info'] ) ? $sdk_data['diagnostic_info'] : false;
817 $extensions = isset( $sdk_data['extensions'] ) ? $sdk_data['extensions'] : false;
818 $is_optin = 'yes' === get_site_option( '_analytify_optin', '' );
819 $all_options_false = ! $communication && ! $diagnostic_info && ! $extensions;
820
821 if ( $communication || $diagnostic_info || $extensions ) {
822 $settings_link .= sprintf(
823 /* translators: %1$s opening link tag, %2$s closing link tag */
824 esc_html__( '%1$s Opt Out %2$s | ', 'wp-analytify' ),
825 '<a class="opt-out" href="#">',
826 '</a>'
827 );
828 } elseif ( $is_optin && $all_options_false ) {
829 update_option(
830 'wpb_sdk_wp-analytify',
831 wp_json_encode(
832 array(
833 'communication' => '1',
834 'diagnostic_info' => '1',
835 'extensions' => '1',
836 'user_skip' => '0',
837 )
838 )
839 );
840 $settings_link .= sprintf(
841 /* translators: %1$s opening link tag, %2$s closing link tag */
842 esc_html__( '%1$s Opt Out %2$s | ', 'wp-analytify' ),
843 '<a class="opt-out" href="#">',
844 '</a>'
845 );
846 } else {
847 $settings_link .= sprintf(
848 /* translators: %1$s opening link tag, %2$s closing link tag */
849 esc_html__( '%1$s Opt In %2$s | ', 'wp-analytify' ),
850 '<a href="' . esc_url( admin_url( 'admin.php?page=analytify-optin' ) ) . '">',
851 '</a>'
852 );
853 }
854
855 if ( ! class_exists( 'WP_Analytify_Pro' ) ) {
856 $settings_link .= sprintf(
857 /* translators: %1$s opening link tag, %2$s closing link tag */
858 esc_html__( '%1$s Get Analytify Pro %2$s | ', 'wp-analytify' ),
859 '<a href="https://analytify.io/pricing/?utm_source=analytify-lite&utm_medium=plugin-action-link&utm_campaign=pro-upgrade&utm_content=Get+Analytify+Pro" target="_blank" rel="noopener noreferrer" style="color:#3db634;">',
860 '</a>'
861 );
862 }
863
864 $settings_link .= sprintf(
865 /* translators: %1$s opening link tag, %2$s closing link tag */
866 esc_html__( '%1$s Settings %2$s', 'wp-analytify' ),
867 '<a href="' . esc_url( admin_url( 'admin.php?page=analytify-settings' ) ) . '">',
868 '</a>'
869 );
870
871 array_unshift( $links, $settings_link );
872 return $links;
873 }
874
875 /**
876 * Plugin row meta links
877 *
878 * @since 1.1
879 * @version 5.0.5
880 * @param array $input already defined meta links.
881 * @param string $file plugin file path && name being processed.
882 * @param array $plugin_data relevent data about the currect plugin.
883 * @param string $status weather plugin is active or disabled.
884 * @return array $input
885 */
886 public function plugin_row_meta( $input, $file, $plugin_data, $status ) {
887
888 $analytify_plugins = array(
889 'wp-analytify/wp-analytify.php',
890 'analytify-analytics-dashboard-widget/wp-analytify-dashboard.php',
891 'wp-analytify-pro/wp-analytify-pro.php',
892 'wp-analytify-woocommerce/wp-analytify-woocommerce.php',
893 'wp-analytify-goals/wp-analytify-goals.php',
894 'wp-analytify-forms/wp-analytify-forms.php',
895 'wp-analytify-email/wp-analytify-email.php',
896 'wp-analytify-edd/wp-analytify-edd.php',
897 'wp-analytify-authors/wp-analytify-authors.php',
898 );
899
900 if ( ! in_array( $file, $analytify_plugins, true ) ) {
901 return $input;
902 }
903
904 if ( isset( $plugin_data['Author'] ) ) {
905
906 $input[1] = sprintf(
907 'By <a href="%s" target="_blank" rel="noopener noreferrer">%s</a>',
908 esc_url( $plugin_data['AuthorURI'] ),
909 esc_html( $plugin_data['Author'] )
910 );
911
912 }
913
914 if ( 'wp-analytify/wp-analytify.php' !== $file && 'analytify-analytics-dashboard-widget/wp-analytify-dashboard.php' !== $file && in_array( $file, $analytify_plugins, true ) ) {
915
916 $input[2] = sprintf(
917 '<a href="%s" target="_blank" rel="noopener noreferrer">Visit Plugin Site</a>',
918 esc_url( $plugin_data['PluginURI'] )
919 );
920 return $input;
921
922 }
923
924 $links = array(
925 sprintf( // translators: Premium features.
926 esc_html__( '%1$s Explore Premium Features %2$s', 'wp-analytify' ),
927 '<a target="_blank" href="https://analytify.io/add-ons/?ref=27&utm_source=analytify-pro&utm_medium=plugin-action-link&utm_campaign=pro-upgrade&utm_content=Explore+Premium+Features">',
928 '</a>'
929 ),
930 );
931
932 $input = array_merge( $input, $links );
933
934 return $input;
935 }
936
937 /**
938 * Output SDK opt-in/opt-out modal on the Plugins screen so the "Opt Out" action link opens the popup.
939 *
940 * @return void
941 */
942 public function wp_analytify_maybe_render_sdk_optout_form() {
943 if ( ! function_exists( 'get_current_screen' ) ) {
944 return;
945 }
946 $screen = get_current_screen();
947 if ( ! $screen || 'plugins' !== $screen->id ) {
948 return;
949 }
950 require_once WP_ANALYTIFY_PLUGIN_DIR . '/inc/analytify-optout-form.php';
951 }
952
953 /**
954 * Display warning if profiles are not selected.
955 *
956 * @return void
957 */
958 public function pa_check_warnings() {
959 add_action( 'admin_footer', array( &$this, 'profile_warning' ) );
960 }
961
962
963 // Page routing function moved to Page_Management component.
964
965
966
967
968 // ========================================.
969 // ADMIN ASSETS & STYLING START.
970 // ========================================.
971
972 // Admin styles function moved to Scripts_Styles component.
973
974 // Functions moved to Scripts_Styles, Module_Manager && Promotions components.
975
976 // ========================================.
977 // ANALYTICS DATA RETRIEVAL START.
978 // ========================================.
979
980 // Analytics accounts function moved to Analytics_Accounts component.
981
982 // Analytics accounts summary function moved to Analytics_Accounts component.
983
984 /**
985 * Get settings URL.
986 *
987 * @return string
988 */
989 public function pa_setting_url() {
990 return admin_url( 'admin.php?page=analytify-settings' );
991 }
992
993 /**
994 * Save Google token data.
995 *
996 * @param mixed $key_google_token The Google token data.
997 * @return bool|void
998 */
999 public function pt_save_data( $key_google_token ) {
1000 try {
1001 update_option( 'post_analytics_token', $key_google_token );
1002
1003 if ( $this->analytify_pa_connect_v2() ) {
1004 return true;
1005 }
1006 } catch ( Exception $e ) {
1007 echo esc_html( $e->getMessage() );
1008 }
1009 }
1010
1011 // Profile warning function moved to Promotions component.
1012
1013 // AJAX handler moved to Analytics_Reports component.
1014
1015 // Module state function moved to Module_Manager component.
1016
1017
1018
1019
1020 // ========================================.
1021 // ANALYTICS DATA RETRIEVAL END.
1022 // ========================================.
1023
1024 // Deprecated analytics function moved to Analytics_Reports component.
1025
1026
1027
1028
1029 // ========================================.
1030 // UTILITY & HELPER FUNCTIONS START.
1031 // ========================================.
1032
1033 // Utility functions moved to Utils component.
1034 // Backward compatibility wrappers.
1035 /**
1036 * Format numbers for display.
1037 *
1038 * @param mixed $num The number to format.
1039 * @return string
1040 */
1041 public function wpa_pretty_numbers( $num ) {
1042 return Analytify_Utils::wpa_pretty_numbers( $num );
1043 }
1044
1045 /**
1046 * Format number with proper formatting.
1047 *
1048 * @param mixed $num The number to format.
1049 * @return string
1050 */
1051 public function wpa_number_format( $num ) {
1052 return Analytify_Utils::wpa_number_format( $num );
1053 }
1054
1055 /**
1056 * Format time for display.
1057 *
1058 * @param mixed $time The time to format.
1059 * @return string
1060 */
1061 public function pa_pretty_time( $time ) {
1062 return Analytify_Utils::pa_pretty_time( $time );
1063 }
1064
1065 /**
1066 * Check user access level.
1067 *
1068 * @param mixed $access_level The required access level.
1069 * @return bool
1070 */
1071 public function pa_check_roles( $access_level ) {
1072 return Analytify_Utils::pa_check_roles( $access_level );
1073 }
1074
1075
1076 /**
1077 * Notice to switch gtag.js tracking mode.
1078 *
1079 * @return void
1080 */
1081 // Welcome message function moved to Promotions component.
1082
1083 // ========================================.
1084 // ADMIN MENU & PAGE ROUTING START.
1085 // ========================================.
1086
1087 /**
1088 * Create Analytics menu at the left side of dashboard
1089 *
1090 * @version 8.1.0
1091 * @return void
1092 */
1093 public function add_admin_menu() {
1094 $allowed_roles = $this->settings->get_option( 'show_analytics_roles_dashboard', 'wp-analytify-dashboard', array() );
1095 $allowed_roles[] = 'administrator';
1096
1097 $current_user = wp_get_current_user();
1098 $is_author_only = $current_user && in_array( 'author', $current_user->roles, true ) && ! in_array( 'administrator', $current_user->roles, true );
1099
1100 // Determine the capability to use for the dashboard.
1101 // If the user has an allowed role, we use 'read' to ensure they can see the menu,
1102 // since add_admin_menu already restricted registration to allowed roles.
1103 $dashboard_cap = 'manage_options';
1104 if ( array_intersect( $current_user->roles, $allowed_roles ) ) {
1105 $dashboard_cap = 'read';
1106 }
1107
1108 // Allow authors to see the menu (so they can access Authors dashboard submenu).
1109 // But restrict them from accessing main dashboard content.
1110 if ( $is_author_only ) {
1111 // Authors can see menu but will be restricted from main dashboard page.
1112 // They need edit_posts capability to see Authors dashboard.
1113 if ( ! current_user_can( 'edit_posts' ) ) {
1114 return;
1115 }
1116 } elseif ( ! $this->pa_check_roles( $allowed_roles ) ) {
1117 // For non-authors, check normal access.
1118 return;
1119 }
1120
1121 add_submenu_page( 'admin.php', __( 'Activate', 'wp-analytify' ), __( 'Activate', 'wp-analytify' ), 'manage_options', 'analytify-optin', array( $this, 'render_optin' ) );
1122
1123 add_menu_page(
1124 ANALYTIFY_NICK,
1125 'Analytify',
1126 $dashboard_cap,
1127 'analytify-dashboard',
1128 array(
1129 $this,
1130 'pa_page_file_path',
1131 ),
1132 'data:image/svg+xml;base64,' . base64_encode( // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- Used for SVG data encoding
1133 '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
1134 width="18px" height="18px" viewBox="0 0 18 18" style="enable-background:new 0 0 18 18;" xml:space="preserve">
1135 <style type="text/css">
1136 .st0{fill-rule:evenodd;clip-rule:evenodd;fill:#23282D;}
1137 .st1{fill-rule:evenodd;clip-rule:evenodd;fill:#9EA3A8;}
1138 </style>
1139 <g>
1140 <path class="st0" d="M17.2,16c-0.4,0-0.8-0.3-0.8-0.8v-0.8V14c-1.6,2.4-4.3,4-7.5,4c-5,0-9-4-9-9s4-9,9-9c3.1,0,5.8,1.6,7.5,4V3.8
1141 v0l0,0c0-0.4,0.4-0.7,0.8-0.7S18,3.4,18,3.8l0,0v0V5v9.5v0.8C18,15.6,17.7,16,17.2,16z M9,1.5C4.9,1.5,1.5,4.9,1.5,9
1142 s3.4,7.5,7.5,7.5s7.5-3.4,7.5-7.5S13.1,1.5,9,1.5z"/>
1143 <g>
1144 <g>
1145 <path class="st1" d="M5.9,8.4c-0.5,0-0.9,0.4-0.9,0.9v2.9c0,0.5,0.4,0.9,0.9,0.9s0.9-0.4,0.9-0.9V9.3C6.7,8.8,6.3,8.4,5.9,8.4z
1146 M9,7C8.5,7,8.1,7.4,8.1,7.9v4.3C8.1,12.7,8.5,13,9,13s0.9-0.4,0.9-0.9V7.9C9.9,7.4,9.5,7,9,7z M12.1,4.9c-0.5,0-0.9,0.4-0.9,0.9
1147 v6.4c0,0.5,0.4,0.9,0.9,0.9s0.9-0.4,0.9-0.9V5.8C12.9,5.3,12.6,4.9,12.1,4.9z"/>
1148 </g>
1149 </g>
1150 </g>
1151 </svg>'
1152 ),
1153 2
1154 );
1155
1156 add_submenu_page(
1157 'analytify-dashboard',
1158 ANALYTIFY_NICK . esc_html__( ' Dashboards', 'wp-analytify' ),
1159 esc_html__( 'Dashboards', 'wp-analytify' ),
1160 $dashboard_cap,
1161 'analytify-dashboard',
1162 array(
1163 $this,
1164 'pa_page_file_path',
1165 ),
1166 10
1167 );
1168
1169 do_action( 'analytify_add_submenu' );
1170
1171 add_submenu_page(
1172 'analytify-dashboard',
1173 ANALYTIFY_NICK . esc_html__( ' Settings', 'wp-analytify' ),
1174 esc_html__( 'Settings', 'wp-analytify' ),
1175 'manage_options',
1176 'analytify-settings',
1177 array(
1178 $this,
1179 'pa_page_file_path',
1180 ),
1181 50
1182 );
1183
1184 add_submenu_page(
1185 'analytify-dashboard',
1186 ANALYTIFY_NICK . esc_html__( ' Help', 'wp-analytify' ),
1187 esc_html__( 'Help', 'wp-analytify' ),
1188 'manage_options',
1189 'analytify-settings#wp-analytify-help',
1190 array(
1191 $this,
1192 'pa_page_file_path',
1193 ),
1194 55
1195 );
1196
1197 // Add license submenu.
1198 if ( class_exists( 'WP_Analytify_Pro_Base' ) ) {
1199 add_submenu_page(
1200 'analytify-dashboard',
1201 ANALYTIFY_NICK . esc_html__( ' License', 'wp-analytify' ),
1202 esc_html__( 'License', 'wp-analytify' ),
1203 'manage_options',
1204 'analytify-settings#wp-analytify-license',
1205 array(
1206 $this,
1207 'pa_page_file_path',
1208 ),
1209 60
1210 );
1211 }
1212
1213 add_submenu_page(
1214 'analytify-dashboard',
1215 ANALYTIFY_NICK . esc_html__( ' list of all Add-ons', 'wp-analytify' ),
1216 esc_html__( 'Add-ons', 'wp-analytify' ),
1217 'manage_options',
1218 'analytify-addons',
1219 array(
1220 $this,
1221 'pa_page_file_path',
1222 ),
1223 65
1224 );
1225
1226 add_submenu_page(
1227 'analytify-dashboard',
1228 ANALYTIFY_NICK . esc_html__( ' PRO vs FREE', 'wp-analytify' ),
1229 esc_html__( 'PRO vs FREE', 'wp-analytify' ),
1230 'manage_options',
1231 'analytify-go-pro',
1232 array(
1233 $this,
1234 'pa_page_file_path',
1235 ),
1236 70
1237 );
1238
1239 // Promo page (will not appear in side menu).
1240 add_submenu_page( 'analytify-dashboard', esc_html__( 'Analytify Promo', 'wp-analytify' ), null, 'manage_options', 'analytify-promo', array( $this, 'addons_promo_screen' ) );
1241 }
1242
1243 /**
1244 * Get current screen details
1245 *
1246 * @return void
1247 */
1248 public function pa_page_file_path() {
1249 $screen = get_current_screen();
1250
1251 if ( strpos( $screen->base, 'analytify-settings' ) !== false ) {
1252 $version = defined( 'ANALYTIFY_PRO_VERSION' ) ? ANALYTIFY_PRO_VERSION : ANALYTIFY_VERSION;
1253
1254 echo '<div class="wrap"><h2 style="display: none;"></h2></div>
1255
1256 <div class="wpanalytify"><div class="wpb_plugin_wraper">
1257
1258 <div class="wpb_plugin_header_wraper">
1259 <div class="graph"></div>
1260
1261 <div class="wpb_plugin_header">
1262
1263 <div class="wpb_plugin_header_title"></div>
1264
1265 <div class="wpb_plugin_header_info">
1266 <a href="https://analytify.io/changelog/" target="_blank" class="btn">View Changelog</a>
1267 </div>
1268 <div class="wpb_plugin_header_logo">
1269 <img src="' . esc_url( plugins_url( 'assets/img/logo.svg', __FILE__ ) ) . '" alt="Analytify">
1270 </div>
1271 </div></div><div class="analytify-settings-body-container"><div class="wpb_plugin_body_wraper"><div class="wpb_plugin_body">';
1272 // Initialize settings before rendering.
1273 $this->settings->set_sections( $this->settings->get_settings_sections() );
1274 $this->settings->set_fields( $this->settings->get_settings_fields() );
1275 $this->settings->rendered_settings();
1276 $this->settings->show_tabs();
1277 echo '<div class="wpb_plugin_tabs_content">';
1278 $this->settings->show_forms();
1279 echo '</div>';
1280
1281 echo '</div></div></div></div>';
1282
1283 } elseif ( strpos( $screen->base, 'analytify-dashboard' ) !== false ) {
1284 // Restrict authors from accessing main dashboard - redirect to Authors dashboard.
1285 $current_user = wp_get_current_user();
1286 $is_author_only = $current_user && in_array( 'author', (array) $current_user->roles, true ) && ! in_array( 'administrator', (array) $current_user->roles, true );
1287
1288 if ( $is_author_only ) {
1289 // Redirect authors to their Authors dashboard.
1290 wp_safe_redirect( admin_url( 'admin.php?page=analytify-authors' ) );
1291 exit;
1292 }
1293
1294 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading URL parameter for display purposes
1295 if ( isset( $_GET['show'] ) ) {
1296 do_action( 'show_detail_dashboard_content' );
1297 } else {
1298 require_once WP_ANALYTIFY_PLUGIN_DIR . '/inc/analytics-dashboard.php';
1299 }
1300 } elseif ( strpos( $screen->base, 'analytify-optin' ) !== false ) {
1301 require_once WP_ANALYTIFY_PLUGIN_DIR . '/inc/analytify-optin-form.php';
1302 } elseif ( strpos( $screen->base, 'analytify-addons' ) !== false ) {
1303 require_once WP_ANALYTIFY_PLUGIN_DIR . '/inc/page-addons.php';
1304 } elseif ( strpos( $screen->base, 'analytify-woocommerce' ) !== false ) {
1305 // WooCommerce page - this might not exist, let's check if file exists first.
1306 $woo_file = WP_ANALYTIFY_PLUGIN_DIR . '/inc/analytify-woocommerce.php';
1307 if ( file_exists( $woo_file ) ) {
1308 require_once $woo_file;
1309 }
1310 } elseif ( strpos( $screen->base, 'analytify-logs' ) !== false ) {
1311 include_once WP_ANALYTIFY_PLUGIN_DIR . '/inc/page-logs.php';
1312 } elseif ( strpos( $screen->base, 'analytify-go-pro' ) !== false ) {
1313 include_once WP_ANALYTIFY_PLUGIN_DIR . '/inc/analytify-go-pro.php';
1314 } elseif ( isset( $_GET['show'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading URL parameter for display purposes
1315 do_action( 'show_detail_dashboard_content' );
1316 } else {
1317 // Dequeue event calendar js.
1318 wp_dequeue_script( 'tribe-common' );
1319 wp_dequeue_script( 'mcw-crypto-common' );
1320 include_once WP_ANALYTIFY_PLUGIN_DIR . '/inc/analytics-dashboard.php';
1321 }
1322 }
1323
1324 // ========================================.
1325 // ADMIN MENU & PAGE ROUTING END.
1326 // ========================================.
1327
1328 /**
1329 * Render optin page
1330 *
1331 * @return void
1332 */
1333 public function render_optin() {
1334 require_once WP_ANALYTIFY_PLUGIN_DIR . '/inc/analytify-optin-form.php';
1335 }
1336
1337 // Functions moved to Promotions && Analytics_Reports components.
1338
1339 /**
1340 * Process logout && clear stored options.
1341 *
1342 * @return void
1343 */
1344 public function logout() {
1345 if ( isset( $_POST['wp_analytify_log_out'] ) && isset( $_POST['analytify_analytics_logout_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['analytify_analytics_logout_nonce'] ) ), 'analytify_analytics_logout' ) ) {
1346 delete_option( 'pt_webprofile' );
1347 delete_option( 'pt_webprofile_dashboard' );
1348 delete_option( 'pt_webprofile_url' );
1349 delete_option( 'pa_google_token' );
1350 delete_option( 'post_analytics_token' );
1351 delete_option( 'hide_profiles' );
1352 delete_option( 'analytify-ga4-streams' );
1353 delete_option( 'analytify_tracking_property_info' );
1354 delete_option( 'analytify_reporting_property_info' );
1355 delete_option( 'analytify_ga4_exception' );
1356 delete_option( 'analytify_ga4_exceptions' );
1357 delete_option( 'profiles_list_summary' );
1358 delete_option( 'analytify_ga_properties_list' );
1359 delete_option( 'wp-analytify-mode' );
1360 delete_option( 'analytify-deprecated-auth' );
1361 delete_option( 'analytify-ga-properties-summery' );
1362 delete_option( 'analytify_profile_exception' );
1363 delete_option( 'profiles_list_summary_backup' );
1364 delete_transient( 'analytify_quota_exception' );
1365
1366 $_analytify_profile = get_option( 'wp-analytify-profile' );
1367 if ( $_analytify_profile ) {
1368 unset( $_analytify_profile['hide_profiles_list'], $_analytify_profile['profile_for_posts'], $_analytify_profile['profile_for_dashboard'] );
1369 update_option( 'wp-analytify-profile', $_analytify_profile );
1370 }
1371
1372 $update_message = sprintf( // translators: Login again notice.
1373 esc_html__( '%1$s %2$s %3$s Authentication Cleared login again. %4$s %5$s %6$s', 'wp-analytify' ),
1374 '<div id="setting-error-settings_updated" class="updated notice is-dismissible settings-error below-h2">',
1375 '<p>',
1376 '<strong>',
1377 '</strong>',
1378 '</p>',
1379 '</div>'
1380 );
1381 }
1382 }
1383
1384 /**
1385 * Used to add query args that need to be removed from url
1386 *
1387 * @since 5.0.6
1388 * @param mixed $args_array The arguments array to process.
1389 * @return array
1390 */
1391 public function Analytify_remove_query( $args_array ) {
1392 $analytify_args_to_remove = array( 'analytify-cache' );
1393 $args_array = array_merge( $args_array, $analytify_args_to_remove );
1394 return $args_array;
1395 }
1396
1397 /**
1398 * Trigger logging cleanup using the logging class.
1399 *
1400 * @since 2.1.23
1401 * @return void
1402 */
1403 public static function analytify_cleanup_logs() {
1404 $logger = analytify_get_logger();
1405 if ( class_exists( 'QM' ) ) {
1406 QM::info( 'Analytify: Starting cleanup of expired logs.' );
1407 }
1408
1409 if ( is_callable( array( $logger, 'clear_expired_logs' ) ) ) {
1410 $logger->clear_expired_logs();
1411 if ( class_exists( 'QM' ) ) {
1412 QM::info( 'Analytify: Expired logs cleared successfully.' );
1413 }
1414 }
1415 }
1416
1417
1418
1419
1420 // ========================================.
1421 // PROFILE & SETTINGS MANAGEMENT START.
1422 // ========================================.
1423
1424 // Functions moved to Profile_Management && GA4_Property_Management components.
1425
1426 // ========================================.
1427 // PROFILE & SETTINGS MANAGEMENT END.
1428 // ========================================.
1429
1430 // Black Friday Deal Notice function moved to Promotions component.
1431
1432 // Function moved to Promotions component.
1433
1434 // Winter Sale promo function moved to Promotions component.
1435
1436 // Winter Sale dismiss notice function moved to Promotions component.
1437
1438 // Rating icon function moved to Promotions component.
1439
1440 // ========================================.
1441 // GDPR COMPLIANCE & META BOXES START.
1442 // ========================================.
1443
1444 // Functions add_exclusion_meta_box && print_exclusion_meta_box moved to GDPR_Compliance component.
1445
1446 // ========================================.
1447 // GDPR COMPLIANCE & META BOXES END.
1448 // ========================================.
1449
1450 /**
1451 * Init the compliance class.
1452 *
1453 * @return void
1454 */
1455 public function init_gdpr_compliance() {
1456 if ( class_exists( 'Class_Analytify_GDPR_Compliance' ) ) {
1457 new Class_Analytify_GDPR_Compliance();
1458 }
1459 }
1460
1461 /**
1462 * Get a component from the loader
1463 *
1464 * @param string $component_name The name of the component to get.
1465 * @return mixed|null The component instance or null if not found
1466 */
1467 public function get_component( $component_name ) {
1468 if ( $this->loader && method_exists( $this->loader, 'get_component' ) ) {
1469 return $this->loader->get_component( $component_name );
1470 }
1471 return null;
1472 }
1473
1474 /**
1475 * Check if a component is loaded
1476 *
1477 * @param string $component_name The name of the component to check.
1478 * @return bool True if component is loaded, false otherwise
1479 */
1480 public function has_component( $component_name ) {
1481 if ( $this->loader && method_exists( $this->loader, 'has_component' ) ) {
1482 return $this->loader->has_component( $component_name );
1483 }
1484 return false;
1485 }
1486
1487 // Welcome message function moved to Promotions component.
1488
1489 /**
1490 * Show promo screen for addons
1491 *
1492 * @return void
1493 */
1494 public function addons_promo_screen() {
1495 include WP_ANALYTIFY_PLUGIN_DIR . '/views/default/admin/addons-promo.php';
1496 }
1497 }
1498 } // End if class_exists check.
1499
1500 // ========================================.
1501 // MAIN PLUGIN CLASS DEFINITION END.
1502 // ========================================.
1503
1504 /**
1505 * Create instance of wp-analytify class.
1506 *
1507 * @return void
1508 */
1509 function analytify_free_instance() {
1510 $GLOBALS['WP_ANALYTIFY'] = WP_Analytify::get_instance();
1511 }
1512 add_action( 'plugins_loaded', 'analytify_free_instance', 10 );
1513
1514 // ========================================.
1515 // PLUGIN INSTANCE INITIALIZATION END.
1516 // ========================================.
1517
1518 /**
1519 * AJAX callback function for performing a factory reset of Analytify plugin settings
1520 *
1521 * This function handles the secure AJAX request to reset all Analytify settings
1522 * to their default values. It includes security checks, capability verification,
1523 * and proper error handling.
1524 *
1525 * @hook wp_ajax_analytify_factory_reset
1526 * @since 8.0.0
1527 * @return void Sends JSON response indicating success or failure
1528 */
1529 function analytify_factory_reset_callback() {
1530 // Verify the nonce for security - prevents CSRF attacks.
1531 check_ajax_referer( 'analytify_factory_reset_nonce', 'nonce' );
1532
1533 // Check if current user has administrative capabilities.
1534 if ( ! current_user_can( 'manage_options' ) ) {
1535 wp_send_json_error( 'Unauthorized' );
1536 }
1537
1538 // Load the factory reset class if not already available.
1539 if ( ! class_exists( 'Analytify_Factory_Reset' ) ) {
1540 require_once plugin_dir_path( __FILE__ ) . 'classes/analytify-factory-reset.php';
1541 }
1542
1543 // Initialize the reset class and execute the reset process.
1544 $reset = new Analytify_Factory_Reset();
1545 $reset->remove_settings();
1546
1547 // Send success response to the AJAX request.
1548 wp_send_json_success();
1549 }
1550
1551 /**
1552 * Hook the factory reset function to WordPress AJAX handlers
1553 *
1554 * This registers the function for both privileged (admin) and non-privileged users,
1555 * but the capability check inside the function will restrict access to admins only.
1556 */
1557 add_action( 'wp_ajax_analytify_factory_reset', 'analytify_factory_reset_callback' );
1558