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

render.php in Analytify – Google Analytics Dashboard For WordPress (GA4 analytics tracking) trunk, at classes/analytify-settings/render.php

975 lines 45.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php // phpcs:ignore Squiz.Commenting.FileComment.Missing -- File doc comment exists
2 /**
3 * Analytify Settings Render Trait
4 *
5 * This trait handles all the rendering and display logic for the Analytify settings page.
6 * It was created to separate the UI rendering concerns from the main settings class,
7 * making the code more maintainable and following the single responsibility principle.
8 *
9 * PURPOSE:
10 * - Renders the settings page HTML structure
11 * - Handles form submissions and processing
12 * - Manages admin notices and messages
13 * - Provides UI components for settings fields
14 *
15 * @package WP_Analytify
16 * @subpackage Settings
17 * @since 8.0.0
18 */
19
20 trait Analytify_Settings_Render {
21
22 // Field callbacks.
23
24 /**
25 * Text field callback.
26 *
27 * @since 1.0.0
28 * @param array<string, mixed> $args Field arguments.
29 * @return void
30 * @version 9.1.0
31 */
32 public function callback_text( $args ) {
33 $option_value = $this->get_option( $args['id'], $args['section'], $args['std'] );
34
35 // Handle array values gracefully - extract secretValue if it exists.
36 if ( is_array( $option_value ) && isset( $option_value['secretValue'] ) ) {
37 $value = $option_value['secretValue'];
38 } elseif ( is_array( $option_value ) ) {
39 $value = ''; // Clear invalid array data.
40 } else {
41 $value = $option_value;
42 }
43
44 $value = esc_attr( $value );
45 $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
46 $type = isset( $args['type'] ) ? $args['type'] : 'text';
47 $extra_attrs = '';
48 $input_format = isset( $args['input_format'] ) ? $args['input_format'] : '';
49
50 if ( ! empty( $input_format ) ) {
51 $extra_attrs .= sprintf( ' data-input-format="%s"', esc_attr( $input_format ) );
52
53 if ( 'digits' === $input_format ) {
54 $extra_attrs .= ' inputmode="numeric" pattern="[0-9]*"';
55 }
56 }
57
58 if ( ! empty( $args['maxlength'] ) ) {
59 $extra_attrs .= sprintf( ' maxlength="%d"', absint( $args['maxlength'] ) );
60 }
61
62 $html = sprintf(
63 '<input type="%1$s" class="%2$s-text" id="%3$s[%4$s]" name="%3$s[%4$s]" value="%5$s"%6$s/>',
64 esc_attr( $type ),
65 esc_attr( $size ),
66 esc_attr( $args['section'] ),
67 esc_attr( $args['id'] ),
68 $value,
69 $extra_attrs
70 );
71
72 if ( ! empty( $args['tooltip'] ) ) {
73 $tooltip_text = is_string( $args['tooltip'] ) ? $args['tooltip'] : $args['desc'];
74 $html .= sprintf( '<span class="dashicons dashicons-editor-help setting-more-info" title="%1$s"></span>', esc_attr( $tooltip_text ) );
75
76 if ( $tooltip_text === $args['desc'] ) {
77 $args['desc'] = '';
78 }
79 }
80
81 $html .= $this->get_field_description( $args );
82 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
83 }
84
85 /**
86 * Button field callback.
87 *
88 * @param array<string, mixed> $args Field arguments.
89 * @return void
90 */
91 public function callback_button( $args ) {
92 $option_value = $this->get_option( $args['id'], $args['section'], $args['std'] );
93
94 // Handle array values gracefully - extract secretValue if it exists.
95 if ( is_array( $option_value ) && isset( $option_value['secretValue'] ) ) {
96 $value = $option_value['secretValue'];
97 } elseif ( is_array( $option_value ) ) {
98 $value = ''; // Clear invalid array data.
99 } else {
100 $value = $option_value;
101 }
102
103 $value = esc_attr( $value );
104 $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'button';
105 $type = isset( $args['type'] ) ? $args['type'] : 'text';
106 $html = sprintf( '<input type="%1$s" class="%2$s button-primary" id="%3$s[%4$s]" name="%3$s[%4$s]" value="%5$s"/>', esc_attr( $type ), esc_attr( $size ), esc_attr( $args['section'] ), esc_attr( $args['id'] ), $value );
107 $html .= $this->get_field_description( $args );
108 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
109 }
110
111 /**
112 * URL field callback.
113 *
114 * @param array<string, mixed> $args Field arguments.
115 * @return void
116 */
117 public function callback_url( $args ) {
118 $this->callback_text( $args );
119 }
120 /**
121 * Number field callback.
122 *
123 * @param array<string, mixed> $args Field arguments.
124 * @return void
125 */
126 public function callback_number( $args ) {
127 $this->callback_text( $args );
128 }
129
130 /**
131 * Field callback.
132 *
133 * @param array<string, mixed> $args Field arguments.
134 * @return void
135 * @version 9.1.0
136 */
137 public function callback_checkbox( $args ) {
138 $option_value = $this->get_option( $args['id'], $args['section'], $args['std'] );
139
140 // Handle array values gracefully - extract secretValue if it exists.
141 if ( is_array( $option_value ) && isset( $option_value['secretValue'] ) ) {
142 $value = $option_value['secretValue'];
143 } elseif ( is_array( $option_value ) ) {
144 $value = ''; // Clear invalid array data.
145 } else {
146 $value = $option_value;
147 }
148
149 $value = esc_attr( $value );
150 $is_disabled = ( isset( $args['options']['disabled'] ) && $args['options']['disabled'] ) ? 'disabled' : '';
151 $defalut_value = ( 'disabled' === $is_disabled && 'on' === $value ) ? 'on' : 'off';
152 $checkbox_value = ( isset( $args['options']['disabled'] ) && $args['options']['disabled'] ) ? 'off' : $value;
153 $checkbox_name_override = ( isset( $args['options']['disabled'] ) && $args['options']['disabled'] ) ? '__' : '';
154 $html = '<fieldset>';
155 $html .= sprintf( '<label for="%1$s[%2$s]"></label>', esc_attr( $args['section'] ), esc_attr( $args['id'] ) );
156 $html .= sprintf( '<input type="hidden" name="%1$s[%2$s]" value="%3$s" />', esc_attr( $args['section'] ), esc_attr( $args['id'] ), esc_attr( $defalut_value ) );
157 $html .= sprintf( '<div class="toggle"><input type="checkbox" class="checkbox" id="%1$s%2$s[%3$s]" name="%1$s%2$s[%3$s]" value="on" %4$s %5$s /><span class="btn-nob"></span><span class="texts"></span><span class="bg"></span></div>', esc_attr( $checkbox_name_override ), esc_attr( $args['section'] ), esc_attr( $args['id'] ), checked( $checkbox_value, 'on', false ), esc_attr( $is_disabled ) );
158
159 if ( ! empty( $args['tooltip'] ) ) {
160 $tooltip_text = is_string( $args['tooltip'] ) ? $args['tooltip'] : $args['desc'];
161 $html .= sprintf( '<span class="dashicons dashicons-editor-help setting-more-info" title="%1$s"></span>', esc_attr( $tooltip_text ) );
162
163 if ( $tooltip_text === $args['desc'] ) {
164 $args['desc'] = '';
165 }
166 }
167
168 $html .= $this->get_field_description( $args );
169 $html .= '</fieldset>';
170 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
171 }
172
173 /**
174 * Field callback.
175 *
176 * @param array<string, mixed> $args Field arguments.
177 * @return void
178 */
179 public function callback_multicheck( $args ) {
180 $value = $this->get_option( $args['id'], $args['section'], $args['std'] );
181 $html = '<fieldset>';
182 foreach ( $args['options'] as $key => $label ) {
183 $checked = isset( $value[ $key ] ) ? $value[ $key ] : '0';
184 $html .= sprintf( '<label for="wp-analytify-%1$s[%2$s][%3$s]">', $args['section'], $args['id'], $key );
185 $html .= sprintf( '<input type="checkbox" class="checkbox" id="wp-analytify-%1$s[%2$s][%3$s]" name="%1$s[%2$s][%3$s]" value="%3$s" %4$s />', $args['section'], $args['id'], $key, checked( $checked, $key, false ) );
186 $html .= sprintf( '%1$s</label><br>', $label );
187 }
188 $html .= $this->get_field_description( $args );
189 $html .= '</fieldset>';
190 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
191 }
192
193 /**
194 * Field callback.
195 *
196 * @param array<string, mixed> $args Field arguments.
197 * @return void
198 */
199 public function callback_radio( $args ) {
200 $value = $this->get_option( $args['id'], $args['section'], $args['std'] );
201 $html = '<fieldset>';
202 foreach ( $args['options'] as $key => $label ) {
203 $html .= sprintf( '<label for="wp-analytify-%1$s[%2$s][%3$s]">', $args['section'], $args['id'], $key );
204 $html .= sprintf( '<input type="radio" class="radio" id="wp-analytify-%1$s[%2$s][%3$s]" name="%1$s[%2$s]" value="%3$s" %4$s />', $args['section'], $args['id'], $key, checked( $value, $key, false ) );
205 $html .= sprintf( '%1$s</label><br>', $label );
206 }
207 $html .= $this->get_field_description( $args );
208 $html .= '</fieldset>';
209 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
210 }
211
212 /**
213 * Field callback.
214 *
215 * @param array<string, mixed> $args Field arguments.
216 * @return void
217 */
218 public function callback_select( $args ) {
219 $option_value = $this->get_option( $args['id'], $args['section'], $args['std'] );
220
221 // Handle array values gracefully - extract secretValue if it exists.
222 if ( is_array( $option_value ) && isset( $option_value['secretValue'] ) ) {
223 $value = $option_value['secretValue'];
224 } elseif ( is_array( $option_value ) ) {
225 $value = ''; // Clear invalid array data.
226 } else {
227 $value = $option_value;
228 }
229
230 $value = esc_attr( $value );
231 $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
232 $html = sprintf( '<select class="%1$s analytify-settings-select" name="%2$s[%3$s]" id="%2$s[%3$s]">', $size, $args['section'], $args['id'] );
233 foreach ( $args['options'] as $key => $label ) {
234 $html .= sprintf( '<option value="%s"%s>%s</option>', $key, selected( $value, $key, false ), $label );
235 }
236 $html .= '</select>';
237 $html .= $this->get_field_description( $args );
238 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
239 }
240
241 /**
242 * Field callback.
243 *
244 * @param array<string, mixed> $args Field arguments.
245 * @return void
246 */
247 public function callback_multi_select( $args ) {
248 $value = ( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
249 $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
250 $html = '';
251 foreach ( $args['options']['main'] as $key => $label ) {
252 $html .= '<div class="analytify-multiselect-container">';
253 $html .= sprintf( '<select class="%1$s" name="%2$s[%3$s][' . $key . ']" id="%2$s[%3$s][value]">', esc_attr( $size ), esc_attr( $args['section'] ), esc_attr( $args['id'] ) );
254 if ( isset( $args['options']['value'][ $key ] ) && is_array( $args['options']['value'][ $key ] ) ) {
255 foreach ( $args['options']['value'][ $key ] as $k => $v ) {
256 $selected_value = isset( $value[ $key ] ) ? $value[ $key ] : '';
257 $html .= sprintf( '<option value="%s"%s>%s</option>', esc_attr( $k ), selected( $k, $selected_value, false ), esc_html( $v ) );
258 }
259 }
260 $html .= '</select>';
261 $html .= '<span class="analytify-multiselect-label">' . esc_html( $label ) . '</span>';
262 $html .= '</div>';
263 }
264 $html .= $this->get_field_description( $args );
265 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
266 }
267
268 /**
269 * Field callback.
270 *
271 * @param array<string, mixed> $args Field arguments.
272 * @return void
273 */
274 public function callback_ga_dimensions_repeater( $args ) {
275 $html = '';
276 $count = 0;
277 $available_dimensions = array();
278
279 foreach ( $args['options'] as $key => $value ) {
280 if ( true !== $value['is_enable'] ) {
281 continue;
282 }
283
284 $available_dimensions[ $key ] = $value;
285 }
286
287 wp_add_inline_script(
288 'analytify_dimension_script',
289 '
290 var wpAnalytifyDimensionOptions = ' . wp_json_encode( $available_dimensions ) . ';
291 '
292 );
293 ?>
294
295 <?php
296 $html .= '<table id="wp-analytify-dimension-table">
297 <thead>
298 <tr>
299 <th>' . __( 'Type', 'wp-analytify' ) . '</th>
300 </tr>
301 </thead>
302 <tbody>';
303
304 $current_values = $this->get_option( $args['id'], $args['section'], $args['std'] );
305 $current_values = array_values( $current_values );
306
307 if ( empty( $current_values ) ) {
308 $html .= '';
309 } else {
310 foreach ( $current_values as $current_value => $vals ) {
311 $html .= '<tr class="single_dimension"><td>';
312 $html .= sprintf( '<select class="select-dimension" name="%1$s[%2$s][' . $count . '][type]" id="%1$s[%2$s]">', $args['section'], $args['id'] );
313
314 $saved_type = ! empty( $vals['type'] ) ? $vals['type'] : '';
315
316 // Only loop if options exist and are iterable.
317 if ( ! empty( $args['options'] ) && is_array( $args['options'] ) ) {
318 foreach ( $args['options'] as $key => $value ) {
319 // Skip SEO options if Yoast is not available, unless it's the saved value.
320 if ( in_array( $key, array( 'seo_score', 'focus_keyword' ), true )
321 && ! class_exists( 'WPSEO_Frontend' )
322 && $saved_type !== $key
323 ) {
324 continue;
325 }
326
327 // Get title safely.
328 $title = is_array( $value ) ? ( $value['title'] ?? '' ) : ( is_object( $value ) ? ( $value->title ?? '' ) : '' );
329
330 $html .= sprintf( '<option value="%s" %s>%s</option>', $key, $saved_type === $key ? 'selected' : '', esc_html( $title ) );
331 }
332 }
333
334 $html .= '</select></td>';
335 $html .= '<td><span class="wp-analytify-rmv-dimension"></span></td>
336 </tr>';
337
338 ++$count;
339 }
340 }
341
342 $html .= '<div class="inside">' . $args['desc'] . '</div>';
343 $html .= '</tbody></table><button type="button" class="button wp-analytify-add-dimension">Add Dimension</button>';
344
345 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is built from sanitized inputs and WordPress functions.
346 echo $html;
347 }
348
349
350
351 /**
352 * Field callback.
353 *
354 * @param array<string, mixed> $args Field arguments.
355 * @return void
356 */
357 public function callback_email_receivers( $args ) {
358 $current_values = $this->get_option( $args['id'], $args['section'], $args['std'] );
359 if ( ! is_array( $current_values ) ) {
360 $basic_values = explode( ',', $current_values );
361 $current_values = array();
362 foreach ( $basic_values as $value ) {
363 $current_values[] = array(
364 'name' => '',
365 'email' => $value,
366 );
367 }
368 }
369 $current_values = array_values( $current_values );
370 $count = 0;
371 $html = '<table id="wp-analytify-email-table"><thead><tr><th>' . esc_html__( 'Name', 'wp-analytify' ) . '</th><th>' . esc_html__( 'Email Address', 'wp-analytify' ) . '</th></tr></thead><tbody>';
372 if ( ! empty( $current_values ) ) {
373 foreach ( $current_values as $current_value => $vals ) {
374 $html .= '<tr class="single_email">';
375 $html .= sprintf(
376 '<td><input type="text" name="%1$s[%2$s][%3$s][name]" id="%1$s[%2$s]"" value="%4$s" placeholder="%5$s"></td>',
377 esc_attr( $args['section'] ),
378 esc_attr( $args['id'] ),
379 esc_attr( $count ),
380 esc_attr( trim( $vals['name'] ) ),
381 esc_attr__( 'Name', 'wp-analytify' )
382 );
383 $html .= sprintf(
384 '<td><input type="email" name="%1$s[%2$s][%3$s][email]" id="%1$s[%2$s]" value="%4$s" placeholder="%5$s" required></td>',
385 esc_attr( $args['section'] ),
386 esc_attr( $args['id'] ),
387 esc_attr( $count ),
388 esc_attr( sanitize_email( $vals['email'] ) ),
389 esc_attr__( 'Email Address', 'wp-analytify' )
390 );
391 $html .= '<td><span class="wp-analytify-rmv-email"></span></td></tr>';
392 ++$count;
393 }
394 }
395 $html .= '<div class="inside">' . wp_kses_post( isset( $args['desc'] ) && ! empty( $args['desc'] ) ? $args['desc'] : '' ) . '</div>';
396 $html .= '</tbody></table><button type="button" class="button wp-analytify-add-email">' . esc_html__( 'Add Receiver', 'wp-analytify' ) . '</button>';
397 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
398 }
399
400 /**
401 * Field callback.
402 *
403 * @param array<string, mixed> $args Field arguments.
404 * @return void
405 */
406 public function callback_affiliates_repeater( $args ) {
407 $count = 0;
408 $html = '<table id="wp-analytify-affiliates-table"><thead><tr><p>' . esc_html( $args['desc'] ) . '</p><th>' . esc_html__( 'Path (example: /refer/)', 'wp-analytify' ) . '</th><th>' . esc_html__( 'Label (example: loginpress link)', 'wp-analytify' ) . '</th></tr></thead><tbody>';
409 $current_values = $this->get_option( $args['id'], $args['section'], $args['std'] );
410 if ( empty( $current_values ) ) {
411 $html .= '<tr class="single_affiliates">';
412 $html .= sprintf(
413 '<td><input type="text" class="affiliates-path" name="%1$s[%2$s][%3$s][path]" id="%1$s[%2$s]" placeholder="%4$s" value="" ></td>',
414 esc_attr( $args['section'] ),
415 esc_attr( $args['id'] ),
416 esc_attr( $count ),
417 esc_attr__( '/refer/', 'wp-analytify' )
418 );
419 $html .= sprintf(
420 '<td><input type="text" class="affiliates-label" name="%1$s[%2$s][%3$s][label]" id="%1$s[%2$s]" placeholder="%4$s" value="" ></td>',
421 esc_attr( $args['section'] ),
422 esc_attr( $args['id'] ),
423 esc_attr( $count ),
424 esc_attr__( 'loginpress link', 'wp-analytify' )
425 );
426 $html .= '<td><span class="wp-analytify-rmv-affiliates"></span></td></tr>';
427 } else {
428 $current_values = array_values( $current_values );
429 foreach ( $current_values as $current_value => $vals ) {
430 $html .= '<tr class="single_affiliates">';
431 $html .= sprintf(
432 '<td><input type="text" class="affiliates-path" placeholder="%4$s" name="%1$s[%2$s][%3$s][path]" id="%1$s[%2$s]" value="%5$s"></td>',
433 esc_attr( $args['section'] ),
434 esc_attr( $args['id'] ),
435 esc_attr( $count ),
436 esc_attr__( '/refer/', 'wp-analytify' ),
437 esc_attr( $vals['path'] )
438 );
439 $html .= sprintf(
440 '<td><input type="text" class="affiliates-label" placeholder="%4$s" name="%1$s[%2$s][%3$s][label]" id="%1$s[%2$s]" value="%5$s"></td>',
441 esc_attr( $args['section'] ),
442 esc_attr( $args['id'] ),
443 esc_attr( $count ),
444 esc_attr__( 'loginpress link', 'wp-analytify' ),
445 esc_attr( $vals['label'] )
446 );
447 $html .= '<td><span class="wp-analytify-rmv-affiliates"></span></td></tr>';
448 ++$count;
449 }
450 }
451 $html .= '</tbody></table><p class="affiliates-err">' . esc_html__( "Affiliates can't be empty!", 'wp-analytify' ) . '</p><button type="button" class="button wp-analytify-add-affiliates">' . esc_html__( 'Add Affiliate Link', 'wp-analytify' ) . '</button>';
452 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
453 }
454
455 /**
456 * Field callback.
457 *
458 * @param array<string, mixed> $args Field arguments.
459 * @return void
460 */
461 public function callback_chosen( $args ) {
462 $value = $this->get_option( $args['id'], $args['section'], $args['std'] );
463 $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
464 $html = sprintf( '<select multiple class="%1$s analytify-chosen" name="%2$s[%3$s][]" id="%2$s[%3$s]">', $size, $args['section'], $args['id'] );
465 foreach ( $args['options'] as $key => $label ) {
466 $selected = in_array( $key, $value, true ) ? 'selected = selected' : '';
467 $html .= sprintf( '<option value="%s"%s>%s</option>', esc_attr( $key ), $selected, esc_html( $label ) );
468 }
469 $html .= '</select>';
470 $html .= $this->get_field_description( $args );
471 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
472 }
473
474 /**
475 * Field callback.
476 *
477 * @param array<string, mixed> $args Field arguments.
478 * @return void
479 */
480 public function callback_select_streams( $args ) {
481 $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
482 $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
483 $html = sprintf( '<select class="%1$s analytify-settings-select" name="%2$s[%3$s]" id="%2$s[%3$s]">', $size, $args['section'], $args['id'] );
484 foreach ( $args['options'] as $key => $label ) {
485 $html .= sprintf( '<option value="%s"%s>%s</option>', esc_attr( $key ), selected( $key, $value, false ), esc_html( $label ) );
486 }
487 $html .= '</select>';
488 $html .= $this->get_field_description( $args );
489 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
490 }
491
492 /**
493 * Select profile field callback.
494 *
495 * @param mixed $args Field arguments.
496 * @return void
497 */
498 public function callback_select_profile( $args ) {
499 $exception = $GLOBALS['WP_ANALYTIFY']->get_exception();
500 if ( $exception ) {
501 if ( isset( $exception[0]['reason'] ) && 'dailyLimitExceeded' === $exception[0]['reason'] ) {
502 $link = 'https://analytify.io/doc/fix-403-daily-limit-exceeded/';
503 // translators: %1$s is bold opening tag, %2$s is bold closing tag, %3$s is tutorial link opening tag, %4$s is tutorial link closing tag, %5$s is paragraph opening tag, %6$s is paragraph closing tag.
504 printf( __( '%5$s%1$sDaily Limit Exceeded:%2$s This Indicates that user has exceeded the daily quota (either per project or per view (profile)). Please %3$sfollow this tutorial%4$s to fix this issue. let us know this issue (if it still doesn\'t work) in the Help tab of Analytify->settings page.%6$s', 'wp-analytify' ), '<b>', '</b>', '<a href="' . esc_url( $link ) . '" target="_blank">', '</a>', '<p class="description" style="color:#ed1515">', '</p>' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- printf with proper escaping
505 return;
506 } elseif ( isset( $exception[0]['reason'] ) && 'insufficientPermissions' === $exception[0]['reason'] && 'global' === $exception[0]['domain'] ) {
507 echo '<p class="description" style="color:#ed1515">' . esc_html__( 'Insufficient Permissions:', 'wp-analytify' ) . ' ' . esc_html( $exception[0]['message'] ) . ' <br>' . esc_html__( 'Check out', 'wp-analytify' ) . ' <a href="https://analytify.io/setup-account-google-analytics/" target="_blank">' . esc_html__( 'this guide here', 'wp-analytify' ) . '</a> ' . esc_html__( 'to setup it properly.', 'wp-analytify' ) . '</p>';
508 return;
509 } elseif ( isset( $exception[0]['reason'] ) && 'unexpected_profile_error' === $exception[0]['reason'] ) {
510 echo '<p class="description" style="color:#ed1515">' . esc_html__( 'An unexpected error occurred while getting profiles list from the Google Analytics account.', 'wp-analytify' ) . ' <br> ' . esc_html__( 'let us know this issue from the Help tab.', 'wp-analytify' ) . '</p>';
511 return;
512 } elseif ( isset( $exception[0]['reason'] ) && 'ACCESS_TOKEN_SCOPE_INSUFFICIENT' === $exception[0]['reason'] ) {
513 echo '<p class="description" style="color:#ed1515">' . esc_html__( 'Insufficient Permissions:', 'wp-analytify' ) . ' ' . esc_html( $exception[0]['message'] ) . ' <br>' . esc_html__( 'Check out', 'wp-analytify' ) . ' <a href="https://analytify.io/setup-account-google-analytics/" target="_blank">' . esc_html__( 'this guide here', 'wp-analytify' ) . '</a> ' . esc_html__( 'to setup it properly.', 'wp-analytify' ) . '</p>';
514 return;
515 } else {
516 echo '<p class="description" style="color:#ed1515">' . esc_html( $exception[0]['reason'] ) . ' : ' . esc_html( $exception[0]['message'] ) . ' </p>';
517 }
518 }
519 $exception = $GLOBALS['WP_ANALYTIFY']->get_ga4_exception();
520 if ( $exception ) {
521 if ( isset( $exception[0]['reason'] ) && 'ACCESS_TOKEN_SCOPE_INSUFFICIENT' === $exception[0]['reason'] ) {
522 echo '<p class="description" style="color:#ed1515">' . esc_html__( 'Insufficient Permissions:', 'wp-analytify' ) . ' ' . esc_html( $exception[0]['message'] ) . ' <br>' . esc_html__( 'Check out', 'wp-analytify' ) . ' <a href="https://analytify.io/setup-account-google-analytics/" target="_blank">' . esc_html__( 'this guide here', 'wp-analytify' ) . '</a> ' . esc_html__( 'to setup it properly.', 'wp-analytify' ) . '</p>';
523 return;
524 } elseif ( isset( $exception[0]['reason'] ) ) {
525 echo '<p class="description" style="color:#ed1515">' . esc_html( $exception[0]['reason'] ) . ' : ' . esc_html( $exception[0]['message'] ) . ' </p>';
526 }
527 }
528 $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
529 $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
530 $html = sprintf( '<select class="%1$s analytify-chosen" name="%2$s[%3$s]" id="%2$s[%3$s]">', $size, $args['section'], $args['id'] );
531 $_analytify_setting = get_option( 'wp-analytify-profile' );
532 if ( isset( $_analytify_setting['hide_profiles_list'] ) && 'on' === $_analytify_setting['hide_profiles_list'] ) {
533 $html .= '<option value="' . esc_attr( $value ) . '" selected>' . esc_html( WP_ANALYTIFY_FUNCTIONS::search_profile_info( $value, 'websiteUrl' ) ) . ' (' . esc_html( WP_ANALYTIFY_FUNCTIONS::search_profile_info( $value, 'name' ) ) . ')' . '</option>'; // phpcs:ignore Generic.Strings.UnnecessaryStringConcat.Found -- Dynamic HTML construction requires concatenation
534 } else {
535 $html .= '<option value="">' . esc_html( $args['std'] ) . '</option>';
536 $is_ga4_mode = 'ga4' === WPANALYTIFY_Utils::get_ga_mode() ? true : false;
537 if ( $is_ga4_mode && isset( $args['options']['GA4'] ) && ! empty( $args['options']['GA4'] ) ) {
538 foreach ( $args['options']['GA4'] as $account => $properties ) {
539 $html .= '<optgroup label=" ' . esc_attr( $account ) . ' ">';
540 foreach ( $properties as $property_id => $property ) {
541 $html .= sprintf( '<option value="%1$s" %2$s>%3$s (%4$s)</option>', esc_attr( $property_id ), selected( $value, $property_id, false ), esc_html( $property['name'] ), esc_html( $property['code'] ) );
542 }
543 $html .= '</optgroup>';
544 }
545 }
546 }
547 $html .= '</select>';
548 if ( ! $args['options'] ) {
549 // No options available - leave as-is per original.
550 $html .= $this->get_field_description( $args );
551 } elseif ( isset( $args['options']->totalResults ) && ( $args['options']->totalResults < 1 ) ) {
552 $html .= $this->get_field_description( $args );
553 $html .= '<p class="description" style="color:#ed1515">Google Analytics account ' . ( isset( $args['options']->username ) ? esc_html( $args['options']->username ) : '' ) . ' doesn\'t have any UA property.<br /> See <a href="https://analytify.io/how-to-setup-your-account-at-google-analytics/" target="_blank">why &&how to fix it</a>.</p>';
554 } else {
555 $html .= $this->get_field_description( $args );
556 }
557 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
558 }
559
560 /**
561 * Field callback.
562 *
563 * @param array<string, mixed> $args Field arguments.
564 * @return void
565 */
566 public function callback_textarea( $args ) {
567 $value = esc_textarea( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
568 $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
569 $html = sprintf( '<textarea rows="5" cols="55" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]">%4$s</textarea>', $size, $args['section'], $args['id'], $value );
570 $html .= $this->get_field_description( $args );
571 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
572 }
573
574 /**
575 * Field callback.
576 *
577 * @param array<string, mixed> $args Field arguments.
578 * @return void
579 */
580 public function callback_html( $args ) {
581 echo $this->get_field_description( $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Method handles escaping
582 }
583
584 /**
585 * Field callback.
586 *
587 * @param array<string, mixed> $args Field arguments.
588 * @return void
589 */
590 public function callback_wysiwyg( $args ) {
591 $value = $this->get_option( $args['id'], $args['section'], $args['std'] );
592 $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : '500px';
593 echo '<div style="max-width: ' . esc_attr( $size ) . ';">'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Size is escaped
594 $editor_settings = array(
595 'teeny' => true,
596 'textarea_name' => $args['section'] . '[' . $args['id'] . ']',
597 'textarea_rows' => 10,
598 );
599 if ( isset( $args['options'] ) && is_array( $args['options'] ) ) {
600 $editor_settings = array_merge( $editor_settings, $args['options'] );
601 }
602 wp_editor( $value, $args['section'] . '-' . $args['id'], $editor_settings );
603 echo '</div>';
604 echo $this->get_field_description( $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Method handles escaping
605 }
606
607 /**
608 * Field callback.
609 *
610 * @param array<string, mixed> $args Field arguments.
611 * @return void
612 */
613 public function callback_image( $args ) {
614 $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
615 $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
616 $id = $args['section'] . '[' . $args['id'] . ']';
617 $label = isset( $args['options']['button_label'] ) ? $args['options']['button_label'] : __( 'Choose Image', 'wp-analytify' );
618 $img = wp_get_attachment_image_src( (int) $value );
619 $img_url = $img ? $img[0] : '';
620 $html = sprintf( '<input type="hidden" class="%1$s-text wpsa-image-id" id="%2$s" name="%2$s" value="%3$s"/>', $size, $id, $value );
621 $html .= '<p class="wpsa-image-preview"><img src="' . esc_url( $img_url ) . '" /></p>';
622 $html .= '<input type="button" class="button wpsa-image-browse" value="' . esc_attr( $label ) . '" />';
623 $html .= '<input type="button" class="button analytify_email_clear" value="' . esc_attr__( 'Remove Logo', 'wp-analytify' ) . '" />';
624 $html .= $this->get_field_description( $args );
625 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
626 }
627
628 /**
629 * Field callback.
630 *
631 * @param array<string, mixed> $args Field arguments.
632 * @return void
633 */
634 public function callback_file( $args ) {
635 $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
636 $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
637 $id = $args['section'] . '[' . $args['id'] . ']';
638 $label = isset( $args['options']['button_label'] ) ? $args['options']['button_label'] : __( 'Choose File', 'wp-analytify' );
639 $html = sprintf( '<input type="text" class="%1$s-text wpsa-url" id="%2$s" name="%2$s" value="%3$s"/>', $size, $id, $value );
640 $html .= '<input type="button" class="button wpsa-browse" value="' . esc_attr( $label ) . '" />';
641 $html .= $this->get_field_description( $args );
642 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
643 }
644
645 /**
646 * Field callback.
647 *
648 * @param array<string, mixed> $args Field arguments.
649 * @return void
650 */
651 public function callback_password( $args ) {
652 $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
653 $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
654 $html = sprintf( '<input type="password" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s"/>', $size, $args['section'], $args['id'], $value );
655 $html .= $this->get_field_description( $args );
656 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
657 }
658
659 /**
660 * Field callback.
661 *
662 * @param array<string, mixed> $args Field arguments.
663 * @return void
664 */
665 public function callback_color( $args ) {
666 $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
667 $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
668 $html = sprintf( '<input type="text" class="%1$s-text wp-color-picker-field" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s" data-default-color="%5$s" />', $size, $args['section'], $args['id'], $value, $args['std'] );
669 $html .= $this->get_field_description( $args );
670 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is properly escaped above
671 }
672
673 // UI renderers.
674
675 /**
676 * Help tab content.
677 *
678 * @return void
679 */
680 public function callback_authentication() {
681 $output = '';
682 ob_start();
683 echo '<div class="inside">' . esc_html__( 'Set up a liaison between Analytify & your Google Analytics account.', 'wp-analytify' ) . '</div>';
684 if ( get_option( 'pa_google_token' ) ) {
685 $analytify_google_email = '';
686 if ( isset( $GLOBALS['WP_ANALYTIFY'] ) && is_object( $GLOBALS['WP_ANALYTIFY'] ) ) {
687 $analytify_google_email = $GLOBALS['WP_ANALYTIFY']->analytify_get_connected_google_account_email();
688 }
689 ?>
690 <div class="inside"></div>
691 <table class="form-table"><form action="" method="post"><tbody><tr>
692 <?php wp_nonce_field( 'analytify_analytics_logout', 'analytify_analytics_logout_nonce' ); ?>
693 <th scope="row"><label class="pt-20">Google Authentication</label></th>
694 <td><input type="submit" class="button-primary" value="Logout" name="wp_analytify_log_out" />
695 <?php if ( is_string( $analytify_google_email ) && is_email( $analytify_google_email ) ) : ?>
696 <p class="description analytify-google-account-email">
697 <?php
698 printf(
699 /* translators: %s: Google account email address used for OAuth. */
700 esc_html__( 'Logged in with %s', 'wp-analytify' ),
701 '<strong>' . esc_html( $analytify_google_email ) . '</strong>'
702 );
703 ?>
704 </p>
705 <?php else : ?>
706 <p class="description analytify-google-account-email analytify-google-account-email--unavailable">
707 <?php esc_html_e( 'Google account is connected; the sign-in email could not be shown.', 'wp-analytify' ); ?>
708 </p>
709 <?php endif; ?>
710 <p class="description">You have allowed your site to access the data from your Google Analytics account. Click on logout button to disconnect or re-authenticate.</p></td>
711 </tr></tbody></form></table>
712 <?php
713 } else {
714 ?>
715 <table class="form-table"><tbody><tr>
716 <th scope="row"><label class="pt-20">Google Authentication</label></th>
717 <td>
718 <a target="_self" title="Log in with your Google Analytics Account" class="button-primary authentication_btn" href="<?php echo esc_url( WP_ANALYTIFY_FUNCTIONS::analytify_create_auth_url() ); ?>"><?php esc_html_e( 'Log in with your Google Analytics Account', 'wp-analytify' ); ?></a>
719 <p class="description">
720 <?php
721 // translators: %1$s is setup account link opening tag, %2$s is setup account link closing tag, %3$s is Google Analytics link opening tag, %4$s is Google Analytics link closing tag.
722 printf( esc_html__( 'It is required to %1$sSet up your account%2$s and a website profile at %3$sGoogle Analytics%4$s to see Analytify Dashboard reports.', 'wp-analytify' ), '<a href="https://analytify.io/setup-account-google-analytics/" target="blank">', '</a>', '<a href="https://analytics.google.com/" target="blank">', '</a>' );
723 ?>
724 </p>
725 </td></tr></tbody></table>
726 <?php
727 }
728 $output .= ob_get_contents();
729 ob_end_clean();
730 echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output is properly escaped
731 }
732
733 /**
734 * Help tab content.
735 *
736 * @since 2.0
737 * @return void
738 */
739 public function callback_help() {
740 ?>
741
742 <div class="wrap">
743
744 <?php
745 if ( has_action( 'anlytify_pro_support_tab' ) ) {
746 do_action( 'anlytify_pro_support_tab' );
747 } else {
748 ?>
749
750 <h3><?php esc_html_e( 'Support', 'wp-analytify' ); ?></h3>
751
752 <p>
753 <?php
754 printf( // translators: Support.
755 esc_html__( 'As this is a free plugin, Post all of your questions to the %1$s WordPress.org support forum %2$s. Response time can range from a couple of days to a week as this is a free support.', 'wp-analytify' ),
756 '<a href="' . esc_url( 'https://wordpress.org/support/plugin/wp-analytify/' ) . '" target="_blank">',
757 '</a>'
758 );
759 ?>
760 </p>
761
762 <p class="upgrade-to-pro">
763 <?php
764 printf( // translators: Upgrade to Pro.
765 esc_html__( 'If you want a %1$s timely response via email from a developer %2$s who works on this plugin, %3$s upgrade to Analytify Pro %4$s & send us an email.', 'wp-analytify' ),
766 '<strong>',
767 '</strong>',
768 '<a href="' . esc_url( analytify_get_update_link( 'https://analytify.io/', '?utm_source=analytify-lite&amp;utm_medium=help-tab&amp;utm_content=support-upgrade&amp;utm_campaign=pro-upgrade' ) ) . '" target="_blank">',
769 '</a>'
770 );
771 ?>
772 </p>
773
774 <p>
775 <?php
776 printf( // translators: Notify the bug.
777 esc_html__( 'If you\'ve found a bug, please %1$s submit an issue at Github %2$s.', 'wp-analytify' ),
778 '<a href="' . esc_url( 'https://github.com/hiddenpearls/wp-analytify/issues' ) . '" target="_blank">',
779 '</a>'
780 );
781 ?>
782 </p>
783
784 <?php } ?>
785
786 </div>
787
788 <div class="wp-analytify-debug">
789 <h3><?php esc_html_e( 'Diagnostic Information', 'wp-analytify' ); ?></h3>
790 <textarea class="debug-log-textarea" autocomplete="off" readonly="" id="debug-log-textarea"></textarea>
791
792 <div class="wp-analytify-view-error-log">
793 </div>
794 <div class="wp-analytify-view-error-log">
795 <button id="analytify-copy-diagnostic" class="button"><?php esc_html_e( 'Copy to Clipboard', 'wp-analytify' ); ?></button>
796 <button id="analytify-download-diagnostic" class="button"><?php esc_html_e( 'Download Diagnostic Log', 'wp-analytify' ); ?></button>
797 <a class="button" href="<?php echo esc_url( admin_url( 'admin.php?page=analytify-logs' ) ); ?>"><?php esc_html_e( 'View Error Logs', 'wp-analytify' ); ?></a>
798 </div>
799 </div>
800
801 <div class="wp-analytify-debug">
802 <h3><?php esc_html_e( 'Tools', 'wp-analytify' ); ?></h3>
803
804 <div class="wp-analytify-import-export">
805 <div class="analytify-export-container">
806 <h4><?php esc_html_e( 'Export Settings', 'wp-analytify' ); ?></h4>
807 <p><?php esc_html_e( 'Export the Analytify settings file in JSON format.', 'wp-analytify' ); ?></p>
808
809 <a id="analytify-export-settings" class="button" href="javascript:void(0)" data-nonce="<?php echo esc_attr( wp_create_nonce( 'import-export' ) ); ?>">
810 <?php esc_html_e( 'Download Export File', 'wp-analytify' ); ?>
811 </a>
812 </div>
813 <div class="analytify-import-container">
814 <h4><?php esc_html_e( 'Import Settings', 'wp-analytify' ); ?></h4>
815 <p><?php esc_html_e( 'Select the export file and click on Upload Import File button.', 'wp-analytify' ); ?></p>
816 <p><?php esc_html_e( 'This will not include your Google authentication, you might need to authenticate again after import.', 'wp-analytify' ); ?></p>
817 <form id="analytify-import-form">
818 <input id="analytify-import-settings" type="file" accept=".json,application/json" title="Upload Import File">
819 <button id="analytify-import-submit" type="submit" class="button" data-nonce="<?php echo esc_attr( wp_create_nonce( 'import-export' ) ); ?>">
820 <?php esc_html_e( 'Upload Import File', 'wp-analytify' ); ?>
821 </button>
822 </form>
823 <p class="analytify-import-error" role="alert"></p>
824 <p class="analytify-import-notice"><?php esc_html_e( 'Import completed successfully!', 'wp-analytify' ); ?></p>
825 <p class="analytify-import-notice"><?php esc_html_e( 'Reloading settings page to reflect settings..', 'wp-analytify' ); ?></p>
826 </div>
827 </div>
828
829 <div class="wp-analytify-tools-actions" style="margin-top: 15px;">
830 <div class="analytify-refresh-container" style="margin-bottom: 10px;">
831 <h4 style="margin-bottom: 5px;"><?php esc_html_e( 'Refresh Statistics', 'wp-analytify' ); ?></h4>
832 <p style="margin-bottom: 8px;"><?php esc_html_e( 'Clear cached data to update your analytics with the latest stats.', 'wp-analytify' ); ?></p>
833 <form class="" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post" style="margin: 0;">
834 <input type="hidden" name="action" value="analytify_delete_cache">
835 <?php
836 wp_nonce_field( 'analytify_delete_cache', 'analytify_delete_cache_nonce' );
837 ?>
838 <button type="submit" class="wp-analytify-delete-cache-button button"><?php esc_html_e( 'Refresh All Stats', 'wp-analytify' ); ?></button>
839 </form>
840 </div>
841
842 <div class="analytify-factory-reset-container">
843 <h4 style="margin-bottom: 5px;"><?php esc_html_e( 'Factory Reset', 'wp-analytify' ); ?></h4>
844 <p style="margin-bottom: 8px;"><?php esc_html_e( 'Restore all settings to their defaults. This will log you out and remove any saved configurations.', 'wp-analytify' ); ?></p>
845 <div style="display: flex; gap: 10px; align-items: center;">
846 <button type="button" id="btn-analytify-factory-reset" class="button analytify-button-danger">
847 <?php esc_html_e( 'Reset Plugin Settings', 'wp-analytify' ); ?>
848 </button>
849 <span class="spinner analytify-factory-reset-spinner" style="float: none; margin: 0;"></span>
850 </div>
851 </div>
852 </div>
853 </div>
854 <script>
855 (function ($) {
856 $(document).ready(function () {
857 $('#btn-analytify-factory-reset').on('click', function () {
858 var confirmMessage = '<?php echo esc_js( __( 'Are you sure you want to reset the plugin? This will delete all settings and data. This cannot be undone.', 'wp-analytify' ) ); ?>';
859 if (!confirm(confirmMessage)) {
860 return;
861 }
862
863 var $btn = $(this);
864 var $spinner = $btn.siblings('.analytify-factory-reset-spinner');
865
866 $btn.prop('disabled', true);
867 $spinner.addClass('is-active');
868
869 $.post(ajaxurl, {
870 action: 'analytify_factory_reset',
871 nonce: '<?php echo esc_js( wp_create_nonce( 'analytify_factory_reset_nonce' ) ); ?>'
872 })
873 .done(function (response) {
874 $spinner.removeClass('is-active');
875 if (response && response.success) {
876 alert('<?php echo esc_js( __( 'Plugin reset successfully. Reloading...', 'wp-analytify' ) ); ?>');
877 location.reload();
878 } else {
879 var errorMsg = (response && response.data) ? response.data : '<?php echo esc_js( __( 'Error resetting plugin.', 'wp-analytify' ) ); ?>';
880 alert(errorMsg);
881 $btn.prop('disabled', false);
882 }
883 })
884 .fail(function () {
885 $spinner.removeClass('is-active');
886 alert('<?php echo esc_js( __( 'Error resetting plugin. Please try again.', 'wp-analytify' ) ); ?>');
887 $btn.prop('disabled', false);
888 });
889 });
890 });
891 }(jQuery));
892 </script>
893
894 <div class="wp-analytify-video-container">
895 <h3>
896 <?php
897 printf( // translators: Video.
898 esc_html__( 'Videos %1$s (Subscribe To Our Youtube Channel) %2$s', 'wp-analytify' ),
899 '<a href="https://www.youtube.com/c/Wp-analytify/videos" target="_blank">',
900 '</a>'
901 );
902 ?>
903 </h3>
904
905 <ul>
906 <li>
907 <h4>Generate Custom API Keys</h4>
908 <p>It is highly recommended by Google to use your own API keys. Check out a <a href="https://analytify.io/google-api-tutorial" target="_blank">comprehensive tutorial</a> & a video guide to get your own ClientID, Client Secret &&Redirect URL to use in Advanced Tab.</p>
909 <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/QJYzXsPJeTo" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
910 </li>
911 <li>
912 <h4>How to Install Analytify Pro</h4>
913 <p>Analytify Core version from wordpress.org is the base (required) to use all the addons (Free & Paid) &&Analytify Pro version.<br />Check out the Analytify Pro <a href="https://analytify.io/features/" target="_blank">features</a>.</p>
914 <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/D02R6eP3olM" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
915 </li>
916 <li>
917 <h4>View Google Analytics within WordPress</h4>
918 <p>This video explains how to check the stats of each page in WordPress.<br />Check out the Analytify Pro <a href="https://analytify.io/features/" target="_blank">features</a></p>
919 <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/6BnJiTOgCrE" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
920 </li>
921 </ul>
922
923 </div>
924
925 <?php
926 }
927 /**
928 * Help tab content.
929 *
930 * @return void
931 */
932 public function callback_email_promo() {
933 if ( class_exists( 'WP_Analytify_Pro_Base' ) ) {
934 $url = 'https://analytify.io/add-ons/email-notifications/?utm_source=analytify-pro&utm_medium=plugin-settings&utm_content=cta&utm_campaign=addons-upgrade';
935 $url_text = __( 'Explore Email Notifications addon', 'wp-analytify' );
936 } else {
937 $url = 'https://analytify.io/add-ons/email-notifications/?utm_source=analytify-lite&utm_medium=plugin-settings&utm_content=cta&utm_campaign=bundle-upgrade';
938 $url_text = sprintf( '%1$s + %2$s', __( 'Explore Analytify Pro', 'wp-analytify' ), __( 'Email Notifications bundle', 'wp-analytify' ) );
939 }
940 ?>
941 <div class="analytify-email-promo-contianer">
942 <img src="<?php echo esc_url( ( defined( 'ANALYTIFY_PLUGIN_URL' ) ? ANALYTIFY_PLUGIN_URL : '' ) . 'assets/img/email-promo.png' ); ?>" alt="promo">
943 <div class="analytify-email-premium-overlay">
944 <div class="analytify-email-premium-popup">
945 <h3 class="analytify-promo-popup-heading"><?php esc_html_e( 'Unlock weekly and monthly reports', 'wp-analytify' ); ?></h3>
946 <p class="analytify-promo-popup-paragraph"><?php esc_html_e( 'Email notifications add-on extends the Analytify Pro, and enables more control on customizing Analytics Email reports for your websites, delivers Analytics summaries straight in your inbox weekly and monthly.', 'wp-analytify' ); ?></p>
947 <ul class="analytify-promo-popup-list">
948 <li><?php esc_html_e( 'Add your logo', 'wp-analytify' ); ?></li>
949 <li><?php esc_html_e( 'Choose your own metrics to display in reports', 'wp-analytify' ); ?></li>
950 <li><?php esc_html_e( 'Edit Email Subject', 'wp-analytify' ); ?></li>
951 <li><?php esc_html_e( 'Add personal note', 'wp-analytify' ); ?></li>
952 <li><?php esc_html_e( 'Schedule weekly reports', 'wp-analytify' ); ?></li>
953 <li><?php esc_html_e( 'Schedule monthly reports', 'wp-analytify' ); ?></li>
954 </ul>
955 <a href="<?php echo esc_url( $url ); ?>" class="analytify-promo-popup-btn" target="_blank"><?php echo esc_html( $url_text ); ?></a>
956 </div>
957 </div>
958 </div>
959 <?php
960 }
961
962 /**
963 * Help tab content.
964 *
965 * @return void
966 */
967 public function callback_email_form() {
968 ?>
969 <form class="analyitfy-email-test" action="" method="post">
970 <input type="submit" name="test_email" class="analytify_test_email_btn" value="<?php esc_attr_e( 'Test Email', 'wp-analytify' ); ?>" />
971 <span class="analytify_setting_note"><?php esc_html_e( 'Note: Please save changes before sending a test email.', 'wp-analytify' ); ?></span>
972 </form>
973 <?php
974 }
975 }