PluginProbe ʕ •ᴥ•ʔ
MonsterInsights – Google Analytics Dashboard for WordPress (Website Stats Made Easy) / 10.1.3
MonsterInsights – Google Analytics Dashboard for WordPress (Website Stats Made Easy) v10.1.3
10.2.2 10.2.1 10.2.0 10.1.3 trunk 10.0.0 10.0.1 10.0.2 10.0.3 10.1.1 10.1.2 8.1.0 8.10.0 8.10.1 8.11.0 8.12.0 8.12.1 8.13.0 8.13.1 8.14.0 8.14.1 8.15 8.16 8.17 8.18 8.19.0 8.2.0 8.20.0 8.20.1 8.21.0 8.22.0 8.23.0 8.23.1 8.24.0 8.25.0 8.26.0 8.27.0 8.28.0 8.3.0 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.5.0 8.5.1 8.5.2 8.5.3 8.6.0 8.7.0 8.8.0 8.8.1 8.8.2 8.9.0 8.9.1 9.0.0 9.0.1 9.1.0 9.1.1 9.10.0 9.10.1 9.11.0 9.11.1 9.2.0 9.2.1 9.2.2 9.2.3 9.2.4 9.3.0 9.3.1 9.4.0 9.4.1 9.5.1 9.5.2 9.5.3 9.6.0 9.6.1 9.7.0 9.8.0 9.9.0
google-analytics-for-wordpress / includes / helpers.php
google-analytics-for-wordpress / includes Last commit date
admin 1 month ago api 1 month ago cache 1 month ago database 1 month ago emails 1 month ago frontend 1 month ago gutenberg 1 month ago overview 1 month ago popular-posts 8 months ago ppc 1 month ago tracking 1 month ago api-request.php 8 months ago auth.php 1 month ago capabilities.php 1 month ago compatibility-check.php 2 years ago connect.php 1 month ago deprecated.php 1 year ago helpers.php 1 month ago index.php 3 years ago install.php 1 month ago measurement-protocol-v4.php 1 month ago options.php 2 years ago
helpers.php
2668 lines
1 <?php
2
3 /**
4 * Helper functions.
5 *
6 * @since 6.0.0
7 *
8 * @package MonsterInsights
9 * @subpackage Helper
10 * @author Chris Christoff
11 * TODO Go through this file and remove UA and dual tracking references/usages
12 */
13
14 // Exit if accessed directly
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 function monsterinsights_get_url($medium = '', $campaign = '', $url = '', $escape = true)
20 {
21 // Setup Campaign variables
22 $source = monsterinsights_is_pro_version() ? 'proplugin' : 'liteplugin';
23 $medium = !empty($medium) ? $medium : 'defaultmedium';
24 $campaign = !empty($campaign) ? $campaign : 'defaultcampaign';
25 $content = MONSTERINSIGHTS_VERSION;
26 $default_url = monsterinsights_is_pro_version() ? '' : 'lite/';
27 $url = !empty($url) ? $url : 'https://www.monsterinsights.com/' . $default_url;
28
29 // Put together redirect URL
30 $url = add_query_arg(
31 array(
32 'utm_source' => $source, // Pro/Lite Plugin
33 'utm_medium' => sanitize_key($medium), // Area of MonsterInsights (example Reports)
34 'utm_campaign' => sanitize_key($campaign), // Which link (example eCommerce Report)
35 'utm_content' => $content, // Version number of MI
36 ),
37 trailingslashit($url)
38 );
39
40 if ($escape) {
41 return esc_url($url);
42 } else {
43 return $url;
44 }
45 }
46
47 function monsterinsights_is_page_reload() {
48 // Can't be a refresh without having a referrer
49 if ( ! isset( $_SERVER['HTTP_REFERER'] ) ) {
50 return false;
51 }
52
53 // IF the referrer is identical to the current page request, then it's a refresh
54 return ( $_SERVER['HTTP_REFERER'] === home_url( $_SERVER['REQUEST_URI'] ) ); // phpcs:ignore
55 }
56
57
58 function monsterinsights_track_user( $user_id = - 1 ) {
59 if ( $user_id === - 1 ) {
60 $user = wp_get_current_user();
61 } else {
62 $user = new WP_User( $user_id );
63 }
64
65 $track_user = true;
66 $roles = monsterinsights_get_option( 'ignore_users', array() );
67
68 if ( ! empty( $roles ) && is_array( $roles ) ) {
69 foreach ( $roles as $role ) {
70 if ( is_string( $role ) ) {
71 if ( user_can( $user, $role ) ) {
72 $track_user = false;
73 break;
74 }
75 }
76 }
77 }
78
79 $track_super_admin = apply_filters( 'monsterinsights_track_super_admins', false );
80 if ( $user_id === - 1 && $track_super_admin === false && is_multisite() && is_super_admin() ) {
81 $track_user = false;
82 }
83
84 // or if tracking code is not entered
85 $tracking_id = monsterinsights_get_v4_id();
86 if ( empty( $tracking_id ) ) {
87 $track_user = false;
88 }
89
90 return apply_filters( 'monsterinsights_track_user', $track_user, $user );
91 }
92
93 /**
94 * Skip tracking status.
95 *
96 * @return bool
97 */
98 function monsterinsights_skip_tracking() {
99 return (bool) apply_filters( 'monsterinsights_skip_tracking', false );
100 }
101
102 function monsterinsights_get_client_id( $payment_id = false ) {
103 if ( is_object( $payment_id ) ) {
104 $payment_id = $payment_id->ID;
105 }
106 $user_cid = monsterinsights_get_uuid();
107 $saved_cid = ! empty( $payment_id ) ? get_post_meta( $payment_id, '_yoast_gau_uuid', true ) : false;
108
109 if ( ! empty( $payment_id ) && ! empty( $saved_cid ) ) {
110 return $saved_cid;
111 } elseif ( ! empty( $user_cid ) ) {
112 return $user_cid;
113 } else {
114 return monsterinsights_generate_uuid();
115 }
116 }
117
118 /**
119 * Returns the Google Analytics clientId to store for later use
120 *
121 * @return bool|string False if cookie isn't set, GA UUID otherwise
122 * @link https://developers.google.com/analytics/devguides/collection/analyticsjs/domains#getClientId
123 *
124 * @since 6.0.0
125 */
126 function monsterinsights_get_uuid() {
127 if ( empty( $_COOKIE['_ga'] ) ) {
128 return false;
129 }
130
131 /**
132 * Example cookie formats:
133 *
134 * GA1.2.XXXXXXX.YYYYY
135 * _ga=1.2.XXXXXXX.YYYYYY -- We want the XXXXXXX.YYYYYY part
136 *
137 * for AMP pages the format is sometimes GA1.3.amp-XXXXXXXXXXXXX-XXXXXXXX
138 * if the first page visited is AMP, the cookie may be in the format amp-XXXXXXXXXXXXX-XXXXXXXX
139 */
140
141 $ga_cookie = sanitize_text_field($_COOKIE['_ga']); // phpcs:ignore WordPressVIPMinimum.Variables.RestrictedVariables.cache_constraints___COOKIE
142 $cookie_parts = explode( '.', $ga_cookie );
143 if ( is_array( $cookie_parts ) && ! empty( $cookie_parts[2] ) ) {
144 $cookie_parts = array_slice( $cookie_parts, 2 );
145 $uuid = implode( '.', $cookie_parts );
146 if ( is_string( $uuid ) ) {
147 return $uuid;
148 } else {
149 return false;
150 }
151 } elseif ( 0 === strpos( $ga_cookie, 'amp-' ) ) {
152 return $ga_cookie;
153 } else {
154 return false;
155 }
156 }
157
158 /**
159 * Gets GA Session Id (GA4 only) from cookies.
160 *
161 * @var string $measurement_id
162 * GA4 Measurement Id (Property Id). E.g., 'G-1YS1VWHG3V'.
163 *
164 * @return string|null
165 * Returns GA4 Session Id or NULL if cookie wasn't found.
166 */
167 function monsterinsights_get_browser_session_id( $measurement_id ) {
168 if ( ! is_string( $measurement_id ) ) {
169 return null;
170 }
171 // Cookie name example: '_ga_1YS1VWHG3V'.
172 $cookie_name = '_ga_' . str_replace( 'G-', '', $measurement_id );
173 if ( ! isset( $_COOKIE[ $cookie_name ] ) ) {
174 return null;
175 }
176
177 $cookie = sanitize_text_field( $_COOKIE[ $cookie_name ] ); // phpcs:ignore WordPressVIPMinimum.Variables.RestrictedVariables.cache_constraints___COOKIE
178
179 // Check if it's GS2 format
180 // New format: 'GS2.1.s1747078634$o1$g1$t1747081074$j0$l0$h0'
181 // Session Id: ^^^^^^^^^^ (1747078634)
182 if ( strpos( $cookie, 'GS2' ) === 0 ) {
183 // Extract the session ID (after 's' and before '$')
184 if ( preg_match( '/\.s(\d+)\$/', $cookie, $matches ) ) {
185 return $matches[1];
186 }
187 return null;
188 }
189
190 // Handle original GS1 format
191 // Cookie value example: 'GS1.1.1659710029.4.1.1659710504.0'.
192 // Session Id: ^^^^^^^^^^. (1659710029)
193 $parts = explode( '.', $cookie );
194 if ( ! isset( $parts[2] ) ){
195 return null;
196 }
197 return $parts[2];
198 }
199
200 /**
201 * Generate UUID v4 function - needed to generate a CID when one isn't available
202 *
203 * @link http://www.stumiller.me/implementing-google-analytics-measurement-protocol-in-php-and-wordpress/
204 *
205 * @since 6.1.8
206 * @return string
207 */
208 function monsterinsights_generate_uuid() {
209
210 return sprintf(
211 '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
212 // 32 bits for "time_low"
213 random_int( 0, 0xffff ),
214 random_int( 0, 0xffff ),
215 // 16 bits for "time_mid"
216 random_int( 0, 0xffff ),
217 // 16 bits for "time_hi_and_version",
218 // four most significant bits holds version number 4
219 random_int( 0, 0x0fff ) | 0x4000,
220 // 16 bits, 8 bits for "clk_seq_hi_res",
221 // 8 bits for "clk_seq_low",
222 // two most significant bits holds zero and one for variant DCE1.1
223 random_int( 0, 0x3fff ) | 0x8000,
224 // 48 bits for "node"
225 random_int( 0, 0xffff ),
226 random_int( 0, 0xffff ),
227 random_int( 0, 0xffff )
228 );
229 }
230
231 /**
232 * Returns the Google Analytics clientId to store for later use
233 *
234 * @return GA UUID or error code.
235 * @since 6.0.0
236 */
237 function monsterinsights_get_cookie( $debug = false ) {
238 if ( empty( $_COOKIE['_ga'] ) ) {
239 return ( $debug ) ? 'FCE' : false;
240 }
241
242 $ga_cookie = sanitize_text_field( $_COOKIE['_ga'] ); // phpcs:ignore WordPressVIPMinimum.Variables.RestrictedVariables.cache_constraints___COOKIE
243 $cookie_parts = explode( '.', $ga_cookie );
244 if ( is_array( $cookie_parts ) && ! empty( $cookie_parts[2] ) ) {
245 $cookie_parts = array_slice( $cookie_parts, 2 );
246 $uuid = implode( '.', $cookie_parts );
247 if ( is_string( $uuid ) ) {
248 return $ga_cookie;
249 } else {
250 return ( $debug ) ? 'FA' : false;
251 }
252 } elseif ( 0 === strpos( $ga_cookie, 'amp-' ) ) {
253 return $ga_cookie;
254 } else {
255 return ( $debug ) ? 'FAE' : false;
256 }
257 }
258
259
260 function monsterinsights_generate_ga_client_id() {
261 return wp_rand( 100000000, 999999999 ) . '.' . time();
262 }
263
264
265 /**
266 * Hours between two timestamps.
267 *
268 * @access public
269 *
270 * @param string $start Timestamp of start time (in seconds since Unix).
271 * @param string $stop Timestamp of stop time (in seconds since Unix). Optional. If not used, current_time (in UTC 0 / GMT ) is used.
272 *
273 * @return int Hours between the two timestamps, rounded.
274 * @since 6.0.0
275 */
276 function monsterinsights_hours_between( $start, $stop = false ) {
277 if ( $stop === false ) {
278 $stop = time();
279 }
280
281 $diff = (int) abs( $stop - $start );
282 $hours = round( $diff / HOUR_IN_SECONDS );
283
284 return $hours;
285 }
286
287 /**
288 * Is This MonsterInsights Pro?
289 *
290 * We use this function monsterinsights_to determine if the install is a pro version or a lite version install of MonsterInsights.
291 * If the install is a lite version we disable the install from admin functionality[1] for addons as WordPress.org requires us to,
292 * we change the links for where to get support (wp.org forum for free; our site for pro), we use this determine what class to load as
293 * the base class in addons (to avoid fatal errors) and we use this on the system info page to know what constants to display values for
294 * as the lite and pro versions of our plugin have different constants (and names for those constants) you can declare and use.
295 *
296 * [1] Note: This is not "feature-locking" under GPL guidelines but rather something WordPress.org requires us to do to stay
297 * in compliance with their rules. We wish we didn't have to do this, as in our oppinion this diminishes the user experience
298 * of users installing our free and premium addons, and we'd love to turn this on for non-Pro installs, but we're not allowed to.
299 * If WordPress.org ever changes their mind on this subject, we'd totally turn on that feature for Lite installs in a heartbeat.
300 *
301 * @return bool True if pro version.
302 * @since 6.0.0
303 * @access public
304 *
305 * @todo Are we allowed to turn on admin installing if the user has to manually declare a PHP constant (and thus would not be on
306 * either by default or via any sort of user interface)? If so, we could add a constant for forcing Pro version so that users can see
307 * for themselves that we're not feature locking anything inside the plugin + it would make it easier for our team to test stuff (both via
308 * Travis-CI but also when installing addons to test with the Lite version). Also this would allow for a better user experience for users
309 * who want that feature.
310 */
311 function monsterinsights_is_pro_version() {
312 if ( class_exists( 'MonsterInsights' ) ) {
313 return true;
314 } else {
315 return false;
316 }
317 }
318
319
320 /**
321 * Get the user roles of this WordPress blog
322 *
323 * @return array
324 */
325 function monsterinsights_get_roles() {
326 global $wp_roles;
327
328 $all_roles = $wp_roles->roles;
329 $roles = array();
330
331 /**
332 * Filter: 'editable_roles' - Allows filtering of the roles shown within the plugin (and elsewhere in WP as it's a WP filter)
333 *
334 * @api array $all_roles
335 */
336 $editable_roles = apply_filters( 'editable_roles', $all_roles );
337
338 foreach ( $editable_roles as $id => $name ) {
339 $roles[ $id ] = translate_user_role( $name['name'] );
340 }
341
342 return $roles;
343 }
344
345 /**
346 * Get the user roles which can manage options. Used to prevent these roles from getting unselected in the settings.
347 *
348 * @return array
349 */
350 function monsterinsights_get_manage_options_roles() {
351 global $wp_roles;
352
353 $all_roles = $wp_roles->roles;
354 $roles = array();
355
356 /**
357 * Filter: 'editable_roles' - Allows filtering of the roles shown within the plugin (and elsewhere in WP as it's a WP filter)
358 *
359 * @api array $all_roles
360 */
361 $editable_roles = apply_filters( 'editable_roles', $all_roles );
362
363 foreach ( $editable_roles as $id => $role ) {
364 if ( isset( $role['capabilities']['manage_options'] ) && $role['capabilities']['manage_options'] ) {
365 $roles[ $id ] = translate_user_role( $role['name'] );
366 }
367 }
368
369 return $roles;
370 }
371
372 /** Need to escape in advance of passing in $text. */
373 function monsterinsights_get_message( $type = 'error', $text = '' ) {
374 $div = '';
375 if ( $type === 'error' || $type === 'alert' || $type === 'success' || $type === 'info' ) {
376 $base = MonsterInsights();
377
378 return $base->notices->display_inline_notice( 'monsterinsights_standard_notice', '', $text, $type, false, array( 'skip_message_escape' => true ) );
379 } else {
380 return '';
381 }
382 }
383
384 function monsterinsights_is_dev_url( $url = '' ) {
385
386 if ( empty( $url ) ) {
387 return false;
388 }
389
390 // Trim it up
391 $url = strtolower( trim( $url ) );
392 // Need to get the host...so let's add the scheme so we can use parse_url
393 if ( false === strpos( $url, 'http://' ) && false === strpos( $url, 'https://' ) ) {
394 $url = 'http://' . $url;
395 }
396 $url_parts = parse_url( $url );
397 $host = ! empty( $url_parts['host'] ) ? $url_parts['host'] : false;
398 if ( ! empty( $url ) && ! empty( $host ) ) {
399 if ( false !== ip2long( $host ) ) {
400 if ( ! filter_var( $host, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) {
401 return true;
402 }
403 } elseif ( 'localhost' === $host ) {
404 return true;
405 }
406
407 $tlds_to_check = array( '.local', ':8888', ':8080', ':8081', '.invalid', '.example', '.test', '.dev' );
408 foreach ( $tlds_to_check as $tld ) {
409 if ( false !== strpos( $host, $tld ) ) {
410 return true;
411 }
412 }
413 if ( substr_count( $host, '.' ) > 1 ) {
414 $subdomains_to_check = array( 'dev.', '*.staging.', 'beta.', 'test.' );
415 foreach ( $subdomains_to_check as $subdomain ) {
416 $subdomain = str_replace( '.', '(.)', $subdomain );
417 $subdomain = str_replace( array( '*', '(.)' ), '(.*)', $subdomain );
418 if ( preg_match( '/^(' . $subdomain . ')/', $host ) ) {
419 return true;
420 break;
421 }
422 }
423 }
424
425 if ( function_exists( 'wp_get_environment_type' ) ) {
426 $env_type = wp_get_environment_type();
427
428 if ( 'development' === $env_type || 'local' === $env_type ) {
429 return true;
430 }
431 }
432
433 if ( defined( 'WP_HTTP_BLOCK_EXTERNAL' ) && WP_HTTP_BLOCK_EXTERNAL ) {
434 if ( defined( 'WP_ACCESSIBLE_HOSTS' ) && WP_ACCESSIBLE_HOSTS ) {
435 $allowed_hosts = preg_split( '|,\s*|', WP_ACCESSIBLE_HOSTS );
436
437 if ( is_array( $allowed_hosts ) && ! empty( $allowed_hosts ) ) {
438 if ( ! in_array( '*.monsterinsights.com', $allowed_hosts, true ) || ! in_array( 'api.monsterinsights.com', $allowed_hosts, true ) ) {
439 return true;
440 }
441 }
442 }
443
444 return true;
445 }
446 }
447
448 return false;
449 }
450
451 // Set cookie to expire in 2 years
452 function monsterinsights_get_cookie_expiration_date( $time ) {
453 return date( 'D, j F Y H:i:s', time() + $time ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
454 }
455
456 function monsterinsights_string_ends_with( $string, $ending ) {
457 $strlen = strlen( $string );
458 $endinglen = strlen( $ending );
459 if ( $endinglen > $strlen ) {
460 return false;
461 }
462
463 return substr_compare( $string, $ending, $strlen - $endinglen, $endinglen ) === 0;
464 }
465
466 function monsterinsights_string_starts_with( $string, $start ) {
467 if ( ! is_string( $string ) || ! is_string( $start ) ) {
468 return false;
469 }
470
471 return substr( $string, 0, strlen( $start ) ) === $start;
472 }
473
474 function monsterinsights_get_country_list( $translated = false ) {
475 if ( $translated ) {
476 $countries = array(
477 '' => '',
478 'US' => __( 'United States', 'google-analytics-for-wordpress' ),
479 'CA' => __( 'Canada', 'google-analytics-for-wordpress' ),
480 'GB' => __( 'United Kingdom', 'google-analytics-for-wordpress' ),
481 'AF' => __( 'Afghanistan', 'google-analytics-for-wordpress' ),
482 'AX' => __( '&#197;land Islands', 'google-analytics-for-wordpress' ),
483 'AL' => __( 'Albania', 'google-analytics-for-wordpress' ),
484 'DZ' => __( 'Algeria', 'google-analytics-for-wordpress' ),
485 'AS' => __( 'American Samoa', 'google-analytics-for-wordpress' ),
486 'AD' => __( 'Andorra', 'google-analytics-for-wordpress' ),
487 'AO' => __( 'Angola', 'google-analytics-for-wordpress' ),
488 'AI' => __( 'Anguilla', 'google-analytics-for-wordpress' ),
489 'AQ' => __( 'Antarctica', 'google-analytics-for-wordpress' ),
490 'AG' => __( 'Antigua and Barbuda', 'google-analytics-for-wordpress' ),
491 'AR' => __( 'Argentina', 'google-analytics-for-wordpress' ),
492 'AM' => __( 'Armenia', 'google-analytics-for-wordpress' ),
493 'AW' => __( 'Aruba', 'google-analytics-for-wordpress' ),
494 'AU' => __( 'Australia', 'google-analytics-for-wordpress' ),
495 'AT' => __( 'Austria', 'google-analytics-for-wordpress' ),
496 'AZ' => __( 'Azerbaijan', 'google-analytics-for-wordpress' ),
497 'BS' => __( 'Bahamas', 'google-analytics-for-wordpress' ),
498 'BH' => __( 'Bahrain', 'google-analytics-for-wordpress' ),
499 'BD' => __( 'Bangladesh', 'google-analytics-for-wordpress' ),
500 'BB' => __( 'Barbados', 'google-analytics-for-wordpress' ),
501 'BY' => __( 'Belarus', 'google-analytics-for-wordpress' ),
502 'BE' => __( 'Belgium', 'google-analytics-for-wordpress' ),
503 'BZ' => __( 'Belize', 'google-analytics-for-wordpress' ),
504 'BJ' => __( 'Benin', 'google-analytics-for-wordpress' ),
505 'BM' => __( 'Bermuda', 'google-analytics-for-wordpress' ),
506 'BT' => __( 'Bhutan', 'google-analytics-for-wordpress' ),
507 'BO' => __( 'Bolivia', 'google-analytics-for-wordpress' ),
508 'BQ' => __( 'Bonaire, Saint Eustatius and Saba', 'google-analytics-for-wordpress' ),
509 'BA' => __( 'Bosnia and Herzegovina', 'google-analytics-for-wordpress' ),
510 'BW' => __( 'Botswana', 'google-analytics-for-wordpress' ),
511 'BV' => __( 'Bouvet Island', 'google-analytics-for-wordpress' ),
512 'BR' => __( 'Brazil', 'google-analytics-for-wordpress' ),
513 'IO' => __( 'British Indian Ocean Territory', 'google-analytics-for-wordpress' ),
514 'BN' => __( 'Brunei Darrussalam', 'google-analytics-for-wordpress' ),
515 'BG' => __( 'Bulgaria', 'google-analytics-for-wordpress' ),
516 'BF' => __( 'Burkina Faso', 'google-analytics-for-wordpress' ),
517 'BI' => __( 'Burundi', 'google-analytics-for-wordpress' ),
518 'KH' => __( 'Cambodia', 'google-analytics-for-wordpress' ),
519 'CM' => __( 'Cameroon', 'google-analytics-for-wordpress' ),
520 'CV' => __( 'Cape Verde', 'google-analytics-for-wordpress' ),
521 'KY' => __( 'Cayman Islands', 'google-analytics-for-wordpress' ),
522 'CF' => __( 'Central African Republic', 'google-analytics-for-wordpress' ),
523 'TD' => __( 'Chad', 'google-analytics-for-wordpress' ),
524 'CL' => __( 'Chile', 'google-analytics-for-wordpress' ),
525 'CN' => __( 'China', 'google-analytics-for-wordpress' ),
526 'CX' => __( 'Christmas Island', 'google-analytics-for-wordpress' ),
527 'CC' => __( 'Cocos Islands', 'google-analytics-for-wordpress' ),
528 'CO' => __( 'Colombia', 'google-analytics-for-wordpress' ),
529 'KM' => __( 'Comoros', 'google-analytics-for-wordpress' ),
530 'CD' => __( 'Congo, Democratic People\'s Republic', 'google-analytics-for-wordpress' ),
531 'CG' => __( 'Congo, Republic of', 'google-analytics-for-wordpress' ),
532 'CK' => __( 'Cook Islands', 'google-analytics-for-wordpress' ),
533 'CR' => __( 'Costa Rica', 'google-analytics-for-wordpress' ),
534 'CI' => __( 'Cote d\'Ivoire', 'google-analytics-for-wordpress' ),
535 'HR' => __( 'Croatia/Hrvatska', 'google-analytics-for-wordpress' ),
536 'CU' => __( 'Cuba', 'google-analytics-for-wordpress' ),
537 'CW' => __( 'Cura&Ccedil;ao', 'google-analytics-for-wordpress' ),
538 'CY' => __( 'Cyprus', 'google-analytics-for-wordpress' ),
539 'CZ' => __( 'Czechia', 'google-analytics-for-wordpress' ),
540 'DK' => __( 'Denmark', 'google-analytics-for-wordpress' ),
541 'DJ' => __( 'Djibouti', 'google-analytics-for-wordpress' ),
542 'DM' => __( 'Dominica', 'google-analytics-for-wordpress' ),
543 'DO' => __( 'Dominican Republic', 'google-analytics-for-wordpress' ),
544 'TP' => __( 'East Timor', 'google-analytics-for-wordpress' ),
545 'EC' => __( 'Ecuador', 'google-analytics-for-wordpress' ),
546 'EG' => __( 'Egypt', 'google-analytics-for-wordpress' ),
547 'GQ' => __( 'Equatorial Guinea', 'google-analytics-for-wordpress' ),
548 'SV' => __( 'El Salvador', 'google-analytics-for-wordpress' ),
549 'ER' => __( 'Eritrea', 'google-analytics-for-wordpress' ),
550 'EE' => __( 'Estonia', 'google-analytics-for-wordpress' ),
551 'ET' => __( 'Ethiopia', 'google-analytics-for-wordpress' ),
552 'FK' => __( 'Falkland Islands', 'google-analytics-for-wordpress' ),
553 'FO' => __( 'Faroe Islands', 'google-analytics-for-wordpress' ),
554 'FJ' => __( 'Fiji', 'google-analytics-for-wordpress' ),
555 'FI' => __( 'Finland', 'google-analytics-for-wordpress' ),
556 'FR' => __( 'France', 'google-analytics-for-wordpress' ),
557 'GF' => __( 'French Guiana', 'google-analytics-for-wordpress' ),
558 'PF' => __( 'French Polynesia', 'google-analytics-for-wordpress' ),
559 'TF' => __( 'French Southern Territories', 'google-analytics-for-wordpress' ),
560 'GA' => __( 'Gabon', 'google-analytics-for-wordpress' ),
561 'GM' => __( 'Gambia', 'google-analytics-for-wordpress' ),
562 'GE' => __( 'Georgia', 'google-analytics-for-wordpress' ),
563 'DE' => __( 'Germany', 'google-analytics-for-wordpress' ),
564 'GR' => __( 'Greece', 'google-analytics-for-wordpress' ),
565 'GH' => __( 'Ghana', 'google-analytics-for-wordpress' ),
566 'GI' => __( 'Gibraltar', 'google-analytics-for-wordpress' ),
567 'GL' => __( 'Greenland', 'google-analytics-for-wordpress' ),
568 'GD' => __( 'Grenada', 'google-analytics-for-wordpress' ),
569 'GP' => __( 'Guadeloupe', 'google-analytics-for-wordpress' ),
570 'GU' => __( 'Guam', 'google-analytics-for-wordpress' ),
571 'GT' => __( 'Guatemala', 'google-analytics-for-wordpress' ),
572 'GG' => __( 'Guernsey', 'google-analytics-for-wordpress' ),
573 'GN' => __( 'Guinea', 'google-analytics-for-wordpress' ),
574 'GW' => __( 'Guinea-Bissau', 'google-analytics-for-wordpress' ),
575 'GY' => __( 'Guyana', 'google-analytics-for-wordpress' ),
576 'HT' => __( 'Haiti', 'google-analytics-for-wordpress' ),
577 'HM' => __( 'Heard and McDonald Islands', 'google-analytics-for-wordpress' ),
578 'VA' => __( 'Holy See (City Vatican State)', 'google-analytics-for-wordpress' ),
579 'HN' => __( 'Honduras', 'google-analytics-for-wordpress' ),
580 'HK' => __( 'Hong Kong', 'google-analytics-for-wordpress' ),
581 'HU' => __( 'Hungary', 'google-analytics-for-wordpress' ),
582 'IS' => __( 'Iceland', 'google-analytics-for-wordpress' ),
583 'IN' => __( 'India', 'google-analytics-for-wordpress' ),
584 'ID' => __( 'Indonesia', 'google-analytics-for-wordpress' ),
585 'IR' => __( 'Iran', 'google-analytics-for-wordpress' ),
586 'IQ' => __( 'Iraq', 'google-analytics-for-wordpress' ),
587 'IE' => __( 'Ireland', 'google-analytics-for-wordpress' ),
588 'IM' => __( 'Isle of Man', 'google-analytics-for-wordpress' ),
589 'IL' => __( 'Israel', 'google-analytics-for-wordpress' ),
590 'IT' => __( 'Italy', 'google-analytics-for-wordpress' ),
591 'JM' => __( 'Jamaica', 'google-analytics-for-wordpress' ),
592 'JP' => __( 'Japan', 'google-analytics-for-wordpress' ),
593 'JE' => __( 'Jersey', 'google-analytics-for-wordpress' ),
594 'JO' => __( 'Jordan', 'google-analytics-for-wordpress' ),
595 'KZ' => __( 'Kazakhstan', 'google-analytics-for-wordpress' ),
596 'KE' => __( 'Kenya', 'google-analytics-for-wordpress' ),
597 'KI' => __( 'Kiribati', 'google-analytics-for-wordpress' ),
598 'KW' => __( 'Kuwait', 'google-analytics-for-wordpress' ),
599 'KG' => __( 'Kyrgyzstan', 'google-analytics-for-wordpress' ),
600 'LA' => __( 'Lao People\'s Democratic Republic', 'google-analytics-for-wordpress' ),
601 'LV' => __( 'Latvia', 'google-analytics-for-wordpress' ),
602 'LB' => __( 'Lebanon', 'google-analytics-for-wordpress' ),
603 'LS' => __( 'Lesotho', 'google-analytics-for-wordpress' ),
604 'LR' => __( 'Liberia', 'google-analytics-for-wordpress' ),
605 'LY' => __( 'Libyan Arab Jamahiriya', 'google-analytics-for-wordpress' ),
606 'LI' => __( 'Liechtenstein', 'google-analytics-for-wordpress' ),
607 'LT' => __( 'Lithuania', 'google-analytics-for-wordpress' ),
608 'LU' => __( 'Luxembourg', 'google-analytics-for-wordpress' ),
609 'MO' => __( 'Macau', 'google-analytics-for-wordpress' ),
610 'MK' => __( 'Macedonia (FYROM)', 'google-analytics-for-wordpress' ),
611 'MG' => __( 'Madagascar', 'google-analytics-for-wordpress' ),
612 'MW' => __( 'Malawi', 'google-analytics-for-wordpress' ),
613 'MY' => __( 'Malaysia', 'google-analytics-for-wordpress' ),
614 'MV' => __( 'Maldives', 'google-analytics-for-wordpress' ),
615 'ML' => __( 'Mali', 'google-analytics-for-wordpress' ),
616 'MT' => __( 'Malta', 'google-analytics-for-wordpress' ),
617 'MH' => __( 'Marshall Islands', 'google-analytics-for-wordpress' ),
618 'MQ' => __( 'Martinique', 'google-analytics-for-wordpress' ),
619 'MR' => __( 'Mauritania', 'google-analytics-for-wordpress' ),
620 'MU' => __( 'Mauritius', 'google-analytics-for-wordpress' ),
621 'YT' => __( 'Mayotte', 'google-analytics-for-wordpress' ),
622 'MX' => __( 'Mexico', 'google-analytics-for-wordpress' ),
623 'FM' => __( 'Micronesia', 'google-analytics-for-wordpress' ),
624 'MD' => __( 'Moldova, Republic of', 'google-analytics-for-wordpress' ),
625 'MC' => __( 'Monaco', 'google-analytics-for-wordpress' ),
626 'MN' => __( 'Mongolia', 'google-analytics-for-wordpress' ),
627 'ME' => __( 'Montenegro', 'google-analytics-for-wordpress' ),
628 'MS' => __( 'Montserrat', 'google-analytics-for-wordpress' ),
629 'MA' => __( 'Morocco', 'google-analytics-for-wordpress' ),
630 'MZ' => __( 'Mozambique', 'google-analytics-for-wordpress' ),
631 'MM' => __( 'Myanmar', 'google-analytics-for-wordpress' ),
632 'NA' => __( 'Namibia', 'google-analytics-for-wordpress' ),
633 'NR' => __( 'Nauru', 'google-analytics-for-wordpress' ),
634 'NP' => __( 'Nepal', 'google-analytics-for-wordpress' ),
635 'NL' => __( 'Netherlands', 'google-analytics-for-wordpress' ),
636 'AN' => __( 'Netherlands Antilles', 'google-analytics-for-wordpress' ),
637 'NC' => __( 'New Caledonia', 'google-analytics-for-wordpress' ),
638 'NZ' => __( 'New Zealand', 'google-analytics-for-wordpress' ),
639 'NI' => __( 'Nicaragua', 'google-analytics-for-wordpress' ),
640 'NE' => __( 'Niger', 'google-analytics-for-wordpress' ),
641 'NG' => __( 'Nigeria', 'google-analytics-for-wordpress' ),
642 'NU' => __( 'Niue', 'google-analytics-for-wordpress' ),
643 'NF' => __( 'Norfolk Island', 'google-analytics-for-wordpress' ),
644 'KP' => __( 'North Korea', 'google-analytics-for-wordpress' ),
645 'MP' => __( 'Northern Mariana Islands', 'google-analytics-for-wordpress' ),
646 'NO' => __( 'Norway', 'google-analytics-for-wordpress' ),
647 'OM' => __( 'Oman', 'google-analytics-for-wordpress' ),
648 'PK' => __( 'Pakistan', 'google-analytics-for-wordpress' ),
649 'PW' => __( 'Palau', 'google-analytics-for-wordpress' ),
650 'PS' => __( 'Palestinian Territories', 'google-analytics-for-wordpress' ),
651 'PA' => __( 'Panama', 'google-analytics-for-wordpress' ),
652 'PG' => __( 'Papua New Guinea', 'google-analytics-for-wordpress' ),
653 'PY' => __( 'Paraguay', 'google-analytics-for-wordpress' ),
654 'PE' => __( 'Peru', 'google-analytics-for-wordpress' ),
655 'PH' => __( 'Philippines', 'google-analytics-for-wordpress' ),
656 'PN' => __( 'Pitcairn Island', 'google-analytics-for-wordpress' ),
657 'PL' => __( 'Poland', 'google-analytics-for-wordpress' ),
658 'PT' => __( 'Portugal', 'google-analytics-for-wordpress' ),
659 'PR' => __( 'Puerto Rico', 'google-analytics-for-wordpress' ),
660 'QA' => __( 'Qatar', 'google-analytics-for-wordpress' ),
661 'XK' => __( 'Republic of Kosovo', 'google-analytics-for-wordpress' ),
662 'RE' => __( 'Reunion Island', 'google-analytics-for-wordpress' ),
663 'RO' => __( 'Romania', 'google-analytics-for-wordpress' ),
664 'RU' => __( 'Russian Federation', 'google-analytics-for-wordpress' ),
665 'RW' => __( 'Rwanda', 'google-analytics-for-wordpress' ),
666 'BL' => __( 'Saint Barth&eacute;lemy', 'google-analytics-for-wordpress' ),
667 'SH' => __( 'Saint Helena', 'google-analytics-for-wordpress' ),
668 'KN' => __( 'Saint Kitts and Nevis', 'google-analytics-for-wordpress' ),
669 'LC' => __( 'Saint Lucia', 'google-analytics-for-wordpress' ),
670 'MF' => __( 'Saint Martin (French)', 'google-analytics-for-wordpress' ),
671 'SX' => __( 'Saint Martin (Dutch)', 'google-analytics-for-wordpress' ),
672 'PM' => __( 'Saint Pierre and Miquelon', 'google-analytics-for-wordpress' ),
673 'VC' => __( 'Saint Vincent and the Grenadines', 'google-analytics-for-wordpress' ),
674 'SM' => __( 'San Marino', 'google-analytics-for-wordpress' ),
675 'ST' => __( 'S&atilde;o Tom&eacute; and Pr&iacute;ncipe', 'google-analytics-for-wordpress' ),
676 'SA' => __( 'Saudi Arabia', 'google-analytics-for-wordpress' ),
677 'SN' => __( 'Senegal', 'google-analytics-for-wordpress' ),
678 'RS' => __( 'Serbia', 'google-analytics-for-wordpress' ),
679 'SC' => __( 'Seychelles', 'google-analytics-for-wordpress' ),
680 'SL' => __( 'Sierra Leone', 'google-analytics-for-wordpress' ),
681 'SG' => __( 'Singapore', 'google-analytics-for-wordpress' ),
682 'SK' => __( 'Slovak Republic', 'google-analytics-for-wordpress' ),
683 'SI' => __( 'Slovenia', 'google-analytics-for-wordpress' ),
684 'SB' => __( 'Solomon Islands', 'google-analytics-for-wordpress' ),
685 'SO' => __( 'Somalia', 'google-analytics-for-wordpress' ),
686 'ZA' => __( 'South Africa', 'google-analytics-for-wordpress' ),
687 'GS' => __( 'South Georgia', 'google-analytics-for-wordpress' ),
688 'KR' => __( 'South Korea', 'google-analytics-for-wordpress' ),
689 'SS' => __( 'South Sudan', 'google-analytics-for-wordpress' ),
690 'ES' => __( 'Spain', 'google-analytics-for-wordpress' ),
691 'LK' => __( 'Sri Lanka', 'google-analytics-for-wordpress' ),
692 'SD' => __( 'Sudan', 'google-analytics-for-wordpress' ),
693 'SR' => __( 'Suriname', 'google-analytics-for-wordpress' ),
694 'SJ' => __( 'Svalbard and Jan Mayen Islands', 'google-analytics-for-wordpress' ),
695 'SZ' => __( 'Swaziland', 'google-analytics-for-wordpress' ),
696 'SE' => __( 'Sweden', 'google-analytics-for-wordpress' ),
697 'CH' => __( 'Switzerland', 'google-analytics-for-wordpress' ),
698 'SY' => __( 'Syrian Arab Republic', 'google-analytics-for-wordpress' ),
699 'TW' => __( 'Taiwan', 'google-analytics-for-wordpress' ),
700 'TJ' => __( 'Tajikistan', 'google-analytics-for-wordpress' ),
701 'TZ' => __( 'Tanzania', 'google-analytics-for-wordpress' ),
702 'TH' => __( 'Thailand', 'google-analytics-for-wordpress' ),
703 'TL' => __( 'Timor-Leste', 'google-analytics-for-wordpress' ),
704 'TG' => __( 'Togo', 'google-analytics-for-wordpress' ),
705 'TK' => __( 'Tokelau', 'google-analytics-for-wordpress' ),
706 'TO' => __( 'Tonga', 'google-analytics-for-wordpress' ),
707 'TT' => __( 'Trinidad and Tobago', 'google-analytics-for-wordpress' ),
708 'TN' => __( 'Tunisia', 'google-analytics-for-wordpress' ),
709 'TR' => __( 'Turkey', 'google-analytics-for-wordpress' ),
710 'TM' => __( 'Turkmenistan', 'google-analytics-for-wordpress' ),
711 'TC' => __( 'Turks and Caicos Islands', 'google-analytics-for-wordpress' ),
712 'TV' => __( 'Tuvalu', 'google-analytics-for-wordpress' ),
713 'UG' => __( 'Uganda', 'google-analytics-for-wordpress' ),
714 'UA' => __( 'Ukraine', 'google-analytics-for-wordpress' ),
715 'AE' => __( 'United Arab Emirates', 'google-analytics-for-wordpress' ),
716 'UY' => __( 'Uruguay', 'google-analytics-for-wordpress' ),
717 'UM' => __( 'US Minor Outlying Islands', 'google-analytics-for-wordpress' ),
718 'UZ' => __( 'Uzbekistan', 'google-analytics-for-wordpress' ),
719 'VU' => __( 'Vanuatu', 'google-analytics-for-wordpress' ),
720 'VE' => __( 'Venezuela', 'google-analytics-for-wordpress' ),
721 'VN' => __( 'Vietnam', 'google-analytics-for-wordpress' ),
722 'VG' => __( 'Virgin Islands (British)', 'google-analytics-for-wordpress' ),
723 'VI' => __( 'Virgin Islands (USA)', 'google-analytics-for-wordpress' ),
724 'WF' => __( 'Wallis and Futuna Islands', 'google-analytics-for-wordpress' ),
725 'EH' => __( 'Western Sahara', 'google-analytics-for-wordpress' ),
726 'WS' => __( 'Western Samoa', 'google-analytics-for-wordpress' ),
727 'YE' => __( 'Yemen', 'google-analytics-for-wordpress' ),
728 'ZM' => __( 'Zambia', 'google-analytics-for-wordpress' ),
729 'ZW' => __( 'Zimbabwe', 'google-analytics-for-wordpress' ),
730 'ZZ' => __( 'Unknown Country', 'google-analytics-for-wordpress' ),
731 );
732 } else {
733 $countries = array(
734 '' => '',
735 'US' => 'United States',
736 'CA' => 'Canada',
737 'GB' => 'United Kingdom',
738 'AF' => 'Afghanistan',
739 'AX' => '&#197;land Islands',
740 'AL' => 'Albania',
741 'DZ' => 'Algeria',
742 'AS' => 'American Samoa',
743 'AD' => 'Andorra',
744 'AO' => 'Angola',
745 'AI' => 'Anguilla',
746 'AQ' => 'Antarctica',
747 'AG' => 'Antigua and Barbuda',
748 'AR' => 'Argentina',
749 'AM' => 'Armenia',
750 'AW' => 'Aruba',
751 'AU' => 'Australia',
752 'AT' => 'Austria',
753 'AZ' => 'Azerbaijan',
754 'BS' => 'Bahamas',
755 'BH' => 'Bahrain',
756 'BD' => 'Bangladesh',
757 'BB' => 'Barbados',
758 'BY' => 'Belarus',
759 'BE' => 'Belgium',
760 'BZ' => 'Belize',
761 'BJ' => 'Benin',
762 'BM' => 'Bermuda',
763 'BT' => 'Bhutan',
764 'BO' => 'Bolivia',
765 'BQ' => 'Bonaire, Saint Eustatius and Saba',
766 'BA' => 'Bosnia and Herzegovina',
767 'BW' => 'Botswana',
768 'BV' => 'Bouvet Island',
769 'BR' => 'Brazil',
770 'IO' => 'British Indian Ocean Territory',
771 'BN' => 'Brunei Darrussalam',
772 'BG' => 'Bulgaria',
773 'BF' => 'Burkina Faso',
774 'BI' => 'Burundi',
775 'KH' => 'Cambodia',
776 'CM' => 'Cameroon',
777 'CV' => 'Cape Verde',
778 'KY' => 'Cayman Islands',
779 'CF' => 'Central African Republic',
780 'TD' => 'Chad',
781 'CL' => 'Chile',
782 'CN' => 'China',
783 'CX' => 'Christmas Island',
784 'CC' => 'Cocos Islands',
785 'CO' => 'Colombia',
786 'KM' => 'Comoros',
787 'CD' => 'Congo, Democratic People\'s Republic',
788 'CG' => 'Congo, Republic of',
789 'CK' => 'Cook Islands',
790 'CR' => 'Costa Rica',
791 'CI' => 'Cote d\'Ivoire',
792 'HR' => 'Croatia/Hrvatska',
793 'CU' => 'Cuba',
794 'CW' => 'Cura&Ccedil;ao',
795 'CY' => 'Cyprus',
796 'CZ' => 'Czechia',
797 'DK' => 'Denmark',
798 'DJ' => 'Djibouti',
799 'DM' => 'Dominica',
800 'DO' => 'Dominican Republic',
801 'TP' => 'East Timor',
802 'EC' => 'Ecuador',
803 'EG' => 'Egypt',
804 'GQ' => 'Equatorial Guinea',
805 'SV' => 'El Salvador',
806 'ER' => 'Eritrea',
807 'EE' => 'Estonia',
808 'ET' => 'Ethiopia',
809 'FK' => 'Falkland Islands',
810 'FO' => 'Faroe Islands',
811 'FJ' => 'Fiji',
812 'FI' => 'Finland',
813 'FR' => 'France',
814 'GF' => 'French Guiana',
815 'PF' => 'French Polynesia',
816 'TF' => 'French Southern Territories',
817 'GA' => 'Gabon',
818 'GM' => 'Gambia',
819 'GE' => 'Georgia',
820 'DE' => 'Germany',
821 'GR' => 'Greece',
822 'GH' => 'Ghana',
823 'GI' => 'Gibraltar',
824 'GL' => 'Greenland',
825 'GD' => 'Grenada',
826 'GP' => 'Guadeloupe',
827 'GU' => 'Guam',
828 'GT' => 'Guatemala',
829 'GG' => 'Guernsey',
830 'GN' => 'Guinea',
831 'GW' => 'Guinea-Bissau',
832 'GY' => 'Guyana',
833 'HT' => 'Haiti',
834 'HM' => 'Heard and McDonald Islands',
835 'VA' => 'Holy See (City Vatican State)',
836 'HN' => 'Honduras',
837 'HK' => 'Hong Kong',
838 'HU' => 'Hungary',
839 'IS' => 'Iceland',
840 'IN' => 'India',
841 'ID' => 'Indonesia',
842 'IR' => 'Iran',
843 'IQ' => 'Iraq',
844 'IE' => 'Ireland',
845 'IM' => 'Isle of Man',
846 'IL' => 'Israel',
847 'IT' => 'Italy',
848 'JM' => 'Jamaica',
849 'JP' => 'Japan',
850 'JE' => 'Jersey',
851 'JO' => 'Jordan',
852 'KZ' => 'Kazakhstan',
853 'KE' => 'Kenya',
854 'KI' => 'Kiribati',
855 'KW' => 'Kuwait',
856 'KG' => 'Kyrgyzstan',
857 'LA' => 'Lao People\'s Democratic Republic',
858 'LV' => 'Latvia',
859 'LB' => 'Lebanon',
860 'LS' => 'Lesotho',
861 'LR' => 'Liberia',
862 'LY' => 'Libyan Arab Jamahiriya',
863 'LI' => 'Liechtenstein',
864 'LT' => 'Lithuania',
865 'LU' => 'Luxembourg',
866 'MO' => 'Macau',
867 'MK' => 'Macedonia',
868 'MG' => 'Madagascar',
869 'MW' => 'Malawi',
870 'MY' => 'Malaysia',
871 'MV' => 'Maldives',
872 'ML' => 'Mali',
873 'MT' => 'Malta',
874 'MH' => 'Marshall Islands',
875 'MQ' => 'Martinique',
876 'MR' => 'Mauritania',
877 'MU' => 'Mauritius',
878 'YT' => 'Mayotte',
879 'MX' => 'Mexico',
880 'FM' => 'Micronesia',
881 'MD' => 'Moldova, Republic of',
882 'MC' => 'Monaco',
883 'MN' => 'Mongolia',
884 'ME' => 'Montenegro',
885 'MS' => 'Montserrat',
886 'MA' => 'Morocco',
887 'MZ' => 'Mozambique',
888 'MM' => 'Myanmar (Burma)',
889 'NA' => 'Namibia',
890 'NR' => 'Nauru',
891 'NP' => 'Nepal',
892 'NL' => 'Netherlands',
893 'AN' => 'Netherlands Antilles',
894 'NC' => 'New Caledonia',
895 'NZ' => 'New Zealand',
896 'NI' => 'Nicaragua',
897 'NE' => 'Niger',
898 'NG' => 'Nigeria',
899 'NU' => 'Niue',
900 'NF' => 'Norfolk Island',
901 'KP' => 'North Korea',
902 'MP' => 'Northern Mariana Islands',
903 'NO' => 'Norway',
904 'OM' => 'Oman',
905 'PK' => 'Pakistan',
906 'PW' => 'Palau',
907 'PS' => 'Palestinian Territories',
908 'PA' => 'Panama',
909 'PG' => 'Papua New Guinea',
910 'PY' => 'Paraguay',
911 'PE' => 'Peru',
912 'PH' => 'Philippines',
913 'PN' => 'Pitcairn Island',
914 'PL' => 'Poland',
915 'PT' => 'Portugal',
916 'PR' => 'Puerto Rico',
917 'QA' => 'Qatar',
918 'XK' => 'Republic of Kosovo',
919 'RE' => 'Reunion Island',
920 'RO' => 'Romania',
921 'RU' => 'Russia',
922 'RW' => 'Rwanda',
923 'BL' => 'Saint Barth&eacute;lemy',
924 'SH' => 'Saint Helena',
925 'KN' => 'Saint Kitts and Nevis',
926 'LC' => 'Saint Lucia',
927 'MF' => 'Saint Martin (French)',
928 'SX' => 'Saint Martin (Dutch)',
929 'PM' => 'Saint Pierre and Miquelon',
930 'VC' => 'Saint Vincent and the Grenadines',
931 'SM' => 'San Marino',
932 'ST' => 'S&atilde;o Tom&eacute; and Pr&iacute;ncipe',
933 'SA' => 'Saudi Arabia',
934 'SN' => 'Senegal',
935 'RS' => 'Serbia',
936 'SC' => 'Seychelles',
937 'SL' => 'Sierra Leone',
938 'SG' => 'Singapore',
939 'SK' => 'Slovak Republic',
940 'SI' => 'Slovenia',
941 'SB' => 'Solomon Islands',
942 'SO' => 'Somalia',
943 'ZA' => 'South Africa',
944 'GS' => 'South Georgia',
945 'KR' => 'South Korea',
946 'SS' => 'South Sudan',
947 'ES' => 'Spain',
948 'LK' => 'Sri Lanka',
949 'SD' => 'Sudan',
950 'SR' => 'Suriname',
951 'SJ' => 'Svalbard and Jan Mayen Islands',
952 'SZ' => 'Swaziland',
953 'SE' => 'Sweden',
954 'CH' => 'Switzerland',
955 'SY' => 'Syrian Arab Republic',
956 'TW' => 'Taiwan',
957 'TJ' => 'Tajikistan',
958 'TZ' => 'Tanzania',
959 'TH' => 'Thailand',
960 'TL' => 'Timor-Leste',
961 'TG' => 'Togo',
962 'TK' => 'Tokelau',
963 'TO' => 'Tonga',
964 'TT' => 'Trinidad and Tobago',
965 'TN' => 'Tunisia',
966 'TR' => 'Turkey',
967 'TM' => 'Turkmenistan',
968 'TC' => 'Turks and Caicos Islands',
969 'TV' => 'Tuvalu',
970 'UG' => 'Uganda',
971 'UA' => 'Ukraine',
972 'AE' => 'United Arab Emirates',
973 'UY' => 'Uruguay',
974 'UM' => 'US Minor Outlying Islands',
975 'UZ' => 'Uzbekistan',
976 'VU' => 'Vanuatu',
977 'VE' => 'Venezuela',
978 'VN' => 'Vietnam',
979 'VG' => 'Virgin Islands (British)',
980 'VI' => 'Virgin Islands (USA)',
981 'WF' => 'Wallis and Futuna Islands',
982 'EH' => 'Western Sahara',
983 'WS' => 'Western Samoa',
984 'YE' => 'Yemen',
985 'ZM' => 'Zambia',
986 'ZW' => 'Zimbabwe',
987 'ZZ' => 'Unknown Country',
988 );
989 }
990
991 return $countries;
992 }
993
994 function monsterinsights_get_api_url() {
995 return apply_filters( 'monsterinsights_get_api_url', 'api.monsterinsights.com/v2/' );
996 }
997 /**
998 * Defines the new dynamic onboarding URL.
999 *
1000 * @since 9.5.0
1001 * @return string
1002 */
1003 function monsterinsights_get_onboarding_url() {
1004 $base_url = apply_filters( 'monsterinsights_get_onboarding_url', 'https://connect.monsterinsights.com' );
1005
1006 $auth = MonsterInsights()->api_auth;
1007 $is_network = is_network_admin();
1008 $params = array(
1009 'tt' => $auth->get_tt(),
1010 'sitei' => $auth->get_sitei(),
1011 'site_url' => get_site_url(),
1012 'onboarding_key' => monsterinsights_get_onboarding_key(),
1013 'triggered_by' => get_current_user_id(),
1014 'rest_url' => rest_url( 'monsterinsights/v1' ),
1015 'return_url' => $is_network ? network_admin_url( 'admin.php?page=monsterinsights_settings' ) : admin_url( 'admin.php?page=monsterinsights_settings' ),
1016 'is_network' => $is_network ? 1 : 0,
1017 'can_install' => monsterinsights_can_install_plugins() ? 1 : 0,
1018 );
1019
1020 // Apply args filter for backwards compatibility.
1021 $request_args = apply_filters( 'monsterinsights_auth_request_body', $params );
1022 return add_query_arg( $request_args, $base_url );
1023 }
1024
1025 /**
1026 * Gets the onboarding key from the transient if it exists, otherwise generates a new one and stores it in the transient
1027 *
1028 * @since 9.5.0
1029 * @return string The onboarding key
1030 */
1031 function monsterinsights_get_onboarding_key() {
1032 $key = get_transient( 'monsterinsights_onboarding_key' );
1033 if ( empty( $key ) ) {
1034 $key = wp_generate_password( 32, false );
1035 set_transient( 'monsterinsights_onboarding_key', $key, 30 * MINUTE_IN_SECONDS );
1036 set_transient( 'monsterinsights_onboarding_user_id', get_current_user_id(), 30 * MINUTE_IN_SECONDS );
1037 }
1038 return $key;
1039 }
1040
1041 function monsterinsights_get_onboarding_user_id() {
1042 return (int) get_transient( 'monsterinsights_onboarding_user_id' );
1043 }
1044 /**
1045 * Clears the onboarding key
1046 *
1047 * @since 9.5.0
1048 */
1049 function monsterinsights_clear_onboarding_key() {
1050 delete_transient( 'monsterinsights_onboarding_key' );
1051 }
1052
1053 /**
1054 * Flag that the Vue 3 localStorage cache registry should be flushed on next page load.
1055 *
1056 * Sets a transient consumed by admin_scripts() to output an inline script
1057 * that removes the 'mi_cache_registry' localStorage key.
1058 */
1059 function monsterinsights_flag_flush_cache_registry() {
1060 set_transient( 'monsterinsights_flush_cache_registry', 1, HOUR_IN_SECONDS );
1061 }
1062
1063 function monsterinsights_get_licensing_url() {
1064 $licensing_website = apply_filters( 'monsterinsights_get_licensing_url', 'https://www.monsterinsights.com' );
1065 return $licensing_website . '/license-api';
1066 }
1067
1068 /**
1069 * Queries the remote URL via wp_remote_post and returns a json decoded response.
1070 *
1071 * @param string $action The name of the $_POST action var.
1072 * @param array $body The content to retrieve from the remote URL.
1073 * @param array $headers The headers to send to the remote URL.
1074 * @param string $return_format The format for returning content from the remote URL.
1075 *
1076 * @return string|bool Json decoded response on success, false on failure.
1077 * @since 6.0.0
1078 */
1079 function monsterinsights_perform_remote_request( $action, $body = array(), $headers = array(), $return_format = 'json' ) {
1080
1081 $key = is_network_admin() ? MonsterInsights()->license->get_network_license_key() : MonsterInsights()->license->get_site_license_key();
1082 // Build the body of the request.
1083 $query_params = wp_parse_args(
1084 $body,
1085 array(
1086 'tgm-updater-action' => $action,
1087 'tgm-updater-key' => $key,
1088 'tgm-updater-wp-version' => get_bloginfo( 'version' ),
1089 'tgm-updater-referer' => site_url(),
1090 'tgm-updater-mi-version' => MONSTERINSIGHTS_VERSION,
1091 'tgm-updater-is-pro' => monsterinsights_is_pro_version(),
1092 )
1093 );
1094 $args = [
1095 'headers' => $headers,
1096 ];
1097 // Perform the query and retrieve the response.
1098 $response = wp_remote_get( add_query_arg( $query_params, monsterinsights_get_licensing_url() ), $args );
1099 $response_code = wp_remote_retrieve_response_code( $response );
1100 $response_body = wp_remote_retrieve_body( $response );
1101
1102 // Bail out early if there are any errors.
1103 if ( 200 != $response_code || is_wp_error( $response_body ) ) {
1104 return false;
1105 }
1106
1107 // Return the json decoded content.
1108 return json_decode( $response_body );
1109 }
1110
1111 function monsterinsights_is_wp_seo_active() {
1112 $wp_seo_active = false; // @todo: improve this check. This is from old Yoast code.
1113
1114 // Makes sure is_plugin_active is available when called from front end
1115 include_once ABSPATH . 'wp-admin/includes/plugin.php';
1116 if ( is_plugin_active( 'wordpress-seo/wp-seo.php' ) || is_plugin_active( 'wordpress-seo-premium/wp-seo-premium.php' ) ) {
1117 $wp_seo_active = true;
1118 }
1119
1120 return $wp_seo_active;
1121 }
1122
1123 function monsterinsights_get_asset_version() {
1124 if ( monsterinsights_is_debug_mode() || ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ) {
1125 return time();
1126 } else {
1127 return MONSTERINSIGHTS_VERSION;
1128 }
1129 }
1130
1131 function monsterinsights_is_debug_mode() {
1132 $debug_mode = false;
1133 if ( defined( 'MONSTERINSIGHTS_DEBUG_MODE' ) && MONSTERINSIGHTS_DEBUG_MODE ) {
1134 $debug_mode = true;
1135 }
1136
1137 return apply_filters( 'monsterinsights_is_debug_mode', $debug_mode );
1138 }
1139
1140 function monsterinsights_is_network_active() {
1141 if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
1142 require_once ABSPATH . '/wp-admin/includes/plugin.php';
1143 }
1144
1145 if ( is_multisite() && is_plugin_active_for_network( plugin_basename( MONSTERINSIGHTS_PLUGIN_FILE ) ) ) {
1146 return true;
1147 } else {
1148 return false;
1149 }
1150 }
1151
1152 if ( ! function_exists( 'remove_class_filter' ) ) {
1153 /**
1154 * Remove Class Filter Without Access to Class Object
1155 *
1156 * In order to use the core WordPress remove_filter() on a filter added with the callback
1157 * to a class, you either have to have access to that class object, or it has to be a call
1158 * to a static method. This method allows you to remove filters with a callback to a class
1159 * you don't have access to.
1160 *
1161 * Works with WordPress 1.2 - 4.7+
1162 *
1163 * @param string $tag Filter to remove
1164 * @param string $class_name Class name for the filter's callback
1165 * @param string $method_name Method name for the filter's callback
1166 * @param int $priority Priority of the filter (default 10)
1167 *
1168 * @return bool Whether the function is removed.
1169 */
1170 function remove_class_filter( $tag, $class_name = '', $method_name = '', $priority = 10 ) {
1171 global $wp_filter;
1172 // Check that filter actually exists first
1173 if ( ! isset( $wp_filter[ $tag ] ) ) {
1174 return false;
1175 }
1176 /**
1177 * If filter config is an object, means we're using WordPress 4.7+ and the config is no longer
1178 * a simple array, rather it is an object that implements the ArrayAccess interface.
1179 *
1180 * To be backwards compatible, we set $callbacks equal to the correct array as a reference (so $wp_filter is updated)
1181 *
1182 * @see https://make.wordpress.org/core/2016/09/08/wp_hook-next-generation-actions-and-filters/
1183 */
1184 if ( is_object( $wp_filter[ $tag ] ) && isset( $wp_filter[ $tag ]->callbacks ) ) {
1185 $callbacks = &$wp_filter[ $tag ]->callbacks;
1186 } else {
1187 $callbacks = &$wp_filter[ $tag ];
1188 }
1189 // Exit if there aren't any callbacks for specified priority
1190 if ( ! isset( $callbacks[ $priority ] ) || empty( $callbacks[ $priority ] ) ) {
1191 return false;
1192 }
1193 // Loop through each filter for the specified priority, looking for our class & method
1194 foreach ( (array) $callbacks[ $priority ] as $filter_id => $filter ) {
1195 // Filter should always be an array - array( $this, 'method' ), if not goto next
1196 if ( ! isset( $filter['function'] ) || ! is_array( $filter['function'] ) ) {
1197 continue;
1198 }
1199 // If first value in array is not an object, it can't be a class
1200 if ( ! is_object( $filter['function'][0] ) ) {
1201 continue;
1202 }
1203 // Method doesn't match the one we're looking for, goto next
1204 if ( $filter['function'][1] !== $method_name ) {
1205 continue;
1206 }
1207 // Method matched, now let's check the Class
1208 if ( get_class( $filter['function'][0] ) === $class_name ) {
1209 // Now let's remove it from the array
1210 unset( $callbacks[ $priority ][ $filter_id ] );
1211 // and if it was the only filter in that priority, unset that priority
1212 if ( empty( $callbacks[ $priority ] ) ) {
1213 unset( $callbacks[ $priority ] );
1214 }
1215 // and if the only filter for that tag, set the tag to an empty array
1216 if ( empty( $callbacks ) ) {
1217 $callbacks = array();
1218 }
1219 // If using WordPress older than 4.7
1220 if ( ! is_object( $wp_filter[ $tag ] ) ) {
1221 // Remove this filter from merged_filters, which specifies if filters have been sorted
1222 unset( $GLOBALS['merged_filters'][ $tag ] );
1223 }
1224
1225 return true;
1226 }
1227 }
1228
1229 return false;
1230 }
1231 } // End function exists
1232
1233 if ( ! function_exists( 'remove_class_action' ) ) {
1234 /**
1235 * Remove Class Action Without Access to Class Object
1236 *
1237 * In order to use the core WordPress remove_action() on an action added with the callback
1238 * to a class, you either have to have access to that class object, or it has to be a call
1239 * to a static method. This method allows you to remove actions with a callback to a class
1240 * you don't have access to.
1241 *
1242 * Works with WordPress 1.2 - 4.7+
1243 *
1244 * @param string $tag Action to remove
1245 * @param string $class_name Class name for the action's callback
1246 * @param string $method_name Method name for the action's callback
1247 * @param int $priority Priority of the action (default 10)
1248 *
1249 * @return bool Whether the function is removed.
1250 */
1251 function remove_class_action( $tag, $class_name = '', $method_name = '', $priority = 10 ) {
1252 remove_class_filter( $tag, $class_name, $method_name, $priority );
1253 }
1254 } // End function exists
1255
1256 /**
1257 * Format a big number, instead of 1000000 you get 1.0M, works with billions also.
1258 *
1259 * @param int $number
1260 * @param int $precision
1261 *
1262 * @return string
1263 */
1264 function monsterinsights_round_number( $number, $precision = 2 ) {
1265
1266 if ( $number < 1000000 ) {
1267 // Anything less than a million
1268 $number = number_format_i18n( $number );
1269 } elseif ( $number < 1000000000 ) {
1270 // Anything less than a billion
1271 $number = number_format_i18n( $number / 1000000, $precision ) . 'M';
1272 } else {
1273 // At least a billion
1274 $number = number_format_i18n( $number / 1000000000, $precision ) . 'B';
1275 }
1276
1277 return $number;
1278 }
1279
1280 if ( ! function_exists( 'wp_get_jed_locale_data' ) ) {
1281 /**
1282 * Returns Jed-formatted localization data. Added for backwards-compatibility.
1283 *
1284 * @param string $domain Translation domain.
1285 *
1286 * @return array
1287 */
1288 function wp_get_jed_locale_data( $domain ) {
1289 $translations = get_translations_for_domain( $domain );
1290
1291 $locale = array(
1292 '' => array(
1293 'domain' => $domain,
1294 'lang' => is_admin() && function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale(),
1295 ),
1296 );
1297
1298 if ( ! empty( $translations->headers['Plural-Forms'] ) ) {
1299 $locale['']['plural_forms'] = $translations->headers['Plural-Forms'];
1300 }
1301
1302 foreach ( $translations->entries as $msgid => $entry ) {
1303 $locale[ $msgid ] = $entry->translations;
1304 }
1305
1306 return $locale;
1307 }
1308 }
1309
1310 /**
1311 * Get JED array of translatable text.
1312 *
1313 * @param $domain string Text domain.
1314 *
1315 * @return array
1316 */
1317 function monsterinsights_get_jed_locale_data( $domain ) {
1318 $translations = get_translations_for_domain( $domain );
1319
1320 $translations_entries = $translations->entries;
1321
1322 if ( empty( $translations_entries ) ) {
1323 return;
1324 }
1325
1326 $messages = array(
1327 '' => array(
1328 'domain' => 'messages',
1329 'lang' => is_admin() && function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale(),
1330 'plural-forms' => 'nplurals=2; plural=(n != 1);',
1331 )
1332 );
1333
1334 foreach ( $translations_entries as $entry ) {
1335 $messages[ $entry->singular ] = $entry->translations;
1336 }
1337
1338 return array(
1339 'domain' => 'messages',
1340 'locale_data' => array(
1341 'messages' => $messages,
1342 ),
1343 );
1344 }
1345
1346 /**
1347 * Get JED array of translatable text.
1348 *
1349 * @param $domain string Text domain.
1350 *
1351 * @return string
1352 */
1353 function monsterinsights_get_printable_translations( $domain ) {
1354 // Validate domain parameter
1355 if ( empty( $domain ) || ! is_string( $domain ) ) {
1356 return '';
1357 }
1358
1359 // Get locale with backward compatibility
1360 if ( function_exists( 'determine_locale' ) ) {
1361 $locale = determine_locale();
1362 } else {
1363 $locale = is_admin() && function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale();
1364 }
1365
1366 if ( 'en_US' == $locale ) {
1367 return '';
1368 }
1369
1370 $locale_data = monsterinsights_get_jed_locale_data( $domain );
1371
1372 if ( ! $locale_data ) {
1373 return '';
1374 }
1375
1376
1377 // Encode with proper handling for Spanish characters
1378 $json_translations = wp_json_encode( $locale_data, JSON_UNESCAPED_UNICODE );
1379
1380 // Fallback if wp_json_encode fails
1381 if ( false === $json_translations ) {
1382 return '';
1383 }
1384
1385 // Verify JSON is valid before outputting
1386 if ( json_last_error() !== JSON_ERROR_NONE ) {
1387 return '';
1388 }
1389
1390 // Check if JSON is too large (> 100KB to prevent browser issues)
1391 if ( strlen( $json_translations ) > 102400 ) {
1392 // If still too large, return empty to prevent page breaking
1393 return '';
1394 }
1395
1396 // Use WordPress recommended approach for inline scripts
1397 $script = sprintf(
1398 '( function( domain, translations ) {
1399 try {
1400 if ( typeof wp !== "undefined" && wp.i18n && typeof wp.i18n.setLocaleData === "function" ) {
1401 var localeData = translations.locale_data[ domain ] || translations.locale_data.messages;
1402 if ( localeData && localeData[""] ) {
1403 localeData[""].domain = domain;
1404 wp.i18n.setLocaleData( localeData, domain );
1405 }
1406 }
1407 } catch( e ) {
1408 if ( window.console && console.warn ) {
1409 console.warn( "MonsterInsights: Error setting locale data for domain " + domain, e );
1410 }
1411 }
1412 } )( %s, %s );',
1413 wp_json_encode( $domain ),
1414 $json_translations
1415 );
1416
1417 return "\n<script type=\"text/javascript\">\n" . $script . "\n</script>\n";
1418 }
1419 function monsterinsights_get_inline_menu_icon() {
1420 $scheme = get_user_option( 'admin_color', get_current_user_id() );
1421 $use_dark_scheme = $scheme === 'light';
1422 if ( $use_dark_scheme ) {
1423 return 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJub256ZXJvIj48cGF0aCBkPSJNOC4zNyA3LjE5OWMuMDI4LS4wMS4wNTQtLjAyLjA4My0uMDI5YTEuNDcgMS40NyAwIDAgMSAuMTExLS4wMzJjLjAzLS4wMDYuMDU1LS4wMTMuMDg0LS4wMTYuMDg2LS4wMTYuMTcyLS4wMjUuMjU5LS4wMzIuMDI4IDAgLjA1Ny0uMDAzLjA5LS4wMDNsLjAwMi4wMDNoLjAwNGMuMDMyIDAgLjA2NCAwIC4wOTYuMDAzLjAxNiAwIC4wMzUuMDA0LjA1LjAwNGwuMDQyLjAwMy4wNjcuMDEuMDIzLjAwM2MuMDI1LjAwMy4wNTEuMDEuMDc3LjAxMmwuMDEyLjAwNGMuMDMuMDA2LjA1NS4wMTIuMDguMDE5aC4wMWMuMDI2LjAwNi4wNTQuMDE2LjA4LjAyMmguMDA2YS43NzIuNzcyIDAgMCAxIC4wOC4wMjZsLjAwNy4wMDMuMDc2LjAzMi4wMDcuMDAzLjAyOS4wMTMuMDA2LjAwM2MuMjUuMTEyLjQ3LjI3OC42NS40OS4xNjUtLjI2LjM2Ny0uNDkuNi0uNjkxYTMuMjg0IDMuMjg0IDAgMCAwLTIuMDQzLTEuODM2Yy0uMDM1LS4wMS0uMDc0LS4wMjMtLjExMi0uMDMybC0uMDMyLS4wMWEzLjk0MyAzLjk0MyAwIDAgMC0uMzg3LS4wNzcgMS43NjIgMS43NjIgMCAwIDAtLjE4Mi0uMDE5IDEuNjI4IDEuNjI4IDAgMCAwLS4xMjUtLjAwNmMtLjA0MiAwLS4wODMtLjAwMy0uMTI4LS4wMDMtLjExNSAwLS4yMy4wMDYtLjM0Mi4wMTlsLS4wODcuMDEtLjA2NC4wMWMtLjA2My4wMDktLjEyNC4wMTgtLjE4OC4wMzRoLS4wMDNjLS4wMjMuMDA0LS4wNDIuMDEtLjA2NC4wMTNhLjUyNS41MjUgMCAwIDAtLjAzNi4wMWMtLjAwNiAwLS4wMTIuMDAzLS4wMTYuMDAzbC0uMDEuMDAzLS4wNTcuMDE2aC0uMDAzbC0uMDE2LjAwMy0uMDI5LjAxLS4wNi4wMTZoLS4wMDRhMy4yODYgMy4yODYgMCAwIDAtMi4xOTcgMi4zMDljMCAuMDAzIDAgLjAwMy0uMDAzLjAwNi0uMDA2LjAyNi0uMDEzLjA1MS0uMDE2LjA3N2EzLjI4IDMuMjggMCAwIDAgMi43MTggMy45ODJjLjAzMi4wMDMuMDYxLjAxLjA5My4wMTJsLjA5My4wMWMuMDk2LjAwNi4xOTIuMDEzLjI4OC4wMTNoLjAwM2MuMDUxIDAgLjEwNiAwIC4xNTctLjAwMy4wNS0uMDA0LjEwMi0uMDA3LjE1My0uMDEzYTQuNjMgNC42MyAwIDAgMCAuMzA0LS4wNDJjLjExMi0uMDIyLjIyNC0uMDQ4LjMzMy0uMDhsLjA4Ni0uMDI4YTMuMzM1IDMuMzM1IDAgMCAwIDEuMTYtLjY3NSAyLjkyNiAyLjkyNiAwIDAgMS0uMTI3LS4zM2gtLjAwM2ExLjgyIDEuODIgMCAwIDEtLjk4NS4zMzNoLS4wNzdjLS4wNDUgMC0uMDg2IDAtLjEyOC0uMDAzLS4wMjItLjAwMy0uMDQyLS4wMDMtLjA2LS4wMDdhMS44NTMgMS44NTMgMCAwIDEtMS40MjctLjk0NmgtLjAwM2ExLjg0NCAxLjg0NCAwIDAgMS0uMjMtLjg5M2MwLS4wMzIgMC0uMDY0LjAwMy0uMDk2YS43NDQuNzQ0IDAgMCAwIC42NTYuMjE3Ljc1Mi43NTIgMCAwIDAgLjYyLS44NjkuNzUzLjc1MyAwIDAgMC0uNjU2LS42MjdoLS4wMDNjLjE3LS4xNS4zNjUtLjI2OC41NzYtLjM0OGwuMDI4LS4wMTNaTTIuODk0IDE0LjEyYy0uNDYtLjAzOS0uNTc5LS4yMTgtLjU5MS0uMzIzLS4wNDItLjQxLS4wODctLjgyMi0uMTI1LTEuMjM1bC0uMDQ4LS41MDItLjIwMi0yLjE1MmMtLjAxMi0uMTI1LS4wMjItLjI1LS4wMzUtLjM3NWE0LjMgNC4zIDAgMCAwLS41MzQuNTE5Yy0uNjMuNzI2LS45OTQgMS42MDgtMS4xODMgMi41NzQtLjEwNi41NS0uMTYzIDEuMTA3LS4xNzYgMS42NjZsLjAwMy4wMDNIMGMuMDIuNDQ4LjExOC44LjMxNyAxLjAxNy4yMDEtLjAxNi4zOC0uMTY2LjUxNS0uMzUxYTEuNyAxLjcgMCAwIDAgLjI4LjY5Yy40NC0uMDkyLjc4NC0uMzMyLjk0MS0uNzEuMDc3LjAwNC4xNTcuMDA0LjIzNC4wMDQuMTEyLjQwMy41MDUuNTk4LjcxLjU4OC4wOTktLjE2Ni4xOTUtLjM4NC4xOTgtLjY0NnYtLjc1MWwtLjEzOC0uMDFjLS4wNiAwLS4xMTItLjAwMy0uMTYzLS4wMDZaTS4zNzcgMTUuMTVhMS4zMzQgMS4zMzQgMCAwIDEtLjIyLS43M2guMDE5Yy4wOTYuMDYuMTk1LjExNS4yOTQuMTYzbC0uMDkzLjU2NlptLjguMzMyYTEuNzY0IDEuNzY0IDAgMCAxLS4yMy0uNzEzYy4xNDQuMDQxLjI5LjA3Ni40MzguMTAybC0uMjA4LjYxWm0xLjc0LS4xLS4xMjgtLjQ1M2MuMDkyLS4wMDcuMTg1LS4wMTYuMjc4LS4wMjZhMS4wNjEgMS4wNjEgMCAwIDEtLjE1LjQ4Wk00LjYyNCAxNC4xOTNsLS4zMjktLjAxNmMtLjIzLjM0NS0uMzkuNzItLjQ0OCAxLjAzMy4xNjcuMjA4LjM2NS4zODcuNTg5LjUzMWEuODcuODcgMCAwIDAtLjE0MS4yNTZoMy4zNjh2LTEuNzI0Yy0uMTEgMC0uMjE4IDAtLjMyMy0uMDAzYTYzLjUxOCA2My41MTggMCAwIDEtMi43MTYtLjA3N1pNMTEuMjY0IDE0LjE5M2E2OS4yMyA2OS4yMyAwIDAgMS0yLjcxMi4wOGMtLjExIDAtLjIxOCAwLS4zMjcuMDAzVjE2aDMuMzY4YS44MjYuODI2IDAgMCAwLS4xNDQtLjI1OWMuMjItLjE0Ny40Mi0uMzI2LjU4NS0uNTMtLjA1Ny0uMzE0LS4yMTctLjY4OS0uNDQ3LTEuMDM0bC0uMzIzLjAxNloiLz48cGF0aCBkPSJNMTUuODE4IDExLjM4OGMtLjA0Mi0uMDQ0LS4wOS0uMDgzLS4xMzUtLjEyNC0uMDU0LjA3Ni0uMTEyLjE1LS4xNy4yMjRhMy4xNTMgMy4xNTMgMCAwIDEtMi4yNTUgMS4xMzVoLS4wMjhhMy41MjcgMy41MjcgMCAwIDEtLjM2Ny0uMDAzbC0uMDc3LS4wMDdhMy4xODYgMy4xODYgMCAwIDEtMi40MTEtMS40OTQgMy42NjEgMy42NjEgMCAwIDEtNS45NTItMy42bC4wMDYtLjAyM2MuMDA0LS4wMjIuMDEtLjA0MS4wMTYtLjA2NHYtLjAwNmEzLjY2OCAzLjY2OCAwIDAgMSAyLjc5LTIuNjY3IDMuNjYyIDMuNjYyIDAgMCAxIDQuMDggMi4wNDcgMy4xNzcgMy4xNzcgMCAwIDEgMi40ODgtLjQ0OGMuMDctLjgyOS4xMzctMS42Ny4yMDUtMi41NTJsLTEuMTIzLS4zMWMuMTIyLS44MDMtLjAxMy0xLjIxOS0uMTc2LTEuOTQ4LS41MDguNDIyLS44MzUuNzI5LTEuNDUyIDEuMDRBNi4yNzQgNi4yNzQgMCAwIDAgMTAuNDYxLjRsLS4yNC0uNGMtLjkwOC42ODQtMS42NzkgMS4yMzQtMi4yOCAyLjE0QzcuMzQ2IDEuMjM0IDYuNTY5LjY4NCA1LjY2NCAwbC0uMjM3LjQwM2E2LjMxMyA2LjMxMyAwIDAgMC0uNzk2IDIuMTljLS42Mi0uMzEzLS45NDQtLjYxNy0xLjQ1Mi0xLjAzOS0uMTY2LjczLS4zIDEuMTQ1LS4xNzYgMS45NDhoLS4wMDZsLTEuMTIzLjMxYTM2OS40MTEgMzY5LjQxMSAwIDAgMCAuNDg2IDUuNjdjLjA2Ny43Mi4xMzEgMS40MzYuMjAyIDIuMTUzbC4wNDguNTAyLjEyNCAxLjIzMWMuMDEzLjEwNi4xMjguMjg1LjU5Mi4zMjMuMDUxLjAwMy4xMDYuMDA2LjE2My4wMDZsLjEzOC4wMWMuMjIzLjAxNi40NDcuMDI5LjY3NC4wMzhhNjkuMjMgNjkuMjMgMCAwIDAgMy4wNDEuMDk2aDEuMjEzYTYzLjM1IDYzLjM1IDAgMCAwIDIuNzEyLS4wOGMuMTA5LS4wMDYuMjE3LS4wMTIuMzI2LS4wMTZsLjgwNi0uMDQ4Yy4xMTUgMCAuMjMtLjAxLjM0Mi0uMDMyLjM0Ni42MTEuOTkyLjk5MiAxLjY5NS45OTJoLjA1MWwuMTQ3LjQzOGMuMDguMjM3Ljk2My0uMDU4Ljg4My0uMjk0bC0uMDctLjIxOGExLjExIDEuMTEgMCAwIDEtLjMwNC0uMDU3IDEuMjE0IDEuMjE0IDAgMCAxLS4zNTItLjE5MiAxLjcxNiAxLjcxNiAwIDAgMS0uMjY5LS4yNmMuMTEyLS4yMTQuMjctLjQwMi40NTgtLjU1YTEuMTUgMS4xNSAwIDAgMS0uNDQ4LS4xODVjLjAzNS4zMTQtLjAzMi42MDUtLjIwOC44MjJhMS4wNjYgMS4wNjYgMCAwIDEtLjEzNC4xMzRjLS40NjctLjA0MS0uNjU5LS40NDQtLjYzLS45MjdsLS4wMDMtLjAwM2MuMTUzLS4wNDIuMzEzLS4wNy40NzMtLjA4My4xNjYtLjAxMy4zMzYuMDA2LjQ5Ni4wNTRhMS42NyAxLjY3IDAgMCAxLS4zMzMtLjMwN2MuMTI4LS4yNDMuMzEtLjQ1LjUzNC0uNjEuMDk2LS4wNzEuMTk1LS4xMzUuMy0uMjAyLjI1LjIxNy40MTcuNDcuNDUyLjcyOWEuNzI1LjcyNSAwIDAgMS0uMDUxLjM3N2MuMTMuMTE5LjIzNi4yNjIuMzEzLjQyMmEuODM2LjgzNiAwIDAgMSAuMDc3LjM0MyAxLjkxMiAxLjkxMiAwIDAgMCAwLTIuN1pNNi40MTIgMy42NWExLjkzOSAxLjkzOSAwIDAgMSAxLjUzMi0uMzhjLjQ1Ny4wODYuODg2LjM2IDEuMTguODY2di4wMDNDNy42NjYgMy45MTQgNi4zOCA0LjI3IDUuNzEgNS4zNzZhMS44MTUgMS44MTUgMCAwIDEgLjcwNC0xLjcyN1oiLz48cGF0aCBkPSJNMTMuMzY4IDYuNjg3YTIuNzg0IDIuNzg0IDAgMCAwLTIuNjc0IDQuMjA5bC41MDItLjY5NGEuNTcyLjU3MiAwIDEgMSAxLjAwMS0uMjgybC44NDUuMzUyYy4wMTMtLjAxNi4wMjUtLjAzNS4wNDEtLjA1LjEtLjExLjI0LS4xNzQuMzg0LS4xODNoLjAwN2EuNDQuNDQgMCAwIDEgLjE0My4wMTNsLjYwMi0xLjI0NGEuNTcuNTcgMCAwIDEtLjA3LS44MDYuNTcuNTcgMCAwIDEgLjgwNS0uMDdjLjEyMi4xMDIuMTk1LjI0OS4yMDUuNDA1di4wMDRsLjUwMi4wOTZoLjAwM2EyLjc4NiAyLjc4NiAwIDAgMC0xLjg5Ni0xLjY3MyAyLjQ1IDIuNDUgMCAwIDAtLjQtLjA3N1oiLz48cGF0aCBkPSJtMTQuNDY4IDguOTI5LS42MDEgMS4yNGEuNTc3LjU3NyAwIDAgMSAuMTUuNjg1LjU3NC41NzQgMCAwIDEtLjY0OS4zMS41NzQuNTc0IDAgMCAxLS40MzItLjY0M2wtLjg0NC0uMzUxYS41NzQuNTc0IDAgMCAxLS42NzIuMTg1bC0uNTYuNzc4YTIuNzcgMi43NyAwIDAgMCAyIDEuMDljLjAxMiAwIC4wMjUuMDAzLjAzOC4wMDMuMTEyLjAwNy4yMjQuMDEuMzM2LjAwMy4wMSAwIC4wMTktLjAwMy4wMzItLjAwMy4wNTctLjAwMy4xMTUtLjAxLjE3Mi0uMDE2YTIuNzkgMi43OSAwIDAgMCAxLjc0Ni0uOTQzYy4wNjEtLjA3NC4xMjItLjE0Ny4xNzYtLjIyN2EyLjc4NyAyLjc4NyAwIDAgMCAuNDEtMi4zMDZoLS4wMDNsLS42NTYtLjEyOGEuNTguNTggMCAwIDEtLjY0My4zMjNaIi8+PC9nPjwvc3ZnPg==';
1424 // return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAFQUlEQVRYha2Yb2hXZRTHP+c3nc6pm07NF0KWWUtSo0wqzBdiZRItTKMaEZXSi0zRNAsqTBKKSFOa0B8Jigqz2lSwLMtqRURgRuCCLLNmselyZups2+/04pzbnt3de3eTDlzufc5znvN8n+ec55zzXFFV8pKITANOqmpTP3JTgIKq7sutPCJVzfUABeAb4DSwMENuKdABNObV3Wv8fwB0C6DAUX8/67sQ9Q8ANsVk5v5vgIDKWHsvcAgYCWzzCbc6kFJgh/PqgVHAb8DnWTpzA3LzHARmeXuqT/Zo0L/eeZuAV/x7fbRrwJPOu9Dbc4EDgJwNoMmurAt4Bljt7cmBjACvOl+BzTEdVzj/EWAj0O3tC84G0AIf3BRMeDz0GZcbBvzqKy+L9Q30A6AxXTdmARqQcPAAyv29CBjjO1RU1SKAiIwGFgLX+MrbgBnAh5ECVe0UkUMO6nHgFLA70J1McacD5gHbfTXzg77qwBeOBysPn830PnnVwXety7wL1AAV/ZoM+MIHdQCfAdfF+s8H/koBEz0rU9xgLtAInHG5j/KYrNWf8ap6OmFD7w+2/Cugwd/NmOkqgbIUS+wEdorIEOAwFqv6UBKgihQwANNc0b2quh1ARIZi/nUqZUycOrDDcCSps5AAaJBPkkStwNVAs4i8JiLHgBPASRFpFZEGEZktIpIBqBIoIWWH4nZegtl3fIofjAKeoyemfAe8hZnu64D/NjAsRcdEl1mcx6lvc+HLU6L3O97/JXBlgszF9KSVvXhswkxUC6wLdKzIA2iWC1+fMNlK72sASlMjrQHf4LIvAw8B7fScwmNAZ7DDs7MARSmjNsYf7oqak0wBjAXuBlb5Lo9wE0Yg6rHAOdjlR2KB9Qc384o0QOe4giUx/u3OX5oA5gEsCoexqBnYAxTTfMXHlvuOF4F5SYBKHPGaGH+jTzQxxefSnnVpYAIdg9x0PwEDkwSOAHUx3hafoDzGP5AB5gQ56h/XU+NjauJxCCxRjo7xOvw9ImKISBUwIWF8RLtVtT2jP6SdWBKe1QuQiCwDLsKcNKSoqJ8e8BJTREAHc4JBVTuBn4Gx/wISkflYndyNOXdI2/29OOAd7mfSIXkBOZUDxTACt2A78SLQnmDnBszOiwLeraT70Ld5/Mf1jPMxqyLGWqxcnYoFMqVvBTgOK9y7gOVAifMfdF4SqJk5Aa3FLFMNduxagQbvvJOUfIb51/f0lKSrsROyHCtlIyDtrrMJqOoHzAysRvrA28wmSBfAtd7uk6u8vwwr/JOqxm4sl01wvZ3AfhJyo+taAPyJhYi/gekCPIXdNitV9YyIXIIFqptVdVsf13MSkVJgJlZF4rvSqKq/BzJzgNexcPEp8LFPXAHcAFzqoKcAddjR5z2Cay/m4Arcl9cp+zFJFfA0dslMOwB1wD1AewGrTw4Ei2/zVcSP/lmRqrap6irs8gAwid7xDOAuzNwlgmXxF1T14ahXRPZjtU1k3+g5Tk8pkUUFzCwVWC003N/DgGVYIXheIF/EfmQcFczDW4DnsVtBCxbUtmIOPAAzY6MPLgMG+/dlDrIADHWlYL4QpZuZWLjYgp3SOb7QMbFFFLF6LDNB7sGcri7FP7qwWmcX9t8oSWaDA6zCqomXUuZ6U1UpYDXxH5jfgKWET/y7zXfolIgkJeJMEpES/xwMXKWq3aq6CLu9PAH8Eog/Fn2UYnlkDWa2c719E3Y/f8NX0AL8GHuianAXtuXx/lZ6brR9/npgcWgHcEfEkyg6ZqyyBrt1ptE+X9SkDJl6VX0/cyKnfwBb6gwNaZ8ExgAAAABJRU5ErkJggg';
1425 } else {
1426 return 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTciIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0iI0ZGRiIgZmlsbC1ydWxlPSJub256ZXJvIj48cGF0aCBkPSJNOC4zNyA3LjE5OWMuMDI4LS4wMS4wNTQtLjAyLjA4My0uMDI5YTEuNDcgMS40NyAwIDAgMSAuMTExLS4wMzJjLjAzLS4wMDYuMDU1LS4wMTMuMDg0LS4wMTYuMDg2LS4wMTYuMTcyLS4wMjUuMjU5LS4wMzIuMDI4IDAgLjA1Ny0uMDAzLjA5LS4wMDNsLjAwMi4wMDNoLjAwNGMuMDMyIDAgLjA2NCAwIC4wOTYuMDAzLjAxNiAwIC4wMzUuMDA0LjA1LjAwNGwuMDQyLjAwMy4wNjcuMDEuMDIzLjAwM2MuMDI1LjAwMy4wNTEuMDEuMDc3LjAxMmwuMDEyLjAwNGMuMDMuMDA2LjA1NS4wMTIuMDguMDE5aC4wMWMuMDI2LjAwNi4wNTQuMDE2LjA4LjAyMmguMDA2YS43NzIuNzcyIDAgMCAxIC4wOC4wMjZsLjAwNy4wMDMuMDc2LjAzMi4wMDcuMDAzLjAyOS4wMTMuMDA2LjAwM2MuMjUuMTEyLjQ3LjI3OC42NS40OS4xNjUtLjI2LjM2Ny0uNDkuNi0uNjkxYTMuMjg0IDMuMjg0IDAgMCAwLTIuMDQzLTEuODM2Yy0uMDM1LS4wMS0uMDc0LS4wMjMtLjExMi0uMDMybC0uMDMyLS4wMWEzLjk0MyAzLjk0MyAwIDAgMC0uMzg3LS4wNzcgMS43NjIgMS43NjIgMCAwIDAtLjE4Mi0uMDE5IDEuNjI4IDEuNjI4IDAgMCAwLS4xMjUtLjAwNmMtLjA0MiAwLS4wODMtLjAwMy0uMTI4LS4wMDMtLjExNSAwLS4yMy4wMDYtLjM0Mi4wMTlsLS4wODcuMDEtLjA2NC4wMWMtLjA2My4wMDktLjEyNC4wMTgtLjE4OC4wMzRoLS4wMDNjLS4wMjMuMDA0LS4wNDIuMDEtLjA2NC4wMTNhLjUyNS41MjUgMCAwIDAtLjAzNi4wMWMtLjAwNiAwLS4wMTIuMDAzLS4wMTYuMDAzbC0uMDEuMDAzLS4wNTcuMDE2aC0uMDAzbC0uMDE2LjAwMy0uMDI5LjAxLS4wNi4wMTZoLS4wMDRhMy4yODYgMy4yODYgMCAwIDAtMi4xOTcgMi4zMDljMCAuMDAzIDAgLjAwMy0uMDAzLjAwNi0uMDA2LjAyNi0uMDEzLjA1MS0uMDE2LjA3N2EzLjI4IDMuMjggMCAwIDAgMi43MTggMy45ODJjLjAzMi4wMDMuMDYxLjAxLjA5My4wMTJsLjA5My4wMWMuMDk2LjAwNi4xOTIuMDEzLjI4OC4wMTNoLjAwM2MuMDUxIDAgLjEwNiAwIC4xNTctLjAwMy4wNS0uMDA0LjEwMi0uMDA3LjE1My0uMDEzYTQuNjMgNC42MyAwIDAgMCAuMzA0LS4wNDJjLjExMi0uMDIyLjIyNC0uMDQ4LjMzMy0uMDhsLjA4Ni0uMDI4YTMuMzM1IDMuMzM1IDAgMCAwIDEuMTYtLjY3NSAyLjkyNiAyLjkyNiAwIDAgMS0uMTI3LS4zM2gtLjAwM2ExLjgyIDEuODIgMCAwIDEtLjk4NS4zMzNoLS4wNzdjLS4wNDUgMC0uMDg2IDAtLjEyOC0uMDAzLS4wMjItLjAwMy0uMDQxLS4wMDMtLjA2LS4wMDdhMS44NTMgMS44NTMgMCAwIDEtMS40MjctLjk0NmgtLjAwM2ExLjg0NCAxLjg0NCAwIDAgMS0uMjMtLjg5M2MwLS4wMzIgMC0uMDY0LjAwMy0uMDk2YS43NDQuNzQ0IDAgMCAwIC42NTYuMjE3Ljc1Mi43NTIgMCAwIDAgLjYyLS44NjkuNzUzLjc1MyAwIDAgMC0uNjU2LS42MjdoLS4wMDNjLjE3LS4xNS4zNjUtLjI2OC41NzYtLjM0OGwuMDI4LS4wMTNaTTIuODk0IDE0LjEyYy0uNDYtLjAzOS0uNTc5LS4yMTgtLjU5MS0uMzIzLS4wNDItLjQxLS4wODctLjgyMi0uMTI1LTEuMjM1bC0uMDQ4LS41MDItLjIwMi0yLjE1MmMtLjAxMi0uMTI1LS4wMjItLjI1LS4wMzUtLjM3NWE0LjMgNC4zIDAgMCAwLS41MzQuNTE5Yy0uNjMuNzI2LS45OTQgMS42MDgtMS4xODMgMi41NzQtLjEwNi41NS0uMTYzIDEuMTA3LS4xNzYgMS42NjZsLjAwMy4wMDNIMGMuMDIuNDQ4LjExOC44LjMxNyAxLjAxNy4yMDEtLjAxNi4zOC0uMTY2LjUxNS0uMzUxYTEuNyAxLjcgMCAwIDAgLjI4LjY5Yy40NC0uMDkyLjc4NC0uMzMyLjk0MS0uNzEuMDc3LjAwNC4xNTcuMDA0LjIzNC4wMDQuMTEyLjQwMy41MDUuNTk4LjcxLjU4OC4wOTktLjE2Ni4xOTUtLjM4NC4xOTgtLjY0NnYtLjc1MWwtLjEzOC0uMDFjLS4wNiAwLS4xMTItLjAwMy0uMTYzLS4wMDZaTS4zNzcgMTUuMTVhMS4zMzQgMS4zMzQgMCAwIDEtLjIyLS43M2guMDE5Yy4wOTYuMDYuMTk1LjExNS4yOTQuMTYzbC0uMDkzLjU2NlptLjguMzMyYTEuNzY0IDEuNzY0IDAgMCAxLS4yMy0uNzEzYy4xNDQuMDQxLjI5LjA3Ni40MzguMTAybC0uMjA4LjYxWm0xLjc0LS4xLS4xMjgtLjQ1M2MuMDkyLS4wMDcuMTg1LS4wMTYuMjc4LS4wMjZhMS4wNjEgMS4wNjEgMCAwIDEtLjE1LjQ4Wk00LjYyNCAxNC4xOTNsLS4zMjktLjAxNmMtLjIzLjM0NS0uMzkuNzItLjQ0OCAxLjAzMy4xNjcuMjA4LjM2NS4zODcuNTg5LjUzMWEuODcuODcgMCAwIDAtLjE0MS4yNTZoMy4zNjh2LTEuNzI0Yy0uMTEgMC0uMjE4IDAtLjMyMy0uMDAzYTYzLjUxOCA2My41MTggMCAwIDEtMi43MTYtLjA3N1pNMTEuMjY0IDE0LjE5M2E2OS4yMyA2OS4yMyAwIDAgMS0yLjcxMi4wOGMtLjExIDAtLjIxOCAwLS4zMjcuMDAzVjE2aDMuMzY4YS44MjYuODI2IDAgMCAwLS4xNDQtLjI1OWMuMjItLjE0Ny40Mi0uMzI2LjU4NS0uNTMtLjA1Ny0uMzE0LS4yMTctLjY4OS0uNDQ3LTEuMDM0bC0uMzIzLjAxNloiLz48cGF0aCBkPSJNMTUuODE4IDExLjM4OGMtLjA0Mi0uMDQ0LS4wOS0uMDgzLS4xMzUtLjEyNC0uMDU0LjA3Ni0uMTEyLjE1LS4xNy4yMjRhMy4xNTMgMy4xNTMgMCAwIDEtMi4yNTUgMS4xMzVoLS4wMjhhMy41MjcgMy41MjcgMCAwIDEtLjM2Ny0uMDAzbC0uMDc3LS4wMDdhMy4xODYgMy4xODYgMCAwIDEtMi40MTEtMS40OTQgMy42NjEgMy42NjEgMCAwIDEtNS45NTItMy42bC4wMDYtLjAyM2MuMDA0LS4wMjIuMDEtLjA0MS4wMTYtLjA2NHYtLjAwNmEzLjY2OCAzLjY2OCAwIDAgMSAyLjc5LTIuNjY3IDMuNjYyIDMuNjYyIDAgMCAxIDQuMDggMi4wNDcgMy4xNzcgMy4xNzcgMCAwIDEgMi40ODgtLjQ0OGMuMDctLjgyOS4xMzctMS42Ny4yMDUtMi41NTJsLTEuMTIzLS4zMWMuMTIyLS44MDMtLjAxMy0xLjIxOS0uMTc2LTEuOTQ4LS41MDguNDIyLS44MzUuNzI5LTEuNDUyIDEuMDRBNi4yNzQgNi4yNzQgMCAwIDAgMTAuNDYxLjRsLS4yNC0uNGMtLjkwOC42ODQtMS42NzkgMS4yMzQtMi4yOCAyLjE0QzcuMzQ2IDEuMjM0IDYuNTY5LjY4NCA1LjY2NCAwbC0uMjM3LjQwM2E2LjMxMyA2LjMxMyAwIDAgMC0uNzk2IDIuMTljLS42Mi0uMzEzLS45NDQtLjYxNy0xLjQ1Mi0xLjAzOS0uMTY2LjczLS4zIDEuMTQ1LS4xNzYgMS45NDhoLS4wMDZsLTEuMTIzLjMxYTM2OS40MTEgMzY5LjQxMSAwIDAgMCAuNDg2IDUuNjdjLjA2Ny43Mi4xMzEgMS40MzYuMjAyIDIuMTUzbC4wNDguNTAyLjEyNCAxLjIzMWMuMDEzLjEwNi4xMjguMjg1LjU5Mi4zMjMuMDUxLjAwMy4xMDYuMDA2LjE2My4wMDZsLjEzOC4wMWMuMjIzLjAxNi40NDcuMDI5LjY3NC4wMzhhNjkuMjMgNjkuMjMgMCAwIDAgMy4wNDEuMDk2aDEuMjEzYTYzLjM1IDYzLjM1IDAgMCAwIDIuNzEyLS4wOGMuMTA5LS4wMDYuMjE3LS4wMTIuMzI2LS4wMTZsLjgwNi0uMDQ4Yy4xMTUgMCAuMjMtLjAxLjM0Mi0uMDMyLjM0Ni42MTEuOTkyLjk5MiAxLjY5NS45OTJoLjA1MWwuMTQ3LjQzOGMuMDguMjM3Ljk2My0uMDU4Ljg4My0uMjk0bC0uMDctLjIxOGExLjExIDEuMTEgMCAwIDEtLjMwNC0uMDU3IDEuMjE0IDEuMjE0IDAgMCAxLS4zNTItLjE5MiAxLjcxNiAxLjcxNiAwIDAgMS0uMjY5LS4yNmMuMTEyLS4yMTQuMjctLjQwMi40NTgtLjU1YTEuMTUgMS4xNSAwIDAgMS0uNDQ4LS4xODVjLjAzNS4zMTQtLjAzMi42MDUtLjIwOC44MjJhMS4wNjYgMS4wNjYgMCAwIDEtLjEzNC4xMzRjLS40NjctLjA0MS0uNjU5LS40NDQtLjYzLS45MjdsLS4wMDMtLjAwM2MuMTUzLS4wNDIuMzEzLS4wNy40NzMtLjA4My4xNjYtLjAxMy4zMzYuMDA2LjQ5Ni4wNTRhMS42NyAxLjY3IDAgMCAxLS4zMzMtLjMwN2MuMTI4LS4yNDMuMzEtLjQ1LjUzNC0uNjEuMDk2LS4wNzEuMTk1LS4xMzUuMy0uMjAyLjI1LjIxNy40MTcuNDcuNDUyLjcyOWEuNzI1LjcyNSAwIDAgMS0uMDUxLjM3N2MuMTMuMTE5LjIzNi4yNjIuMzEzLjQyMmEuODM2LjgzNiAwIDAgMSAuMDc3LjM0MyAxLjkxMiAxLjkxMiAwIDAgMCAwLTIuN1pNNi40MTIgMy42NWExLjkzOSAxLjkzOSAwIDAgMSAxLjUzMi0uMzhjLjQ1Ny4wODYuODg2LjM2IDEuMTguODY2di4wMDNDNy42NjYgMy45MTQgNi4zOCA0LjI3IDUuNzEgNS4zNzZhMS44MTUgMS44MTUgMCAwIDEgLjcwNC0xLjcyN1oiLz48cGF0aCBkPSJNMTMuMzY4IDYuNjg3YTIuNzg0IDIuNzg0IDAgMCAwLTIuNjc0IDQuMjA5bC41MDItLjY5NGEuNTcyLjU3MiAwIDEgMSAxLjAwMS0uMjgybC44NDUuMzUyYy4wMTMtLjAxNi4wMjUtLjAzNS4wNDEtLjA1LjEtLjExLjI0LS4xNzQuMzg0LS4xODNoLjAwN2EuNDQuNDQgMCAwIDEgLjE0My4wMTNsLjYwMi0xLjI0NGEuNTcuNTcgMCAwIDEtLjA3LS44MDYuNTcuNTcgMCAwIDEgLjgwNS0uMDdjLjEyMi4xMDIuMTk1LjI0OS4yMDUuNDA1di4wMDRsLjUwMi4wOTZoLjAwM2EyLjc4NiAyLjc4NiAwIDAgMC0xLjg5Ni0xLjY3MyAyLjQ1IDIuNDUgMCAwIDAtLjQtLjA3N1oiLz48cGF0aCBkPSJtMTQuNDY4IDguOTI5LS42MDEgMS4yNGEuNTc3LjU3NyAwIDAgMSAuMTUuNjg1LjU3NC41NzQgMCAwIDEtLjY0OS4zMS41NzQuNTc0IDAgMCAxLS40MzItLjY0M2wtLjg0NC0uMzUxYS41NzQuNTc0IDAgMCAxLS42NzIuMTg1bC0uNTYuNzc4YTIuNzcgMi43NyAwIDAgMCAyIDEuMDljLjAxMiAwIC4wMjUuMDAzLjAzOC4wMDMuMTEyLjAwNy4yMjQuMDEuMzM2LjAwMy4wMSAwIC4wMTktLjAwMy4wMzItLjAwMy4wNTctLjAwMy4xMTUtLjAxLjE3Mi0uMDE2YTIuNzkgMi43OSAwIDAgMCAyLjMzMi0zLjQ3NmgtLjAwM2wtLjY1Ni0uMTI4YS41OC41OCAwIDAgMS0uNjQzLjMyM1oiLz48L2c+PC9zdmc+';
1427 // return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4AoEBjcfBsDvpwAABQBJREFUWMO1mGmollUQgJ9z79Vc01LLH0GLWRqlUhYV5o+LbRIVbVQSUSn9qJTKsqDCoqCINKUbtBEUFbbeDGyz1SIiaCHIINu18KZ1bbkuV+/Tj+arw8v7fvdVcuDjvGdmzsycM3Nm5nywE6BOVSfW4JukTmF3gtqifqJuVmc34ZunblFX7W6DzvYf2BDjPWpLRm9T7y/wzPw/DRhZmH+sfq/urb4YCp8JQwaqLwXuBXW0+pP6XjOZO+ueb9X2mE8OZTdl9MWBu199NL4XN05NvT1wh8R8prpGTbti0BEhbLt6t7ow5kdkPEl9zP/gkYKMowN/o7pU3RHzg3fFoHNj8epM4aY8ZoJvuPpj7HxwgTYgLoAFWac1091WgR8a4xxgH2Ah0JdS6gtlY4DZwAnADmAjMA14vSEgpdSrfg9sBm4BeoCVmex6gayepS6P3ZyT0SZksbDJcnikcPMmZN+zgud59Qx1RB2D3o9FW9R31ZMK9IPUP20O11XInqmuUrcG3xt1XNYVvwNSSptL+K/IjvxDoDPGteG6kcDgMkUppRXACnUIsA7YUNegERXGAEwNQZellJbHzodFfPXUjIwtwHDglzJiS4lBe4SSMugCjgfWqo+rvwF/AH+pXWqnOqOfXDMSaK06oaKf54Z/D6igj1bvzXLK5+rTYchHGf5ZdXiFjPHBc2Udg84P5qMqsvdzQf9APbaEZ2JWVj5u5KbIV7PURZmM+XUMag/mk0to1wWtUx3YT9lZErwPq9er3dkt/E3tzU54Rp2SMauA3zMErS1zhTpWvURdEKe8V7jQrOBOUwcF/97qbPWrcPP8KoP2DQFzC/gLAj+vZM1Vak8hF61V31L7msWKOjROvE89q4yhNSy+rYBfGorGV8RcFSyqESZ7hOu+UQeUMfyidhRwy0LB0AJ+TRNj/qjb/0QpUT2jpYS+ERhTkswA9sqEjALGNdGzMqXUXTNZrogi3F5sJ64GDgXGFhasjvGYDDe4HyXf1i3qKaVe4DtgbF6ZzwHuiZq0b2HN8hjzAF3Xj9IhO9mGDQX68gy8PpqoB9XuEj93hp/nZLjzmsTQZzvR9uwXaxY0EHdEuzo5EpklHeB+0bhvV69RWwN/beDKYHpNg+6I2z2hce261M4gXlRVz9RD1S+zlnRh3JBropVtQHfIXB3B38yYadEjvdZAzMjLhXpizI+tEDA4Gv+yrnFH1LJxIbdX/aKsNma9+++RIrapxyT1TmAeMDKltFU9HPgcODOl9GKTnQ0EpgMHBaobWJVS+jnjOQV4ItLFO8CbwDZgBHAqMAXoBSYBHcBm1JfzZ28EuOrl/9ODc5R6Vzwyq6BDvVTtbgHGA2sKiXFbydXfJUgpbUwpLQAateqwQj4DuDjSTWuKru+BlNIN2a6+ACYCv0dH2PhtCtfYjx0t4ZYR0a7uGeNw4GpgLnBgxt8HfAJsSOpWYD1wH7AqvocAz0Q2bgNGB62RoQfF95FhZAswLIQSZaBRbqYDPwHLogqcEhvdp7CJPqC9vwL5VtyUjor42B69zqvqXxU8S+IFOyq6iYcqdD3VONqngV8jbhol4e0sntqAnuIzumZAt8bnIOC4lNKOlNKceL3cCvyQsd/87/WNRuk29T51/5ifHu/zJ2MH69WvCz+zE+oroXdlL9pUkYdeUi/89xLU6VWAZn88fQoMjNtTBS+klF6pc6p/A2ye4OCYzm1lAAAAAElFTkSuQmCC';
1428 }
1429 }
1430
1431 function monsterinsights_get_ai_menu_icon() {
1432 return '
1433 <span class="monsterinsights-sidebar-icon">
1434 <svg width="17" height="18" viewBox="0 0 17 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M11.9301 1.27472C12.1523 0.259572 13.5986 0.253501 13.8305 1.26743L13.8402 1.31479L13.8621 1.4095C14.1292 2.54364 15.0472 3.40943 16.1959 3.60979C17.2548 3.79436 17.2548 5.31464 16.1959 5.49922C15.6311 5.59753 15.1078 5.86056 14.6919 6.25526C14.2761 6.64996 13.9861 7.15875 13.8584 7.71771L13.8293 7.84157C13.5986 8.8555 12.1536 8.84943 11.9301 7.83429L11.9071 7.72743C11.7845 7.16626 11.4975 6.65435 11.0826 6.25704C10.6678 5.85974 10.144 5.59505 9.57806 5.49679C8.52163 5.31343 8.52163 3.79557 9.57806 3.61221C10.142 3.51435 10.6641 3.25127 11.0783 2.85631C11.4925 2.46136 11.7801 1.95232 11.9046 1.39372L11.9216 1.31357L11.9301 1.27472ZM12.8129 9.918C12.2343 9.90674 11.6813 9.6773 11.2647 9.27564C11.1731 9.33603 11.0933 9.41256 11.0291 9.5015C10.4827 10.2252 9.84278 10.9647 9.11906 11.6872C8.57021 12.2361 8.01406 12.7351 7.4652 13.1808C6.91635 12.7351 6.3602 12.2361 5.81135 11.6872C5.28543 11.1624 4.78691 10.6107 4.31778 10.0346C4.76342 9.4845 5.2637 8.92957 5.81135 8.38071C6.49514 7.69453 7.22544 7.05633 7.99706 6.47064C8.07764 6.41292 8.1482 6.34236 8.20592 6.26179C7.97508 6.05132 7.79016 5.79548 7.66271 5.51028C7.53525 5.22508 7.46802 4.91666 7.4652 4.60429C6.27399 3.77007 5.09613 3.152 4.04456 2.83021C2.90556 2.48172 1.56985 2.38822 0.694348 3.2625C0.127276 3.83079 -0.026938 4.60307 0.0167763 5.33771C0.0604906 6.07357 0.306991 6.88229 0.679776 7.70314C1.06006 8.51991 1.51406 9.30029 2.03613 10.0346C1.51419 10.7681 1.06019 11.5476 0.679776 12.3636C0.306991 13.1844 0.0604906 13.9931 0.0167763 14.729C-0.026938 15.4636 0.126062 16.2359 0.694348 16.8042C1.26263 17.3713 2.03492 17.5255 2.76956 17.4818C3.5042 17.4369 4.31413 17.1916 5.13499 16.8188C5.87571 16.4824 6.66378 16.0234 7.46642 15.4624C8.26785 16.0234 9.0547 16.4824 9.79663 16.8188C10.6163 17.1916 11.4262 17.4381 12.1621 17.4818C12.8967 17.5255 13.6678 17.3713 14.2361 16.803C15.1116 15.9287 15.0181 14.593 14.6696 13.454C14.3368 12.3684 13.6896 11.1481 12.8129 9.918ZM3.51149 4.5715C4.21092 4.78521 5.04513 5.19079 5.94856 5.7785C4.9622 6.61536 4.046 7.53157 3.20913 8.51793C2.88027 8.01716 2.58886 7.49278 2.33728 6.94907C2.01792 6.24479 1.86128 5.66193 1.83456 5.22843C1.80906 4.7925 1.91592 4.61764 1.9827 4.55086C2.09199 4.44157 2.49513 4.26186 3.51149 4.5715ZM2.33728 13.1189C2.5607 12.6271 2.85335 12.0989 3.20913 11.55C4.0464 12.5364 4.96301 13.4526 5.94978 14.2894C5.44943 14.6186 4.92546 14.9105 4.38213 15.1625C3.67785 15.4819 3.09499 15.6385 2.66149 15.6652C2.22435 15.6907 2.0507 15.5839 1.98392 15.5171C1.91713 15.4503 1.81028 15.2742 1.83578 14.8395C1.86249 14.406 2.01792 13.8231 2.33849 13.1189H2.33728ZM10.5495 15.1625C10.0064 14.9108 9.48279 14.619 8.98306 14.2894C9.96858 13.4525 10.884 12.5363 11.7201 11.55C12.3066 12.4546 12.7121 13.2889 12.9258 13.9883C13.2367 15.0034 13.057 15.4078 12.9477 15.5171C12.8797 15.5839 12.7048 15.6907 12.2701 15.664C11.8354 15.6397 11.2538 15.4819 10.5495 15.1625ZM6.25092 10.0346C6.25092 9.71252 6.37885 9.40366 6.60658 9.17594C6.8343 8.94822 7.14316 8.82029 7.4652 8.82029C7.78725 8.82029 8.09611 8.94822 8.32383 9.17594C8.55156 9.40366 8.67949 9.71252 8.67949 10.0346C8.67949 10.3566 8.55156 10.6655 8.32383 10.8932C8.09611 11.1209 7.78725 11.2489 7.4652 11.2489C7.14316 11.2489 6.8343 11.1209 6.60658 10.8932C6.37885 10.6655 6.25092 10.3566 6.25092 10.0346Z" fill="currentColor"/></svg>
1435 </span>
1436 ';
1437 }
1438
1439
1440 function monsterinsights_get_shareasale_id() {
1441 // Check if there's a constant.
1442 $shareasale_id = '';
1443 if ( defined( 'MONSTERINSIGHTS_SHAREASALE_ID' ) ) {
1444 $shareasale_id = MONSTERINSIGHTS_SHAREASALE_ID;
1445 }
1446
1447 // If there's no constant, check if there's an option.
1448 if ( empty( $shareasale_id ) ) {
1449 $shareasale_id = get_option( 'monsterinsights_shareasale_id', '' );
1450 }
1451
1452 // Whether we have an ID or not, filter the ID.
1453 $shareasale_id = apply_filters( 'monsterinsights_shareasale_id', $shareasale_id );
1454
1455 // Ensure it's a number
1456 $shareasale_id = absint( $shareasale_id );
1457
1458 return $shareasale_id;
1459 }
1460
1461 /**
1462 * Passed in with mandatory default redirect and shareasaleid from monsterinsights_get_upgrade_link
1463 * @deprecated
1464 * @param $shareasale_id
1465 * @param $shareasale_redirect
1466 *
1467 * @return mixed|null
1468 */
1469 function monsterinsights_get_shareasale_url( $shareasale_id, $shareasale_redirect ) {
1470 // Check if there's a constant.
1471 $custom = false;
1472 if ( defined( 'MONSTERINSIGHTS_SHAREASALE_REDIRECT_URL' ) ) {
1473 $shareasale_redirect = MONSTERINSIGHTS_SHAREASALE_REDIRECT_URL;
1474 $custom = true;
1475 }
1476
1477 // If there's no constant, check if there's an option.
1478 if ( empty( $custom ) ) {
1479 $shareasale_redirect = get_option( 'monsterinsights_shareasale_redirect_url', '' );
1480 $custom = true;
1481 }
1482
1483 // Whether we have an ID or not, filter the ID.
1484 $shareasale_redirect = apply_filters( 'monsterinsights_shareasale_redirect_url', $shareasale_redirect, $custom );
1485 $shareasale_url = "https://www.monsterinsights.com/ref/590/";
1486 $shareasale_url = apply_filters( 'monsterinsights_shareasale_redirect_entire_url', $shareasale_url);
1487
1488 return $shareasale_url;
1489 }
1490
1491 /**
1492 * Get a clean page title for archives.
1493 */
1494 function monsterinsights_get_page_title() {
1495
1496 $title = __( 'Archives' );
1497
1498 if ( is_category() ) {
1499 /* translators: Category archive title. %s: Category name */
1500 $title = sprintf( __( 'Category: %s' ), single_cat_title( '', false ) );
1501 } elseif ( is_tag() ) {
1502 /* translators: Tag archive title. %s: Tag name */
1503 $title = sprintf( __( 'Tag: %s' ), single_tag_title( '', false ) );
1504 } elseif ( is_author() ) {
1505 /* translators: Author archive title. %s: Author name */
1506 $title = sprintf( __( 'Author: %s' ), '<span class="vcard">' . get_the_author() . '</span>' );
1507 } elseif ( is_year() ) {
1508 /* translators: Yearly archive title. %s: Year */
1509 $title = sprintf( __( 'Year: %s' ), get_the_date( _x( 'Y', 'yearly archives date format' ) ) );
1510 } elseif ( is_month() ) {
1511 /* translators: Monthly archive title. %s: Month name and year */
1512 $title = sprintf( __( 'Month: %s' ), get_the_date( _x( 'F Y', 'monthly archives date format' ) ) );
1513 } elseif ( is_day() ) {
1514 /* translators: Daily archive title. %s: Date */
1515 $title = sprintf( __( 'Day: %s' ), get_the_date( _x( 'F j, Y', 'daily archives date format' ) ) );
1516 } elseif ( is_tax( 'post_format' ) ) {
1517 if ( is_tax( 'post_format', 'post-format-aside' ) ) {
1518 $title = _x( 'Asides', 'post format archive title' );
1519 } elseif ( is_tax( 'post_format', 'post-format-gallery' ) ) {
1520 $title = _x( 'Galleries', 'post format archive title' );
1521 } elseif ( is_tax( 'post_format', 'post-format-image' ) ) {
1522 $title = _x( 'Images', 'post format archive title' );
1523 } elseif ( is_tax( 'post_format', 'post-format-video' ) ) {
1524 $title = _x( 'Videos', 'post format archive title' );
1525 } elseif ( is_tax( 'post_format', 'post-format-quote' ) ) {
1526 $title = _x( 'Quotes', 'post format archive title' );
1527 } elseif ( is_tax( 'post_format', 'post-format-link' ) ) {
1528 $title = _x( 'Links', 'post format archive title' );
1529 } elseif ( is_tax( 'post_format', 'post-format-status' ) ) {
1530 $title = _x( 'Statuses', 'post format archive title' );
1531 } elseif ( is_tax( 'post_format', 'post-format-audio' ) ) {
1532 $title = _x( 'Audio', 'post format archive title' );
1533 } elseif ( is_tax( 'post_format', 'post-format-chat' ) ) {
1534 $title = _x( 'Chats', 'post format archive title' );
1535 }
1536 } elseif ( is_post_type_archive() ) {
1537 /* translators: Post type archive title. %s: Post type name */
1538 $title = sprintf( __( 'Archives: %s' ), post_type_archive_title( '', false ) );
1539 } elseif ( is_tax() ) {
1540 $queried_object = get_queried_object();
1541 if ( $queried_object && isset( $queried_object->taxonomy ) ) {
1542 $tax = get_taxonomy( $queried_object->taxonomy );
1543 /* translators: Taxonomy term archive title. 1: Taxonomy singular name, 2: Current taxonomy term */
1544 $title = sprintf( '%1$s: %2$s', $tax->labels->singular_name, single_term_title( '', false ) );
1545 }
1546 }
1547
1548 return $title;
1549 }
1550
1551 /**
1552 * Count the number of occurrences of UA tags inserted by third-party plugins.
1553 *
1554 * @param string $body
1555 *
1556 * @return int
1557 */
1558 function monsterinsights_count_third_party_v4_codes($body) {
1559 $count = 0;
1560 return $count;
1561 }
1562
1563 /**
1564 * Count the number of times the same tracking ID is used for Ads and Performance
1565 *
1566 * @param $current_code
1567 *
1568 * @return int
1569 */
1570 function monsterinsights_count_addon_codes( $current_code ) {
1571 $count = 0;
1572
1573 // If the ads addon is installed and its conversion ID is the same as the current code, then increase the count
1574 if ( class_exists( 'MonsterInsights_Ads' ) ) {
1575 $ads_id = esc_attr( monsterinsights_get_option( 'gtag_ads_conversion_id' ) );
1576
1577 if ( $ads_id === $current_code ) {
1578 $count ++;
1579 }
1580 }
1581
1582 return $count;
1583 }
1584
1585 /**
1586 * Detect tracking code error depending on the type of tracking code
1587 *
1588 * @param string $body
1589 *
1590 * @return array
1591 */
1592 function monsterinsights_detect_tracking_code_error( $body ) {
1593 $errors = array();
1594
1595 $current_code = monsterinsights_get_v4_id_to_output();
1596
1597 $url = monsterinsights_get_url( 'notice', 'using-cache', 'https://www.wpbeginner.com/beginners-guide/how-to-clear-your-cache-in-wordpress/' );
1598 // Translators: The placeholders are for making the "We noticed you're using a caching plugin" text bold.
1599 $cache_error = sprintf(
1600 esc_html__( '%1$sWe noticed you\'re using a caching plugin or caching from your hosting provider.%2$s Be sure to clear the cache to ensure the tracking appears on all pages and posts. %3$s(See this guide on how to clear cache)%4$s.', 'google-analytics-for-wordpress' ),
1601 '<b>',
1602 '</b>',
1603 '<a target="_blank" href="' . esc_url( $url ) . '" target="_blank">',
1604 '</a>'
1605 );
1606
1607 // Check if the current UA code is actually present.
1608 if ( $current_code && false === strpos( $body, $current_code ) ) {
1609 // We have the tracking code but using another UA, so it's cached.
1610 $errors[] = $cache_error;
1611
1612 return $errors;
1613 }
1614
1615 if ( empty( $current_code ) ) {
1616 return $errors;
1617 }
1618
1619 if ( false === strpos( $body, '__gtagTracker' ) ) {
1620 if ( ! isset ( $errors ) ) {
1621 $errors[] = $cache_error;
1622 }
1623
1624 return $errors;
1625 }
1626
1627 $limit = 3;
1628
1629 $limit += monsterinsights_count_addon_codes( $current_code );
1630
1631 // TODO: Need to re-evaluate this regularly when third party plugins start supporting v4
1632 $limit += monsterinsights_count_third_party_v4_codes( $body );
1633
1634 // Count all the codes from the page.
1635 $total_count = substr_count( $body, $current_code );
1636
1637 // Count the `send_to` instances which are valid
1638 $pattern = '/send_to[\'"]*?:\s*[\'"]' . $current_code . '/m';
1639 if ( preg_match_all( $pattern, $body, $matches ) ) {
1640 $total_count -= count( $matches[0] );
1641 }
1642
1643 // Main property always has a ?id=(UA|G|GT)-XXXXXXXX script
1644 if ( strpos( $body, 'googletagmanager.com/gtag/js?id=' . $current_code ) !== false ) {
1645 // In that case, we can safely deduct one from the total count
1646 -- $total_count;
1647 }
1648
1649 // Test for Advanced Ads plugin tracking code.
1650 $pattern = '/advanced_ads_ga_UID.*?"' . $current_code . '"/m';
1651 if ( preg_match_all( $pattern, $body, $matches ) ) {
1652 $total_count -= count( $matches[0] );
1653 }
1654
1655 // Test for WP Popups tracking code.
1656 $pattern = '/wppopups_pro_vars.*?"' . $current_code . '"/m';
1657 if ( preg_match_all( $pattern, $body, $matches ) ) {
1658 $total_count -= count( $matches[0] );
1659 }
1660
1661 if ( $total_count > $limit ) {
1662 // Translators: The placeholders are for making the "We have detected multiple tracking codes" text bold & adding a link to support.
1663 $message = esc_html__( '%1$sWe have detected multiple tracking codes%2$s! You should remove non-MonsterInsights ones. If you need help finding them please %3$sread this article%4$s.', 'google-analytics-for-wordpress' );
1664 $url = monsterinsights_get_url( 'site-health', 'comingsoon', 'https://www.monsterinsights.com/docs/how-to-find-duplicate-google-analytics-tracking-codes-in-wordpress/' );
1665 $multiple_ua_error = sprintf(
1666 $message,
1667 '<b>',
1668 '</b>',
1669 '<a target="_blank" href="' . $url . '" target="_blank">',
1670 '</a>'
1671 );
1672
1673 $errors[] = $multiple_ua_error;
1674 }
1675
1676 return $errors;
1677 }
1678
1679 /**
1680 * Make a request to the front page and check if the tracking code is present. Moved here from onboarding wizard
1681 * to be used in the site health check.
1682 *
1683 * @return array
1684 */
1685 function monsterinsights_is_code_installed_frontend() {
1686 // Grab the front page html.
1687 $request = wp_remote_request(
1688 home_url(),
1689 array(
1690 'sslverify' => false,
1691 )
1692 );
1693 $errors = array();
1694
1695 $accepted_http_codes = array(
1696 200,
1697 503,
1698 );
1699
1700 $response_code = wp_remote_retrieve_response_code( $request );
1701
1702 if ( in_array( $response_code, $accepted_http_codes, true ) ) {
1703 $body = wp_remote_retrieve_body( $request );
1704
1705 $errors = monsterinsights_detect_tracking_code_error( $body );
1706 }
1707
1708 return $errors;
1709 }
1710
1711 /**
1712 * Returns a HEX color to highlight menu items based on the admin color scheme.
1713 */
1714 function monsterinsights_menu_highlight_color() {
1715
1716 $color_scheme = get_user_option( 'admin_color' );
1717 $color = '#1da867';
1718 if ( 'light' === $color_scheme || 'blue' === $color_scheme ) {
1719 $color = '#5f3ea7';
1720 }
1721
1722 return $color;
1723 }
1724
1725 /**
1726 * Track Pretty Links redirects with MonsterInsights.
1727 *
1728 * @param string $url The url to which users get redirected.
1729 */
1730 function monsterinsights_custom_track_pretty_links_redirect( $url ) {
1731 if ( ! function_exists( 'monsterinsights_mp_collect_v4' ) ) {
1732 return;
1733 }
1734
1735 // Track if it is a file.
1736 monsterinsights_track_pretty_links_file_download_redirect( $url );
1737
1738 // Try to determine if click originated on the same site.
1739 $referer = ! empty( $_SERVER['HTTP_REFERER'] ) ? esc_url( $_SERVER['HTTP_REFERER'] ) : '';
1740 if ( ! empty( $referer ) ) {
1741 $current_site_url = get_bloginfo( 'url' );
1742 $current_site_parsed = wp_parse_url( $current_site_url );
1743 $parsed_referer = wp_parse_url( $referer );
1744 if ( ! empty( $parsed_referer['host'] ) && ! empty( $current_site_parsed['host'] ) && $current_site_parsed['host'] === $parsed_referer['host'] ) {
1745 // Don't track clicks originating from same site as those are tracked with JS.
1746 return;
1747 }
1748 }
1749 // Check if this is an affiliate link and use the appropriate category.
1750 $inbound_paths = monsterinsights_get_option( 'affiliate_links', array() );
1751 $path = empty( $_SERVER['REQUEST_URI'] ) ? '' : $_SERVER['REQUEST_URI']; // phpcs:ignore
1752 if ( ! empty( $inbound_paths ) && is_array( $inbound_paths ) && ! empty( $path ) ) {
1753 $found = false;
1754 foreach ( $inbound_paths as $inbound_path ) {
1755 if ( empty( $inbound_path['path'] ) ) {
1756 continue;
1757 }
1758 if ( 0 === strpos( $path, trim( $inbound_path['path'] ) ) ) {
1759 $label = ! empty( $inbound_path['label'] ) ? trim( $inbound_path['label'] ) : 'aff';
1760 $found = true;
1761 break;
1762 }
1763 }
1764 if ( ! $found ) {
1765 return;
1766 }
1767 } else {
1768 // no paths setup in MonsterInsights settings
1769 return;
1770 }
1771
1772 if ( monsterinsights_get_v4_id_to_output() ) {
1773 // Get Pretty Links settings.
1774 $pretty_track = monsterinsights_get_option( 'pretty_links_backend_track', '' );
1775
1776 if ( 'pretty_link' == $pretty_track ) {
1777 global $prli_link;
1778 $pretty_link = $prli_link->get_one_by( 'url', $url );
1779 $link_url = PrliUtils::get_pretty_link_url( $pretty_link->slug );
1780 } else {
1781 $link_url = $url;
1782 }
1783
1784 $url_components = parse_url( $url );
1785 $params_args = array(
1786 'link_text' => 'external-redirect',
1787 'link_url' => $link_url,
1788 'link_domain' => $url_components['host'],
1789 'outbound' => 'true',
1790 );
1791
1792 if ( ! empty( $label ) ) {
1793 $params_args['affiliate_label'] = $label;
1794 $params_args['is_affiliate_link'] = 'true';
1795 }
1796
1797 monsterinsights_mp_collect_v4( array(
1798 'events' => array(
1799 array(
1800 'name' => 'click',
1801 'params' => $params_args,
1802 )
1803 ),
1804 ) );
1805 }
1806 }
1807
1808 add_action( 'prli_before_redirect', 'monsterinsights_custom_track_pretty_links_redirect' );
1809
1810 /**
1811 * Track Pretty Links file download redirects with MonsterInsights.
1812 *
1813 * @param string $url The url to which users get redirected.
1814 */
1815 function monsterinsights_track_pretty_links_file_download_redirect( $url ) {
1816 $file_info = pathinfo( $url );
1817
1818 // If no extension in URL.
1819 if ( ! isset( $file_info['extension'] ) ) {
1820 return;
1821 }
1822
1823 if ( ! $file_info['extension'] ) {
1824 return;
1825 }
1826
1827 // Get download extensions to track.
1828 $download_extensions = monsterinsights_get_option( 'extensions_of_files', '' );
1829
1830 if ( ! $download_extensions ) {
1831 return;
1832 }
1833
1834 $download_extensions = explode( ',', str_replace( '.', '', $download_extensions ) );
1835
1836 if ( ! is_array( $download_extensions ) ) {
1837 $download_extensions = array( $download_extensions );
1838 }
1839
1840 // If current URL extension is not in settings.
1841 if ( ! in_array( $file_info['extension'], $download_extensions ) ) {
1842 return;
1843 }
1844
1845 $url_components = parse_url( $url );
1846
1847 global $prli_link;
1848 $pretty_link = $prli_link->get_one_by( 'url', $url );
1849
1850 $args = array(
1851 'events' => array(
1852 array(
1853 'name' => 'file_download',
1854 'params' => array(
1855 'link_text' => $pretty_link->name,
1856 'link_url' => $url,
1857 'link_domain' => $url_components['host'],
1858 'file_extension' => $file_info['extension'],
1859 'file_name' => $file_info['basename'],
1860 )
1861 )
1862 ),
1863 );
1864
1865 monsterinsights_mp_collect_v4( $args );
1866 }
1867
1868 /**
1869 * Get post type in admin side
1870 */
1871 function monsterinsights_get_current_post_type() {
1872 global $post, $typenow, $current_screen;
1873
1874 if ( $post && $post->post_type ) {
1875 return $post->post_type;
1876 } elseif ( $typenow ) {
1877 return $typenow;
1878 } elseif ( $current_screen && $current_screen->post_type ) {
1879 return $current_screen->post_type;
1880 } elseif ( isset( $_REQUEST['post_type'] ) ) {
1881 return sanitize_key( $_REQUEST['post_type'] );
1882 }
1883
1884 return null;
1885 }
1886
1887 /** Decode special characters, both alpha- (<) and numeric-based (').
1888 *
1889 * @param string $string Raw string to decode.
1890 *
1891 * @return string
1892 * @since 7.10.5
1893 */
1894 function monsterinsights_decode_string( $string ) {
1895
1896 if ( ! is_string( $string ) ) {
1897 return $string;
1898 }
1899
1900 return wp_kses_decode_entities( html_entity_decode( $string, ENT_QUOTES ) );
1901 }
1902
1903 add_filter( 'monsterinsights_email_message', 'monsterinsights_decode_string' );
1904
1905 /**
1906 * Sanitize a string, that can be a multiline.
1907 * If WP core `sanitize_textarea_field()` exists (after 4.7.0) - use it.
1908 * Otherwise - split onto separate lines, sanitize each one, merge again.
1909 *
1910 * @param string $string
1911 *
1912 * @return string If empty var is passed, or not a string - return unmodified. Otherwise - sanitize.
1913 * @since 7.10.5
1914 */
1915 function monsterinsights_sanitize_textarea_field( $string ) {
1916
1917 if ( empty( $string ) || ! is_string( $string ) ) {
1918 return $string;
1919 }
1920
1921 if ( function_exists( 'sanitize_textarea_field' ) ) {
1922 $string = sanitize_textarea_field( $string );
1923 } else {
1924 $string = implode( "\n", array_map( 'sanitize_text_field', explode( "\n", $string ) ) );
1925 }
1926
1927 return $string;
1928 }
1929
1930 /**
1931 * Trim a sentence
1932 *
1933 * @param string $string
1934 * @param int $count
1935 *
1936 * @return trimed sentence
1937 * @since 7.10.5
1938 */
1939 function monsterinsights_trim_text( $text, $count ) {
1940 $text = str_replace( ' ', ' ', $text );
1941 $string = explode( ' ', $text );
1942 $trimed = '';
1943
1944 for ( $wordCounter = 0; $wordCounter <= $count; $wordCounter ++ ) {
1945 $trimed .= isset( $string[ $wordCounter ] ) ? $string[ $wordCounter ] : '';
1946
1947 if ( $wordCounter < $count ) {
1948 $trimed .= ' ';
1949 } else {
1950 $trimed .= '...';
1951 }
1952 }
1953
1954 $trimed = trim( $trimed );
1955
1956 return $trimed;
1957 }
1958
1959 /**
1960 * Add newly generated builder URL to PrettyLinks &
1961 * Clear localStorage key(MonsterInsightsURL) after saving PrettyLink
1962 */
1963 function monsterinsights_tools_copy_url_to_prettylinks() {
1964 global $pagenow;
1965
1966 $post_type = isset( $_GET['post_type'] ) ? sanitize_text_field( $_GET['post_type'] ) : '';
1967 $monsterinsights_reference = isset( $_GET['monsterinsights_reference'] ) ? sanitize_text_field( $_GET['monsterinsights_reference'] ) : '';
1968
1969 if ( 'post-new.php' === $pagenow && 'pretty-link' === $post_type && 'url_builder' === $monsterinsights_reference ) { ?>
1970 <script>
1971 let targetTitleField = document.querySelector("input[name='post_title']");
1972 let targetUrlField = document.querySelector("textarea[name='prli_url']");
1973 let MonsterInsightsUrl = JSON.parse(localStorage.getItem('MonsterInsightsURL'));
1974 if ('undefined' !== typeof targetUrlField && 'undefined' !== typeof MonsterInsightsUrl) {
1975 let url = MonsterInsightsUrl.value;
1976 let postTitle = '';
1977 let pathArray = url.split('?');
1978 if (pathArray.length <= 1) {
1979 pathArray = url.split('#');
1980 }
1981 let urlParams = new URLSearchParams(pathArray[1]);
1982 if (urlParams.has('utm_campaign')) {
1983 let campaign_name = urlParams.get('utm_campaign');
1984 postTitle += campaign_name;
1985 }
1986 if (urlParams.has('utm_medium')) {
1987 let campaign_medium = urlParams.get('utm_medium');
1988 postTitle += ` ${campaign_medium}`;
1989 }
1990 if (urlParams.has('utm_source')) {
1991 let campaign_source = urlParams.get('utm_source');
1992 postTitle += ` on ${campaign_source}`;
1993 }
1994 if (urlParams.has('utm_term')) {
1995 let campaign_term = urlParams.get('utm_term');
1996 postTitle += ` for ${campaign_term}`;
1997 }
1998 if (urlParams.has('utm_content')) {
1999 let campaign_content = urlParams.get('utm_content');
2000 postTitle += ` - ${campaign_content}`;
2001 }
2002 if ('undefined' !== typeof targetTitleField && postTitle) {
2003 targetTitleField.value = postTitle;
2004 }
2005 if (url) {
2006 targetUrlField.value = url;
2007 }
2008 }
2009 let form = document.getElementById('post');
2010 form.addEventListener('submit', function() {
2011 localStorage.removeItem('MonsterInsightsURL');
2012 });
2013 </script>
2014 <?php
2015 }
2016 }
2017
2018 add_action( 'admin_footer', 'monsterinsights_tools_copy_url_to_prettylinks' );
2019
2020 /**
2021 * When click on 'Create New Pretty Link" button(on tools/prettylinks-flow page) after installing & activating prettylinks plugin
2022 * it redirects to PrettyLinks welcome scree page instead of prettylinks add new page.
2023 * This function will skip that welcome screen
2024 */
2025 function monsterinsights_skip_prettylinks_welcome_screen() {
2026 global $pagenow;
2027
2028 $post_type = isset( $_GET['post_type'] ) ? sanitize_text_field( $_GET['post_type'] ) : '';
2029 $monsterinsights_reference = isset( $_GET['monsterinsights_reference'] ) ? sanitize_text_field( $_GET['monsterinsights_reference'] ) : '';
2030
2031 if ( 'post-new.php' === $pagenow && 'pretty-link' === $post_type && 'url_builder' === $monsterinsights_reference ) {
2032 $onboard = get_option( 'prli_onboard' );
2033
2034 if ( $onboard == 'welcome' || $onboard == 'update' ) {
2035 update_option( 'monsterinsights_backup_prli_onboard_value', $onboard );
2036 delete_option( 'prli_onboard' );
2037 }
2038 }
2039 }
2040
2041 add_action( 'wp_loaded', 'monsterinsights_skip_prettylinks_welcome_screen', 9 );
2042
2043 /**
2044 * Restore the `prli_onboard` value after creating a prettylinks with monsterinsights prettylinks flow
2045 * users will see the prettylinks welcome screen after fresh installation & creating prettylinks with monsterinsights prettylinks flow
2046 */
2047 function monsterinsights_restore_prettylinks_onboard_value() {
2048 global $pagenow;
2049
2050 $post_type = isset( $_GET['post_type'] ) ? sanitize_text_field( $_GET['post_type'] ) : '';
2051
2052 if ( 'edit.php' === $pagenow && 'pretty-link' === $post_type ) {
2053 $onboard = get_option( 'monsterinsights_backup_prli_onboard_value' );
2054
2055 if ( class_exists( 'PrliBaseController' ) && ( $onboard == 'welcome' || $onboard == 'update' ) ) {
2056 update_option( 'prli_onboard', $onboard );
2057 delete_option( 'monsterinsights_backup_prli_onboard_value' );
2058 }
2059 }
2060 }
2061
2062 add_action( 'wp_loaded', 'monsterinsights_restore_prettylinks_onboard_value', 15 );
2063
2064 /**
2065 * Check WP version and include the compatible upgrader skin.
2066 *
2067 * @param bool $custom_upgrader If true it will include our custom upgrader, otherwise it will use the default WP one.
2068 */
2069 function monsterinsights_require_upgrader( $custom_upgrader = true ) {
2070
2071 global $wp_version;
2072
2073 $base = MonsterInsights();
2074
2075 if ( ! $custom_upgrader ) {
2076 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
2077 }
2078
2079 // WP 5.3 changes the upgrader skin.
2080 if ( version_compare( $wp_version, '5.3', '<' ) ) {
2081 if ( $custom_upgrader ) {
2082 require_once plugin_dir_path( $base->file ) . 'includes/admin/licensing/plugin-upgrader.php';
2083 }
2084 require_once plugin_dir_path( $base->file ) . '/includes/admin/licensing/skin-legacy.php';
2085 } else {
2086 if ( $custom_upgrader ) {
2087 require_once plugin_dir_path( $base->file ) . 'includes/admin/licensing/plugin-upgrader.php';
2088 }
2089 require_once plugin_dir_path( $base->file ) . '/includes/admin/licensing/skin.php';
2090 }
2091 }
2092
2093 /**
2094 * Load headline analyzer if wp version is higher than/equal to 5.4
2095 *
2096 * @return boolean
2097 * @since 7.12.3
2098 */
2099 function monsterinsights_load_gutenberg_app() {
2100 global $wp_version;
2101
2102 if ( version_compare( $wp_version, '5.4', '<' ) ) {
2103 return false;
2104 }
2105
2106 return true;
2107 }
2108
2109 /**
2110 * Helper function for frontend script attributes
2111 *
2112 * @return string
2113 * @since 7.12.3
2114 */
2115 function monsterinsights_get_frontend_analytics_script_atts() {
2116 $attr_string = '';
2117
2118 $default_attributes = array(
2119 'data-cfasync' => 'false',
2120 'data-wpfc-render' => 'false',
2121 );
2122 if ( ! current_theme_supports( 'html5', 'script' ) ) {
2123 $default_attributes['type'] = 'text/javascript';
2124 }
2125
2126 $attributes = apply_filters( 'monsterinsights_tracking_analytics_script_attributes', $default_attributes );
2127
2128 if ( ! empty( $attributes ) ) {
2129 foreach ( $attributes as $attr_name => $attr_value ) {
2130 if ( ! empty( $attr_name ) ) {
2131 $attr_string .= ' ' . sanitize_key( $attr_name ) . '="' . esc_attr( $attr_value ) . '"';
2132 } else {
2133 $attr_string .= ' ' . esc_attr( $attr_value );
2134 }
2135 }
2136 }
2137
2138 return $attr_string;
2139 }
2140
2141 /**
2142 * Helper function instead of wp_localize_script with our script tag attributes.
2143 *
2144 * @return string
2145 * @since 8.5.0
2146 */
2147 function monsterinsights_localize_script( $handle, $object_name, $data, $priority = 100 ) {
2148 $theme_supports_html5 = current_theme_supports( 'html5', 'script' );
2149 $script_js = ! $theme_supports_html5 ? "/* <![CDATA[ */\n" : '';
2150 $script_js .= "var $object_name = " . wp_json_encode( $data ) . ';';
2151 $script_js .= ! $theme_supports_html5 ? "/* ]]> */\n" : '';
2152
2153 $script = sprintf(
2154 "<script%s id='%s-js-extra'>%s</script>\n",
2155 monsterinsights_get_frontend_analytics_script_atts(),
2156 esc_attr( $handle ),
2157 $script_js
2158 );
2159
2160 add_filter(
2161 'script_loader_tag',
2162 function ( $tag, $current_handle ) use ( $handle, $script ) {
2163 if ( $current_handle !== $handle ) {
2164 return $tag;
2165 }
2166
2167 return $tag . $script;
2168 },
2169 $priority,
2170 2
2171 );
2172 }
2173
2174 /**
2175 * Get native english speaking countries
2176 *
2177 * @return array
2178 *
2179 * @since 7.12.3
2180 */
2181 function monsterinsights_get_english_speaking_countries() {
2182 return array(
2183 'AG' => __( 'Antigua and Barbuda', 'google-analytics-for-wordpress' ),
2184 'AU' => __( 'Australia', 'google-analytics-for-wordpress' ),
2185 'BB' => __( 'Barbados', 'google-analytics-for-wordpress' ),
2186 'BZ' => __( 'Belize', 'google-analytics-for-wordpress' ),
2187 'BW' => __( 'Botswana', 'google-analytics-for-wordpress' ),
2188 'BI' => __( 'Burundi', 'google-analytics-for-wordpress' ),
2189 'CM' => __( 'Cameroon', 'google-analytics-for-wordpress' ),
2190 'CA' => __( 'Canada', 'google-analytics-for-wordpress' ),
2191 'DM' => __( 'Dominica', 'google-analytics-for-wordpress' ),
2192 'FJ' => __( 'Fiji', 'google-analytics-for-wordpress' ),
2193 'GD' => __( 'Grenada', 'google-analytics-for-wordpress' ),
2194 'GY' => __( 'Guyana', 'google-analytics-for-wordpress' ),
2195 'GM' => __( 'Gambia', 'google-analytics-for-wordpress' ),
2196 'GH' => __( 'Ghana', 'google-analytics-for-wordpress' ),
2197 'IE' => __( 'Ireland', 'google-analytics-for-wordpress' ),
2198 'IN' => __( 'India', 'google-analytics-for-wordpress' ),
2199 'JM' => __( 'Jamaica', 'google-analytics-for-wordpress' ),
2200 'KE' => __( 'Kenya', 'google-analytics-for-wordpress' ),
2201 'KI' => __( 'Kiribati', 'google-analytics-for-wordpress' ),
2202 'LS' => __( 'Lesotho', 'google-analytics-for-wordpress' ),
2203 'LR' => __( 'Liberia', 'google-analytics-for-wordpress' ),
2204 'MW' => __( 'Malawi', 'google-analytics-for-wordpress' ),
2205 'MT' => __( 'Malta', 'google-analytics-for-wordpress' ),
2206 'MH' => __( 'Marshall Islands', 'google-analytics-for-wordpress' ),
2207 'MU' => __( 'Mauritius', 'google-analytics-for-wordpress' ),
2208 'FM' => __( 'Micronesia', 'google-analytics-for-wordpress' ),
2209 'NZ' => __( 'New Zealand', 'google-analytics-for-wordpress' ),
2210 'NA' => __( 'Namibia', 'google-analytics-for-wordpress' ),
2211 'NR' => __( 'Nauru', 'google-analytics-for-wordpress' ),
2212 'NG' => __( 'Nigeria', 'google-analytics-for-wordpress' ),
2213 'PK' => __( 'Pakistan', 'google-analytics-for-wordpress' ),
2214 'PW' => __( 'Palau', 'google-analytics-for-wordpress' ),
2215 'PG' => __( 'Papua New Guinea', 'google-analytics-for-wordpress' ),
2216 'PH' => __( 'Philippines', 'google-analytics-for-wordpress' ),
2217 'RW' => __( 'Rwanda', 'google-analytics-for-wordpress' ),
2218 'SG' => __( 'Singapore', 'google-analytics-for-wordpress' ),
2219 'KN' => __( 'St Kitts and Nevis', 'google-analytics-for-wordpress' ),
2220 'LC' => __( 'St Lucia', 'google-analytics-for-wordpress' ),
2221 'VC' => __( 'St Vincent and the Grenadines', 'google-analytics-for-wordpress' ),
2222 'SZ' => __( 'Swaziland', 'google-analytics-for-wordpress' ),
2223 'WS' => __( 'Samoa', 'google-analytics-for-wordpress' ),
2224 'SC' => __( 'Seychelles', 'google-analytics-for-wordpress' ),
2225 'SL' => __( 'Sierra Leone', 'google-analytics-for-wordpress' ),
2226 'SB' => __( 'Solomon Islands', 'google-analytics-for-wordpress' ),
2227 'ZA' => __( 'South Africa', 'google-analytics-for-wordpress' ),
2228 'SS' => __( 'South Sudan', 'google-analytics-for-wordpress' ),
2229 'SD' => __( 'Sudan', 'google-analytics-for-wordpress' ),
2230 'TT' => __( 'Trinidad and Tobago', 'google-analytics-for-wordpress' ),
2231 'BS' => __( 'The Bahamas', 'google-analytics-for-wordpress' ),
2232 'TZ' => __( 'Tanzania', 'google-analytics-for-wordpress' ),
2233 'TO' => __( 'Tonga', 'google-analytics-for-wordpress' ),
2234 'TV' => __( 'Tuvalu', 'google-analytics-for-wordpress' ),
2235 'GB' => __( 'United Kingdom', 'google-analytics-for-wordpress' ),
2236 'US' => __( 'United States of America', 'google-analytics-for-wordpress' ),
2237 'UG' => __( 'Uganda', 'google-analytics-for-wordpress' ),
2238 'VU' => __( 'Vanuatu', 'google-analytics-for-wordpress' ),
2239 'ZM' => __( 'Zambia', 'google-analytics-for-wordpress' ),
2240 'ZW' => __( 'Zimbabwe', 'google-analytics-for-wordpress' ),
2241 );
2242 }
2243
2244 /**
2245 * Helper function to check if the current user can install a plugin.
2246 *
2247 * @return bool
2248 */
2249 function monsterinsights_can_install_plugins( $user_id = null ) {
2250 if ( empty( $user_id ) ) {
2251 $user_id = get_current_user_id();
2252 }
2253 if ( ! user_can( $user_id, 'install_plugins' ) ) {
2254 return false;
2255 }
2256 // Determine whether file modifications are allowed.
2257 if ( function_exists( 'wp_is_file_mod_allowed' ) && ! wp_is_file_mod_allowed( 'monsterinsights_can_install' ) ) {
2258 return false;
2259 }
2260 return true;
2261 }
2262
2263 /**
2264 * Check if current date is between given dates. Date format: Y-m-d.
2265 *
2266 * @param string $start_date Start Date. Eg: 2021-01-01.
2267 * @param string $end_date End Date. Eg: 2021-01-14.
2268 *
2269 * @return bool
2270 * @since 7.13.2
2271 */
2272 function monsterinsights_date_is_between( $start_date, $end_date ) {
2273
2274 $current_date = current_time( 'Y-m-d' );
2275
2276 $start_date = date( 'Y-m-d', strtotime( $start_date ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
2277 $end_date = date( 'Y-m-d', strtotime( $end_date ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
2278
2279 if ( ( $current_date >= $start_date ) && ( $current_date <= $end_date ) ) {
2280 return true;
2281 }
2282
2283 return false;
2284 }
2285
2286 /**
2287 * Check is All-In-One-Seo plugin is active or not.
2288 *
2289 * @return bool
2290 * @since 7.17.0
2291 */
2292 function monsterinsights_is_aioseo_active() {
2293
2294 if ( function_exists( 'aioseo' ) ) {
2295 return true;
2296 }
2297
2298 return false;
2299 }
2300
2301 // /**
2302 // * Return FunnelKit Stripe Woo Gateway Settings URL if plugin is active.
2303 // *
2304 // * @return string
2305 // * @since 8.24.0
2306 // */
2307 // function monsterinsights_funnelkit_stripe_woo_gateway_dashboard_url() {
2308 // $url = '';
2309
2310 // if ( class_exists( 'FKWCS_Gateway_Stripe' ) ) {
2311 // $url = is_multisite() ? network_admin_url( 'admin.php?page=wc-settings&tab=fkwcs_api_settings' ) : admin_url( 'admin.php?page=wc-settings&tab=fkwcs_api_settings' );
2312 // }
2313
2314 // return $url;
2315 // }
2316
2317 /**
2318 * Return AIOSEO Dashboard URL if plugin is active.
2319 *
2320 * @return string
2321 * @since 7.17.0
2322 */
2323 function monsterinsights_aioseo_dashboard_url() {
2324 $url = '';
2325
2326 if ( function_exists( 'aioseo' ) ) {
2327 $url = is_multisite() ? network_admin_url( 'admin.php?page=aioseo' ) : admin_url( 'admin.php?page=aioseo' );
2328 }
2329
2330 return $url;
2331 }
2332
2333 /**
2334 * Check if AIOSEO Pro version is installed or not.
2335 *
2336 * @return bool
2337 * @since 7.17.10
2338 */
2339 function monsterinsights_is_installed_aioseo_pro() {
2340 $installed_plugins = get_plugins();
2341
2342 if ( array_key_exists( 'all-in-one-seo-pack-pro/all_in_one_seo_pack.php', $installed_plugins ) ) {
2343 return true;
2344 }
2345
2346 return false;
2347 }
2348
2349 /**
2350 * Check if Cookiebot plugin functionality active.
2351 *
2352 * @since 8.9.0
2353 *
2354 * @return bool
2355 */
2356 function monsterinsights_is_cookiebot_active() {
2357
2358 if ( function_exists( '\cybot\cookiebot\lib\cookiebot_active' ) ) {
2359 return \cybot\cookiebot\lib\cookiebot_active();
2360 }
2361
2362 if ( function_exists( 'cookiebot_active' ) ) {
2363 return cookiebot_active();
2364 }
2365
2366 return false;
2367 }
2368
2369 if ( ! function_exists( 'wp_date' ) ) {
2370 /**
2371 * Retrieves the date, in localized format.
2372 *
2373 * This is a newer function, intended to replace `date_i18n()` without legacy quirks in it.
2374 *
2375 * Note that, unlike `date_i18n()`, this function accepts a true Unix timestamp, not summed
2376 * with timezone offset.
2377 *
2378 * @since WP 5.3.0
2379 *
2380 * @global WP_Locale $wp_locale WordPress date and time locale object.
2381 *
2382 * @param string $format PHP date format.
2383 * @param int $timestamp Optional. Unix timestamp. Defaults to current time.
2384 * @param DateTimeZone $timezone Optional. Timezone to output result in. Defaults to timezone
2385 * from site settings.
2386 * @return string|false The date, translated if locale specifies it. False on invalid timestamp input.
2387 */
2388 function wp_date( $format, $timestamp = null, $timezone = null ) {
2389 global $wp_locale;
2390
2391 if ( null === $timestamp ) {
2392 $timestamp = time();
2393 } elseif ( ! is_numeric( $timestamp ) ) {
2394 return false;
2395 }
2396
2397 if ( ! $timezone ) {
2398 $timezone = wp_timezone();
2399 }
2400
2401 $datetime = date_create( '@' . $timestamp );
2402 $datetime->setTimezone( $timezone );
2403
2404 if ( empty( $wp_locale->month ) || empty( $wp_locale->weekday ) ) {
2405 $date = $datetime->format( $format );
2406 } else {
2407 // We need to unpack shorthand `r` format because it has parts that might be localized.
2408 $format = preg_replace( '/(?<!\\\\)r/', DATE_RFC2822, $format );
2409
2410 $new_format = '';
2411 $format_length = strlen( $format );
2412 $month = $wp_locale->get_month( $datetime->format( 'm' ) );
2413 $weekday = $wp_locale->get_weekday( $datetime->format( 'w' ) );
2414
2415 for ( $i = 0; $i < $format_length; $i ++ ) {
2416 switch ( $format[ $i ] ) {
2417 case 'D':
2418 $new_format .= addcslashes( $wp_locale->get_weekday_abbrev( $weekday ), '\\A..Za..z' );
2419 break;
2420 case 'F':
2421 $new_format .= addcslashes( $month, '\\A..Za..z' );
2422 break;
2423 case 'l':
2424 $new_format .= addcslashes( $weekday, '\\A..Za..z' );
2425 break;
2426 case 'M':
2427 $new_format .= addcslashes( $wp_locale->get_month_abbrev( $month ), '\\A..Za..z' );
2428 break;
2429 case 'a':
2430 $new_format .= addcslashes( $wp_locale->get_meridiem( $datetime->format( 'a' ) ), '\\A..Za..z' );
2431 break;
2432 case 'A':
2433 $new_format .= addcslashes( $wp_locale->get_meridiem( $datetime->format( 'A' ) ), '\\A..Za..z' );
2434 break;
2435 case '\\':
2436 $new_format .= $format[ $i ];
2437
2438 // If character follows a slash, we add it without translating.
2439 if ( $i < $format_length ) {
2440 $new_format .= $format[ ++$i ];
2441 }
2442 break;
2443 default:
2444 $new_format .= $format[ $i ];
2445 break;
2446 }
2447 }
2448
2449 $date = $datetime->format( $new_format );
2450 $date = wp_maybe_decline_date( $date, $format );
2451 }
2452
2453 /**
2454 * Filters the date formatted based on the locale.
2455 *
2456 * @since WP 5.3.0
2457 *
2458 * @param string $date Formatted date string.
2459 * @param string $format Format to display the date.
2460 * @param int $timestamp Unix timestamp.
2461 * @param DateTimeZone $timezone Timezone.
2462 */
2463 $date = apply_filters( 'wp_date', $date, $format, $timestamp, $timezone );
2464
2465 return $date;
2466 }
2467 }
2468
2469 if ( ! function_exists( 'wp_timezone_string' ) ) {
2470 /**
2471 * Retrieves the timezone of the site as a string.
2472 *
2473 * Uses the `timezone_string` option to get a proper timezone name if available,
2474 * otherwise falls back to a manual UTC ± offset.
2475 *
2476 * Example return values:
2477 *
2478 * - 'Europe/Rome'
2479 * - 'America/North_Dakota/New_Salem'
2480 * - 'UTC'
2481 * - '-06:30'
2482 * - '+00:00'
2483 * - '+08:45'
2484 *
2485 * @since WP 5.3.0
2486 *
2487 * @return string PHP timezone name or a ±HH:MM offset.
2488 */
2489 function wp_timezone_string() {
2490 $timezone_string = get_option( 'timezone_string' );
2491
2492 if ( $timezone_string ) {
2493 return $timezone_string;
2494 }
2495
2496 $offset = (float) get_option( 'gmt_offset' );
2497 $hours = (int) $offset;
2498 $minutes = ( $offset - $hours );
2499
2500 $sign = ( $offset < 0 ) ? '-' : '+';
2501 $abs_hour = abs( $hours );
2502 $abs_mins = abs( $minutes * 60 );
2503 $tz_offset = sprintf( '%s%02d:%02d', $sign, $abs_hour, $abs_mins );
2504
2505 return $tz_offset;
2506 }
2507 }
2508
2509 if ( ! function_exists( 'wp_timezone' ) ) {
2510 /**
2511 * Retrieves the timezone of the site as a `DateTimeZone` object.
2512 *
2513 * Timezone can be based on a PHP timezone string or a ±HH:MM offset.
2514 *
2515 * @since WP 5.3.0
2516 *
2517 * @return DateTimeZone Timezone object.
2518 */
2519 function wp_timezone() {
2520 return new DateTimeZone( wp_timezone_string() );
2521 }
2522 }
2523
2524 if ( ! function_exists( 'current_datetime' ) ) {
2525 /**
2526 * Retrieves the current time as an object using the site's timezone.
2527 *
2528 * @since WP 5.3.0
2529 *
2530 * @return DateTimeImmutable Date and time object.
2531 */
2532 function current_datetime() {
2533 return new DateTimeImmutable( 'now', wp_timezone() );
2534 }
2535 }
2536
2537
2538 if ( ! function_exists( 'monsterinsights_is_authed' ) ) {
2539 function monsterinsights_is_authed() {
2540 $site_profile = get_option('monsterinsights_site_profile');
2541 return isset($site_profile['key']);
2542 }
2543 }
2544 // Prevents being redirected to Duplicator once plugin is installed through the onboarding wizard.
2545 add_filter( 'duplicator_disable_onboarding_redirect', '__return_true' );
2546 // Prevents being redirected to WP Consent once plugin is installed through the onboarding wizard.
2547 add_action( 'admin_init', 'monsterinsights_disable_wpconsent_onboarding_redirect', 10 );
2548 /**
2549 * Disable WP Consent onboarding redirect if the plugin is active.
2550 *
2551 * @return void
2552 */
2553 function monsterinsights_disable_wpconsent_onboarding_redirect() {
2554 if ( is_plugin_active( 'wpconsent-cookies-banner-privacy-suite/wpconsent.php' ) ) {
2555 delete_transient( 'wpconsent_onboarding_redirect' );
2556 }
2557 }
2558 add_action( 'wp_ajax_monsterinsights_report_error', 'monsterinsights_report_error' );
2559 /**
2560 * Capture the last plugin error and save it.
2561 * @since 9.7.0
2562 * @return string
2563 */
2564 function monsterinsights_report_error() {
2565 check_ajax_referer( 'mi-admin-nonce', 'nonce' );
2566 if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
2567 return;
2568 }
2569 if ( ! isset( $_POST['error_code'] ) || ! isset( $_POST['current_screen'] ) ) {
2570 return;
2571 }
2572 $error_code = sanitize_text_field( wp_unslash( $_POST['error_code'] ) );
2573 $current_screen = sanitize_text_field( wp_unslash( $_POST['current_screen'] ) );
2574 $last_plugin_error = array(
2575 'code' => $error_code,
2576 'screen' => $current_screen,
2577 'date' => time()
2578 );
2579 update_option( 'monsterinsights_last_plugin_error', $last_plugin_error );
2580 wp_send_json_success();
2581 }
2582
2583 /**
2584 * Check any of the following CMP plugis is active.
2585 *
2586 * @return bool
2587 */
2588 function monsterinsights_wpconsent_is_cmp_plugin_active() {
2589 // Complianz
2590 if ( defined( 'cmplz_plugin' ) || defined( 'cmplz_premium' ) ) {
2591 return true;
2592 }
2593
2594 // CookieYes (cookie-law-info)
2595 if ( defined( 'CLI_SETTINGS_FIELD' ) ) {
2596 return true;
2597 }
2598
2599 // GDPR Cookie Compliance
2600 if ( defined( 'MOOVE_GDPR_VERSION' ) ) {
2601 return true;
2602 }
2603
2604 // Cookie Notice
2605 if ( function_exists( 'Cookie_Notice' ) ) {
2606 return true;
2607 }
2608
2609 return false;
2610 }
2611
2612 /**
2613 * Get the eCommerce currency code from the active eCommerce platform.
2614 *
2615 * Checks for WooCommerce, Easy Digital Downloads, MemberPress, LifterLMS,
2616 * Restrict Content Pro, and GiveWP. Falls back to 'USD' if no platform is detected.
2617 *
2618 * @since 9.4.0
2619 *
2620 * @return string The 3-letter ISO 4217 currency code.
2621 */
2622 function monsterinsights_get_ecommerce_currency() {
2623 // Check WooCommerce first (most common).
2624 if ( function_exists( 'get_woocommerce_currency' ) ) {
2625 return get_woocommerce_currency();
2626 }
2627
2628 // Check Easy Digital Downloads.
2629 if ( function_exists( 'edd_get_currency' ) ) {
2630 return edd_get_currency();
2631 }
2632
2633 // Check MemberPress.
2634 if ( class_exists( 'MeprOptions' ) ) {
2635 $mepr_options = MeprOptions::fetch();
2636 if ( ! empty( $mepr_options->currency_code ) ) {
2637 return $mepr_options->currency_code;
2638 }
2639 }
2640
2641 // Check LifterLMS.
2642 if ( function_exists( 'get_lifterlms_currency' ) ) {
2643 return get_lifterlms_currency();
2644 }
2645
2646 // Check Restrict Content Pro.
2647 if ( function_exists( 'rcp_get_currency' ) ) {
2648 return rcp_get_currency();
2649 }
2650
2651 // Check GiveWP.
2652 if ( function_exists( 'give_get_currency' ) ) {
2653 return give_get_currency();
2654 }
2655
2656 /**
2657 * Filter the eCommerce currency code.
2658 *
2659 * Allows other plugins or custom code to provide the currency code
2660 * when no supported eCommerce platform is detected.
2661 *
2662 * @since 9.4.0
2663 *
2664 * @param string $currency The 3-letter ISO 4217 currency code. Default 'USD'.
2665 */
2666 return apply_filters( 'monsterinsights_ecommerce_currency', 'USD' );
2667 }
2668