PluginProbe ʕ •ᴥ•ʔ
Hustle – Email Marketing, Lead Generation, Optins, Popups / 7.3.7
Hustle – Email Marketing, Lead Generation, Optins, Popups v7.3.7
7.8.14 7.8.14.1 7.8.13 7.8.13.1 trunk 3.0 3.1 3.1.1 3.1.2 3.1.3 3.1.4 4.3.2 4.4.4 4.4.5 4.4.5.1 4.4.5.4 4.6 4.6.1.1 4.6.1.4 4.7.0.2 4.7.0.3 4.7.0.7 4.7.0.9 4.7.1.0 4.7.1.1 4.8.0.0 5.0.0 5.0.1 5.0.1.1 5.0.1.2 5.1 5.1.1 5.1.2 5.1.3 5.1.3.1 5.1.3.2 5.1.4 5.1.5 6.0 6.0.1 6.0.2 6.0.3 6.0.4.2 6.0.5 6.0.6.1 6.0.7 6.0.8.1 6.0.9 7.0.0.1 7.0.2 7.0.3 7.0.4 7.1.0 7.1.1 7.2.0 7.2.1 7.3.0 7.3.1 7.3.3 7.3.5 7.3.6 7.3.7 7.4.0 7.4.1 7.4.11 7.4.13 7.4.13.1 7.4.2 7.4.3 7.4.4 7.4.5 7.4.5.1 7.4.5.2 7.4.6 7.4.7 7.5.0 7.6.0 7.6.1 7.6.3 7.6.4 7.6.6 7.7.0 7.7.1 7.8.0 7.8.1 7.8.10 7.8.10.1 7.8.10.2 7.8.11 7.8.12 7.8.12.1 7.8.2 7.8.3 7.8.4 7.8.5 7.8.6 7.8.7 7.8.8 7.8.9 7.8.9.1 7.8.9.2 7.8.9.3
wordpress-popup / inc / class-hustle-wp-dashboard-page.php
wordpress-popup / inc Last commit date
display-conditions 5 years ago front 5 years ago helpers 5 years ago metas 5 years ago palettes 5 years ago provider 5 years ago providers 5 years ago templates 5 years ago update 5 years ago class-hustle-admin-page-abstract.php 5 years ago class-hustle-condition-factory.php 6 years ago class-hustle-dashboard-admin.php 5 years ago class-hustle-data.php 5 years ago class-hustle-db.php 6 years ago class-hustle-module-admin.php 5 years ago class-hustle-module-collection.php 5 years ago class-hustle-module-decorator.php 5 years ago class-hustle-module-page-abstract.php 5 years ago class-hustle-notifications.php 5 years ago class-hustle-settings-admin.php 5 years ago class-hustle-upsell-page.php 5 years ago class-hustle-wp-dashboard-page.php 5 years ago hustle-collection.php 6 years ago hustle-deletion.php 5 years ago hustle-embedded-admin.php 6 years ago hustle-entries-admin.php 5 years ago hustle-entry-model.php 5 years ago hustle-general-data-protection.php 6 years ago hustle-init.php 5 years ago hustle-mail.php 5 years ago hustle-meta.php 5 years ago hustle-migration.php 5 years ago hustle-model.php 5 years ago hustle-module-model.php 5 years ago hustle-module-widget-legacy.php 5 years ago hustle-module-widget.php 5 years ago hustle-modules-common-admin-ajax.php 5 years ago hustle-popup-admin.php 6 years ago hustle-providers-admin.php 5 years ago hustle-providers.php 6 years ago hustle-settings-admin-ajax.php 5 years ago hustle-settings-page.php 5 years ago hustle-slidein-admin.php 6 years ago hustle-sshare-admin.php 5 years ago hustle-sshare-model.php 5 years ago hustle-tracking-model.php 5 years ago opt-in-geo.php 5 years ago opt-in-utils.php 5 years ago opt-in-wpmudev-api.php 6 years ago
class-hustle-wp-dashboard-page.php
546 lines
1 <?php
2 /**
3 * File for Hustle_Wp_Dashboard_Page class.
4 *
5 * @package Hustle
6 * @since 4.2.1
7 */
8
9 /**
10 * Class Hustle_Wp_Dashboard_Page.
11 * Handles scripts and actions for the WP Dashboard Page.
12 *
13 * @since 4.2.1
14 */
15 class Hustle_Wp_Dashboard_Page {
16
17 /**
18 * Hustle's settings for the WP Dashboard analytics widget.
19 *
20 * @since 4.2.1
21 * @var array
22 */
23 private $settings;
24
25 /**
26 * Class constructor.
27 *
28 * @since 4.2.1
29 * @param array $analytics_settings Hustle's settings for the WP Dashboard analytics widget.
30 */
31 public function __construct( $analytics_settings ) {
32
33 $this->settings = $analytics_settings;
34
35 // Load styles for Dashboard.
36 add_action( 'admin_print_styles', array( $this, 'register_dashboard_styles' ) );
37 add_filter( 'admin_body_class', array( $this, 'admin_dashboard_body_class' ), 99 );
38
39 // Load scripts for Dashboard.
40 add_action( 'admin_enqueue_scripts', array( $this, 'register_scripts' ) );
41
42 add_action( 'wp_dashboard_setup', array( $this, 'analytics_widget_setup' ) );
43
44 add_action( 'wp_ajax_hustle_get_wp_dashboard_widget_data', array( $this, 'get_wp_dashboard_widget_data' ) );
45 }
46
47 /**
48 * Registers styles for admin dashboard.
49 *
50 * @since 4.2.1
51 */
52 public function register_dashboard_styles() {
53 wp_register_style(
54 'hstl-roboto',
55 'https://fonts.googleapis.com/css?family=Roboto+Condensed:300,300i,400,400i,700,700i|Roboto:300,300i,400,400i,500,500i,700,700i',
56 array(),
57 Opt_In::VERSION
58 );
59
60 wp_register_style(
61 'hstl-opensans',
62 'https://fonts.googleapis.com/css?family=Open+Sans:400,400i,700,700i',
63 array(),
64 Opt_In::VERSION
65 );
66
67 wp_enqueue_style( 'hstl-roboto' );
68 wp_enqueue_style( 'hstl-opensans' );
69
70 wp_enqueue_style(
71 'hustle_dashboard_styles',
72 Opt_In::$plugin_url . 'assets/css/dashboard.min.css',
73 array(),
74 Opt_In::VERSION
75 );
76 }
77
78 /**
79 * Registers scripts.
80 *
81 * @since 4.2.1
82 */
83 public function register_scripts() {
84
85 wp_enqueue_script(
86 'chartjs',
87 Opt_In::$plugin_url . 'assets/js/vendor/chartjs/Chart.bundle.min.js',
88 array(),
89 '2.7.2',
90 true
91 );
92
93 $file_suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'debug' : 'min';
94 wp_register_script(
95 'hustle_wp_dashboard_script',
96 Opt_In::$plugin_url . 'assets/js/wp-dashboard.' . $file_suffix . '.js',
97 array( 'jquery', 'chartjs' ),
98 Opt_In::VERSION,
99 true
100 );
101
102 // Days labels for the chart.
103 for ( $h = 89; $h >= 0; $h-- ) {
104 $time = strtotime( '-' . $h . ' days' );
105 $days_array[] = strftime( '%B %d', $time );
106 }
107
108 // These are the labels for the different tracking types.
109 $tracking_actions = array(
110 'view' => esc_html__( 'Views', 'hustle' ),
111 'conversion' => esc_html__( 'All Conversions', 'hustle' ),
112 'cta_conversion' => esc_html__( 'CTA Conversions', 'hustle' ),
113 'optin_conversion' => esc_html__( 'Optin Conversions', 'hustle' ),
114 'rate' => esc_html__( 'Conversion Rate', 'hustle' ),
115 );
116
117 $data = array(
118 'days_labels' => $days_array,
119 'tracking_actions' => $tracking_actions,
120 'active_module_types' => $this->settings['modules'],
121 );
122
123 wp_localize_script( 'hustle_wp_dashboard_script', 'hustleVars', $data );
124 wp_enqueue_script( 'hustle_wp_dashboard_script' );
125 }
126
127 /**
128 * Modify admin dashboard body class to our own advantage.
129 *
130 * @since 4.2.1
131 *
132 * @param string $classes Current classes.
133 * @return mixed
134 */
135 public function admin_dashboard_body_class( $classes ) {
136 $classes .= ' sui-hustle-dashboard';
137
138 return $classes;
139
140 }
141
142 /**
143 * Setup the Hustle analytics dashboard widgets.
144 *
145 * @since 4.1.0
146 */
147 public function analytics_widget_setup() {
148
149 $title = ! empty( $this->settings['title'] ) ? $this->settings['title'] : ' ';
150 wp_add_dashboard_widget(
151 'hustle_analytics',
152 esc_html( $title ),
153 array( $this, 'render_analytics_widget' )
154 );
155 }
156
157 /**
158 * Outputs the Analytics dashboard widget.
159 *
160 * @since 4.1.0
161 *
162 * @param string $post Widget Control ID.
163 */
164 public function render_analytics_widget( $post ) {
165
166 $renderer = new Hustle_Layout_Helper( $this );
167 $renderer->render(
168 'admin/widget-analytics',
169 array(
170 'settings' => $this->settings,
171 )
172 );
173 }
174
175 /**
176 * Get analytics ranges for dashboard widget
177 *
178 * @since 4.2.1
179 * @return array
180 */
181 public function get_analytic_ranges() {
182 $ranges = array(
183 7 => __( 'Last 7 days', 'hustle' ),
184 30 => __( 'Last 30 days', 'hustle' ),
185 90 => __( 'Last 90 days', 'hustle' ),
186 );
187
188 return $ranges;
189 }
190
191 /**
192 * Retrieves the data for the widget via AJAX.
193 *
194 * @since 4.2.1
195 */
196 public function get_wp_dashboard_widget_data() {
197
198 Opt_In_Utils::validate_ajax_call( 'hustle_update_wp_dashboard_chart' );
199
200 $days_range = filter_input( INPUT_POST, 'days', FILTER_VALIDATE_INT );
201 $tracking_type = filter_input( INPUT_POST, 'trackingType', FILTER_SANITIZE_STRING );
202
203 $module_types_to_display = $this->settings['modules'];
204
205 // The required fields are missing. Abort.
206 if ( ! $days_range || ! $tracking_type || empty( $module_types_to_display ) ) {
207 wp_send_json_error();
208 }
209
210 $allowed_ranges = array_keys( $this->get_analytic_ranges() );
211 $days_range = in_array( $days_range, $allowed_ranges, true ) ? $days_range : 7;
212
213 // Try to retrieve the cached data.
214 $transient_key = 'hustle_wp_widget_daily_stats_' . $days_range;
215 // $widget_data = get_transient( $transient_key );
216
217 // Retrieve the data if not cached.
218 // if ( false === $widget_data ) {
219
220 $widget_data = $this->get_formatted_tracking_data( $days_range );
221
222 // Cache for today.
223 // The transient expires tonight at midnight, following WP's timezone.
224 // $timezone = wp_timezone();
225 // $date = new DateTime( 'tomorrow', $timezone );
226 // $trasient_expire = $date->format( 'U' ) - time();
227 // set_transient( $transient_key, $widget_data, $trasient_expire );
228 // }
229
230 wp_send_json_success( $widget_data );
231 }
232
233 /**
234 * Gets the data formatted as it's expected for the chart.
235 *
236 * @since 4.2.1
237 *
238 * @param integer $days_range Days before today.
239 * @return array
240 */
241 private function get_formatted_tracking_data( $days_range ) {
242
243 $tracking = Hustle_Tracking_Model::get_instance();
244
245 // Daily stats for the period.
246 $daily_stats = $this->get_and_format_daily_stats( $days_range, $tracking );
247
248 // Totals from the previous range.
249 $previous_range_totals = $this->get_and_format_prev_range_totals( $days_range, $tracking );
250
251 // Overall totals to show, including the growth rate.
252 $totals = $this->get_analytics_totals( $daily_stats, $previous_range_totals );
253
254 $widget_data = array(
255 'data' => $daily_stats,
256 'totals' => $totals,
257 );
258
259 return $widget_data;
260 }
261
262 /**
263 * Gets the raw values for the daily stats and formats it.
264 *
265 * @since 4.2.1
266 *
267 * @param integer $days_range Number of days before today.
268 * @param Hustle_Tracking_Model $tracking Instance of the tracking model.
269 * @return array
270 */
271 private function get_and_format_daily_stats( $days_range, $tracking ) {
272
273 $raw_result = $tracking->get_wp_dash_daily_stats_data( $days_range );
274 $final_data = $this->get_default_analytics_stats( $days_range );
275
276 foreach ( $raw_result as $data ) {
277
278 $module_type = $data['module_type'];
279 $action = $data['action'];
280
281 $day = explode( ' ', $data['date_created'] )[0];
282
283 // Use the default days as the base. Skip the current day if it's not defined.
284 if ( ! isset( $final_data[ $module_type ][ $action ][ $day ] ) ) {
285 continue;
286 }
287 $final_data[ $module_type ][ $action ][ $day ] += $data['counter'];
288 $final_data['overall'][ $action ][ $day ] += $data['counter'];
289
290 // We have 2 conversion types: CTA and Optin. We also have an overall
291 // count for conversions under simply 'conversion'. Sum these for that metric.
292 if ( 'optin_conversion' === $action || 'cta_conversion' === $action ) {
293 $final_data[ $module_type ]['conversion'][ $day ] += $data['counter'];
294 $final_data['overall']['conversion'][ $day ] += $data['counter'];
295 }
296
297 // Module types for embeds and ssharing module have the display type suffixed.
298 // Map these to their main module type.
299 if ( 0 === strpos( $module_type, 'embedded_' ) ) {
300 $final_data['embedded'][ $action ][ $day ] += $data['counter'];
301
302 // Same check as before: We merge CTA and Optin conversions into the 'conversion' key.
303 if ( 'optin_conversion' === $action || 'cta_conversion' === $action ) {
304 $final_data['embedded']['conversion'][ $day ] += $data['counter'];
305 }
306 }
307 if ( 0 === strpos( $module_type, 'social_sharing_' ) ) {
308 $final_data['social_sharing'][ $action ][ $day ] += $data['counter'];
309 }
310 }
311
312 // Count rates.
313 foreach ( $final_data as $block => $types ) {
314
315 // Calculate the rates.
316 foreach ( $types as $type => $days ) {
317 if ( 'rate' !== $type ) {
318 continue;
319 }
320 foreach ( $days as $day => $val ) {
321 if ( ! empty( $final_data[ $block ]['view'][ $day ] ) && ! empty( $final_data[ $block ]['conversion'][ $day ] ) ) {
322 $final_data[ $block ]['rate'][ $day ] = round( 100 * $final_data[ $block ]['conversion'][ $day ] / $final_data[ $block ]['view'][ $day ], 2 );
323 }
324 }
325 }
326 }
327
328 return $final_data;
329 }
330
331 /**
332 * Gets default analytics stats with zero values.
333 *
334 * @since 4.1.0
335 *
336 * @param int $days_ago Number of days ago when to begin the stats.
337 * @return array
338 */
339 private function get_default_analytics_stats( $days_ago ) {
340 $days = array();
341 $days_ago--;
342
343 for ( $i = $days_ago; 0 <= $i; $i-- ) {
344 $days[] = date( 'Y-m-d', time() - $i * DAY_IN_SECONDS ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
345 }
346
347 $all_blocks = array(
348 'overall',
349 'popup',
350 'slidein',
351 'embedded',
352 'embedded_inline',
353 'embedded_widget',
354 'embedded_shortcode',
355 'social_sharing',
356 'social_sharing_floating',
357 'social_sharing_inline',
358 'social_sharing_widget',
359 'social_sharing_shortcode',
360 );
361
362 $all_types = array(
363 'view',
364 'conversion',
365 'cta_conversion',
366 'optin_conversion',
367 'rate',
368 );
369 $final_data = array();
370 foreach ( $all_blocks as $block ) {
371 foreach ( $all_types as $type ) {
372 foreach ( $days as $day ) {
373 $final_data[ $block ][ $type ][ $day ] = 0;
374 }
375 }
376 }
377
378 return $final_data;
379 }
380
381 /**
382 * Gets the raw values for the previous range totals and formats it.
383 * This is used to define the growth rate.
384 *
385 * @since 4.2.1
386 *
387 * @param integer $days_range Number of days before today.
388 * @param Hustle_Tracking_Model $tracking Instance of the tracking model.
389 * @return array
390 */
391 private function get_and_format_prev_range_totals( $days_range, $tracking ) {
392
393 $module_types_map = array(
394 'popup' => Hustle_Module_Model::POPUP_MODULE,
395 'slidein' => Hustle_Module_Model::SLIDEIN_MODULE,
396 'embedded_inline' => Hustle_Module_Model::EMBEDDED_MODULE,
397 'embedded_shortcode' => Hustle_Module_Model::EMBEDDED_MODULE,
398 'embedded_widget' => Hustle_Module_Model::EMBEDDED_MODULE,
399 'social_sharing_inline' => Hustle_Module_Model::SOCIAL_SHARING_MODULE,
400 'social_sharing_shortcode' => Hustle_Module_Model::SOCIAL_SHARING_MODULE,
401 'social_sharing_widget' => Hustle_Module_Model::SOCIAL_SHARING_MODULE,
402 'social_sharing_floating' => Hustle_Module_Model::SOCIAL_SHARING_MODULE,
403 );
404
405 $default_action_counters = array(
406 'view' => 0,
407 'conversion' => 0,
408 'cta_conversion' => 0,
409 'optin_conversion' => 0,
410 'rate' => 0,
411 );
412
413 $main_counter = array(
414 'overall' => $default_action_counters,
415 Hustle_Module_Model::POPUP_MODULE => $default_action_counters,
416 Hustle_Module_Model::SLIDEIN_MODULE => $default_action_counters,
417 Hustle_Module_Model::EMBEDDED_MODULE => $default_action_counters,
418 Hustle_Module_Model::SOCIAL_SHARING_MODULE => $default_action_counters,
419 );
420
421 // Get the raw data from the tracking model.
422 $raw_result = $tracking->get_per_module_type_totals_prev_range( $days_range );
423
424 // Loop through the results, which are grouped by module type.
425 // The possible module types are the keys from the array $module_types_map.
426 foreach ( $raw_result as $data ) {
427
428 // Not a valid module type, abort.
429 if ( empty( $module_types_map[ $data->module_type ] ) ) {
430 continue;
431 }
432
433 // Not a valid action, abort.
434 if ( ! isset( $default_action_counters[ $data->action ] ) ) {
435 continue;
436 }
437
438 $module_type = $module_types_map[ $data->module_type ];
439 $action = $data->action;
440 $count = $data->tracked_count;
441
442 $main_counter[ $module_type ][ $action ] += $count;
443
444 $main_counter['overall'][ $action ] += $count;
445 }
446
447 // Let's now calculate the total conversions (CTA + Optin), the conversion rate, and overalls.
448 foreach ( $main_counter as $module_type => $action_counter ) {
449
450 $conversion_count = $action_counter['optin_conversion'] + $action_counter['cta_conversion'];
451
452 $rate = 0;
453 $total_views = $action_counter['view'];
454 if ( $total_views && $conversion_count ) {
455 $rate = round( ( $conversion_count / $total_views ) * 100, 2 );
456 }
457
458 $main_counter[ $module_type ]['rate'] = $rate;
459
460 $main_counter[ $module_type ]['conversion'] = $conversion_count;
461 }
462
463 return $main_counter;
464 }
465
466 /**
467 * Calculate the totals from the numbers we already got.
468 * Here you get the per module total for each tracking
469 * action (cta conversion, optin conversion, view),
470 * as well as the growth rate compared to the previous
471 * period of the same current length.
472 *
473 * @since 4.2.1
474 *
475 * @param array $stats The per day tracking data already retrieved for the chart.
476 * @param array $previous_range_totals The totals for the previous range.
477 * @return array
478 */
479 private function get_analytics_totals( $stats, $previous_range_totals ) {
480
481 $total_count = array();
482 foreach ( $stats as $module_type => $action_data ) {
483
484 // Skip the module types with their display type attached. We won't be using these.
485 if ( 0 === strpos( $module_type, 'embedded_' ) || 0 === strpos( $module_type, 'social_sharing_' ) ) {
486 continue;
487 }
488
489 foreach ( $action_data as $tracking_action => $data ) {
490
491 // We'll handle the conversion rate in a sec.
492 if ( 'rate' === $tracking_action ) {
493 continue;
494 }
495
496 $prev_period_total = $previous_range_totals[ $module_type ][ $tracking_action ];
497 $current_total = array_sum( $data );
498 $growth = $this->calculate_growth( $current_total, $prev_period_total );
499
500 $total_count[ $module_type ][ $tracking_action ] = array(
501 'total' => $current_total,
502 'trend' => $growth,
503 );
504
505 }
506
507 // Let's calculate the conversion rate.
508 $rate = 0;
509 $total_views = $total_count[ $module_type ]['view']['total'];
510 $total_conversions = $total_count[ $module_type ]['conversion']['total'];
511 if ( $total_views && $total_conversions ) {
512 $rate = round( ( $total_conversions / $total_views ) * 100, 2 );
513 }
514 $prev_period_rate = $previous_range_totals[ $module_type ]['rate'];
515 $rate_growth = $this->calculate_growth( $rate, $prev_period_rate );
516
517 $total_count[ $module_type ]['rate'] = array(
518 'total' => $rate,
519 'trend' => $rate_growth,
520 );
521 }
522
523 return $total_count;
524 }
525
526 /**
527 * Calculates the growth between two values.
528 *
529 * @since 4.2.1
530 *
531 * @param int $current_total Value of the current range.
532 * @param int $prev_period_total Value of the previous range.
533 * @return int
534 */
535 private function calculate_growth( $current_total, $prev_period_total ) {
536
537 $growth = 0;
538 if ( $current_total && $prev_period_total ) {
539
540 $growth = ( $current_total - $prev_period_total ) / $prev_period_total * 100;
541 $growth = round( $growth, 2 );
542 }
543 return $growth;
544 }
545 }
546