__( 'Report', 'email-subscribers' ), // singular name of the listed records
'plural' => __( 'Reports', 'email-subscribers' ), // plural name of the listed records
'ajax' => true, // does this table support ajax?,
'screen' => 'es_reports',
)
);
add_action( 'ig_es_view_report_data_lite', array( $this, 'view_report_data_lite' ) );
add_action( 'ig_es_view_report_description_lite', array( $this, 'view_report_description_lite' ), 10, 2 );
add_action( 'ig_es_view_activity_table_html', array( $this, 'view_activity_report_table' ), 10, 3 );
add_action( 'admin_footer', array( $this, 'es_view_activity_report_sort_and_filter' ) );
}
/**
* Get individual reports data
*
* @version 5.4.2
*/
public static function view_report_data_lite( $id ) {
global $wpdb;
$notification = ES_DB_Mailing_Queue::get_notification_by_hash( $id );
$report_id = $notification['id'];
$notification_campaign_id = $notification['campaign_id'];
$total_email_sent = ES()->actions_db->get_count_based_on_id_type( $notification_campaign_id, $report_id, IG_MESSAGE_SENT );
$email_viewed_count = ES()->actions_db->get_count_based_on_id_type( $notification_campaign_id, $report_id, IG_MESSAGE_OPEN );
//--->
$email_unsubscribed_count = ES()->actions_db->get_count_based_on_id_type( $notification_campaign_id, $report_id, IG_CONTACT_UNSUBSCRIBE );
$avg_unsubscribed_rate = !empty($total_email_sent) ? number_format_i18n(( ( $email_unsubscribed_count/$total_email_sent ) * 100 ), 2) : 0;
//--->
$avg_open_rate = ! empty( $total_email_sent) ? number_format_i18n( ( ( $email_viewed_count * 100 ) / $total_email_sent ), 2 ) : 0;
$email_click_count = ! empty( $notification_campaign_id ) ? ES()->actions_db->get_count_based_on_id_type( $notification_campaign_id, $report_id, IG_LINK_CLICK ) : 0;
$avg_click_rate = ! empty( $total_email_sent ) ? number_format_i18n( ( ( $email_click_count * 100 ) / $total_email_sent ), 2 ) : 0;
if ( empty( $notification['campaign_id'] ) ) {
$notification_type = __( 'Post Notification', 'email-subscribers' );
} else {
$notification_type = ES()->campaigns_db->get_campaign_type_by_id( $notification['campaign_id'] );
$notification_type = strtolower( $notification_type );
$notification_type = ( 'newsletter' === $notification_type ) ? __( 'Broadcast', 'email-subscribers' ) : $notification_type;
}
$report_kpi_statistics = array(
'total_email_sent' => number_format_i18n( $total_email_sent ),
'email_viewed_count' => number_format_i18n( $email_viewed_count ),
'email_unsubscribed_count' => number_format_i18n( $email_unsubscribed_count ),
'email_click_count' => number_format_i18n( $email_click_count ),
'avg_open_rate' => $avg_open_rate,
'avg_click_rate' => $avg_click_rate,
'avg_unsubscribed_rate' => $avg_unsubscribed_rate,
);
$notification['type'] = ucwords( str_replace( '_', ' ', $notification_type ) );
$notification_subject = $notification['subject'];
$notification_campaign = ES()->campaigns_db->get_campaign_by_id( $notification_campaign_id, - 1 );
$notification['from_email'] = ! empty( $notification_campaign['from_email'] ) ? $notification_campaign['from_email'] : '';
$notification_lists_ids = ! empty( $notification_campaign['list_ids'] ) ? explode( ',', $notification_campaign['list_ids'] ) : array();
$notification['list_name'] = ES_Common::prepare_list_name_by_ids( $notification_lists_ids );
$total_contacts = $notification['count'];
$notification_status = $notification['status'];
$campaign_meta = ! empty( $notification_campaign['meta'] ) ? unserialize( $notification_campaign['meta']) : '';
$notification['list_conditions'] = ! empty( $campaign_meta['list_conditions'] ) ? $campaign_meta['list_conditions'] : '';
$where = $wpdb->prepare( 'message_id = %d ORDER BY updated_at DESC', $report_id );
$notification_actions = ES()->actions_db->get_by_conditions( $where );
$links_where = $wpdb->prepare( 'message_id = %d', $report_id );
$notification_links = ES()->links_db->get_by_conditions( $links_where );
$activity_data = array();
$time_offset = get_option( 'gmt_offset' ) * HOUR_IN_SECONDS;
$date_format = get_option( 'date_format' );
if ( ! empty( $notification_actions ) ) {
foreach ( $notification_actions as $notification_action ) {
$action_type = (int) $notification_action['type'];
if ( in_array( $action_type, array( IG_MESSAGE_OPEN, IG_LINK_CLICK ), true ) ) {
$created_timestamp = $notification_action['created_at'];
//$created_date = date_i18n( $date_format, $created_timestamp + $time_offset );
$created_date = gmdate( 'Y-m-d', $created_timestamp + $time_offset );
if ( ! isset( $activity_data[ $created_date ] ) ) {
$activity_data[ $created_date ] = array(
'opened' => 0,
'clicked' => 0,
);
}
if ( IG_MESSAGE_OPEN === $action_type ) {
$activity_data[ $created_date ]['opened'] ++;
} elseif ( IG_LINK_CLICK === $action_type ) {
$activity_data[ $created_date ]['clicked'] ++;
}
}
}
}
if ( ! empty( $activity_data ) ) {
ksort( $activity_data );
}
// To display report header information and KPI values
do_action( 'ig_es_view_report_description_lite', $notification, $report_kpi_statistics );
}
/**
* Display Report header information and KPI values
*
* @version 5.4.2
*/
public function view_report_description_lite( $notification, $report_kpi_statistics ) {
?>
'campaign-report-analytics',
'url' => 'https://www.icegram.com/documentation/what-analytics-does-email-subscribers-track/'
);
$pricing_url = ES_Common::get_utm_tracking_url( $utm_args );
?>
ajax_response();
$paged = ig_es_get_request_data( 'paged', 1 );
$campaign_class = '';
if ( ES()->is_pro() ) {
$campaign_class = 'es_campaign_premium';
}
?>
prepare_items();
$no_placeholder = ig_es_get_request_data( 'no_placeholder', '' );
extract( $this->_args );
extract( $this->_pagination_args, EXTR_SKIP );
ob_start();
if ( ! empty( $no_placeholder ) ) {
$this->display_rows();
} else {
$this->display_rows_or_placeholder();
}
$rows = ob_get_clean();
ob_start();
$this->print_column_headers();
$headers = ob_get_clean();
ob_start();
$this->pagination( 'top' );
$pagination_top = ob_get_clean();
ob_start();
$this->pagination( 'bottom' );
$pagination_bottom = ob_get_clean();
$response = array( 'rows' => $rows );
$response['column_headers'] = $headers;
$response['pagination']['top'] = $pagination_top;
$response['pagination']['bottom'] = $pagination_bottom;
if ( isset( $total_items ) ) {
/* translators: %s: Total items in the table */
$response['total_items_i18n'] = sprintf( _n( '%s item', '%s items', $total_items, 'email-subscribers' ), number_format_i18n( $total_items ) );
}
if ( isset( $total_pages ) ) {
$response['total_pages'] = $total_pages;
$response['total_pages_i18n'] = number_format_i18n( $total_pages );
}
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
die( json_encode( $response ) );
} else {
return $response;
}
}
/**
* Columns to make sortable.
*
* @return array
*/
public function get_sortable_columns() {
$sortable_columns = array(
'email' => array( 'email', false ),
'country_flag' => array( 'country_flag', false ),
'os' => array( 'os', false ),
'email_client' => array( 'email_client', false ),
'sent_at' => array( 'sent_at', false ),
'opened_at' => array( 'opened_at', false ),
'status' => array( 'status', false ),
);
return $sortable_columns;
}
/**
* Handles data query and filter, sorting, and pagination.
*/
public function prepare_items() {
$per_page = 100;
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array( $columns, $hidden, $sortable );
$data = $this->get_activity_table_data();
$total_items = $this->get_activity_table_data( true );
$this->items = $data;
/**
* Call to _set_pagination_args method for informations about
* total items, items for page, total pages and ordering
*/
$this->set_pagination_args(
array(
'total_items' => $total_items,
'per_page' => $per_page,
)
);
}
/**
* Method to handle display of WP_List table
*
* @Override of display method
*/
public function display() {
$search = ig_es_get_request_data( 's' );
$this->search_box( $search, 'campaign-reports-search-input' );
parent::display();
}
/**
* Prepare search box
*
* @param string $text
* @param string $input_id
*
* @since 4.6.12
*/
public function search_box( $text = '', $input_id = '' ) {
do_action( 'ig_es_campaign_reports_filter_options', $text, $input_id );
}
/**
* Associative array of columns
*
* @return array
*/
public function get_columns() {
$columns = array(
'sr_no' => '#',
'email' => __( 'Email', 'email-subscribers' ),
'status' => __( 'Status', 'email-subscribers' ),
'sent_at' => __( 'Sent Date', 'email-subscribers' ),
'opened_at' => __( 'Viewed Date', 'email-subscribers' ),
);
$columns = apply_filters( 'additional_es_campaign_report_columns', $columns );
return $columns;
}
/**
* Render a column when no column specific method exist.
*
* @param array $item
* @param string $column_name
*
* @return mixed
*/
public function column_default( $item, $column_name ) {
$column_data = ! empty( $item[ $column_name ] ) ? $item[ $column_name ] : '-';
return $column_data;
}
public function column_status( $item ) {
$status = ! empty( $item['status'] ) ? $item['status'] : ( ! empty( $item['es_deliver_sentstatus'] ) ? $item['es_deliver_sentstatus'] : '' );
switch ( $status ) {
case 'Sent':
?>
campaigns_db->table_exists( $wpbd->prefix . 'es_deliverreport' );
// We are assigning NULL values to sent_at and opened_at columns as actions tables have NULL values for these columns when no data is present in the column.
// Assigning NULL ensures sorting works as expected when both the tables are combined.
$queue_query = "SELECT queue.contact_id AS `contact_id`, queue.email AS `email`, 0 AS `type`, NULL AS `sent_at`, NULL AS `opened_at`, queue.status, '' AS `country`, '' AS `device`, '' AS `email_client`, '' AS `os`
FROM {$wpbd->prefix}ig_sending_queue AS queue
WHERE `mailing_queue_id` = %d AND `contact_id` NOT IN ( SELECT `contact_id` FROM {$wpbd->prefix}ig_actions WHERE campaign_id = %d AND message_id = %d )";
$delivery_query = $wpbd->prepare(
"SELECT
es_deliver_emailid AS `contact_id`,
es_deliver_emailmail AS `email`,
0 AS `type`,
UNIX_TIMESTAMP(es_deliver_sentdate) AS `sent_at`,
UNIX_TIMESTAMP(es_deliver_viewdate) AS `opened_at`,
es_deliver_sentstatus AS `status`,
'' AS `country`,
'' AS `device`,
'' AS `email_client`,
'' AS `os`
FROM {$wpbd->prefix}es_deliverreport WHERE es_deliver_sentguid = %s",
array( $hash )
);
$selects[] = $wpbd->prepare( $queue_query, $message_id, $campaign_id, $message_id );
}
$action_query = "SELECT
MAX(contacts.id) AS `contact_id`,
contacts.email AS `email`,
MAX(actions.type) AS `type`,
MAX(CASE WHEN actions.type = %d THEN actions.created_at END) AS `sent_at`,
MAX(CASE WHEN actions.type = %d THEN actions.created_at END) AS `opened_at`,
CASE WHEN MAX(actions.type) = %d THEN 'Sent' WHEN MAX(actions.type) = %d THEN 'Opened' END AS `status`,
MAX(actions.country) AS `country`,
MAX(actions.device) AS `device`,
MAX(actions.email_client) AS `email_client`,
MAX(actions.os) AS `os`
FROM {$wpbd->prefix}ig_actions AS actions
LEFT JOIN {$wpbd->prefix}ig_contacts AS contacts ON actions.contact_id = contacts.id
WHERE actions.campaign_id = %d AND actions.message_id = %d AND actions.type IN (%d, %d)
GROUP BY email";
$query_args = array(
IG_MESSAGE_SENT,
IG_MESSAGE_OPEN,
IG_MESSAGE_SENT,
IG_MESSAGE_OPEN,
$campaign_id,
$message_id,
IG_MESSAGE_SENT,
IG_MESSAGE_OPEN,
);
$selects[] = $wpbd->prepare( $action_query, $query_args );
if ( $return_count ) {
$notification_query = 'SELECT count(*) FROM ( ';
} else {
$notification_query = 'SELECT * FROM ( ';
}
$notification_query .= implode( ' UNION ALL ', $selects );
$notification_query .= ') AS `activity`';
$notification = ES()->campaigns_db->get( $campaign_id );
$total_email_sent = ES()->actions_db->get_count_based_on_id_type( $notification['id'], $message_id, IG_MESSAGE_SENT );
$email_viewed_count = ES()->actions_db->get_count_based_on_id_type( $notification['id'], $message_id, IG_MESSAGE_OPEN );
$notification_query .= ' WHERE 1';
$search_query = '';
if ( ! empty( $search ) ) {
$search_query = $wpbd->prepare( ' AND email LIKE %s', '%' . $wpbd->esc_like( $search ) . '%' );
}
$status_query = '';
if ( ! empty( $filter_by_status ) ) {
$status = 'not_opened' === $filter_by_status ? 'Sent' : 'Opened';
$status_query = $wpbd->prepare( ' AND `status` = %s', $status );
}
$country_query = '';
if ( ! empty( $filter_by_country ) ) {
$country_query = $wpbd->prepare( ' AND `country` = %s', $filter_by_country );
}
$order_by_query = '';
$offset = 0;
if ( ! $return_count ) {
if ( empty( $orderby ) ) {
// By default sort by opened_at and sent_at columns.
$orderby = "`opened_at` {$order}, `sent_at` {$order}";
} else {
$orderby = "{$orderby} {$order}";
}
$orderby = sanitize_sql_orderby( $orderby );
if ( $orderby ) {
$per_page = 100;
$offset = $page_number > 1 ? ( $page_number - 1 ) * $per_page : 0;
$order_by_query = " ORDER BY {$orderby} LIMIT {$offset}, {$per_page}";
}
}
$notification_query .= $search_query . $status_query . $country_query . $order_by_query;
if ( $return_count ) {
$count = $wpbd->get_var( $notification_query );
if ( empty( $count ) && $delivery_table_exists ) {
$count_query = 'SELECT count(*) FROM ( ' . $delivery_query . ' ) AS delivery_report WHERE 1';
$count_query .= $search_query . $status_query . $country_query . $order_by_query;
// If no results exists then check data into es_deliverreport table as earlier version were using this table.
$count = $wpbd->get_var(
$count_query
);
}
return $count;
} else {
$results = $wpbd->get_results( $notification_query, ARRAY_A );
// If no results exists then check data into es_deliverreport table as earlier version were using this table.
if ( empty( $results ) && $delivery_table_exists ) {
$delivery_query = 'SELECT * FROM ( ' . $delivery_query . ' ) AS delivery_report WHERE 1';
$delivery_query .= $search_query . $status_query . $country_query . $order_by_query;
$results = $wpbd->get_results(
$delivery_query,
ARRAY_A
);
}
$sr_no = $offset + 1;
if ( ! empty( $results ) ) {
$date_format = get_option( 'date_format' );
$time_format = get_option( 'time_format' );
$gmt_offset = ig_es_get_gmt_offset( true );
$format = $date_format . ' ' . $time_format;
foreach ( $results as $notification_action ) {
$contact_id = $notification_action['contact_id'];
$sent_at = '';
if ( ! empty( $notification_action['sent_at'] ) ) {
$sent_timestamp = (int) $notification_action['sent_at'];
$sent_timestamp += $gmt_offset;
$sent_at = ES_Common::convert_timestamp_to_date( $sent_timestamp, $format );
}
$opened_at = '';
if ( ! empty( $notification_action['opened_at'] ) ) {
$opened_timestamp = (int) $notification_action['opened_at'];
$opened_timestamp += $gmt_offset;
$opened_at = ES_Common::convert_timestamp_to_date( $opened_timestamp, $format );
}
$view_activity_data[ $contact_id ] = array(
'sr_no' => $sr_no++,
'email' => $notification_action['email'],
'opened_at' => $opened_at,
'sent_at' => $sent_at,
'status' => $notification_action['status'],
'country_flag' => '',
'device' => '',
'email_client' => '',
'os' => '',
);
$view_activity_data = apply_filters( 'additional_es_report_activity_data', $view_activity_data, $contact_id, $notification_action );
}
}
}
if ( ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
$insight = ig_es_get_request_data( 'insight', '' );
$_wpnonce = ig_es_get_request_data( '_wpnonce', '' );
if ( ( ES()->is_pro() || $insight ) && 0 !== $message_id ) {
do_action( 'ig_es_view_report_data', $hash );
}
?>
is_pro() && ! $insight ) { ?>