Email Subscribers & Newsletters - Version 5.3.16

Version Description

  • Enhancement: Improved dashboard stats
  • Fix: Warning message when using Gmail/Yahoo email addresses in From email setting
  • Fix: Email sending issue with Amazon SES when subject contains emojis[PRO]
  • Fix: Duplicate post digest notifications[PRO]
  • Fix: Unsubscribe message getting inserted after HTML tag
  • Fix: Caching issue when editing campaign when Redis cache enable
  • Fix: PHP warning when subscription form is deleted from backend and form widget is active on frontend
  • Fix: Incorrect link tracking stats for campaigns created using Drag-n-Drop editor[PR0]

=

Download this release

Release Info

Developer Icegram
Plugin Icon 128x128 Email Subscribers & Newsletters
Version 5.3.16
Comparing to
See all releases

Code changes from version 5.3.15 to 5.3.16

email-subscribers.php CHANGED
@@ -3,11 +3,11 @@
3
  * Plugin Name: Email Subscribers & Newsletters
4
  * Plugin URI: https://www.icegram.com/
5
  * Description: Add subscription forms on website, send HTML newsletters & automatically notify subscribers about new blog posts once it is published.
6
- * Version: 5.3.15
7
  * Author: Icegram
8
  * Author URI: https://www.icegram.com/
9
  * Requires at least: 3.9
10
- * Tested up to: 5.9.3
11
  * WC requires at least: 3.6.0
12
  * WC tested up to: 5.5.1
13
  * ES Woo: 7120515:9f4c7f8bb491260ef19edf9699db73e6
@@ -187,7 +187,7 @@ if ( 'premium' === $ig_es_plan ) {
187
  /* ***************************** Initial Compatibility Work (End) ******************* */
188
 
189
  if ( ! defined( 'ES_PLUGIN_VERSION' ) ) {
190
- define( 'ES_PLUGIN_VERSION', '5.3.15' );
191
  }
192
 
193
  // Plugin Folder Path.
3
  * Plugin Name: Email Subscribers & Newsletters
4
  * Plugin URI: https://www.icegram.com/
5
  * Description: Add subscription forms on website, send HTML newsletters & automatically notify subscribers about new blog posts once it is published.
6
+ * Version: 5.3.16
7
  * Author: Icegram
8
  * Author URI: https://www.icegram.com/
9
  * Requires at least: 3.9
10
+ * Tested up to: 6.0
11
  * WC requires at least: 3.6.0
12
  * WC tested up to: 5.5.1
13
  * ES Woo: 7120515:9f4c7f8bb491260ef19edf9699db73e6
187
  /* ***************************** Initial Compatibility Work (End) ******************* */
188
 
189
  if ( ! defined( 'ES_PLUGIN_VERSION' ) ) {
190
+ define( 'ES_PLUGIN_VERSION', '5.3.16' );
191
  }
192
 
193
  // Plugin Folder Path.
lite/admin/class-email-subscribers-admin.php CHANGED
@@ -219,6 +219,10 @@ class Email_Subscribers_Admin {
219
  'is_pro' => ES()->is_pro() ? true : false,
220
  );
221
 
 
 
 
 
222
  wp_localize_script( $this->email_subscribers, 'ig_es_js_data', $ig_es_js_data );
223
 
224
  if ( 'es_workflows' === $get_page ) {
219
  'is_pro' => ES()->is_pro() ? true : false,
220
  );
221
 
222
+ if ( 'es_settings' === $get_page ) {
223
+ $ig_es_js_data['popular_domains'] = ES_Common::get_popular_domains();
224
+ }
225
+
226
  wp_localize_script( $this->email_subscribers, 'ig_es_js_data', $ig_es_js_data );
227
 
228
  if ( 'es_workflows' === $get_page ) {
lite/admin/css/email-subscribers-admin.css CHANGED
@@ -2227,6 +2227,7 @@ body[class*="es_reports"] .recipient-text {
2227
  transform: translate(-50%,0%);
2228
  left: 50%;
2229
  opacity: 0.9;
 
2230
  }
2231
 
2232
  .es-tooltip .tooltip-text svg {
@@ -2451,4 +2452,150 @@ button#close-campaign-preview-popup {
2451
  color: #8b8f95;
2452
  pointer-events: none;
2453
  }
2454
- /** Onboarding CSS - END */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2227
  transform: translate(-50%,0%);
2228
  left: 50%;
2229
  opacity: 0.9;
2230
+ z-index: 9999;
2231
  }
2232
 
2233
  .es-tooltip .tooltip-text svg {
2452
  color: #8b8f95;
2453
  pointer-events: none;
2454
  }
2455
+ /** Onboarding CSS - END */
2456
+
2457
+ /** Enagement Score CSS - START **/
2458
+
2459
+ /* Variables */
2460
+ .es-items-lists table.contacts, .dashboard-engagement-score-stat {
2461
+ --rating-size: 30px;
2462
+ --bar-size: 3px;
2463
+ --background-color: #e7f2fa;
2464
+ --rating-color-default: #2980b9;
2465
+ --rating-color-background: #c7e1f3;
2466
+ --rating-color-excellent: #56C624;
2467
+ --rating-color-good: #AAD31F;
2468
+ --rating-color-low: #FCD10F;
2469
+ --rating-color-very-low: #FD7925;
2470
+ --rating-color-bad: #FF2F22;
2471
+ --bounce-color-background-low: rgba(255,165,0,0.1);
2472
+ --bounce-color-background-high: rgba(255,0,0,0.1);
2473
+ }
2474
+
2475
+ .es-items-lists table.contacts #engagement_score {
2476
+ width: 70px;
2477
+ }
2478
+
2479
+ /* Rating item */
2480
+ .es-items-lists table.contacts .es-engagement-score,
2481
+ .dashboard-engagement-score-stat .es-engagement-score {
2482
+ position: relative;
2483
+ display: flex;
2484
+ align-items: center;
2485
+ justify-content: center;
2486
+ border-radius: 100%;
2487
+ overflow: hidden;
2488
+
2489
+ background: var(--rating-color-default);
2490
+ color: var(--rating-color-default);
2491
+ width: var(--rating-size);
2492
+ height: var(--rating-size);
2493
+
2494
+ /* Basic style for the text */
2495
+ font-size: calc(var(--rating-size) / 3);
2496
+ line-height: 1;
2497
+ }
2498
+
2499
+ /* Rating circle content */
2500
+ .es-items-lists table.contacts .es-engagement-score span,
2501
+ .dashboard-engagement-score-stat .es-engagement-score span {
2502
+ position: relative;
2503
+ display: flex;
2504
+ font-weight: normal;
2505
+ color:#000;
2506
+ z-index: 2;
2507
+ }
2508
+
2509
+ .es-items-lists table.contacts .es-engagement-score span small,
2510
+ .dashboard-engagement-score-stat .es-engagement-score span small {
2511
+ font-size: 0.5em;
2512
+ font-weight: 900;
2513
+ align-self: center;
2514
+ }
2515
+
2516
+ /* Bar mask, creates an inner circle with the same color as thee background */
2517
+ .es-items-lists table.contacts .es-engagement-score::after,
2518
+ .dashboard-engagement-score-stat .es-engagement-score::after {
2519
+ content: "";
2520
+ position: absolute;
2521
+ top: var(--bar-size);
2522
+ right: var(--bar-size);
2523
+ bottom: var(--bar-size);
2524
+ left: var(--bar-size);
2525
+ background: var(--background-color);
2526
+ border-radius: inherit;
2527
+ z-index: 1;
2528
+ }
2529
+
2530
+ /* Bar background */
2531
+ .es-items-lists table.contacts .es-engagement-score::before,
2532
+ .dashboard-engagement-score-stat .es-engagement-score::before {
2533
+ content: "";
2534
+ position: absolute;
2535
+ top: var(--bar-size);
2536
+ right: var(--bar-size);
2537
+ bottom: var(--bar-size);
2538
+ left: var(--bar-size);
2539
+ border-radius: inherit;
2540
+ box-shadow: 0 0 0 1rem var(--rating-color-background);
2541
+ z-index: -1;
2542
+ }
2543
+
2544
+ /* Classes to give different colors to ratings, based on their score */
2545
+ .es-items-lists table.contacts .es-engagement-score.excellent,
2546
+ .dashboard-engagement-score-stat .es-engagement-score.excellent {
2547
+ background: var(--rating-color-excellent);
2548
+ color: var(--rating-color-excellent);
2549
+ }
2550
+
2551
+ .es-items-lists table.contacts .es-engagement-score.good,
2552
+ .dashboard-engagement-score-stat .es-engagement-score.good {
2553
+ background: var(--rating-color-good);
2554
+ color: var(--rating-color-good);
2555
+ }
2556
+
2557
+ .es-items-lists table.contacts .es-engagement-score.low,
2558
+ .dashboard-engagement-score-stat .es-engagement-score.low {
2559
+ background: var(--rating-color-low);
2560
+ color: var(--rating-color-low);
2561
+ }
2562
+
2563
+ .es-items-lists table.contacts .es-engagement-score.very-low,
2564
+ .es-items-lists table.contacts .es-engagement-score.very-low {
2565
+ background: var(--rating-color-very-low);
2566
+ color: var(--rating-color-very-low);
2567
+ }
2568
+
2569
+ .es-items-lists table.contacts .es-engagement-score.bad,
2570
+ .dashboard-engagement-score-stat .es-engagement-score.bad {
2571
+ background: var(--rating-color-bad);
2572
+ }
2573
+
2574
+ .es-items-lists table.contacts .es-engagement-score.bad span,
2575
+ .dashboard-engagement-score-stat .es-engagement-score.bad span {
2576
+ color: var(--rating-color-bad);;
2577
+ }
2578
+
2579
+ .es-items-lists table.contacts #es_email_status,
2580
+ .dashboard-engagement-score-stat #es_email_status {
2581
+ width: 120px;
2582
+ }
2583
+
2584
+ /* .es-tooltip .tooltip-text #device_open_graph svg,
2585
+ .es-tooltip .tooltip-text #sources_graph svg,
2586
+ .es-tooltip .tooltip-text #unsubscribe_feedbacks_graph svg {
2587
+ left: 0;
2588
+ transform: none;
2589
+ top: 50%;}
2590
+
2591
+
2592
+
2593
+ .es-dashboard-stats-item .tooltip-text {background: transparent;}
2594
+
2595
+ .es-dashboard-stats-item .es-tooltip .tooltip-text {right: 25px;
2596
+ top: 50%;left: initial;transform: translate(50%,0%);
2597
+ /* left: 50%; */
2598
+ /* opacity: 0.9;z-index: 999;} */
2599
+
2600
+ /* .es-dashboard-stats-item svg.tooltip-arrow {display: none;} */
2601
+ /** Enagement Score CSS - END **/
lite/admin/js/email-subscribers-admin.js CHANGED
@@ -880,6 +880,19 @@
880
 
881
  jQuery('.es-note-category-parent').trigger('change');
882
 
 
 
 
 
 
 
 
 
 
 
 
 
 
883
 
884
  //es mailer settings
885
  jQuery(document).on('change', '.es_mailer', function (e) {
@@ -2614,6 +2627,38 @@
2614
 
2615
  }
2616
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2617
  });
2618
 
2619
  function ig_es_uc_first(string){
@@ -2936,7 +2981,10 @@ function ig_es_is_valid_json( string ) {
2936
  return true;
2937
  }
2938
 
2939
-
 
 
 
2940
 
2941
  window.ig_es_is_valid_json = ig_es_is_valid_json;
2942
 
880
 
881
  jQuery('.es-note-category-parent').trigger('change');
882
 
883
+ jQuery('#tabs-general input[name="ig_es_from_email"]').on('change', function () {
884
+ let from_email = jQuery(this).val();
885
+ let is_valid_email = ig_es_is_valid_email(from_email);
886
+ if ( is_valid_email ) {
887
+ let from_email_domain = from_email.split('@')[1].toLowerCase();
888
+ let is_popolar_domain = ig_es_js_data.popular_domains.indexOf(from_email_domain) > -1;
889
+ if ( is_popolar_domain ) {
890
+ jQuery('#ig-es-from-email-notice').removeClass('hidden');
891
+ } else {
892
+ jQuery('#ig-es-from-email-notice').addClass('hidden');
893
+ }
894
+ }
895
+ });
896
 
897
  //es mailer settings
898
  jQuery(document).on('change', '.es_mailer', function (e) {
2627
 
2628
  }
2629
 
2630
+
2631
+ // Find al rating items
2632
+ const ratings = document.querySelectorAll(".es-engagement-score");
2633
+
2634
+ // Iterate over all rating items
2635
+ ratings.forEach((rating) => {
2636
+ // Get content and get score as an int
2637
+ const ratingContent = rating.innerHTML;
2638
+ const ratingScore = ratingContent;
2639
+ const ratingPercentage = ( ratingScore / 5 ) * 100;
2640
+
2641
+ // Define if the score is good, meh or bad according to its value
2642
+ // const scoreClass =
2643
+ // ratingScore < 40 ? "bad" : ratingScore < 60 ? "meh" : "good";
2644
+
2645
+ // // Add score class to the rating
2646
+ // rating.classList.add(scoreClass);
2647
+
2648
+ // After adding the class, get its color
2649
+ const ratingColor = window.getComputedStyle(rating).backgroundColor;
2650
+
2651
+ // Define the background gradient according to the score and color
2652
+ const gradient = `background: conic-gradient(${ratingColor} ${ratingPercentage}%, transparent 0 100%)`;
2653
+
2654
+ // Set the gradient as the rating background
2655
+ rating.setAttribute("style", gradient);
2656
+
2657
+ // Wrap the content in a tag to show it above the pseudo element that masks the bar
2658
+ rating.innerHTML = `<span>${ratingScore} ${
2659
+ ratingContent.indexOf("%") >= 0 ? "<small>%</small>" : ""
2660
+ }</span>`;
2661
+ });
2662
  });
2663
 
2664
  function ig_es_uc_first(string){
2981
  return true;
2982
  }
2983
 
2984
+ function ig_es_is_valid_email( email ) {
2985
+ let regex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/;
2986
+ return regex.test(email);
2987
+ }
2988
 
2989
  window.ig_es_is_valid_json = ig_es_is_valid_json;
2990
 
lite/admin/partials/dashboard.php CHANGED
@@ -5,9 +5,11 @@ if ( ! defined( 'ABSPATH' ) ) {
5
  exit;
6
  }
7
 
8
-
 
9
  $reports_data = ES_Reports_Data::get_dashboard_reports_data( 'es_dashboard', true );
10
 
 
11
  $active_contacts = isset( $reports_data['total_contacts'] ) ? $reports_data['total_contacts'] : 0;
12
  $total_forms = isset( $reports_data['total_forms'] ) ? $reports_data['total_forms'] : 0;
13
  $total_campaigns = isset( $reports_data['total_campaigns'] ) ? $reports_data['total_campaigns'] : 0;
@@ -24,6 +26,21 @@ $avg_click_rate = isset( $reports_data['avg_click_rate'] ) ? $reports_data['
24
  $contacts_growth = isset( $reports_data['contacts_growth'] ) ? $reports_data['contacts_growth'] : array();
25
  $campaigns = isset( $reports_data['campaigns'] ) ? $reports_data['campaigns'] : array();
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  $labels = '';
28
  $values = '';
29
  if ( ! empty( $contacts_growth ) ) {
@@ -45,6 +62,7 @@ $templates_url = admin_url( 'edit.php?post_type=es_template' );
45
  $settings_url = admin_url( 'admin.php?page=es_settings' );
46
  $facebook_url = 'https://www.facebook.com/groups/2298909487017349/';
47
 
 
48
  $feature_blocks = array(
49
 
50
  'form' => array(
@@ -137,6 +155,7 @@ $feature_blocks = array_merge( $trial_block, $feature_blocks );
137
  $topics = ES_Common::get_useful_articles();
138
 
139
  $topics_indexes = array_rand( $topics, 3 );
 
140
 
141
  ?>
142
  <div class="wrap pt-4 font-sans" id="ig-es-container">
@@ -202,56 +221,363 @@ $topics_indexes = array_rand( $topics, 3 );
202
 
203
  <main class="mx-auto max-w-7xl">
204
 
205
- <section class="py-4 my-8 bg-white rounded-lg shadow md:flex md:items-start md:justify-between sm:px-4 sm:grid sm:grid-cols-3">
206
- <div class="flex-1 min-w-0">
207
- <p class="px-3 text-lg font-medium leading-6 text-gray-400">
208
- <span class="text-black"><?php echo esc_html( $active_contacts ); ?></span><?php echo esc_html__( ' active contacts', 'email-subscribers' ); ?>
209
- </p>
210
- <div class="text-center bg-white-100" id="ig-es-contacts-growth">
211
-
212
- </div>
213
- </div>
214
- <div class="flex-1 min-w-0">
215
  <p class="px-3 text-lg font-medium leading-6 text-gray-400">
216
  <?php echo esc_html__( 'Last 60 days', 'email-subscribers' ); ?>
217
  </p>
218
- <div class="sm:grid sm:grid-cols-2">
219
- <div class="p-3">
220
- <p class="text-2xl font-bold leading-none text-indigo-600">
221
- <?php echo esc_html( $total_email_opens ); ?>
222
- </p>
223
- <p class="mt-1 font-medium leading-6 text-gray-500">
224
- <?php echo esc_html__( 'Opens', 'email-subscribers' ); ?>
225
- </p>
226
- </div>
227
- <div class="p-3">
228
- <p class="text-2xl font-bold leading-none text-indigo-600">
229
- <?php echo esc_html( $avg_open_rate ); ?> %
230
- </p>
231
- <p class="mt-1 font-medium leading-6 text-gray-500">
232
- <?php echo esc_html__( ' Avg Open Rate', 'email-subscribers' ); ?>
233
- </p>
234
- </div>
235
- <div class="p-3">
236
- <p class="text-2xl font-bold leading-none text-indigo-600">
237
- <?php echo esc_html( $total_message_sent ); ?>
238
- </p>
239
- <p class="mt-1 font-medium leading-6 text-gray-500">
240
- <?php echo esc_html__( 'Messages Sent', 'email-subscribers' ); ?>
241
- </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
  </div>
243
- <div class="p-3">
244
- <p class="text-2xl font-bold leading-none text-indigo-600">
245
- <?php echo esc_html( $avg_click_rate ); ?> %
246
- </p>
247
- <p class="mt-1 font-medium leading-6 text-gray-500">
248
- <?php echo esc_html__( 'Avg Click Rate', 'email-subscribers' ); ?>
249
- </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  </div>
 
251
  </div>
252
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
 
254
- <div class="flex-1 min-w-0">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  <div class="overflow-hidden">
256
  <ul>
257
  <!-- Start-IG-Code -->
@@ -406,20 +732,20 @@ if ( $show_trial_optin ) {
406
  ]
407
  };
408
 
409
- const chart = new frappe.Chart("#ig-es-contacts-growth", {
410
- title: "",
411
- data: data,
412
- type: 'line',
413
- colors: ['#743ee2'],
414
- lineOptions: {
415
- hideDots: 1,
416
- heatline: 1
417
- },
418
- height: 150,
419
- axisOptions: {
420
- xIsSeries: true
421
- }
422
- });
423
  }
424
 
425
  });
5
  exit;
6
  }
7
 
8
+ global $wpdb;
9
+ $number_of_days = 60;
10
  $reports_data = ES_Reports_Data::get_dashboard_reports_data( 'es_dashboard', true );
11
 
12
+ $total_contacts_subscribed = isset( $reports_data['total_contacts_subscribed'] ) ? $reports_data['total_contacts_subscribed'] : 0;
13
  $active_contacts = isset( $reports_data['total_contacts'] ) ? $reports_data['total_contacts'] : 0;
14
  $total_forms = isset( $reports_data['total_forms'] ) ? $reports_data['total_forms'] : 0;
15
  $total_campaigns = isset( $reports_data['total_campaigns'] ) ? $reports_data['total_campaigns'] : 0;
26
  $contacts_growth = isset( $reports_data['contacts_growth'] ) ? $reports_data['contacts_growth'] : array();
27
  $campaigns = isset( $reports_data['campaigns'] ) ? $reports_data['campaigns'] : array();
28
 
29
+ $open_percentage_growth = isset( $reports_data['open_percentage_growth'] ) ? $reports_data['open_percentage_growth'] : 0;
30
+ $open_before_two_months = isset( $reports_data['open_before_two_months'] ) ? $reports_data['open_before_two_months'] : 0;
31
+ $click_percentage_growth = isset( $reports_data['click_percentage_growth'] ) ? $reports_data['click_percentage_growth'] : 0;
32
+ $click_before_two_months = isset( $reports_data['click_before_two_months'] ) ? $reports_data['click_before_two_months'] : 0;
33
+ $average_engagement_score = isset( $reports_data['average_engagement_score'] ) ? $reports_data['average_engagement_score'] : 0;
34
+ $top_performing_campaigns = isset( $reports_data['top_performing_campaigns'] ) ? $reports_data['top_performing_campaigns'] : array();
35
+
36
+ $growth_percentage = ES_Reports_Data::get_contacts_growth_percentage( $number_of_days );
37
+ $total_unsubscribed = ES_Reports_Data::get_total_unsubscribed_contacts( $number_of_days );
38
+ $last_subscribed_contacts = (int) ES()->contacts_db->get_total_subscribed_contacts_between_days( $number_of_days );
39
+ $convert_date_format = get_option( 'date_format' );
40
+ $last_period_start_date = gmdate( $convert_date_format, strtotime( '-' . ( 2 * $number_of_days ) . ' days' ) );
41
+ $last_period_end_date = gmdate( $convert_date_format, strtotime( '-' . $number_of_days . ' days' ) );
42
+
43
+
44
  $labels = '';
45
  $values = '';
46
  if ( ! empty( $contacts_growth ) ) {
62
  $settings_url = admin_url( 'admin.php?page=es_settings' );
63
  $facebook_url = 'https://www.facebook.com/groups/2298909487017349/';
64
 
65
+
66
  $feature_blocks = array(
67
 
68
  'form' => array(
155
  $topics = ES_Common::get_useful_articles();
156
 
157
  $topics_indexes = array_rand( $topics, 3 );
158
+ $allowed_html_tags = ig_es_allowed_html_tags_in_esc();
159
 
160
  ?>
161
  <div class="wrap pt-4 font-sans" id="ig-es-container">
221
 
222
  <main class="mx-auto max-w-7xl">
223
 
224
+ <section class="es-dashboard-stats-item py-4 my-8 bg-white rounded-lg shadow md:flex md:items-start md:justify-between sm:px-4 sm:grid sm:grid-cols-3">
225
+ <div class="flex-auto min-w-0">
 
 
 
 
 
 
 
 
226
  <p class="px-3 text-lg font-medium leading-6 text-gray-400">
227
  <?php echo esc_html__( 'Last 60 days', 'email-subscribers' ); ?>
228
  </p>
229
+ <div class="grid grid-cols-12 gap-8 p-4 pr-0 text-gray-600">
230
+
231
+ <div class="col-span-6">
232
+ <div class="p-1">
233
+ <span class="text-2xl font-bold leading-none text-indigo-600">
234
+ <?php echo esc_html( $total_contacts_subscribed ); ?>
235
+ </span>
236
+ <?php
237
+ $text_color_class = '';
238
+ $arraw_html = '';
239
+ if ( $growth_percentage < 0 ) {
240
+ $text_color_class = 'text-red-600';
241
+ $arraw_html = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" class="inline-block" fill="currentColor" width="12" height="12"><path fill-rule="evenodd" d="M16.707 10.293a1 1 0 010 1.414l-6 6a1 1 0 01-1.414 0l-6-6a1 1 0 111.414-1.414L9 14.586V3a1 1 0 012 0v11.586l4.293-4.293a1 1 0 011.414 0z" clip-rule="evenodd"></path></svg>';
242
+ } elseif ( 0 === $growth_percentage ) {
243
+ $text_color_class = 'text-orange-600';
244
+ $arraw_html = '';
245
+ } else {
246
+ $text_color_class = 'text-green-600';
247
+ $arraw_html = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" class="inline-block" fill="currentColor" width="12" height="12"><path fill-rule="evenodd" d="M3.293 9.707a1 1 0 010-1.414l6-6a1 1 0 011.414 0l6 6a1 1 0 01-1.414 1.414L11 5.414V17a1 1 0 11-2 0V5.414L4.707 9.707a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg>';
248
+ }
249
+ ?>
250
+ <div class="inline-block es-new-subscriber-growth-percentage es-tooltip relative align-middle cursor-pointer">
251
+ <span class="text-sm mr-0.5 <?php echo esc_attr( $text_color_class ); ?>">
252
+ <?php echo esc_html( $growth_percentage ); ?>%
253
+ <?php echo wp_kses( $arraw_html, $allowed_html_tags ); ?>
254
+ </span>
255
+ <span class="break-words invisible h-auto lg:w-48 xl:w-64 tracking-wide absolute z-70 tooltip-text bg-black text-gray-300 text-xs rounded p-3 py-2">
256
+ <div class="text-white-100">
257
+ <div>
258
+ <span class="text-lg text-base">
259
+ <?php echo esc_html__( 'New subscribers', 'email-subscribers' ); ?>:
260
+ <?php echo esc_html( number_format_i18n( $last_subscribed_contacts ) ); ?>
261
+ </span>
262
+ </div>
263
+ </div>
264
+ <div class="text-xs mt-1 pt-1 text-gray-100 border-t border-gray-100">
265
+ <?php
266
+ /* translators: 1. Start date 2. End date */
267
+ echo esc_html__( sprintf( '%1$s to %2$s', $last_period_start_date, $last_period_end_date ), 'email-subscribers' );
268
+ ?>
269
+ </div>
270
+ <svg class="tooltip-arrow absolute mt-2 text-black text-opacity-100 h-2.5 left-0" viewBox="0 0 255 255">
271
+ <polygon class="fill-current" points="0,0 127.5,127.5 255,0"></polygon>
272
+ </svg>
273
+ </span>
274
+ </div>
275
+ <p class="mt-1 font-medium leading-6 text-gray-500">
276
+ <?php echo esc_html__( 'New subscribers', 'email-subscribers' ); ?> </p>
277
+ </div>
278
+ <div class="p-1">
279
+ <span class="text-2xl font-bold leading-none text-indigo-600">
280
+ <?php echo esc_html( $total_unsubscribed ); ?> </span>
281
+
282
+
283
+ <p class="mt-1 font-medium leading-6 text-gray-500">
284
+ <?php echo esc_html__( 'Unsubscribed', 'email-subscribers' ); ?> </p>
285
+ </div>
286
+ <div class="p-1">
287
+ <span class="text-2xl font-bold leading-none text-indigo-600 dashboard-engagement-score-stat">
288
+ <?php
289
+ $score_class = '';
290
+ $score_text = '';
291
+
292
+ if ( ! ES()->is_pro() ) {
293
+ $average_engagement_score = 4.2;
294
+ }
295
+
296
+ $average_engagement_score_html = ES_Common::get_engagement_score_html( $average_engagement_score );
297
+ ?>
298
+ <?php echo wp_kses_post( $average_engagement_score_html ) ; ?>
299
+ </span>
300
+ <p class="mt-1 font-medium leading-6 text-gray-500">
301
+ <?php echo esc_html__( 'Engagement score', 'email-subscribers' ); ?>
302
+ <?php
303
+ if ( ! ES()->is_pro() ) {
304
+ $utm_args = array(
305
+ 'utm_medium' => 'dashboard-engagement-score-stat',
306
+ 'url' => 'https://www.icegram.com/documentation/how-does-engagement-score-work-in-the-email-subscribers/'
307
+ );
308
+
309
+ $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
310
+ ?>
311
+ <a target="_blank" href="<?php echo esc_url( $pricing_url ); ?>">
312
+ <span class="premium-icon inline-block"></span>
313
+ </a>
314
+ <?php
315
+ }
316
+ ?>
317
+ </p>
318
+ </div>
319
  </div>
320
+ <div class="col-span-6">
321
+ <div class="p-1">
322
+ <span class="text-2xl font-bold leading-none text-indigo-600">
323
+ <?php echo esc_html( $total_message_sent ); ?> </span>
324
+
325
+
326
+
327
+ <p class="mt-1 font-medium leading-6 text-gray-500">
328
+ <?php echo esc_html__( 'Messages sent', 'email-subscribers' ); ?> </p>
329
+ </div>
330
+ <div class="p-1">
331
+ <span class="text-2xl font-bold leading-none text-indigo-600">
332
+ <?php echo esc_html( $total_email_opens ); ?>
333
+ </span>
334
+ <?php
335
+ $text_color_class = '';
336
+ $arraw_html = '';
337
+ if ( $open_percentage_growth < 0 ) {
338
+ $text_color_class = 'text-red-600';
339
+ $arraw_html = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" class="inline-block" fill="currentColor" width="12" height="12"><path fill-rule="evenodd" d="M16.707 10.293a1 1 0 010 1.414l-6 6a1 1 0 01-1.414 0l-6-6a1 1 0 111.414-1.414L9 14.586V3a1 1 0 012 0v11.586l4.293-4.293a1 1 0 011.414 0z" clip-rule="evenodd"></path></svg>';
340
+ } elseif ( 0 === $open_percentage_growth ) {
341
+ $text_color_class = 'text-orange-600';
342
+ $arraw_html = '';
343
+ } else {
344
+ $text_color_class = 'text-green-600';
345
+ $arraw_html = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" class="inline-block" fill="currentColor" width="12" height="12"><path fill-rule="evenodd" d="M3.293 9.707a1 1 0 010-1.414l6-6a1 1 0 011.414 0l6 6a1 1 0 01-1.414 1.414L11 5.414V17a1 1 0 11-2 0V5.414L4.707 9.707a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg>';
346
+ }
347
+ ?>
348
+ <div class="inline-block es-tooltip relative align-middle cursor-pointer">
349
+ <span class="text-sm mr-0.5 <?php echo esc_attr( $text_color_class ); ?>">
350
+ <?php echo esc_html( $open_percentage_growth ); ?>%
351
+ <?php echo wp_kses( $arraw_html, $allowed_html_tags ); ?>
352
+ </span>
353
+ <span class="break-words invisible h-auto lg:w-48 xl:w-64 tracking-wide absolute z-70 tooltip-text bg-black text-gray-300 text-xs rounded p-3 py-2">
354
+ <div class="text-white-100">
355
+ <div>
356
+ <span class="text-lg text-base">
357
+ <?php echo esc_html__( 'Opens', 'email-subscribers' ); ?>:
358
+ <?php echo esc_html( $open_before_two_months ); ?>
359
+ </span>
360
+ </div>
361
+ </div>
362
+ <div class="text-xs mt-1 pt-1 text-gray-100 border-t border-gray-100">
363
+ <?php
364
+ /* translators: 1. Start date 2. End date */
365
+ echo esc_html__( sprintf( '%1$s to %2$s', $last_period_start_date, $last_period_end_date ), 'email-subscribers' );
366
+ ?>
367
+ </div>
368
+ <svg class="tooltip-arrow absolute mt-2 text-black text-opacity-100 h-2.5 left-0" viewBox="0 0 255 255">
369
+ <polygon class="fill-current" points="0,0 127.5,127.5 255,0"></polygon>
370
+ </svg>
371
+ </span>
372
+ </div>
373
+ <span class="es-open-percentage-growth text-2xl font-bold leading-none text-indigo-600">
374
+ <p class="mt-1 font-medium leading-6 text-gray-500">
375
+ <?php echo esc_html__( 'Opens', 'email-subscribers' ); ?>
376
+ </p>
377
+ </span>
378
+ </div>
379
+ <div class="p-1">
380
+ <?php
381
+ $text_color_class = '';
382
+ $arraw_html = '';
383
+ if ( $click_percentage_growth < 0 ) {
384
+ $text_color_class = 'text-red-600';
385
+ $arraw_html = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" class="inline-block" fill="currentColor" width="12" height="12"><path fill-rule="evenodd" d="M16.707 10.293a1 1 0 010 1.414l-6 6a1 1 0 01-1.414 0l-6-6a1 1 0 111.414-1.414L9 14.586V3a1 1 0 012 0v11.586l4.293-4.293a1 1 0 011.414 0z" clip-rule="evenodd"></path></svg>';
386
+ } elseif ( 0 === $click_percentage_growth ) {
387
+ $text_color_class = 'text-orange-600';
388
+ $arraw_html = '';
389
+ } else {
390
+ $text_color_class = 'text-green-600';
391
+ $arraw_html = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" class="inline-block" fill="currentColor" width="12" height="12"><path fill-rule="evenodd" d="M3.293 9.707a1 1 0 010-1.414l6-6a1 1 0 011.414 0l6 6a1 1 0 01-1.414 1.414L11 5.414V17a1 1 0 11-2 0V5.414L4.707 9.707a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg>';
392
+ }
393
+ ?>
394
+ <div id="es-dashboard-click-stats">
395
+ <span class="text-2xl font-bold leading-none text-indigo-600">
396
+ <?php echo esc_html( $total_links_clicks ); ?>
397
+ </span>
398
+ <div class="inline-block es-tooltip relative align-middle cursor-pointer">
399
+ <span class="text-sm mr-0.5 <?php echo esc_attr( $text_color_class ); ?>">
400
+ <?php echo esc_html( $click_percentage_growth ); ?>%
401
+ <?php echo wp_kses( $arraw_html, $allowed_html_tags ); ?>
402
+ </span>
403
+ <span class="break-words invisible h-auto lg:w-48 xl:w-64 tracking-wide absolute z-70 tooltip-text bg-black text-gray-300 text-xs rounded p-3 py-2">
404
+ <div class="text-white-100">
405
+ <div>
406
+ <span class="text-lg text-base">
407
+ <?php echo esc_html__( 'Clicks', 'email-subscribers' ); ?>:
408
+ <?php echo esc_html( $click_before_two_months ); ?>
409
+ </span>
410
+ </div>
411
+ </div>
412
+ <div class="text-xs mt-1 pt-1 text-gray-100 border-t border-gray-100">
413
+ <?php
414
+ /* translators: 1. Start date 2. End date */
415
+ echo esc_html__( sprintf( '%1$s to %2$s', $last_period_start_date, $last_period_end_date ), 'email-subscribers' );
416
+ ?>
417
+ </div>
418
+ <svg class="tooltip-arrow absolute mt-2 text-black text-opacity-100 h-2.5 left-0" viewBox="0 0 255 255">
419
+ <polygon class="fill-current" points="0,0 127.5,127.5 255,0"></polygon>
420
+ </svg>
421
+ </span>
422
+ </div>
423
+ <p class="mt-1 font-medium leading-6 text-gray-500">
424
+ <?php echo esc_html__( 'Clicks', 'email-subscribers' ); ?>
425
+ <?php
426
+ if ( ! ES()->is_pro() ) {
427
+ $utm_args = array(
428
+ 'utm_medium' => 'dashboard-click-stat',
429
+ 'url' => 'https://www.icegram.com/documentation/what-analytics-does-email-subscribers-track/'
430
+ );
431
+
432
+ $pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
433
+ ?>
434
+ <a target="_blank" href="<?php echo esc_url( $pricing_url ); ?>">
435
+ <span class="premium-icon inline-block"></span>
436
+ </a>
437
+ <?php
438
+ }
439
+ ?>
440
+ </p>
441
+ </div>
442
+ </div>
443
+
444
  </div>
445
+
446
  </div>
447
  </div>
448
+ <div class="flex-auto min-w-0">
449
+ <p class="px-3 text-lg font-medium leading-6 text-gray-400">
450
+ <?php echo esc_html__( 'Top campaigns', 'email-subscribers' ); ?>
451
+ </p>
452
+
453
+ <?php
454
+ if ( ! empty( $top_performing_campaigns ) ) {
455
+ $es_nonce = wp_create_nonce( 'es_notification' );
456
+ ?>
457
+ <ul class="pr-4">
458
+ <?php
459
+ foreach ( $top_performing_campaigns as $campaign ) {
460
+ $campaign_id = $campaign['campaign_id'];
461
+ $message_id = $campaign['message_id'];
462
+ $message = ES_DB_Mailing_Queue::get_mailing_queue_by_id( $message_id );
463
+ if ( empty( $message ) ) {
464
+ continue;
465
+ }
466
+ $message_title = $message['subject'];
467
+ $campaign_report_url = admin_url( 'admin.php?page=es_reports&action=view&list=' . $message['hash'] . '&_wpnonce=' . $es_nonce );
468
+ $results = $wpdb->get_results( $wpdb->prepare( "SELECT type, count(DISTINCT (contact_id) ) as total FROM {$wpdb->prefix}ig_actions WHERE message_id = %d AND campaign_id = %d GROUP BY type", $message_id, $campaign_id ), ARRAY_A );
469
+
470
+ $stats = array();
471
+ $action_type = '';
472
+ $type_text = '';
473
+
474
+ if ( count( $results ) > 0 ) {
475
+
476
+ foreach ( $results as $result ) {
477
+
478
+ $action_type = $result['type'];
479
+ $total = $result['total'];
480
+
481
+ switch ( $action_type ) {
482
+ case IG_MESSAGE_SENT:
483
+ $type_text = 'total_sent';
484
+ break;
485
+ case IG_MESSAGE_OPEN:
486
+ $type_text = 'total_opens';
487
+ break;
488
+ case IG_LINK_CLICK:
489
+ $type_text = 'total_clicks';
490
+ break;
491
+ case IG_CONTACT_UNSUBSCRIBE:
492
+ $type_text = 'total_unsubscribe';
493
+ break;
494
+ }
495
+
496
+ $stats[ $type_text ] = $total;
497
+ }
498
+ }
499
 
500
+ $stats = wp_parse_args(
501
+ $stats,
502
+ array(
503
+ 'total_sent' => 0,
504
+ 'total_opens' => 0,
505
+ 'total_clicks' => 0,
506
+ 'total_unsubscribe' => 0,
507
+ )
508
+ );
509
+
510
+ if ( 0 != $stats['total_sent'] ) {
511
+ $campaign_opens_rate = ( $stats['total_opens'] * 100 ) / $stats['total_sent'];
512
+ $campaign_clicks_rate = ( $stats['total_clicks'] * 100 ) / $stats['total_sent'];
513
+ $campaign_losts_rate = ( $stats['total_unsubscribe'] * 100 ) / $stats['total_sent'];
514
+ } else {
515
+ $campaign_opens_rate = 0;
516
+ $campaign_clicks_rate = 0;
517
+ $campaign_losts_rate = 0;
518
+ }
519
+ ?>
520
+ <li class="border-b border-gray-200">
521
+ <a href="<?php echo esc_url( $campaign_report_url ); ?>" target="_blank" class="block hover:bg-gray-50 focus:outline-none focus:bg-gray-50 transition duration-150 ease-in-out" target="_blank">
522
+ <div class="flex items-center px-2 py-2">
523
+ <div class="w-3/5 min-w-0 flex-1">
524
+ <div class="flex flex-1 items-center text-sm ">
525
+ <?php echo esc_html( $message_title ); ?>
526
+ </div>
527
+ <div class="text-base mt-2 pr-4">
528
+ </div>
529
+ </div>
530
+ <div class="grid grid-cols-3">
531
+ <div class="p-3">
532
+ <span class="leading-none text-sm text-indigo-500">
533
+ <?php echo esc_html( number_format_i18n( $campaign_opens_rate, 2 ) ); ?>%
534
+ </span>
535
+ <p class="mt-1 leading-6 text-gray-400">
536
+ <?php echo esc_html__( 'Opens', 'email-subscribers' ); ?>
537
+ </p>
538
+ </div>
539
+ <div class="p-3">
540
+ <span class="leading-none text-sm text-indigo-500">
541
+ <?php echo esc_html( number_format_i18n( $campaign_clicks_rate, 2 ) ); ?>%
542
+ </span>
543
+ <p class="mt-1 leading-6 text-gray-400">
544
+ <?php echo esc_html__( 'Clicks', 'email-subscribers' ); ?>
545
+ </p>
546
+ </div>
547
+ <div class="p-3">
548
+ <span class="leading-none text-sm text-indigo-500">
549
+ <?php echo esc_html( number_format_i18n( $campaign_losts_rate, 2 ) ); ?>%
550
+ </span>
551
+ <p class="mt-1 leading-6 text-gray-400">
552
+ <?php echo esc_html__( 'Lost', 'email-subscribers' ); ?>
553
+ </p>
554
+ </div>
555
+ </div>
556
+ <div>
557
+ <svg class="h-5 w-5 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
558
+ <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path>
559
+ </svg>
560
+ </div>
561
+ </div>
562
+ </a>
563
+ </li>
564
+ <?php
565
+ }
566
+ ?>
567
+ </ul>
568
+ <?php
569
+ } else {
570
+ ?>
571
+ <div class="px-3 mt-1 text-sm leading-5 text-gray-900">
572
+ <?php
573
+ echo esc_html__( 'No campaigns found', 'email-subscribers' );
574
+ ?>
575
+ </div>
576
+ <?php
577
+ }
578
+ ?>
579
+ </div>
580
+ <div class="flex-auto min-w-0">
581
  <div class="overflow-hidden">
582
  <ul>
583
  <!-- Start-IG-Code -->
732
  ]
733
  };
734
 
735
+ // const chart = new frappe.Chart("#ig-es-contacts-growth", {
736
+ // title: "",
737
+ // data: data,
738
+ // type: 'line',
739
+ // colors: ['#743ee2'],
740
+ // lineOptions: {
741
+ // hideDots: 1,
742
+ // heatline: 1
743
+ // },
744
+ // height: 150,
745
+ // axisOptions: {
746
+ // xIsSeries: true
747
+ // }
748
+ // });
749
  }
750
 
751
  });
lite/includes/class-es-common.php CHANGED
@@ -474,7 +474,7 @@ class ES_Common {
474
  * @since 4.8.2
475
  */
476
  public static function generate_random_string( $length = 6 ) {
477
- $str = 'abcdefghijklmnopqrstuvwxyz';
478
 
479
  return substr( str_shuffle( $str ), 0, $length );
480
  }
@@ -2300,7 +2300,7 @@ class ES_Common {
2300
  <svg class="w-4 h-4 text-gray-600" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path></svg>
2301
  <span class="break-words invisible h-auto lg:w-48 xl:w-64 tracking-wide absolute z-70 tooltip-text bg-black text-gray-300 text-xs rounded p-3 py-2">
2302
  ' . $tooltip_text . '
2303
- <svg class="absolute mt-2 text-black text-opacity-100 h-2.5 left-0" x="0px" y="0px" viewBox="0 0 255 255" xml:space="preserve">
2304
  <polygon class="fill-current" points="0,0 127.5,127.5 255,0"/>
2305
  </svg>
2306
  </span>
@@ -2586,4 +2586,106 @@ class ES_Common {
2586
  return '';
2587
  }
2588
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2589
  }
474
  * @since 4.8.2
475
  */
476
  public static function generate_random_string( $length = 6 ) {
477
+ $str = 'abcdefghijklmnopqrstuvwxyz';
478
 
479
  return substr( str_shuffle( $str ), 0, $length );
480
  }
2300
  <svg class="w-4 h-4 text-gray-600" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path></svg>
2301
  <span class="break-words invisible h-auto lg:w-48 xl:w-64 tracking-wide absolute z-70 tooltip-text bg-black text-gray-300 text-xs rounded p-3 py-2">
2302
  ' . $tooltip_text . '
2303
+ <svg class="tooltip-arrow absolute mt-2 text-black text-opacity-100 h-2.5 left-0" x="0px" y="0px" viewBox="0 0 255 255" xml:space="preserve">
2304
  <polygon class="fill-current" points="0,0 127.5,127.5 255,0"/>
2305
  </svg>
2306
  </span>
2586
  return '';
2587
  }
2588
 
2589
+ public static function get_popular_domains() {
2590
+ /** Domains list from https://github.com/mailcheck/mailcheck/wiki/List-of-Popular-Domains */
2591
+ $popular_domains = array(
2592
+ /* Default domains included */
2593
+ 'aol.com', 'att.net', 'comcast.net', 'facebook.com', 'gmail.com', 'gmx.com', 'googlemail.com',
2594
+ 'google.com', 'hotmail.com', 'hotmail.co.uk', 'mac.com', 'me.com', 'mail.com', 'msn.com',
2595
+ 'live.com', 'sbcglobal.net', 'verizon.net', 'yahoo.com', 'yahoo.co.uk',
2596
+
2597
+ /* Other global domains */
2598
+ 'email.com', 'fastmail.fm', 'games.com' /* AOL */, 'gmx.net', 'hush.com', 'hushmail.com', 'icloud.com',
2599
+ 'iname.com', 'inbox.com', 'lavabit.com', 'love.com' /* AOL */, 'outlook.com', 'pobox.com', 'protonmail.ch', 'protonmail.com', 'tutanota.de', 'tutanota.com', 'tutamail.com', 'tuta.io',
2600
+ 'keemail.me', 'rocketmail.com' /* Yahoo */, 'safe-mail.net', 'wow.com' /* AOL */, 'ygm.com' /* AOL */,
2601
+ 'ymail.com' /* Yahoo */, 'zoho.com', 'yandex.com',
2602
+
2603
+ /* United States ISP domains */
2604
+ 'bellsouth.net', 'charter.net', 'cox.net', 'earthlink.net', 'juno.com',
2605
+
2606
+ /* British ISP domains */
2607
+ 'btinternet.com', 'virginmedia.com', 'blueyonder.co.uk', 'live.co.uk',
2608
+ 'ntlworld.com', 'orange.net', 'sky.com', 'talktalk.co.uk', 'tiscali.co.uk',
2609
+ 'virgin.net', 'bt.com',
2610
+
2611
+ /* Domains used in Asia */
2612
+ 'sina.com', 'sina.cn', 'qq.com', 'naver.com', 'hanmail.net', 'daum.net', 'nate.com', 'yahoo.co.jp', 'yahoo.co.kr', 'yahoo.co.id', 'yahoo.co.in', 'yahoo.com.sg', 'yahoo.com.ph', '163.com', 'yeah.net', '126.com', '21cn.com', 'aliyun.com', 'foxmail.com',
2613
+
2614
+ /* French ISP domains */
2615
+ 'hotmail.fr', 'live.fr', 'laposte.net', 'yahoo.fr', 'wanadoo.fr', 'orange.fr', 'gmx.fr', 'sfr.fr', 'neuf.fr', 'free.fr',
2616
+
2617
+ /* German ISP domains */
2618
+ 'gmx.de', 'hotmail.de', 'live.de', 'online.de', 't-online.de' /* T-Mobile */, 'web.de', 'yahoo.de',
2619
+
2620
+ /* Italian ISP domains */
2621
+ 'libero.it', 'virgilio.it', 'hotmail.it', 'aol.it', 'tiscali.it', 'alice.it', 'live.it', 'yahoo.it', 'email.it', 'tin.it', 'poste.it', 'teletu.it',
2622
+
2623
+ /* Russian ISP domains */
2624
+ 'bk.ru', 'inbox.ru', 'list.ru', 'mail.ru', 'rambler.ru', 'yandex.by', 'yandex.com', 'yandex.kz', 'yandex.ru', 'yandex.ua', 'ya.ru',
2625
+
2626
+ /* Belgian ISP domains */
2627
+ 'hotmail.be', 'live.be', 'skynet.be', 'voo.be', 'tvcablenet.be', 'telenet.be',
2628
+
2629
+ /* Argentinian ISP domains */
2630
+ 'hotmail.com.ar', 'live.com.ar', 'yahoo.com.ar', 'fibertel.com.ar', 'speedy.com.ar', 'arnet.com.ar',
2631
+
2632
+ /* Domains used in Mexico */
2633
+ 'yahoo.com.mx', 'live.com.mx', 'hotmail.es', 'hotmail.com.mx', 'prodigy.net.mx',
2634
+
2635
+ /* Domains used in Canada */
2636
+ 'yahoo.ca', 'hotmail.ca', 'bell.net', 'shaw.ca', 'sympatico.ca', 'rogers.com',
2637
+
2638
+ /* Domains used in Brazil */
2639
+ 'yahoo.com.br', 'hotmail.com.br', 'outlook.com.br', 'uol.com.br', 'bol.com.br', 'terra.com.br', 'ig.com.br', 'r7.com', 'zipmail.com.br', 'globo.com', 'globomail.com', 'oi.com.br'
2640
+ );
2641
+
2642
+ return $popular_domains;
2643
+ }
2644
+
2645
+ public static function is_popular_domain( $email ) {
2646
+
2647
+ $is_email = is_email( $email );
2648
+ if ( ! $is_email ) {
2649
+ return false;
2650
+ }
2651
+
2652
+ $email_parts = explode( '@', $email );
2653
+ $domain = end( $email_parts );
2654
+ $$domain = strtolower( $domain );
2655
+
2656
+ $popular_domains = self::get_popular_domains();
2657
+
2658
+ return in_array( $domain, $popular_domains, true );
2659
+ }
2660
+
2661
+ public static function get_domain_from_url( $url ) {
2662
+ $pieces = parse_url($url);
2663
+ $domain = isset($pieces['host']) ? $pieces['host'] : $pieces['path'];
2664
+ return $domain;
2665
+ }
2666
+ public static function get_engagement_score_html( $engagement_score ) {
2667
+ if ( is_numeric( $engagement_score ) ) {
2668
+ $score_class = 'bad';
2669
+
2670
+ if ( $engagement_score > 0 ) {
2671
+ $score_text = number_format_i18n( $engagement_score, 1 );
2672
+ } else {
2673
+ $score_text = 0;
2674
+ }
2675
+
2676
+ if ( $engagement_score >= 4 ) {
2677
+ $score_class = 'excellent';
2678
+ } elseif ( $engagement_score >= 3 ) {
2679
+ $score_class = 'good';
2680
+ } elseif ( $engagement_score >= 2 ) {
2681
+ $score_class = 'low';
2682
+ } elseif ( $engagement_score >= 1 ) {
2683
+ $score_class = 'very-low';
2684
+ }
2685
+ }
2686
+ $engagement_score_html = ( is_numeric( $engagement_score ) ? '<div class="es-engagement-score ' . $score_class . '">' . $score_text . '</div>' : '-' );
2687
+
2688
+ return $engagement_score_html;
2689
+ }
2690
+
2691
  }
lite/includes/classes/class-es-admin-settings.php CHANGED
@@ -191,8 +191,25 @@ class ES_Admin_Settings {
191
  <?php
192
  }
193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  public static function get_registered_settings() {
195
 
 
 
 
 
196
  $general_settings = array(
197
 
198
  'sender_information' => array(
@@ -211,7 +228,7 @@ class ES_Admin_Settings {
211
  'from_email' => array(
212
  'id' => 'ig_es_from_email',
213
  'name' => __( 'Email', 'email-subscribers' ),
214
- 'desc' => __( 'The "from" email address for all emails.', 'email-subscribers' ),
215
  'type' => 'text',
216
  'placeholder' => __( 'Email Address', 'email-subscribers' ),
217
  'default' => '',
191
  <?php
192
  }
193
 
194
+ public static function get_from_email_notice( $from_email ) {
195
+ $from_email_notice = '';
196
+ $from_email = get_option( 'ig_es_from_email' );
197
+ $is_popular_domain = ES_Common::is_popular_domain( $from_email );
198
+ $from_email_notice_class = $is_popular_domain ? '' : 'hidden';
199
+ $from_email_notice = '<span id="ig-es-from-email-notice" class="text-red-600 ' . $from_email_notice_class . '">' . __( 'Your emails might land in spam if you use above email address..', 'email-subscribers' );
200
+ $site_url = site_url();
201
+ $site_domain = ES_Common::get_domain_from_url( $site_url );
202
+ /* translators: %s: Site domain */
203
+ $from_email_notice .= '<br/>' . sprintf( __( 'Consider using email address matching your site domain like %s', 'email-subscribers' ), 'info@' . $site_domain ) . '</span>';
204
+ return $from_email_notice;
205
+ }
206
+
207
  public static function get_registered_settings() {
208
 
209
+ $from_email_description = __( 'The "from" email address for all emails.', 'email-subscribers' );
210
+
211
+ $from_email = get_option( 'ig_es_from_email' );
212
+ $from_email_description .= '<br/>' . self::get_from_email_notice( $from_email );
213
  $general_settings = array(
214
 
215
  'sender_information' => array(
228
  'from_email' => array(
229
  'id' => 'ig_es_from_email',
230
  'name' => __( 'Email', 'email-subscribers' ),
231
+ 'desc' => $from_email_description,
232
  'type' => 'text',
233
  'placeholder' => __( 'Email Address', 'email-subscribers' ),
234
  'default' => '',
lite/includes/classes/class-es-campaign.php CHANGED
@@ -212,17 +212,10 @@ if ( ! class_exists( 'ES_Campaign' ) ) {
212
  if ( ! $campaign_id ) {
213
  return false;
214
  }
215
-
216
- $_campaign = wp_cache_get( $campaign_id, 'ig_es_campaign' );
217
 
 
218
  if ( ! $_campaign ) {
219
- $_campaign = ES()->campaigns_db->get( $campaign_id, 'object' );
220
-
221
- if ( ! $_campaign ) {
222
- return false;
223
- }
224
-
225
- wp_cache_add( $campaign_id, $_campaign, 'ig_es_campaign' );
226
  }
227
 
228
  return new ES_Campaign( $_campaign );
212
  if ( ! $campaign_id ) {
213
  return false;
214
  }
 
 
215
 
216
+ $_campaign = ES()->campaigns_db->get( $campaign_id, 'object' );
217
  if ( ! $_campaign ) {
218
+ return false;
 
 
 
 
 
 
219
  }
220
 
221
  return new ES_Campaign( $_campaign );
lite/includes/classes/class-es-form-widget.php CHANGED
@@ -29,8 +29,9 @@ class ES_Form_Widget extends WP_Widget {
29
  if ( ! empty( $form_id ) ) {
30
 
31
  $form = ES()->forms_db->get_form_by_id( $form_id );
32
-
33
- $form_data = ES_Forms_Table::get_form_data_from_body( $form );
 
34
  }
35
 
36
  $data = array();
29
  if ( ! empty( $form_id ) ) {
30
 
31
  $form = ES()->forms_db->get_form_by_id( $form_id );
32
+ if ( $form ) {
33
+ $form_data = ES_Forms_Table::get_form_data_from_body( $form );
34
+ }
35
  }
36
 
37
  $data = array();
lite/includes/classes/class-es-mailer.php CHANGED
@@ -704,7 +704,12 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
704
  if ( $this->add_unsubscribe_link ) {
705
  $unsubscribe_message = get_option( 'ig_es_unsubscribe_link_content', '' );
706
  $unsubscribe_message = stripslashes( $unsubscribe_message );
707
- $content .= $unsubscribe_message;
 
 
 
 
 
708
  }
709
 
710
  $subject = $this->replace_global_tags( $subject );
@@ -718,7 +723,12 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
718
  if ( $this->can_track_open() ) {
719
  $tracking_pixel_variable_name = $this->mailer->get_variable_prefix() . $this->mailer->get_variable_string( 'tracking_pixel_url' ) . $this->mailer->get_variable_suffix();
720
  $tracking_image = '<img src="' . $tracking_pixel_variable_name . '" width="1" height="1" alt=""/>';
721
- $content .= $tracking_image;
 
 
 
 
 
722
  }
723
 
724
  if ( $this->unsubscribe_headers_enabled() && is_callable( array( $this->mailer, 'set_list_unsubscribe_header' ) ) ) {
@@ -968,7 +978,14 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
968
  // Can Track Email Open? Add pixel.
969
  $email_tracking_image = $this->get_tracking_pixel();
970
 
971
- $message->body = $message->body . $unsubscribe_message . $email_tracking_image;
 
 
 
 
 
 
 
972
 
973
  if ( $nl2br ) {
974
  $message->body = nl2br( $message->body );
@@ -1252,7 +1269,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1252
  $link_data['action'] = 'click';
1253
 
1254
  // get all links from the basecontent
1255
- preg_match_all( '# href=(\'|")?(https?[^\'"]+)(\'|")?#', $content, $links );
1256
 
1257
  $links = $links[2];
1258
 
@@ -1332,7 +1349,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1332
  if ( $this->can_track_clicks() ) {
1333
 
1334
  // get all links from the basecontent
1335
- preg_match_all( '# href=(\'|")?(https?[^\'"]+)(\'|")?#', $content, $links );
1336
 
1337
  $links = $links[2];
1338
 
@@ -1761,7 +1778,7 @@ if ( ! class_exists( 'ES_Mailer' ) ) {
1761
  $mail_to_subject = sprintf( __( 'Unsubscribe %1$s from %2$s', 'email-subscribers' ), $email, get_bloginfo( 'name' ) );
1762
  $list_unsub_header = sprintf(
1763
  /* translators: 1. Unsubscribe link 2. Blog admin email */
1764
- '<%1$s>,<mailto:%2$s?subject=%3$s',
1765
  $unsubscribe_link,
1766
  get_bloginfo( 'admin_email' ),
1767
  $mail_to_subject
704
  if ( $this->add_unsubscribe_link ) {
705
  $unsubscribe_message = get_option( 'ig_es_unsubscribe_link_content', '' );
706
  $unsubscribe_message = stripslashes( $unsubscribe_message );
707
+ if ( false === strpos( $content, '<html' ) ) {
708
+ $content = $content . $unsubscribe_message;
709
+ } else {
710
+ // If content is HTML then we need to place unsubscribe message and tracking image inside body tag.
711
+ $content = str_replace( '</body>', $unsubscribe_message . '</body>', $content );
712
+ }
713
  }
714
 
715
  $subject = $this->replace_global_tags( $subject );
723
  if ( $this->can_track_open() ) {
724
  $tracking_pixel_variable_name = $this->mailer->get_variable_prefix() . $this->mailer->get_variable_string( 'tracking_pixel_url' ) . $this->mailer->get_variable_suffix();
725
  $tracking_image = '<img src="' . $tracking_pixel_variable_name . '" width="1" height="1" alt=""/>';
726
+ if ( false === strpos( $content, '<html' ) ) {
727
+ $content = $content . $tracking_image;
728
+ } else {
729
+ // If content is HTML then we need to place unsubscribe message and tracking image inside body tag.
730
+ $content = str_replace( '</body>', $tracking_image . '</body>', $content );
731
+ }
732
  }
733
 
734
  if ( $this->unsubscribe_headers_enabled() && is_callable( array( $this->mailer, 'set_list_unsubscribe_header' ) ) ) {
978
  // Can Track Email Open? Add pixel.
979
  $email_tracking_image = $this->get_tracking_pixel();
980
 
981
+
982
+ if ( false === strpos( $message->body, '<html' ) ) {
983
+ $message->body = $message->body . $unsubscribe_message . $email_tracking_image;
984
+ } else {
985
+ // If content is HTML then we need to place unsubscribe message and tracking image inside body tag.
986
+ $message->body = str_replace( '</body>', $unsubscribe_message . $email_tracking_image . '</body>', $message->body );
987
+ }
988
+
989
 
990
  if ( $nl2br ) {
991
  $message->body = nl2br( $message->body );
1269
  $link_data['action'] = 'click';
1270
 
1271
  // get all links from the basecontent
1272
+ preg_match_all( '#<a\s+(?:[^>]*?\s+)?href=(\'|")?(https?[^\'"]+)(\'|")?#', $content, $links );
1273
 
1274
  $links = $links[2];
1275
 
1349
  if ( $this->can_track_clicks() ) {
1350
 
1351
  // get all links from the basecontent
1352
+ preg_match_all( '#<a\s+(?:[^>]*?\s+)?href=(\'|")?(https?[^\'"]+)(\'|")?#', $content, $links );
1353
 
1354
  $links = $links[2];
1355
 
1778
  $mail_to_subject = sprintf( __( 'Unsubscribe %1$s from %2$s', 'email-subscribers' ), $email, get_bloginfo( 'name' ) );
1779
  $list_unsub_header = sprintf(
1780
  /* translators: 1. Unsubscribe link 2. Blog admin email */
1781
+ '<%1$s>,<mailto:%2$s?subject=%3$s>',
1782
  $unsubscribe_link,
1783
  get_bloginfo( 'admin_email' ),
1784
  $mail_to_subject
lite/includes/classes/class-es-reports-data.php CHANGED
@@ -253,6 +253,8 @@ if ( ! class_exists( 'ES_Reports_Data' ) ) {
253
  $data = self::get_campaign_stats( $campaign_count );
254
  }
255
 
 
 
256
  $reports_data = array(
257
  'total_contacts' => number_format( $total_contacts ),
258
  'total_lists' => number_format( $total_lists ),
@@ -260,6 +262,7 @@ if ( ! class_exists( 'ES_Reports_Data' ) ) {
260
  'total_campaigns' => number_format( $total_campaigns ),
261
  'total_contacts_subscribed' => number_format( $total_contacts_subscribed ),
262
  'total_email_opens' => number_format( $total_email_opens ),
 
263
  'total_message_sent' => number_format( $total_message_sent ),
264
  'total_contact_lost' => number_format( $total_contact_lost ),
265
  'avg_open_rate' => number_format( $avg_open_rate, 2 ),
@@ -270,6 +273,47 @@ if ( ! class_exists( 'ES_Reports_Data' ) ) {
270
  'contacts_growth' => $contacts_growth,
271
  );
272
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
  $data = array_merge( $data, $reports_data );
274
 
275
  ES_Cache::set_transient( $cache_key, $data, 1 * HOUR_IN_SECONDS );
@@ -392,5 +436,185 @@ if ( ! class_exists( 'ES_Reports_Data' ) ) {
392
 
393
  return true;
394
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
395
  }
 
396
  }
253
  $data = self::get_campaign_stats( $campaign_count );
254
  }
255
 
256
+
257
+
258
  $reports_data = array(
259
  'total_contacts' => number_format( $total_contacts ),
260
  'total_lists' => number_format( $total_lists ),
262
  'total_campaigns' => number_format( $total_campaigns ),
263
  'total_contacts_subscribed' => number_format( $total_contacts_subscribed ),
264
  'total_email_opens' => number_format( $total_email_opens ),
265
+ 'total_links_clicks' => number_format( $total_links_clicks ),
266
  'total_message_sent' => number_format( $total_message_sent ),
267
  'total_contact_lost' => number_format( $total_contact_lost ),
268
  'avg_open_rate' => number_format( $avg_open_rate, 2 ),
273
  'contacts_growth' => $contacts_growth,
274
  );
275
 
276
+ $is_dashboard_page = 'es_dashboard' === $source;
277
+ if ( $is_dashboard_page ) {
278
+ $comparison_days = 120;
279
+ $last_four_months_opens = self::get_total_contacts_opened_emails( $comparison_days, false );
280
+
281
+ $open_before_two_months = $last_four_months_opens - $total_email_opens;
282
+ if ( $open_before_two_months > 0 ) {
283
+ $open_percentage_growth = ( ( $total_email_opens - $open_before_two_months ) / $open_before_two_months ) * 100;
284
+ } elseif ( 0 === (int) $total_email_opens && 0 === (int) $open_before_two_months) {
285
+ $open_percentage_growth = 0;
286
+ } else {
287
+ $open_percentage_growth = 100;
288
+ }
289
+
290
+ $last_four_months_clicks = self::get_total_contacts_clicks_links( $comparison_days, false );
291
+ $click_before_two_months = $last_four_months_clicks - $total_links_clicks;
292
+ if ( $click_before_two_months > 0 ) {
293
+ $click_percentage_growth = ( ( $total_links_clicks - $click_before_two_months ) / $click_before_two_months ) * 100;
294
+ } elseif ( 0 === (int) $total_links_clicks && 0 === (int) $click_before_two_months) {
295
+ $click_percentage_growth = 0;
296
+ } else {
297
+ $click_percentage_growth = 100;
298
+ }
299
+
300
+ $reports_data['open_percentage_growth'] = $open_percentage_growth > 0 ? number_format_i18n( $open_percentage_growth, 2 ) : $open_percentage_growth;
301
+ $reports_data['open_before_two_months'] = number_format_i18n( $open_before_two_months );
302
+ $reports_data['click_percentage_growth'] = $click_percentage_growth > 0 ? number_format_i18n( $click_percentage_growth, 2 ) : $click_percentage_growth;
303
+ $reports_data['click_before_two_months'] = number_format_i18n( $click_before_two_months );
304
+
305
+ $start_time = strtotime( '-' . $days . ' days', time() );
306
+
307
+ if ( ES()->is_pro() ) {
308
+ $average_engagement_score = ES_Engagement_Score::get_average_engagement_score( $start_time );
309
+
310
+ $reports_data['average_engagement_score'] = number_format_i18n( $average_engagement_score, 1 );
311
+ }
312
+
313
+ $top_performing_campaigns = self::get_top_performing_campaigns( $start_time );
314
+ $reports_data['top_performing_campaigns'] = $top_performing_campaigns;
315
+ }
316
+
317
  $data = array_merge( $data, $reports_data );
318
 
319
  ES_Cache::set_transient( $cache_key, $data, 1 * HOUR_IN_SECONDS );
436
 
437
  return true;
438
  }
439
+
440
+ public static function get_top_performing_campaigns( $start_time, $campaign_count = 3 ) {
441
+ global $wpdb;
442
+
443
+ $top_campaigns = $wpdb->get_results(
444
+ $wpdb->prepare(
445
+ "SELECT campaign_id,message_id, SUM( IF( `type` = 2, 1, 0 ) ) AS 'sent',SUM(IF( `type` = 3, 1, 0 )) AS 'opens_count', (SUM(IF( `type` = 3, 1, 0 ))/SUM( IF( `type` = 2, 1, 0 ))) * 100 AS opened_percentage FROM `{$wpdb->prefix}ig_actions` WHERE campaign_id IS NOT NULL AND message_id IS NOT NULL AND message_id != 0 AND updated_at > %d GROUP BY campaign_id, message_id ORDER BY `opened_percentage` DESC LIMIT %d",
446
+ $start_time,
447
+ $campaign_count
448
+ ),
449
+ ARRAY_A
450
+ );
451
+
452
+ return $top_campaigns;
453
+ }
454
+
455
+ public static function show_device_opens_stats( $device_opens_data ) {
456
+
457
+ //Graph for Device Opens
458
+ $device_opened = array();
459
+ $device_label = array();
460
+ ob_start();
461
+ if ( ! empty( $device_opens_data ) && ! empty( array_filter( $device_opens_data ) ) ) {
462
+ $device_label = array_map( 'ucfirst' , array_keys( $device_opens_data ) );
463
+ $device_opened = array_values( $device_opens_data );
464
+
465
+ ?>
466
+ <div class="relative bg-white mt-2" id="device_open_graph"></div>
467
+
468
+ <?php
469
+ } else {
470
+ ?>
471
+ <div class="mt-2 bg-white text-sm text-gray-500 py-3 px-6 tracking-wide">
472
+ <?php echo esc_html__( 'No device data found', 'email-subscribers' ); ?>
473
+ </div>
474
+ <?php
475
+ }
476
+ $stats_html = ob_get_clean();
477
+ $allowedtags = ig_es_allowed_html_tags_in_esc();
478
+ //$stats_html = ES_Common::get_tooltip_html( $stats_html );
479
+ echo wp_kses( $stats_html, $allowedtags );
480
+ ?>
481
+ <script type="text/javascript">
482
+
483
+ jQuery(document).ready(function ($) {
484
+ let device_data = {
485
+ labels: <?php echo json_encode( $device_label ); ?>,
486
+ datasets: [
487
+ {
488
+ name: "device",
489
+ type: "pie",
490
+ values: <?php echo json_encode( $device_opened ); ?>,
491
+ }
492
+ ]
493
+ }
494
+
495
+ const device_chart = new frappe.Chart("#device_open_graph", {
496
+ title: "",
497
+ data: device_data,
498
+ type: 'pie',
499
+ colors: ['#743ee2', '#5DADE2', '#F6608B'],
500
+ height: 30,
501
+ width:30,
502
+ maxSlices: 3,
503
+ });
504
+
505
+ });
506
+ </script>
507
+ <?php
508
+ }
509
+
510
+ public static function show_sources_stats( $subscriber_source_counts ) {
511
+
512
+
513
+ //Graph for Device Opens
514
+ $source_opened = array();
515
+ $source_label = array();
516
+ ob_start();
517
+ if ( ! empty( $subscriber_source_counts ) && ! empty( array_filter( $subscriber_source_counts ) ) ) {
518
+ $source_label = array_map( 'ucfirst' , array_keys( $subscriber_source_counts ) );
519
+ $source_opened = array_values( $subscriber_source_counts );
520
+ ?>
521
+ <div class="bg-white mt-2" id="sources_graph"></div>
522
+
523
+ <?php
524
+ } else {
525
+ ?>
526
+ <div class="mt-2 bg-white text-sm text-gray-500 py-3 px-6">
527
+ <?php echo esc_html__( 'No source data found', 'email-subscribers' ); ?>
528
+ </div>
529
+ <?php
530
+ }
531
+ $stats_html = ob_get_clean();
532
+ $allowedtags = ig_es_allowed_html_tags_in_esc();
533
+ //$stats_html = ES_Common::get_tooltip_html( $stats_html );
534
+ echo wp_kses( $stats_html, $allowedtags );
535
+ ?>
536
+ <script type="text/javascript">
537
+
538
+ jQuery(document).ready(function ($) {
539
+ let source_data = {
540
+ labels: <?php echo json_encode( $source_label ); ?>,
541
+ datasets: [
542
+ {
543
+ name: "source",
544
+ type: "percentage",
545
+ values: <?php echo json_encode( $source_opened ); ?>,
546
+ }
547
+ ]
548
+ }
549
+
550
+ const source_chart = new frappe.Chart("#sources_graph", {
551
+ title: "",
552
+ data: source_data,
553
+ type: 'percentage',
554
+ colors: ['#743ee2', '#5DADE2', '#F6608B'],
555
+ height: 80,
556
+ maxSlices: 3,
557
+ });
558
+
559
+ });
560
+ </script>
561
+ <?php
562
+ }
563
+
564
+ public static function show_unsubscribe_feedback_percentage_stats( $feedback_percentages ) {
565
+
566
+
567
+ //Graph for Device Opens
568
+ $unsubscribe_feedback_opened = array();
569
+ $unsubscribe_feedback_label = array();
570
+ ob_start();
571
+ if ( ! empty( $feedback_percentages ) && ! empty( array_filter( $feedback_percentages ) ) ) {
572
+ $unsubscribe_feedback_label = array_map( 'ucfirst' , array_keys( $feedback_percentages ) );
573
+ $unsubscribe_feedback_opened = array_values( $feedback_percentages );
574
+
575
+ ?>
576
+ <div class="relative bg-white mt-2 rounded-md shadow" id="unsubscribe_feedbacks_graph"></div>
577
+
578
+ <?php
579
+ } else {
580
+ ?>
581
+ <div class="mt-2 bg-white text-sm text-gray-500 rounded-md shadow py-3 px-6 tracking-wide">
582
+ <?php echo esc_html__( 'No data found', 'email-subscribers' ); ?>
583
+ </div>
584
+ <?php
585
+ }
586
+ $stats_html = ob_get_clean();
587
+ $allowedtags = ig_es_allowed_html_tags_in_esc();
588
+ $stats_html = ES_Common::get_tooltip_html( $stats_html );
589
+ echo wp_kses( $stats_html, $allowedtags );
590
+ ?>
591
+ <script type="text/javascript">
592
+
593
+ jQuery(document).ready(function ($) {
594
+ let unsubscribe_feedback_data = {
595
+ labels: <?php echo json_encode( $unsubscribe_feedback_label ); ?>,
596
+ datasets: [
597
+ {
598
+ name: "unsubscribe_feedback",
599
+ type: "pie",
600
+ values: <?php echo json_encode( $unsubscribe_feedback_opened ); ?>,
601
+ }
602
+ ]
603
+ }
604
+
605
+ const unsubscribe_feedback_chart = new frappe.Chart("#unsubscribe_feedbacks_graph", {
606
+ title: "",
607
+ data: unsubscribe_feedback_data,
608
+ type: 'pie',
609
+ colors: ['#743ee2', '#5DADE2', '#F6608B'],
610
+ height: 280,
611
+ maxSlices: 3,
612
+ });
613
+
614
+ });
615
+ </script>
616
+ <?php
617
+ }
618
  }
619
+
620
  }
lite/includes/db/class-ig-es-db-unsubscribe-feedback.php CHANGED
@@ -150,4 +150,22 @@ class IG_ES_DB_Unsubscribe_Feedback extends ES_DB {
150
 
151
  return $existing_feedback_id;
152
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  }
150
 
151
  return $existing_feedback_id;
152
  }
153
+
154
+ public static function get_feedback_counts( $start_time ) {
155
+ global $wpdb;
156
+
157
+ if ( is_numeric( $start_time ) ) {
158
+ $start_time = gmdate( 'Y-m-d H:i:s', $start_time );
159
+ }
160
+
161
+ $feedback_counts = $wpdb->get_results(
162
+ $wpdb->prepare(
163
+ "SELECT feedback_slug, COUNT(feedback_slug) AS feedback_count FROM `{$wpdb->prefix}ig_unsubscribe_feedback` WHERE `updated_at` > %s GROUP BY `feedback_slug`"
164
+ , $start_time
165
+ ),
166
+ ARRAY_A
167
+ );
168
+
169
+ return $feedback_counts;
170
+ }
171
  }
readme.txt CHANGED
@@ -4,9 +4,9 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
4
  Author URI: https://www.icegram.com/
5
  Tags: email marketing, subscription, autoresponder, post notification, welcome email
6
  Requires at least: 3.9
7
- Tested up to: 5.9.3
8
  Requires PHP: 5.6
9
- Stable tag: 5.3.15
10
  License: GPLv3
11
  License URI: http://www.gnu.org/licenses
12
 
@@ -310,13 +310,29 @@ Refer [here](https://www.icegram.com/documentation/es-faq/).
310
 
311
  == Upgrade Notice ==
312
 
313
- = 5.3.15 =
314
 
315
- * New: Advanced audience filters[PRO]
316
- * Fix: Template already exists issue on some setup using Amazon SES[PRO]
 
 
 
 
 
 
317
 
318
  == Changelog ==
319
 
 
 
 
 
 
 
 
 
 
 
320
  **5.3.15 (18.05.2022)**
321
 
322
  * New: Advanced audience filters[PRO]
4
  Author URI: https://www.icegram.com/
5
  Tags: email marketing, subscription, autoresponder, post notification, welcome email
6
  Requires at least: 3.9
7
+ Tested up to: 6.0
8
  Requires PHP: 5.6
9
+ Stable tag: 5.3.16
10
  License: GPLv3
11
  License URI: http://www.gnu.org/licenses
12
 
310
 
311
  == Upgrade Notice ==
312
 
313
+ = 5.3.16 =
314
 
315
+ * Enhancement: Improved dashboard stats
316
+ * Fix: Warning message when using Gmail/Yahoo email addresses in From email setting
317
+ * Fix: Email sending issue with Amazon SES when subject contains emojis[PRO]
318
+ * Fix: Duplicate post digest notifications[PRO]
319
+ * Fix: Unsubscribe message getting inserted after HTML tag
320
+ * Fix: Caching issue when editing campaign when Redis cache enable
321
+ * Fix: PHP warning when subscription form is deleted from backend and form widget is active on frontend
322
+ * Fix: Incorrect link tracking stats for campaigns created using Drag-n-Drop editor[PR0]
323
 
324
  == Changelog ==
325
 
326
+ **5.3.16 (02.06.2022)**
327
+ * Enhancement: Improved dashboard stats
328
+ * Fix: Warning message when using Gmail/Yahoo email addresses in From email setting
329
+ * Fix: Email sending issue with Amazon SES when subject contains emojis[PRO]
330
+ * Fix: Duplicate post digest notifications[PRO]
331
+ * Fix: Unsubscribe message getting inserted after HTML tag
332
+ * Fix: Caching issue when editing campaign when Redis cache enable
333
+ * Fix: PHP warning when subscription form is deleted from backend and form widget is active on frontend
334
+ * Fix: Incorrect link tracking stats for campaigns created using Drag-n-Drop editor[PR0]
335
+
336
  **5.3.15 (18.05.2022)**
337
 
338
  * New: Advanced audience filters[PRO]