Google Analytics - Version 2.1

Version Description

  • NEW: Trending Content - trending content shows you a list of content that is performing better than average
  • NEW: Alerts - option to sign up for alerts via email or Slack when your content is taking off
  • Additional caching to always show Google Analytics dashboards
  • User interface improvements
Download this release

Release Info

Developer ShareThis
Plugin Icon wp plugin Google Analytics
Version 2.1
Comparing to
See all releases

Code changes from version 2.0.5 to 2.1

class/Ga_Admin.php CHANGED
@@ -2,59 +2,56 @@
2
 
3
  class Ga_Admin {
4
 
5
- const GA_WEB_PROPERTY_ID_OPTION_NAME = 'googleanalytics_web_property_id';
6
-
7
- const GA_EXCLUDE_ROLES_OPTION_NAME = 'googleanalytics_exclude_roles';
8
-
9
- const GA_SHARETHIS_TERMS_OPTION_NAME = 'googleanalytics_sharethis_terms';
10
-
11
- const GA_HIDE_TERMS_OPTION_NAME = 'googleanalytics_hide_terms';
12
-
13
- const GA_VERSION_OPTION_NAME = 'googleanalytics_version';
14
-
15
- const GA_SELECTED_ACCOUNT = 'googleanalytics_selected_account';
16
-
17
- const GA_OAUTH_AUTH_CODE_OPTION_NAME = 'googleanalytics_oauth_auth_code';
18
-
19
- const GA_OAUTH_AUTH_TOKEN_OPTION_NAME = 'googleanalytics_oauth_auth_token';
20
-
21
- const GA_ACCOUNT_DATA_OPTION_NAME = 'googleanalytics_account_data';
22
-
23
- const GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME = 'googleanalytics_web_property_id_manually';
24
-
25
- const GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME = 'googleanalytics_web_property_id_manually_value';
26
-
27
- const MIN_WP_VERSION = '3.8';
28
-
29
- const NOTICE_SUCCESS = 'success';
30
-
31
- const NOTICE_WARNING = 'warning';
32
-
33
- const NOTICE_ERROR = 'error';
34
 
35
  /**
36
  * Instantiate API client.
37
  *
38
- * @return Ga_Lib_Api_Client|null
39
- */
40
- public static function api_client() {
41
- $instance = Ga_Lib_Api_Client::get_instance();
42
- $token = Ga_Helper::get_option( self::GA_OAUTH_AUTH_TOKEN_OPTION_NAME );
43
- try {
44
- if ( ! empty( $token ) ) {
45
- $token = json_decode( $token, true );
46
- $instance->set_access_token( $token );
 
 
 
 
 
 
47
  }
48
- } catch ( Exception $e ) {
49
- Ga_Helper::ga_oauth_notice( $e->getMessage() );
50
  }
51
-
52
  return $instance;
53
  }
54
 
55
  /*
56
  * Initializes plugin's options during plugin activation process.
57
  */
 
58
  public static function activate_googleanalytics() {
59
  add_option( self::GA_WEB_PROPERTY_ID_OPTION_NAME, Ga_Helper::GA_DEFAULT_WEB_ID );
60
  add_option( self::GA_EXCLUDE_ROLES_OPTION_NAME, wp_json_encode( array() ) );
@@ -67,11 +64,14 @@ class Ga_Admin {
67
  add_option( self::GA_SELECTED_ACCOUNT );
68
  add_option( self::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME );
69
  add_option( self::GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME );
 
 
70
  }
71
 
72
  /*
73
  * Deletes plugin's options during plugin activation process.
74
  */
 
75
  public static function deactivate_googleanalytics() {
76
  delete_option( self::GA_WEB_PROPERTY_ID_OPTION_NAME );
77
  delete_option( self::GA_EXCLUDE_ROLES_OPTION_NAME );
@@ -81,6 +81,8 @@ class Ga_Admin {
81
  delete_option( self::GA_SELECTED_ACCOUNT );
82
  delete_option( self::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME );
83
  delete_option( self::GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME );
 
 
84
  }
85
 
86
  /**
@@ -90,6 +92,9 @@ class Ga_Admin {
90
  delete_option( self::GA_SHARETHIS_TERMS_OPTION_NAME );
91
  delete_option( self::GA_HIDE_TERMS_OPTION_NAME );
92
  delete_option( self::GA_VERSION_OPTION_NAME );
 
 
 
93
  }
94
 
95
  /**
@@ -104,9 +109,9 @@ class Ga_Admin {
104
  */
105
  public static function update_googleanalytics() {
106
 
107
- $version = get_option( self::GA_VERSION_OPTION_NAME );
108
- $installed_version = get_option( self::GA_VERSION_OPTION_NAME, '1.0.7' );
109
- $old_property_value = Ga_Helper::get_option( 'web_property_id' );
110
  if ( version_compare( $installed_version, GOOGLEANALYTICS_VERSION, 'eq' ) ) {
111
  return;
112
  }
@@ -116,7 +121,7 @@ class Ga_Admin {
116
 
117
  if ( version_compare( $installed_version, GOOGLEANALYTICS_VERSION, 'lt' ) ) {
118
 
119
- if ( ! empty( $old_property_value ) ) {
120
  Ga_Helper::update_option( self::GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME, $old_property_value );
121
  Ga_Helper::update_option( self::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME, 1 );
122
  delete_option( 'web_property_id' );
@@ -126,9 +131,8 @@ class Ga_Admin {
126
  update_option( self::GA_VERSION_OPTION_NAME, GOOGLEANALYTICS_VERSION );
127
  }
128
 
129
-
130
  public static function preupdate_exclude_roles( $new_value, $old_value ) {
131
- if ( ! Ga_Helper::are_terms_accepted() ) {
132
  return '';
133
  }
134
 
@@ -144,18 +148,26 @@ class Ga_Admin {
144
  * @return mixed
145
  */
146
  public static function preupdate_selected_account( $new_value, $old_value ) {
147
- $data = null;
148
- if ( ! empty( $new_value ) ) {
149
  $data = explode( "_", $new_value );
150
 
151
- if ( ! empty( $data[1] ) ) {
152
- Ga_Helper::update_option( self::GA_WEB_PROPERTY_ID_OPTION_NAME, $data[1] );
153
  }
154
  }
155
 
156
  return wp_json_encode( $data );
157
  }
158
 
 
 
 
 
 
 
 
 
159
  /**
160
  * Registers plugin's settings.
161
  */
@@ -166,10 +178,10 @@ class Ga_Admin {
166
  register_setting( GA_NAME, self::GA_OAUTH_AUTH_CODE_OPTION_NAME );
167
  register_setting( GA_NAME, self::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME );
168
  register_setting( GA_NAME, self::GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME );
169
- add_filter( 'pre_update_option_' . Ga_Admin::GA_EXCLUDE_ROLES_OPTION_NAME, 'Ga_Admin::preupdate_exclude_roles',
170
- 1, 2 );
171
- add_filter( 'pre_update_option_' . Ga_Admin::GA_SELECTED_ACCOUNT, 'Ga_Admin::preupdate_selected_account', 1,
172
- 2 );
173
  }
174
 
175
  /**
@@ -177,21 +189,40 @@ class Ga_Admin {
177
  */
178
  public static function admin_menu_googleanalytics() {
179
  if ( current_user_can( 'manage_options' ) ) {
180
- add_menu_page( 'Google Analytics', 'Google Analytics', 'manage_options', 'googleanalytics',
181
- 'Ga_Admin::statistics_page_googleanalytics', 'dashicons-chart-line', 1000 );
182
- add_submenu_page( 'googleanalytics', 'Google Analytics', __( 'Dashboard' ), 'manage_options',
183
- 'googleanalytics', 'Ga_Admin::statistics_page_googleanalytics' );
184
- add_submenu_page( 'googleanalytics', 'Google Analytics', __( 'Settings' ), 'manage_options',
185
- 'googleanalytics/settings', 'Ga_Admin::options_page_googleanalytics' );
186
  }
187
  }
188
 
189
  /**
190
- * Sets accept terms option to TRUE.
191
  */
192
- public static function update_terms() {
193
- update_option( self::GA_SHARETHIS_TERMS_OPTION_NAME, true );
194
- wp_redirect( admin_url( Ga_Helper::GA_SETTINGS_PAGE_URL ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  }
196
 
197
  /**
@@ -199,15 +230,19 @@ class Ga_Admin {
199
  */
200
  public static function statistics_page_googleanalytics() {
201
 
202
- if ( ! Ga_Helper::is_wp_version_valid() || ! Ga_Helper::is_php_version_valid() ) {
203
  return false;
204
  }
205
 
206
  $data = self::get_stats_page();
207
- Ga_View::load( 'statistics', array(
208
  'data' => $data
209
  ) );
210
 
 
 
 
 
211
  self::display_api_errors();
212
  }
213
 
@@ -216,7 +251,7 @@ class Ga_Admin {
216
  */
217
  public static function options_page_googleanalytics() {
218
 
219
- if ( ! Ga_Helper::is_wp_version_valid() || ! Ga_Helper::is_php_version_valid() ) {
220
  return false;
221
  }
222
 
@@ -227,40 +262,42 @@ class Ga_Admin {
227
  */
228
  $data = array();
229
 
230
- $data[ self::GA_WEB_PROPERTY_ID_OPTION_NAME ] = get_option( self::GA_WEB_PROPERTY_ID_OPTION_NAME );
231
  $data[ self::GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME ] = get_option( self::GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME );
232
- $data[ self::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME ] = get_option( self::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME );
 
233
 
234
- $roles = Ga_Helper::get_user_roles();
235
- $saved = json_decode( get_option( self::GA_EXCLUDE_ROLES_OPTION_NAME ), true );
236
 
237
  $tmp = array();
238
- if ( ! empty( $roles ) ) {
239
  foreach ( $roles as $role ) {
240
  $role_id = Ga_Helper::prepare_role_id( $role );
241
- $tmp[] = array(
242
- 'name' => $role,
243
- 'id' => $role_id,
244
- 'checked' => ( ! empty( $saved[ $role_id ] ) && $saved[ $role_id ] === 'on' )
245
  );
246
  }
247
  }
248
- $data['roles'] = $tmp;
249
 
250
  if ( Ga_Helper::is_authorized() ) {
251
- $data['ga_accounts_selector'] = self::get_accounts_selector();
252
  } else {
253
- $data['popup_url'] = self::get_auth_popup_url();
254
  }
255
- if ( ! empty( $_GET['err'] ) ) {
256
- switch ( $_GET['err'] ) {
257
  case 1:
258
- $data['error_message'] = Ga_Helper::ga_oauth_notice( 'There was a problem with Google Oauth2 authentication process.' );
259
  break;
260
  }
261
  }
262
- Ga_View::load( 'page', array(
263
- 'data' => $data
 
264
  ) );
265
 
266
  self::display_api_errors();
@@ -273,7 +310,7 @@ class Ga_Admin {
273
  * @return mixed
274
  */
275
  public static function get_auth_popup_url() {
276
- return admin_url( Ga_Helper::GA_SETTINGS_PAGE_URL . '&ga_action=ga_auth' );
277
  }
278
 
279
  /**
@@ -284,10 +321,10 @@ class Ga_Admin {
284
  public static function get_accounts_selector() {
285
  $selected = Ga_Helper::get_selected_account_data();
286
 
287
- return Ga_View::load( 'ga_accounts_selector', array(
288
- 'selector' => json_decode( get_option( self::GA_ACCOUNT_DATA_OPTION_NAME ), true ),
289
- 'selected' => $selected ? implode( "_", $selected ) : null,
290
- 'add_manually_enabled' => Ga_Helper::is_code_manually_enabled()
291
  ), true );
292
  }
293
 
@@ -309,7 +346,10 @@ class Ga_Admin {
309
  wp_register_style( GA_NAME . '-additional-css', GA_PLUGIN_URL . '/css/ga_additional.css', false, null, 'all' );
310
  wp_enqueue_style( GA_NAME . '-css' );
311
  wp_enqueue_style( GA_NAME . '-additional-css' );
312
-
 
 
 
313
  wp_register_style( GA_NAME . '-modal-css', GA_PLUGIN_URL . '/css/ga_modal.css', false, null, 'all' );
314
  wp_enqueue_style( GA_NAME . '-modal-css' );
315
  }
@@ -355,46 +395,19 @@ class Ga_Admin {
355
  * @return string HTML code
356
  */
357
  public static function get_stats_page() {
358
- $chart = null;
359
- $boxes = null;
360
- $labels = null;
361
  $sources = null;
362
- if ( Ga_Helper::is_authorized() && Ga_Helper::is_account_selected() ) {
363
- $selected = Ga_Helper::get_selected_account_data( true );
364
-
365
- $query_params = Ga_Stats::get_query( 'main_chart', $selected['view_id'] );
366
- $stats_data = self::api_client()->call( 'ga_api_data', array(
367
-
368
- $query_params
369
- ) );
370
-
371
- $boxes_data = self::api_client()->call( 'ga_api_data', array(
372
-
373
- Ga_Stats::get_query( 'boxes', $selected['view_id'] )
374
- ) );
375
- $sources_data = self::api_client()->call( 'ga_api_data', array(
376
-
377
- Ga_Stats::get_query( 'sources', $selected['view_id'] )
378
- ) );
379
- $chart = ! empty( $stats_data ) ? Ga_Stats::get_chart( $stats_data->getData() ) : array();
380
- $boxes = ! empty( $boxes_data ) ? Ga_Stats::get_boxes( $boxes_data->getData() ) : array();
381
- $last_chart_date = ! empty( $chart ) ? $chart['date'] : strtotime( 'now' );
382
- unset( $chart['date'] );
383
- $labels = array(
384
- 'thisWeek' => date( 'M d, Y', strtotime( '-6 day', $last_chart_date ) ) . ' - ' . date( 'M d, Y',
385
- $last_chart_date ),
386
- 'lastWeek' => date( 'M d, Y', strtotime( '-13 day', $last_chart_date ) ) . ' - ' . date( 'M d, Y',
387
- strtotime( '-7 day', $last_chart_date ) )
388
- );
389
- $sources = ! empty( $sources_data ) ? Ga_Stats::get_sources( $sources_data->getData() ) : array();
390
  }
391
 
392
  return Ga_Helper::get_chart_page( 'stats', array(
393
-
394
- 'chart' => $chart,
395
- 'boxes' => $boxes,
396
- 'labels' => $labels,
397
- 'sources' => $sources
398
  ) );
399
  }
400
 
@@ -402,18 +415,24 @@ class Ga_Admin {
402
  * Shows plugin's notice on the admin area.
403
  */
404
  public static function admin_notice_googleanalytics() {
405
- if ( ( ! get_option( self::GA_SHARETHIS_TERMS_OPTION_NAME ) && Ga_Helper::is_plugin_page() ) || ( ! get_option( self::GA_SHARETHIS_TERMS_OPTION_NAME ) && ! get_option( self::GA_HIDE_TERMS_OPTION_NAME ) ) ) {
406
  $current_url = Ga_Helper::get_current_url();
407
- $url = ( strstr( $current_url,
408
- '?' ) ? $current_url . '&' : $current_url . '?' ) . http_build_query( array( 'ga_action' => 'update_terms' ) );
409
- Ga_View::load( 'ga_notice', array(
410
  'url' => $url
411
  ) );
412
  }
413
 
414
- if ( ! empty( $_GET['settings-updated'] ) ) {
415
  echo Ga_Helper::ga_wp_notice( _( 'Settings saved' ), self::NOTICE_SUCCESS );
416
  }
 
 
 
 
 
 
 
417
  }
418
 
419
  /**
@@ -421,8 +440,7 @@ class Ga_Admin {
421
  * @return string
422
  */
423
  public static function admin_notice_googleanalytics_php_version() {
424
- echo Ga_Helper::ga_wp_notice( _( 'Cannot use Google Analytics plugin. PHP version ' . phpversion() . ' is to low. Required PHP version: ' . Ga_Helper::PHP_VERSION_REQUIRED ),
425
- self::NOTICE_ERROR );
426
  }
427
 
428
  /**
@@ -430,8 +448,7 @@ class Ga_Admin {
430
  * @return string
431
  */
432
  public static function admin_notice_googleanalytics_wp_version() {
433
- echo Ga_Helper::ga_wp_notice( _( 'Google Analytics plugin requires at least WordPress version ' . self::MIN_WP_VERSION ),
434
- self::NOTICE_ERROR );
435
  }
436
 
437
  /**
@@ -446,8 +463,7 @@ class Ga_Admin {
446
  */
447
  public static function add_dashboard_device_widget() {
448
  if ( Ga_Helper::is_administrator() ) {
449
- wp_add_dashboard_widget( 'ga_dashboard_widget', __( 'Google Analytics Dashboard' ),
450
- 'Ga_Helper::add_ga_dashboard_widget' );
451
  }
452
  }
453
 
@@ -461,12 +477,29 @@ class Ga_Admin {
461
  add_action( 'wp_dashboard_setup', 'Ga_Admin::add_dashboard_device_widget' );
462
  add_action( 'wp_ajax_ga_ajax_data_change', 'Ga_Admin::ga_ajax_data_change' );
463
  add_action( 'admin_notices', 'Ga_Admin::admin_notice_googleanalytics' );
 
464
 
465
- if ( ! get_option( self::GA_SHARETHIS_TERMS_OPTION_NAME ) && ! get_option( self::GA_HIDE_TERMS_OPTION_NAME ) ) {
466
  add_action( 'wp_ajax_googleanalytics_hide_terms', 'Ga_Admin::admin_notice_hide_googleanalytics' );
467
  }
468
  }
469
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
470
  /**
471
  * Adds plugin's filters
472
  */
@@ -485,8 +518,7 @@ class Ga_Admin {
485
  public static function ga_action_links( $actions, $plugin_file ) {
486
 
487
  if ( basename( $plugin_file ) == GA_NAME . '.php' ) {
488
- array_unshift( $actions, '<a href="' . esc_url( get_admin_url( null,
489
- Ga_Helper::GA_SETTINGS_PAGE_URL ) ) . '">' . _( 'Settings' ) . '</a>' );
490
  }
491
 
492
  return $actions;
@@ -496,7 +528,7 @@ class Ga_Admin {
496
 
497
  $code = Ga_Helper::get_option( self::GA_OAUTH_AUTH_CODE_OPTION_NAME );
498
 
499
- if ( ! Ga_Helper::is_authorized() && ! empty( $code ) ) {
500
  Ga_Helper::update_option( self::GA_OAUTH_AUTH_CODE_OPTION_NAME, "" );
501
 
502
  // Get access token
@@ -505,7 +537,7 @@ class Ga_Admin {
505
  return false;
506
  }
507
  $param = '';
508
- if ( ! self::save_access_token( $response ) ) {
509
  $param = '&err=1';
510
  } else {
511
  self::api_client()->set_access_token( $response->getData() );
@@ -519,29 +551,6 @@ class Ga_Admin {
519
  }
520
  }
521
 
522
- public static function handle_actions() {
523
- $action = ! empty( $_GET['ga_action'] ) ? $_GET['ga_action'] : null;
524
-
525
- if ( $action ) {
526
- $class = __CLASS__;
527
- if ( is_callable( array(
528
-
529
- $class,
530
- $action
531
- ) ) ) {
532
- call_user_func( $class . '::' . $action );
533
- }
534
- }
535
- }
536
-
537
- public static function ga_auth() {
538
- if ( Ga_Helper::are_terms_accepted() ) {
539
- header( 'Location:' . self::api_client()->create_auth_url() );
540
- } else {
541
- wp_die( Ga_Helper::ga_oauth_notice( __( 'Please accept the terms to use this feature' ) ) );
542
- }
543
- }
544
-
545
  /**
546
  * Save access token.
547
  *
@@ -551,14 +560,14 @@ class Ga_Admin {
551
  */
552
  public static function save_access_token( $response, $refresh_token = '' ) {
553
  $access_token = $response->getData();
554
- if ( ! empty( $access_token ) ) {
555
- $access_token['created'] = time();
556
  } else {
557
  return false;
558
  }
559
 
560
- if ( ! empty( $refresh_token ) ) {
561
- $access_token['refresh_token'] = $refresh_token;
562
  }
563
 
564
  return update_option( self::GA_OAUTH_AUTH_TOKEN_OPTION_NAME, wp_json_encode( $access_token ) );
@@ -573,29 +582,27 @@ class Ga_Admin {
573
  */
574
  public static function save_ga_account_summaries( $data ) {
575
  $return = array();
576
- if ( ! empty( $data['items'] ) ) {
577
- foreach ( $data['items'] as $item ) {
578
- $tmp = array();
579
- $tmp['id'] = $item['id'];
580
- $tmp['name'] = $item['name'];
581
- if ( is_array( $item['webProperties'] ) ) {
582
- foreach ( $item['webProperties'] as $property ) {
583
  $profiles = array();
584
- if ( is_array( $property['profiles'] ) ) {
585
- foreach ( $property['profiles'] as $profile ) {
586
  $profiles[] = array(
587
-
588
- 'id' => $profile['id'],
589
- 'name' => $profile['name']
590
  );
591
  }
592
  }
593
 
594
- $tmp['webProperties'][] = array(
595
-
596
- 'webPropertyId' => $property['id'],
597
- 'name' => $property['name'],
598
- 'profiles' => $profiles
599
  );
600
  }
601
  }
@@ -614,8 +621,8 @@ class Ga_Admin {
614
  * Handle AJAX data for the GA dashboard widget.
615
  */
616
  public static function ga_ajax_data_change() {
617
- $date_range = ! empty( $_POST['date_range'] ) ? $_POST['date_range'] : null;
618
- $metric = ! empty( $_POST['metric'] ) ? $_POST['metric'] : null;
619
  echo Ga_Helper::get_ga_dashboard_widget_data_json( $date_range, $metric, false, true );
620
  wp_die();
621
  }
@@ -623,18 +630,45 @@ class Ga_Admin {
623
  /**
624
  * Displays API error messages.
625
  */
626
- public static function display_api_errors() {
627
- $errors = self::api_client()->get_errors();
628
- if ( ! empty( $errors ) ) {
629
  foreach ( $errors as $error ) {
630
- if ( $error['class'] == 'Ga_Lib_Api_Request_Exception' ){
631
- echo Ga_Helper::ga_wp_notice( _( 'There are temporary connection issues, please try again later or go to Google Analytics website to see the dashboards' ), self::NOTICE_ERROR );
632
- }
633
- else{
634
- echo Ga_Helper::ga_wp_notice( _( '[' . $error['class'] . ']' ) . ' ' . $error['message'],
635
- self::NOTICE_ERROR );
636
- }
637
  }
638
  }
639
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
640
  }
2
 
3
  class Ga_Admin {
4
 
5
+ const GA_WEB_PROPERTY_ID_OPTION_NAME = 'googleanalytics_web_property_id';
6
+ const GA_EXCLUDE_ROLES_OPTION_NAME = 'googleanalytics_exclude_roles';
7
+ const GA_SHARETHIS_TERMS_OPTION_NAME = 'googleanalytics_sharethis_terms';
8
+ const GA_HIDE_TERMS_OPTION_NAME = 'googleanalytics_hide_terms';
9
+ const GA_VERSION_OPTION_NAME = 'googleanalytics_version';
10
+ const GA_SELECTED_ACCOUNT = 'googleanalytics_selected_account';
11
+ const GA_OAUTH_AUTH_CODE_OPTION_NAME = 'googleanalytics_oauth_auth_code';
12
+ const GA_OAUTH_AUTH_TOKEN_OPTION_NAME = 'googleanalytics_oauth_auth_token';
13
+ const GA_ACCOUNT_DATA_OPTION_NAME = 'googleanalytics_account_data';
14
+ const GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME = 'googleanalytics_web_property_id_manually';
15
+ const GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME = 'googleanalytics_web_property_id_manually_value';
16
+ const GA_SHARETHIS_PROPERTY_ID = 'googleanalytics_sherethis_property_id';
17
+ const GA_SHARETHIS_PROPERTY_SECRET = 'googleanalytics_sherethis_property_secret';
18
+ const GA_SHARETHIS_VERIFICATION_RESULT = 'googleanalytics_sherethis_verification_result';
19
+ const MIN_WP_VERSION = '3.8';
20
+ const GA_SHARETHIS_TRENDING_CONTENT_PLUGIN_VERSION = '2.1';
21
+ const NOTICE_SUCCESS = 'success';
22
+ const NOTICE_WARNING = 'warning';
23
+ const NOTICE_ERROR = 'error';
24
+ const GA_SHARETHIS_API_ALIAS = 'sharethis';
25
+ const GA_DISABLE_ALL_FEATURES = 'googleanalytics_disable_all_features';
26
+ const GA_HEARTBEAT_API_CACHE_UPDATE = true;
 
 
 
 
 
 
 
27
 
28
  /**
29
  * Instantiate API client.
30
  *
31
+ * @return Ga_Lib_Google_Api_Client|null
32
+ */
33
+ public static function api_client( $type = '' ) {
34
+ if ( $type === self::GA_SHARETHIS_API_ALIAS ) {
35
+ $instance = Ga_Lib_Sharethis_Api_Client::get_instance();
36
+ } else {
37
+ $instance = Ga_Lib_Google_Api_Client::get_instance();
38
+ $token = Ga_Helper::get_option( self::GA_OAUTH_AUTH_TOKEN_OPTION_NAME );
39
+ try {
40
+ if ( !empty( $token ) ) {
41
+ $token = json_decode( $token, true );
42
+ $instance->set_access_token( $token );
43
+ }
44
+ } catch ( Exception $e ) {
45
+ Ga_Helper::ga_oauth_notice( $e->getMessage() );
46
  }
 
 
47
  }
 
48
  return $instance;
49
  }
50
 
51
  /*
52
  * Initializes plugin's options during plugin activation process.
53
  */
54
+
55
  public static function activate_googleanalytics() {
56
  add_option( self::GA_WEB_PROPERTY_ID_OPTION_NAME, Ga_Helper::GA_DEFAULT_WEB_ID );
57
  add_option( self::GA_EXCLUDE_ROLES_OPTION_NAME, wp_json_encode( array() ) );
64
  add_option( self::GA_SELECTED_ACCOUNT );
65
  add_option( self::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME );
66
  add_option( self::GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME );
67
+ add_option( self::GA_DISABLE_ALL_FEATURES );
68
+ Ga_Cache::add_cache_options();
69
  }
70
 
71
  /*
72
  * Deletes plugin's options during plugin activation process.
73
  */
74
+
75
  public static function deactivate_googleanalytics() {
76
  delete_option( self::GA_WEB_PROPERTY_ID_OPTION_NAME );
77
  delete_option( self::GA_EXCLUDE_ROLES_OPTION_NAME );
81
  delete_option( self::GA_SELECTED_ACCOUNT );
82
  delete_option( self::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME );
83
  delete_option( self::GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME );
84
+ delete_option( self::GA_DISABLE_ALL_FEATURES );
85
+ Ga_Cache::delete_cache_options();
86
  }
87
 
88
  /**
92
  delete_option( self::GA_SHARETHIS_TERMS_OPTION_NAME );
93
  delete_option( self::GA_HIDE_TERMS_OPTION_NAME );
94
  delete_option( self::GA_VERSION_OPTION_NAME );
95
+ delete_option( self::GA_SHARETHIS_PROPERTY_ID );
96
+ delete_option( self::GA_SHARETHIS_PROPERTY_SECRET );
97
+ delete_option( self::GA_SHARETHIS_VERIFICATION_RESULT );
98
  }
99
 
100
  /**
109
  */
110
  public static function update_googleanalytics() {
111
 
112
+ $version = get_option( self::GA_VERSION_OPTION_NAME );
113
+ $installed_version = get_option( self::GA_VERSION_OPTION_NAME, '1.0.7' );
114
+ $old_property_value = Ga_Helper::get_option( 'web_property_id' );
115
  if ( version_compare( $installed_version, GOOGLEANALYTICS_VERSION, 'eq' ) ) {
116
  return;
117
  }
121
 
122
  if ( version_compare( $installed_version, GOOGLEANALYTICS_VERSION, 'lt' ) ) {
123
 
124
+ if ( !empty( $old_property_value ) ) {
125
  Ga_Helper::update_option( self::GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME, $old_property_value );
126
  Ga_Helper::update_option( self::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME, 1 );
127
  delete_option( 'web_property_id' );
131
  update_option( self::GA_VERSION_OPTION_NAME, GOOGLEANALYTICS_VERSION );
132
  }
133
 
 
134
  public static function preupdate_exclude_roles( $new_value, $old_value ) {
135
+ if ( !Ga_Helper::are_features_enabled() ) {
136
  return '';
137
  }
138
 
148
  * @return mixed
149
  */
150
  public static function preupdate_selected_account( $new_value, $old_value ) {
151
+ $data = null;
152
+ if ( !empty( $new_value ) ) {
153
  $data = explode( "_", $new_value );
154
 
155
+ if ( !empty( $data[ 1 ] ) ) {
156
+ Ga_Helper::update_option( self::GA_WEB_PROPERTY_ID_OPTION_NAME, $data[ 1 ] );
157
  }
158
  }
159
 
160
  return wp_json_encode( $data );
161
  }
162
 
163
+ public static function preupdate_disable_all_features( $new_value, $old_value ) {
164
+ if ( $old_value == 'on' ) {
165
+ Ga_Helper::update_option( Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME, false );
166
+ }
167
+
168
+ return $new_value;
169
+ }
170
+
171
  /**
172
  * Registers plugin's settings.
173
  */
178
  register_setting( GA_NAME, self::GA_OAUTH_AUTH_CODE_OPTION_NAME );
179
  register_setting( GA_NAME, self::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME );
180
  register_setting( GA_NAME, self::GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME );
181
+ register_setting( GA_NAME, self::GA_DISABLE_ALL_FEATURES );
182
+ add_filter( 'pre_update_option_' . Ga_Admin::GA_EXCLUDE_ROLES_OPTION_NAME, 'Ga_Admin::preupdate_exclude_roles', 1, 2 );
183
+ add_filter( 'pre_update_option_' . Ga_Admin::GA_SELECTED_ACCOUNT, 'Ga_Admin::preupdate_selected_account', 1, 2 );
184
+ // add_filter( 'pre_update_option_' . Ga_Admin::GA_DISABLE_ALL_FEATURES, 'Ga_Admin::preupdate_disable_all_features', 1, 2 );
185
  }
186
 
187
  /**
189
  */
190
  public static function admin_menu_googleanalytics() {
191
  if ( current_user_can( 'manage_options' ) ) {
192
+ add_menu_page( 'Google Analytics', 'Google Analytics', 'manage_options', 'googleanalytics', 'Ga_Admin::statistics_page_googleanalytics', 'dashicons-chart-line', 1000 );
193
+ add_submenu_page( 'googleanalytics', 'Google Analytics', __( 'Dashboard' ), 'manage_options', 'googleanalytics', 'Ga_Admin::statistics_page_googleanalytics' );
194
+ add_submenu_page( 'googleanalytics', 'Google Analytics', __( 'Trending Content' ), 'manage_options', 'googleanalytics/trending', 'Ga_Admin::trending_page_googleanalytics' );
195
+ add_submenu_page( 'googleanalytics', 'Google Analytics', __( 'Settings' ), 'manage_options', 'googleanalytics/settings', 'Ga_Admin::options_page_googleanalytics' );
 
 
196
  }
197
  }
198
 
199
  /**
200
+ * Prepares and displays plugin's trending content page.
201
  */
202
+ public static function trending_page_googleanalytics() {
203
+
204
+ if ( !Ga_Helper::is_wp_version_valid() || !Ga_Helper::is_php_version_valid() ) {
205
+ return false;
206
+ }
207
+ $data = Ga_Sharethis::create_sharethis_options( self::api_client( self::GA_SHARETHIS_API_ALIAS ) );
208
+
209
+ Ga_Sharethis::sharethis_installation_verification( self::api_client( self::GA_SHARETHIS_API_ALIAS ) );
210
+
211
+ $alerts = Ga_Sharethis::load_sharethis_trending_alerts( self::api_client( self::GA_SHARETHIS_API_ALIAS ) );
212
+ // Handle invitation result
213
+ $data = Ga_Helper::handle_url_message( $data );
214
+ if ( Ga_Helper::is_wp_old() ) {
215
+ self::display_api_errors( self::GA_SHARETHIS_API_ALIAS );
216
+ }
217
+ Ga_View_Core::load( 'trending', array(
218
+ 'data' => $data,
219
+ 'alerts' => $alerts,
220
+ 'tooltip' => Ga_Helper::get_tooltip(),
221
+ 'errors' => self::api_client( self::GA_SHARETHIS_API_ALIAS )->get_errors()
222
+ ) );
223
+ if ( !Ga_Helper::is_wp_old() ) {
224
+ self::display_api_errors( self::GA_SHARETHIS_API_ALIAS );
225
+ }
226
  }
227
 
228
  /**
230
  */
231
  public static function statistics_page_googleanalytics() {
232
 
233
+ if ( !Ga_Helper::is_wp_version_valid() || !Ga_Helper::is_php_version_valid() ) {
234
  return false;
235
  }
236
 
237
  $data = self::get_stats_page();
238
+ Ga_View_Core::load( 'statistics', array(
239
  'data' => $data
240
  ) );
241
 
242
+ if ( Ga_Cache::is_data_cache_outdated( '', Ga_Helper::get_account_id() ) ) {
243
+ self::api_client()->add_own_error( '1', _( 'Saved data is shown, it will be refreshed soon' ), 'Ga_Data_Outdated_Exception' );
244
+ }
245
+
246
  self::display_api_errors();
247
  }
248
 
251
  */
252
  public static function options_page_googleanalytics() {
253
 
254
+ if ( !Ga_Helper::is_wp_version_valid() || !Ga_Helper::is_php_version_valid() ) {
255
  return false;
256
  }
257
 
262
  */
263
  $data = array();
264
 
265
+ $data[ self::GA_WEB_PROPERTY_ID_OPTION_NAME ] = get_option( self::GA_WEB_PROPERTY_ID_OPTION_NAME );
266
  $data[ self::GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME ] = get_option( self::GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME );
267
+ $data[ self::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME ] = get_option( self::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME );
268
+ $data[ self::GA_DISABLE_ALL_FEATURES ] = get_option( self::GA_DISABLE_ALL_FEATURES );
269
 
270
+ $roles = Ga_Helper::get_user_roles();
271
+ $saved = json_decode( get_option( self::GA_EXCLUDE_ROLES_OPTION_NAME ), true );
272
 
273
  $tmp = array();
274
+ if ( !empty( $roles ) ) {
275
  foreach ( $roles as $role ) {
276
  $role_id = Ga_Helper::prepare_role_id( $role );
277
+ $tmp[] = array(
278
+ 'name' => $role,
279
+ 'id' => $role_id,
280
+ 'checked' => (!empty( $saved[ $role_id ] ) && $saved[ $role_id ] === 'on' )
281
  );
282
  }
283
  }
284
+ $data[ 'roles' ] = $tmp;
285
 
286
  if ( Ga_Helper::is_authorized() ) {
287
+ $data[ 'ga_accounts_selector' ] = self::get_accounts_selector();
288
  } else {
289
+ $data[ 'popup_url' ] = self::get_auth_popup_url();
290
  }
291
+ if ( !empty( $_GET[ 'err' ] ) ) {
292
+ switch ( $_GET[ 'err' ] ) {
293
  case 1:
294
+ $data[ 'error_message' ] = Ga_Helper::ga_oauth_notice( 'There was a problem with Google Oauth2 authentication process.' );
295
  break;
296
  }
297
  }
298
+ Ga_View_Core::load( 'page', array(
299
+ 'data' => $data,
300
+ 'tooltip' => Ga_Helper::get_tooltip()
301
  ) );
302
 
303
  self::display_api_errors();
310
  * @return mixed
311
  */
312
  public static function get_auth_popup_url() {
313
+ return admin_url( Ga_Helper::create_url( Ga_Helper::GA_SETTINGS_PAGE_URL, array( Ga_Controller_Core::ACTION_PARAM_NAME => 'ga_action_auth' ) ) );
314
  }
315
 
316
  /**
321
  public static function get_accounts_selector() {
322
  $selected = Ga_Helper::get_selected_account_data();
323
 
324
+ return Ga_View_Core::load( 'ga_accounts_selector', array(
325
+ 'selector' => json_decode( get_option( self::GA_ACCOUNT_DATA_OPTION_NAME ), true ),
326
+ 'selected' => $selected ? implode( "_", $selected ) : null,
327
+ 'add_manually_enabled' => Ga_Helper::is_code_manually_enabled() || Ga_Helper::is_all_feature_disabled()
328
  ), true );
329
  }
330
 
346
  wp_register_style( GA_NAME . '-additional-css', GA_PLUGIN_URL . '/css/ga_additional.css', false, null, 'all' );
347
  wp_enqueue_style( GA_NAME . '-css' );
348
  wp_enqueue_style( GA_NAME . '-additional-css' );
349
+ if ( Ga_Helper::is_wp_old() ) {
350
+ wp_register_style( GA_NAME . '-old-wp-support-css', GA_PLUGIN_URL . '/css/ga_old_wp_support.css', false, null, 'all' );
351
+ wp_enqueue_style( GA_NAME . '-old-wp-support-css' );
352
+ }
353
  wp_register_style( GA_NAME . '-modal-css', GA_PLUGIN_URL . '/css/ga_modal.css', false, null, 'all' );
354
  wp_enqueue_style( GA_NAME . '-modal-css' );
355
  }
395
  * @return string HTML code
396
  */
397
  public static function get_stats_page() {
398
+ $chart = null;
399
+ $boxes = null;
400
+ $labels = null;
401
  $sources = null;
402
+ if ( Ga_Helper::is_authorized() && Ga_Helper::is_account_selected() && !Ga_Helper::is_all_feature_disabled() ) {
403
+ list( $chart, $boxes, $labels, $sources ) = self::generate_stats_data();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
404
  }
405
 
406
  return Ga_Helper::get_chart_page( 'stats', array(
407
+ 'chart' => $chart,
408
+ 'boxes' => $boxes,
409
+ 'labels' => $labels,
410
+ 'sources' => $sources
 
411
  ) );
412
  }
413
 
415
  * Shows plugin's notice on the admin area.
416
  */
417
  public static function admin_notice_googleanalytics() {
418
+ if ( (!get_option( self::GA_SHARETHIS_TERMS_OPTION_NAME ) && Ga_Helper::is_plugin_page() ) || (!get_option( self::GA_SHARETHIS_TERMS_OPTION_NAME ) && !get_option( self::GA_HIDE_TERMS_OPTION_NAME ) ) ) {
419
  $current_url = Ga_Helper::get_current_url();
420
+ $url = ( strstr( $current_url, '?' ) ? $current_url . '&' : $current_url . '?' ) . http_build_query( array( Ga_Controller_Core::ACTION_PARAM_NAME => 'ga_action_update_terms' ) );
421
+ Ga_View_Core::load( 'ga_notice', array(
 
422
  'url' => $url
423
  ) );
424
  }
425
 
426
+ if ( !empty( $_GET[ 'settings-updated' ] ) && Ga_Helper::is_plugin_page() ) {
427
  echo Ga_Helper::ga_wp_notice( _( 'Settings saved' ), self::NOTICE_SUCCESS );
428
  }
429
+
430
+ if ( Ga_Helper::get_option( self::GA_DISABLE_ALL_FEATURES ) ) {
431
+ echo Ga_Helper::ga_wp_notice( _( 'You have disabled all extra features, click here to enable Dashboards, Viral Alerts and Google API.' ), self::NOTICE_WARNING, false, array(
432
+ 'url' => admin_url( Ga_Helper::create_url( Ga_Helper::GA_SETTINGS_PAGE_URL, array( Ga_Controller_Core::ACTION_PARAM_NAME => 'ga_action_enable_all_features' ) ) ),
433
+ 'label' => _( 'Enable' )
434
+ ) );
435
+ }
436
  }
437
 
438
  /**
440
  * @return string
441
  */
442
  public static function admin_notice_googleanalytics_php_version() {
443
+ echo Ga_Helper::ga_wp_notice( _( 'Cannot use Google Analytics plugin. PHP version ' . phpversion() . ' is to low. Required PHP version: ' . Ga_Helper::PHP_VERSION_REQUIRED ), self::NOTICE_ERROR );
 
444
  }
445
 
446
  /**
448
  * @return string
449
  */
450
  public static function admin_notice_googleanalytics_wp_version() {
451
+ echo Ga_Helper::ga_wp_notice( _( 'Google Analytics plugin requires at least WordPress version ' . self::MIN_WP_VERSION ), self::NOTICE_ERROR );
 
452
  }
453
 
454
  /**
463
  */
464
  public static function add_dashboard_device_widget() {
465
  if ( Ga_Helper::is_administrator() ) {
466
+ wp_add_dashboard_widget( 'ga_dashboard_widget', __( 'Google Analytics Dashboard' ), 'Ga_Helper::add_ga_dashboard_widget' );
 
467
  }
468
  }
469
 
477
  add_action( 'wp_dashboard_setup', 'Ga_Admin::add_dashboard_device_widget' );
478
  add_action( 'wp_ajax_ga_ajax_data_change', 'Ga_Admin::ga_ajax_data_change' );
479
  add_action( 'admin_notices', 'Ga_Admin::admin_notice_googleanalytics' );
480
+ add_action( 'heartbeat_tick', 'Ga_Admin::run_heartbeat_jobs' );
481
 
482
+ if ( !get_option( self::GA_SHARETHIS_TERMS_OPTION_NAME ) && !get_option( self::GA_HIDE_TERMS_OPTION_NAME ) ) {
483
  add_action( 'wp_ajax_googleanalytics_hide_terms', 'Ga_Admin::admin_notice_hide_googleanalytics' );
484
  }
485
  }
486
 
487
+ /**
488
+ * Runs jobs
489
+ * @param $response
490
+ * @param $screen_id
491
+ */
492
+ public static function run_heartbeat_jobs( $response, $screen_id = '' ) {
493
+
494
+ if ( Ga_Admin::GA_HEARTBEAT_API_CACHE_UPDATE ) {
495
+ // Disable cache for ajax request
496
+ self::api_client()->set_disable_cache( true );
497
+
498
+ // Try to regenerate cache if needed
499
+ self::generate_stats_data();
500
+ }
501
+ }
502
+
503
  /**
504
  * Adds plugin's filters
505
  */
518
  public static function ga_action_links( $actions, $plugin_file ) {
519
 
520
  if ( basename( $plugin_file ) == GA_NAME . '.php' ) {
521
+ array_unshift( $actions, '<a href="' . esc_url( get_admin_url( null, Ga_Helper::GA_SETTINGS_PAGE_URL ) ) . '">' . _( 'Settings' ) . '</a>' );
 
522
  }
523
 
524
  return $actions;
528
 
529
  $code = Ga_Helper::get_option( self::GA_OAUTH_AUTH_CODE_OPTION_NAME );
530
 
531
+ if ( !Ga_Helper::is_authorized() && !empty( $code ) ) {
532
  Ga_Helper::update_option( self::GA_OAUTH_AUTH_CODE_OPTION_NAME, "" );
533
 
534
  // Get access token
537
  return false;
538
  }
539
  $param = '';
540
+ if ( !self::save_access_token( $response ) ) {
541
  $param = '&err=1';
542
  } else {
543
  self::api_client()->set_access_token( $response->getData() );
551
  }
552
  }
553
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
554
  /**
555
  * Save access token.
556
  *
560
  */
561
  public static function save_access_token( $response, $refresh_token = '' ) {
562
  $access_token = $response->getData();
563
+ if ( !empty( $access_token ) ) {
564
+ $access_token[ 'created' ] = time();
565
  } else {
566
  return false;
567
  }
568
 
569
+ if ( !empty( $refresh_token ) ) {
570
+ $access_token[ 'refresh_token' ] = $refresh_token;
571
  }
572
 
573
  return update_option( self::GA_OAUTH_AUTH_TOKEN_OPTION_NAME, wp_json_encode( $access_token ) );
582
  */
583
  public static function save_ga_account_summaries( $data ) {
584
  $return = array();
585
+ if ( !empty( $data[ 'items' ] ) ) {
586
+ foreach ( $data[ 'items' ] as $item ) {
587
+ $tmp = array();
588
+ $tmp[ 'id' ] = $item[ 'id' ];
589
+ $tmp[ 'name' ] = $item[ 'name' ];
590
+ if ( is_array( $item[ 'webProperties' ] ) ) {
591
+ foreach ( $item[ 'webProperties' ] as $property ) {
592
  $profiles = array();
593
+ if ( is_array( $property[ 'profiles' ] ) ) {
594
+ foreach ( $property[ 'profiles' ] as $profile ) {
595
  $profiles[] = array(
596
+ 'id' => $profile[ 'id' ],
597
+ 'name' => $profile[ 'name' ]
 
598
  );
599
  }
600
  }
601
 
602
+ $tmp[ 'webProperties' ][] = array(
603
+ 'webPropertyId' => $property[ 'id' ],
604
+ 'name' => $property[ 'name' ],
605
+ 'profiles' => $profiles
 
606
  );
607
  }
608
  }
621
  * Handle AJAX data for the GA dashboard widget.
622
  */
623
  public static function ga_ajax_data_change() {
624
+ $date_range = !empty( $_POST[ 'date_range' ] ) ? $_POST[ 'date_range' ] : null;
625
+ $metric = !empty( $_POST[ 'metric' ] ) ? $_POST[ 'metric' ] : null;
626
  echo Ga_Helper::get_ga_dashboard_widget_data_json( $date_range, $metric, false, true );
627
  wp_die();
628
  }
630
  /**
631
  * Displays API error messages.
632
  */
633
+ public static function display_api_errors( $alias = '' ) {
634
+ $errors = self::api_client( $alias )->get_errors();
635
+ if ( !empty( $errors ) ) {
636
  foreach ( $errors as $error ) {
637
+ echo Ga_Notice::get_message( $error );
 
 
 
 
 
 
638
  }
639
  }
640
  }
641
+
642
+ /**
643
+ * Gets dashboard data.
644
+ *
645
+ * @return array
646
+ */
647
+ public static function generate_stats_data() {
648
+ $selected = Ga_Helper::get_selected_account_data( true );
649
+
650
+ $query_params = Ga_Stats::get_query( 'main_chart', $selected[ 'view_id' ] );
651
+ $stats_data = self::api_client()->call( 'ga_api_data', array(
652
+ $query_params
653
+ ) );
654
+
655
+ $boxes_data = self::api_client()->call( 'ga_api_data', array(
656
+ Ga_Stats::get_query( 'boxes', $selected[ 'view_id' ] )
657
+ ) );
658
+ $sources_data = self::api_client()->call( 'ga_api_data', array(
659
+ Ga_Stats::get_query( 'sources', $selected[ 'view_id' ] )
660
+ ) );
661
+ $chart = !empty( $stats_data ) ? Ga_Stats::get_chart( $stats_data->getData() ) : array();
662
+ $boxes = !empty( $boxes_data ) ? Ga_Stats::get_boxes( $boxes_data->getData() ) : array();
663
+ $last_chart_date = !empty( $chart ) ? $chart[ 'date' ] : strtotime( 'now' );
664
+ unset( $chart[ 'date' ] );
665
+ $labels = array(
666
+ 'thisWeek' => date( 'M d, Y', strtotime( '-6 day', $last_chart_date ) ) . ' - ' . date( 'M d, Y', $last_chart_date ),
667
+ 'lastWeek' => date( 'M d, Y', strtotime( '-13 day', $last_chart_date ) ) . ' - ' . date( 'M d, Y', strtotime( '-7 day', $last_chart_date ) )
668
+ );
669
+ $sources = !empty( $sources_data ) ? Ga_Stats::get_sources( $sources_data->getData() ) : array();
670
+
671
+ return array( $chart, $boxes, $labels, $sources );
672
+ }
673
+
674
  }
class/Ga_Autoloader.php CHANGED
@@ -15,11 +15,36 @@ class Ga_Autoloader {
15
  * @param $class_name
16
  */
17
  private static function loader( $class_name ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  $file_name = GA_PLUGIN_DIR . '/class/' . $class_name . '.php';
19
  if ( file_exists( $file_name ) ) {
20
  require $file_name;
21
  }
22
 
 
 
 
 
 
 
 
23
  if ( preg_match( '/Ga_Lib/', $class_name ) ) {
24
  $file_name = GA_PLUGIN_DIR . '/lib/' . $class_name . '.php';
25
  if ( file_exists( $file_name ) ) {
@@ -27,4 +52,5 @@ class Ga_Autoloader {
27
  }
28
  }
29
  }
30
- }
 
15
  * @param $class_name
16
  */
17
  private static function loader( $class_name ) {
18
+
19
+ // Core classes
20
+ if ( preg_match( '/_Core/', $class_name ) ) {
21
+ $file_name = GA_PLUGIN_DIR . '/class/core/' . $class_name . '.php';
22
+ if ( file_exists( $file_name ) ) {
23
+ require $file_name;
24
+ }
25
+ }
26
+
27
+ // Controllers
28
+ if ( preg_match( '/_Controller/', $class_name ) ) {
29
+ $file_name = GA_PLUGIN_DIR . '/class/controller/' . $class_name . '.php';
30
+ if ( file_exists( $file_name ) ) {
31
+ require $file_name;
32
+ }
33
+ }
34
+
35
+ // classes
36
  $file_name = GA_PLUGIN_DIR . '/class/' . $class_name . '.php';
37
  if ( file_exists( $file_name ) ) {
38
  require $file_name;
39
  }
40
 
41
+ // tools
42
+ $file_name_tools = GA_PLUGIN_DIR . '/tools/' . $class_name . '.php';
43
+ if ( file_exists( $file_name_tools ) ) {
44
+ require $file_name_tools;
45
+ }
46
+
47
+ // Libs
48
  if ( preg_match( '/Ga_Lib/', $class_name ) ) {
49
  $file_name = GA_PLUGIN_DIR . '/lib/' . $class_name . '.php';
50
  if ( file_exists( $file_name ) ) {
52
  }
53
  }
54
  }
55
+
56
+ }
class/Ga_Frontend.php CHANGED
@@ -2,52 +2,31 @@
2
 
3
  class Ga_Frontend {
4
 
5
- public static function insights_googleanalytics() {
6
- if ( is_ssl() ) {
7
- $url = 'https://ws.sharethis.com/button/st_insights.js';
8
- } else {
9
- $url = 'http://w.sharethis.com/button/st_insights.js';
10
- }
11
- $url = add_query_arg( array(
12
-
13
- 'publisher' => '75560ae7-5c5f-483e-936f-e426496af114',
14
- 'product' => 'GA'
15
- ), $url );
16
- wp_register_script( GA_NAME . '-sharethis', $url, null, null, false );
17
- wp_enqueue_script( GA_NAME . '-sharethis' );
18
- }
19
 
20
- public static function loader_tag_googleanalytics( $tag, $handle ) {
21
- if ( GA_NAME . '-sharethis' === $handle ) {
22
- $tag = str_replace( '<script', '<script id=\'st_insights_js\'', $tag );
 
23
  }
24
-
25
- return $tag;
26
  }
27
 
28
  /**
29
  * Adds frontend actions hooks.
30
  */
31
  public static function add_actions() {
32
- if ( Ga_Helper::can_add_ga_code() ) {
33
- add_action( 'wp_head', 'Ga_Frontend::googleanalytics' );
34
- if ( get_option( Ga_Admin::GA_SHARETHIS_TERMS_OPTION_NAME ) && Ga_Helper::is_sharethis_included() ) {
35
- add_action( 'wp_enqueue_scripts', 'Ga_Frontend::insights_googleanalytics' );
36
- add_filter( 'script_loader_tag', 'Ga_Frontend::loader_tag_googleanalytics', 10, 2 );
37
- }
38
  }
 
39
  }
40
 
41
- /**
42
- * Displays Google Analytics Tracking code.
43
- */
44
- public static function googleanalytics() {
45
- $web_property_id = self::get_web_property_id();
46
- if ( Ga_Helper::is_configured( $web_property_id ) ) {
47
- Ga_View::load( 'ga_code', array(
48
- 'data' => array(
49
- Ga_Admin::GA_WEB_PROPERTY_ID_OPTION_NAME => $web_property_id
50
- )
51
  ) );
52
  }
53
  }
@@ -57,12 +36,13 @@ class Ga_Frontend {
57
  *
58
  * @return string Web Property Id
59
  */
60
- private static function get_web_property_id() {
61
  $web_property_id = get_option( Ga_Admin::GA_WEB_PROPERTY_ID_OPTION_NAME );
62
- if ( Ga_Helper::is_code_manually_enabled() ) {
63
  $web_property_id = get_option( Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME );
64
  }
65
 
66
  return $web_property_id;
67
  }
68
- }
 
2
 
3
  class Ga_Frontend {
4
 
5
+ const GA_SHARETHIS_PLATFORM_URL = '//platform-api.sharethis.com/js/sharethis.js';
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ public static function platform_sharethis() {
8
+ $url = self::GA_SHARETHIS_PLATFORM_URL . '#product=ga';
9
+ if ( get_option( Ga_Admin::GA_SHARETHIS_PROPERTY_ID ) ) {
10
+ $url = $url . '&property=' . get_option( Ga_Admin::GA_SHARETHIS_PROPERTY_ID );
11
  }
12
+ wp_register_script( GA_NAME . '-platform-sharethis', $url, null, null, false );
13
+ wp_enqueue_script( GA_NAME . '-platform-sharethis' );
14
  }
15
 
16
  /**
17
  * Adds frontend actions hooks.
18
  */
19
  public static function add_actions() {
20
+ if ( Ga_Helper::are_features_enabled() ) {
21
+ add_action( 'wp_enqueue_scripts', 'Ga_Frontend::platform_sharethis' );
 
 
 
 
22
  }
23
+ add_action( 'wp_footer', 'Ga_Frontend::insert_ga_script' );
24
  }
25
 
26
+ public static function insert_ga_script() {
27
+ if ( Ga_Helper::can_add_ga_code() || Ga_Helper::is_all_feature_disabled() ) {
28
+ Ga_View_Core::load( 'ga_googleanalytics_loader', array(
29
+ 'ajaxurl' => add_query_arg( Ga_Controller_Core::ACTION_PARAM_NAME, 'googleanalytics_get_script', home_url() )
 
 
 
 
 
 
30
  ) );
31
  }
32
  }
36
  *
37
  * @return string Web Property Id
38
  */
39
+ public static function get_web_property_id() {
40
  $web_property_id = get_option( Ga_Admin::GA_WEB_PROPERTY_ID_OPTION_NAME );
41
+ if ( Ga_Helper::is_code_manually_enabled() || Ga_Helper::is_all_feature_disabled() ) {
42
  $web_property_id = get_option( Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_VALUE_OPTION_NAME );
43
  }
44
 
45
  return $web_property_id;
46
  }
47
+
48
+ }
class/Ga_Helper.php CHANGED
@@ -2,17 +2,17 @@
2
 
3
  class Ga_Helper {
4
 
5
- const ROLE_ID_PREFIX = "role-id-";
6
-
7
- const GA_DEFAULT_WEB_ID = "UA-0000000-0";
8
-
9
- const GA_STATISTICS_PAGE_URL = "admin.php?page=googleanalytics";
10
-
11
- const GA_SETTINGS_PAGE_URL = "admin.php?page=googleanalytics/settings";
12
-
13
- const DASHBOARD_PAGE_NAME = "dashboard";
14
-
15
- const PHP_VERSION_REQUIRED = "5.2.17";
16
 
17
  /**
18
  * Init plugin actions.
@@ -21,28 +21,36 @@ class Ga_Helper {
21
  public static function init() {
22
 
23
  // Displays errors related to required PHP version
24
- if ( ! self::is_php_version_valid() ) {
25
  add_action( 'admin_notices', 'Ga_Admin::admin_notice_googleanalytics_php_version' );
26
 
27
  return false;
28
  }
29
 
30
  // Displays errors related to required WP version
31
- if ( ! self::is_wp_version_valid() ) {
32
  add_action( 'admin_notices', 'Ga_Admin::admin_notice_googleanalytics_wp_version' );
33
 
34
  return false;
35
  }
36
 
37
- if ( ! is_admin() ) {
38
  Ga_Frontend::add_actions();
 
 
 
39
  }
40
 
41
  if ( is_admin() ) {
42
  Ga_Admin::add_filters();
43
  Ga_Admin::add_actions();
44
- Ga_Admin::init_oauth();
45
- Ga_Admin::handle_actions();
 
 
 
 
 
46
  }
47
  }
48
 
@@ -53,8 +61,7 @@ class Ga_Helper {
53
  public static function is_plugin_page() {
54
  $site = get_current_screen();
55
 
56
- return preg_match( '/' . GA_NAME . '/i', $site->base ) || preg_match( '/' . GA_NAME . '/i',
57
- $_SERVER['REQUEST_URI'] );
58
  }
59
 
60
  /**
@@ -67,6 +74,16 @@ class Ga_Helper {
67
  return preg_match( '/' . self::DASHBOARD_PAGE_NAME . '/', $site->base );
68
  }
69
 
 
 
 
 
 
 
 
 
 
 
70
  /**
71
  * Check whether the plugin is configured.
72
  *
@@ -75,7 +92,7 @@ class Ga_Helper {
75
  * @return boolean
76
  */
77
  public static function is_configured( $web_id ) {
78
- return $web_id !== self::GA_DEFAULT_WEB_ID;
79
  }
80
 
81
  /**
@@ -85,7 +102,7 @@ class Ga_Helper {
85
  */
86
  public static function get_user_roles() {
87
  global $wp_roles;
88
- if ( ! isset( $wp_roles ) ) {
89
  $wp_roles = new WP_Roles();
90
  }
91
 
@@ -122,15 +139,15 @@ class Ga_Helper {
122
  * @return boolean
123
  */
124
  public static function can_add_ga_code() {
125
- $current_user = wp_get_current_user();
126
- $user_roles = ! empty( $current_user->roles ) ? $current_user->roles : array();
127
- $exclude_roles = json_decode( get_option( Ga_Admin::GA_EXCLUDE_ROLES_OPTION_NAME ), true );
128
 
129
  array_walk( $user_roles, 'Ga_Helper::prepare_role' );
130
 
131
  $return = true;
132
  foreach ( $user_roles as $role ) {
133
- if ( ! empty( $exclude_roles[ $role ] ) ) {
134
  $return = false;
135
  break;
136
  }
@@ -145,7 +162,6 @@ class Ga_Helper {
145
  */
146
  public static function add_ga_dashboard_widget() {
147
  echo self::get_ga_dashboard_widget();
148
-
149
  }
150
 
151
  /**
@@ -167,14 +183,14 @@ class Ga_Helper {
167
 
168
  if ( $text_mode ) {
169
  return self::get_chart_page( 'ga_dashboard_widget' . ( $ajax ? "_ajax" : "" ), array(
170
- 'chart' => $data['chart'],
171
- 'boxes' => $data['boxes']
172
  ) );
173
  } else {
174
  echo self::get_chart_page( 'ga_dashboard_widget' . ( $ajax ? "_ajax" : "" ), array(
175
- 'chart' => $data['chart'],
176
- 'boxes' => $data['boxes'],
177
- 'more_details_url' => admin_url( self::GA_STATISTICS_PAGE_URL )
178
  ) );
179
  }
180
 
@@ -192,10 +208,7 @@ class Ga_Helper {
192
  * @return string|false Returns JSON data string
193
  */
194
  public static function get_ga_dashboard_widget_data_json(
195
- $date_range = null,
196
- $metric = null,
197
- $text_mode = false,
198
- $ajax = false
199
  ) {
200
  if ( empty( $date_range ) ) {
201
  $date_range = '30daysAgo';
@@ -221,25 +234,22 @@ class Ga_Helper {
221
  private static function get_dashboard_widget_data( $date_range, $metric = null ) {
222
  $selected = self::get_selected_account_data( true );
223
  if ( self::is_authorized() && self::is_account_selected() ) {
224
- $query_params = Ga_Stats::get_query( 'main_chart', $selected['view_id'], $date_range, $metric );
225
- $stats_data = Ga_Admin::api_client()->call( 'ga_api_data', array(
226
-
227
  $query_params
228
  ) );
229
 
230
- $boxes_query = Ga_Stats::get_query( 'dashboard_boxes', $selected['view_id'], $date_range );
231
- $boxes_data = Ga_Admin::api_client()->call( 'ga_api_data', array(
232
-
233
  $boxes_query
234
  ) );
235
  }
236
- $chart = ! empty( $stats_data ) ? Ga_Stats::get_dashboard_chart( $stats_data->getData() ) : array();
237
- $boxes = ! empty( $boxes_data ) ? Ga_Stats::get_dashboard_boxes_data( $boxes_data->getData() ) : array();
238
 
239
  return array(
240
-
241
- 'chart' => $chart,
242
- 'boxes' => $boxes
243
  );
244
  }
245
 
@@ -256,16 +266,14 @@ class Ga_Helper {
256
  */
257
  public static function get_chart_page( $view, $params ) {
258
 
259
- $message = sprintf( __( 'Statistics can only be seen after you authenticate with your Google account on the <a href="%s">Settings page</a>.' ),
260
- admin_url( self::GA_SETTINGS_PAGE_URL ) );
261
 
262
- if ( self::is_authorized() && ! self::is_code_manually_enabled() ) {
263
  if ( self::is_account_selected() ) {
264
  if ( $params ) {
265
- return Ga_View::load( $view, $params, true );
266
  } else {
267
- return self::ga_oauth_notice( sprintf( 'Please configure your <a href="%s">Google Analytics settings</a>.',
268
- admin_url( self::GA_SETTINGS_PAGE_URL ) ) );
269
  }
270
  } else {
271
  return self::ga_oauth_notice( $message );
@@ -294,7 +302,7 @@ class Ga_Helper {
294
  public static function get_option( $name ) {
295
  $opt = get_option( $name );
296
 
297
- return ! empty( $opt ) ? $opt : null;
298
  }
299
 
300
  /**
@@ -308,7 +316,7 @@ class Ga_Helper {
308
  public static function update_option( $name, $value ) {
309
  $opt = update_option( $name, $value );
310
 
311
- return ! empty( $opt ) ? $opt : null;
312
  }
313
 
314
  /**
@@ -320,7 +328,7 @@ class Ga_Helper {
320
  * @return string
321
  */
322
  public static function ga_oauth_notice( $message ) {
323
- return Ga_View::load( 'ga_oauth_notice', array(
324
  'msg' => $message
325
  ), true );
326
  }
@@ -330,13 +338,17 @@ class Ga_Helper {
330
  *
331
  * @param $message
332
  * @param string $type
 
 
333
  *
334
  * @return string
335
  */
336
- public static function ga_wp_notice( $message, $type = '' ) {
337
- return Ga_View::load( 'ga_wp_notice', array(
338
- 'type' => empty( $type ) ? Ga_Admin::NOTICE_WARNING : $type,
339
- 'msg' => $message
 
 
340
  ), true );
341
  }
342
 
@@ -348,16 +360,15 @@ class Ga_Helper {
348
  * @return mixed
349
  */
350
  public static function get_selected_account_data( $assoc = false ) {
351
- $data = json_decode( self::get_option( Ga_Admin::GA_SELECTED_ACCOUNT ) );
352
- $data = ( ! empty( $data ) && count( $data ) == 3 ) ? $data : false;
353
 
354
  if ( $data ) {
355
  if ( $assoc ) {
356
  return array(
357
-
358
- 'account_id' => $data[0],
359
- 'web_property_id' => $data[1],
360
- 'view_id' => $data[2]
361
  );
362
  } else {
363
  return $data;
@@ -444,18 +455,111 @@ class Ga_Helper {
444
  * @return mixed
445
  */
446
  public static function is_php_version_valid() {
447
- $p = '#(\.0+)+($|-)#';
448
- $ver1 = preg_replace( $p, '', phpversion() );
449
- $ver2 = preg_replace( $p, '', self::PHP_VERSION_REQUIRED );
450
- $operator = 'ge';
451
- $compare = isset( $operator ) ?
452
- version_compare( $ver1, $ver2, $operator ) :
453
- version_compare( $ver1, $ver2 );
454
 
455
  return $compare;
456
  }
457
 
458
  public static function get_current_url() {
459
- return $_SERVER['REQUEST_URI'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
460
  }
461
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  class Ga_Helper {
4
 
5
+ const ROLE_ID_PREFIX = "role-id-";
6
+ const GA_DEFAULT_WEB_ID = "UA-0000000-0";
7
+ const GA_STATISTICS_PAGE_URL = "admin.php?page=googleanalytics";
8
+ const GA_SETTINGS_PAGE_URL = "admin.php?page=googleanalytics/settings";
9
+ const GA_TRENDING_PAGE_URL = 'admin.php?page=googleanalytics/trending';
10
+ const DASHBOARD_PAGE_NAME = "dashboard";
11
+ const PHP_VERSION_REQUIRED = "5.2.17";
12
+ const GA_WP_MODERN_VERSION = "4.1";
13
+ const GA_TOOLTIP_TERMS_NOT_ACCEPTED = 'Please accept the terms to use this feature.';
14
+ const GA_TOOLTIP_FEATURES_DISABLED = 'Click the Enable button at the top to start using this feature.';
15
+ const GA_DEBUG_MODE = false;
16
 
17
  /**
18
  * Init plugin actions.
21
  public static function init() {
22
 
23
  // Displays errors related to required PHP version
24
+ if ( !self::is_php_version_valid() ) {
25
  add_action( 'admin_notices', 'Ga_Admin::admin_notice_googleanalytics_php_version' );
26
 
27
  return false;
28
  }
29
 
30
  // Displays errors related to required WP version
31
+ if ( !self::is_wp_version_valid() ) {
32
  add_action( 'admin_notices', 'Ga_Admin::admin_notice_googleanalytics_wp_version' );
33
 
34
  return false;
35
  }
36
 
37
+ if ( !is_admin() ) {
38
  Ga_Frontend::add_actions();
39
+
40
+ $frontend_controller = new Ga_Frontend_Controller();
41
+ $frontend_controller->handle_actions();
42
  }
43
 
44
  if ( is_admin() ) {
45
  Ga_Admin::add_filters();
46
  Ga_Admin::add_actions();
47
+
48
+ if ( false === self::is_trending_page() ) {
49
+ Ga_Admin::init_oauth();
50
+ }
51
+
52
+ $admin_controller = new Ga_Admin_Controller();
53
+ $admin_controller->handle_actions();
54
  }
55
  }
56
 
61
  public static function is_plugin_page() {
62
  $site = get_current_screen();
63
 
64
+ return preg_match( '/' . GA_NAME . '/i', $site->base ) || preg_match( '/' . GA_NAME . '/i', $_SERVER[ 'REQUEST_URI' ] );
 
65
  }
66
 
67
  /**
74
  return preg_match( '/' . self::DASHBOARD_PAGE_NAME . '/', $site->base );
75
  }
76
 
77
+ /**
78
+ * Checks if current page is a trending page.
79
+ * @return number
80
+ */
81
+ public static function is_trending_page() {
82
+ $site_uri = urldecode( basename( $_SERVER[ 'REQUEST_URI' ] ) );
83
+
84
+ return preg_match( '/' . preg_quote( self::GA_TRENDING_PAGE_URL, '/' ) . '/', $site_uri, $matches ) == 1;
85
+ }
86
+
87
  /**
88
  * Check whether the plugin is configured.
89
  *
92
  * @return boolean
93
  */
94
  public static function is_configured( $web_id ) {
95
+ return ( $web_id !== self::GA_DEFAULT_WEB_ID ) && !empty( $web_id );
96
  }
97
 
98
  /**
102
  */
103
  public static function get_user_roles() {
104
  global $wp_roles;
105
+ if ( !isset( $wp_roles ) ) {
106
  $wp_roles = new WP_Roles();
107
  }
108
 
139
  * @return boolean
140
  */
141
  public static function can_add_ga_code() {
142
+ $current_user = wp_get_current_user();
143
+ $user_roles = !empty( $current_user->roles ) ? $current_user->roles : array();
144
+ $exclude_roles = json_decode( get_option( Ga_Admin::GA_EXCLUDE_ROLES_OPTION_NAME ), true );
145
 
146
  array_walk( $user_roles, 'Ga_Helper::prepare_role' );
147
 
148
  $return = true;
149
  foreach ( $user_roles as $role ) {
150
+ if ( !empty( $exclude_roles[ $role ] ) ) {
151
  $return = false;
152
  break;
153
  }
162
  */
163
  public static function add_ga_dashboard_widget() {
164
  echo self::get_ga_dashboard_widget();
 
165
  }
166
 
167
  /**
183
 
184
  if ( $text_mode ) {
185
  return self::get_chart_page( 'ga_dashboard_widget' . ( $ajax ? "_ajax" : "" ), array(
186
+ 'chart' => $data[ 'chart' ],
187
+ 'boxes' => $data[ 'boxes' ]
188
  ) );
189
  } else {
190
  echo self::get_chart_page( 'ga_dashboard_widget' . ( $ajax ? "_ajax" : "" ), array(
191
+ 'chart' => $data[ 'chart' ],
192
+ 'boxes' => $data[ 'boxes' ],
193
+ 'more_details_url' => admin_url( self::GA_STATISTICS_PAGE_URL )
194
  ) );
195
  }
196
 
208
  * @return string|false Returns JSON data string
209
  */
210
  public static function get_ga_dashboard_widget_data_json(
211
+ $date_range = null, $metric = null, $text_mode = false, $ajax = false
 
 
 
212
  ) {
213
  if ( empty( $date_range ) ) {
214
  $date_range = '30daysAgo';
234
  private static function get_dashboard_widget_data( $date_range, $metric = null ) {
235
  $selected = self::get_selected_account_data( true );
236
  if ( self::is_authorized() && self::is_account_selected() ) {
237
+ $query_params = Ga_Stats::get_query( 'main_chart', $selected[ 'view_id' ], $date_range, $metric );
238
+ $stats_data = Ga_Admin::api_client()->call( 'ga_api_data', array(
 
239
  $query_params
240
  ) );
241
 
242
+ $boxes_query = Ga_Stats::get_query( 'dashboard_boxes', $selected[ 'view_id' ], $date_range );
243
+ $boxes_data = Ga_Admin::api_client()->call( 'ga_api_data', array(
 
244
  $boxes_query
245
  ) );
246
  }
247
+ $chart = !empty( $stats_data ) ? Ga_Stats::get_dashboard_chart( $stats_data->getData() ) : array();
248
+ $boxes = !empty( $boxes_data ) ? Ga_Stats::get_dashboard_boxes_data( $boxes_data->getData() ) : array();
249
 
250
  return array(
251
+ 'chart' => $chart,
252
+ 'boxes' => $boxes
 
253
  );
254
  }
255
 
266
  */
267
  public static function get_chart_page( $view, $params ) {
268
 
269
+ $message = sprintf( __( 'Statistics can only be seen after you authenticate with your Google account on the <a href="%s">Settings page</a>.' ), admin_url( self::GA_SETTINGS_PAGE_URL ) );
 
270
 
271
+ if ( self::is_authorized() && !self::is_code_manually_enabled() && !self::is_all_feature_disabled() ) {
272
  if ( self::is_account_selected() ) {
273
  if ( $params ) {
274
+ return Ga_View_Core::load( $view, $params, true );
275
  } else {
276
+ return self::ga_oauth_notice( sprintf( 'Please configure your <a href="%s">Google Analytics settings</a>.', admin_url( self::GA_SETTINGS_PAGE_URL ) ) );
 
277
  }
278
  } else {
279
  return self::ga_oauth_notice( $message );
302
  public static function get_option( $name ) {
303
  $opt = get_option( $name );
304
 
305
+ return !empty( $opt ) ? $opt : null;
306
  }
307
 
308
  /**
316
  public static function update_option( $name, $value ) {
317
  $opt = update_option( $name, $value );
318
 
319
+ return !empty( $opt ) ? $opt : null;
320
  }
321
 
322
  /**
328
  * @return string
329
  */
330
  public static function ga_oauth_notice( $message ) {
331
+ return Ga_View_Core::load( 'ga_oauth_notice', array(
332
  'msg' => $message
333
  ), true );
334
  }
338
  *
339
  * @param $message
340
  * @param string $type
341
+ * @param $is_dismissable
342
+ * @param $action
343
  *
344
  * @return string
345
  */
346
+ public static function ga_wp_notice( $message, $type = '', $is_dismissable = false, $action = array() ) {
347
+ return Ga_View_Core::load( 'ga_wp_notice', array(
348
+ 'type' => empty( $type ) ? Ga_Admin::NOTICE_WARNING : $type,
349
+ 'msg' => $message,
350
+ 'is_dismissable' => $is_dismissable,
351
+ 'action' => $action
352
  ), true );
353
  }
354
 
360
  * @return mixed
361
  */
362
  public static function get_selected_account_data( $assoc = false ) {
363
+ $data = json_decode( self::get_option( Ga_Admin::GA_SELECTED_ACCOUNT ) );
364
+ $data = (!empty( $data ) && count( $data ) == 3 ) ? $data : false;
365
 
366
  if ( $data ) {
367
  if ( $assoc ) {
368
  return array(
369
+ 'account_id' => $data[ 0 ],
370
+ 'web_property_id' => $data[ 1 ],
371
+ 'view_id' => $data[ 2 ]
 
372
  );
373
  } else {
374
  return $data;
455
  * @return mixed
456
  */
457
  public static function is_php_version_valid() {
458
+ $p = '#(\.0+)+($|-)#';
459
+ $ver1 = preg_replace( $p, '', phpversion() );
460
+ $ver2 = preg_replace( $p, '', self::PHP_VERSION_REQUIRED );
461
+ $operator = 'ge';
462
+ $compare = isset( $operator ) ?
463
+ version_compare( $ver1, $ver2, $operator ) :
464
+ version_compare( $ver1, $ver2 );
465
 
466
  return $compare;
467
  }
468
 
469
  public static function get_current_url() {
470
+ return $_SERVER[ 'REQUEST_URI' ];
471
+ }
472
+
473
+ public static function create_url( $url, $data = array() ) {
474
+ return !empty( $data ) ? ( strstr( $url, '?' ) ? ( $url . '&' ) : ( $url . '?' ) ) . http_build_query( $data ) : $url;
475
+ }
476
+
477
+ public static function handle_url_message( $data ) {
478
+ if ( !empty( $_GET[ 'ga_msg' ] ) ) {
479
+ $invite_result = json_decode( base64_decode( $_GET[ 'ga_msg' ] ), true );
480
+ if ( !empty( $invite_result[ 'status' ] ) && !empty( $invite_result[ 'message' ] ) ) {
481
+ $data[ 'ga_msg' ] = Ga_Helper::ga_wp_notice( $invite_result[ 'message' ], $invite_result[ 'status' ], true );
482
+ }
483
+ }
484
+
485
+ return $data;
486
+ }
487
+
488
+ /**
489
+ * Create base64 url message
490
+ *
491
+ * @param $msg
492
+ * @param $status
493
+ *
494
+ * @return string
495
+ */
496
+ public static function create_url_msg( $msg, $status ) {
497
+ $msg = array( 'status' => $status, 'message' => $msg );
498
+
499
+ return base64_encode( json_encode( $msg ) );
500
+ }
501
+
502
+ public static function is_all_feature_disabled() {
503
+ return self::get_option( Ga_Admin::GA_DISABLE_ALL_FEATURES );
504
+ }
505
+
506
+ public static function are_features_enabled() {
507
+ return self::are_terms_accepted() && !self::is_all_feature_disabled();
508
+ }
509
+
510
+ public static function are_sharethis_properties_verified() {
511
+ return ( get_option( Ga_Admin::GA_SHARETHIS_VERIFICATION_RESULT ) && self::are_sharethis_properties_set() );
512
+ }
513
+
514
+ public static function are_sharethis_properties_ready_to_verify() {
515
+ return ( self::are_sharethis_properties_set() && !get_option( Ga_Admin::GA_SHARETHIS_VERIFICATION_RESULT ) );
516
+ }
517
+
518
+ public static function are_sharethis_properties_set() {
519
+ return ( get_option( Ga_Admin::GA_SHARETHIS_PROPERTY_ID ) && get_option( Ga_Admin::GA_SHARETHIS_PROPERTY_SECRET ) );
520
+ }
521
+
522
+ public static function is_plugin_version_with_trending_content() {
523
+ return ( version_compare( get_option( Ga_Admin::GA_VERSION_OPTION_NAME ), Ga_Admin::GA_SHARETHIS_TRENDING_CONTENT_PLUGIN_VERSION, '>=' ) );
524
+ }
525
+
526
+ public static function should_create_sharethis_property() {
527
+ return ( self::is_plugin_version_with_trending_content() && self::are_features_enabled() && !self::are_sharethis_properties_set() );
528
+ }
529
+
530
+ public static function should_verify_sharethis_installation() {
531
+ return ( self::is_plugin_version_with_trending_content() && self::are_features_enabled() && self::are_sharethis_properties_ready_to_verify() );
532
  }
533
+
534
+ public static function should_load_trending_alerts() {
535
+ return ( self::is_plugin_version_with_trending_content() && self::are_features_enabled() && self::are_sharethis_properties_verified() );
536
+ }
537
+
538
+ public static function get_tooltip() {
539
+ if ( !self::are_terms_accepted() ) {
540
+ return self::GA_TOOLTIP_TERMS_NOT_ACCEPTED;
541
+ } else if ( !self::are_features_enabled() ) {
542
+ return self::GA_TOOLTIP_FEATURES_DISABLED;
543
+ } else {
544
+ return '';
545
+ }
546
+ }
547
+
548
+ public static function is_wp_old() {
549
+ return version_compare( get_bloginfo( 'version' ), self::GA_WP_MODERN_VERSION, 'lt' );
550
+ }
551
+
552
+ public static function should_load_ga_javascript( $web_property_id ) {
553
+ return ( self::is_configured( $web_property_id ) && ( self::can_add_ga_code() || self::is_all_feature_disabled() ) );
554
+ }
555
+
556
+ /**
557
+ * @return string
558
+ */
559
+ public static function get_account_id() {
560
+ $account_id = json_decode( Ga_Helper::get_option( Ga_Admin::GA_SELECTED_ACCOUNT ) );
561
+
562
+ return ! empty( $account_id[0] ) ? $account_id[0] : '';
563
+ }
564
+
565
+ }
class/Ga_Hook.php CHANGED
@@ -12,4 +12,5 @@ class Ga_Hook {
12
  register_deactivation_hook( $plugin_file_path, 'Ga_Admin::deactivate_googleanalytics' );
13
  register_uninstall_hook( $plugin_file_path, 'Ga_Admin::uninstall_googleanalytics' );
14
  }
15
- }
 
12
  register_deactivation_hook( $plugin_file_path, 'Ga_Admin::deactivate_googleanalytics' );
13
  register_uninstall_hook( $plugin_file_path, 'Ga_Admin::uninstall_googleanalytics' );
14
  }
15
+
16
+ }
class/Ga_Notice.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Handles exception translations.
5
+ *
6
+ * Created by PhpStorm.
7
+ * User: mdn
8
+ * Date: 2017-01-25
9
+ * Time: 14:37
10
+ */
11
+ class Ga_Notice {
12
+
13
+ public static function get_message( $error ) {
14
+ $message = '';
15
+
16
+ if ( Ga_Helper::GA_DEBUG_MODE ) {
17
+ $message = Ga_Helper::ga_wp_notice( (!empty( $error[ 'class' ] ) ? _( '[' . $error[ 'class' ] . ']' ) : '' ) . ' ' . $error[ 'message' ], Ga_Admin::NOTICE_ERROR );
18
+ } elseif ( $error[ 'class' ] == 'Ga_Lib_Sharethis_Api_Client_InvalidDomain_Exception' ) {
19
+ $message = Ga_Helper::ga_wp_notice( $error[ 'message' ], Ga_Admin::NOTICE_ERROR );
20
+ } elseif ( $error[ 'class' ] == 'Ga_Lib_Sharethis_Api_Client_Invite_Exception' ) {
21
+ $message = Ga_Helper::ga_wp_notice( $error[ 'message' ], Ga_Admin::NOTICE_ERROR );
22
+ } elseif ( in_array( $error[ 'class' ], array( 'Ga_Lib_Sharethis_Api_Client_Verify_Exception', 'Ga_Lib_Sharethis_Api_Client_Alerts_Exception' ) ) ) {
23
+ $message = Ga_Helper::ga_wp_notice( Ga_Sharethis::GA_SHARETHIS_ALERTS_ERROR, Ga_Admin::NOTICE_ERROR );
24
+ } elseif ( $error[ 'class' ] == 'Ga_Data_Outdated_Exception' ) {
25
+ $message = Ga_Helper::ga_wp_notice( $error[ 'message' ], Ga_Admin::NOTICE_WARNING );
26
+ } else {
27
+ $message = Ga_Helper::ga_wp_notice( _( 'There are temporary connection issues, please try again later or go to Google Analytics website to see the dashboards' ), Ga_Admin::NOTICE_ERROR );
28
+ }
29
+
30
+ return $message;
31
+ }
32
+
33
+ }
class/Ga_Sharethis.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Ga_Sharethis class
5
+ *
6
+ * Preparing request and parsing response from Sharethis Platform Api
7
+ *
8
+ * @author wle@adips.com
9
+ * @version 1.0
10
+ */
11
+ class Ga_Sharethis {
12
+
13
+ const GA_SHARETHIS_ALERTS_ERROR = 'Trending content alerts are temporarily unavailable, please try again later or contact support@sharethis.com';
14
+
15
+ public static function get_body( $data ) {
16
+ $body = $data->getBody();
17
+ return json_decode( $body );
18
+ }
19
+
20
+ /**
21
+ * Create sharethis options
22
+ */
23
+ public static function create_sharethis_options( $api_client ) {
24
+ $data = array();
25
+ if ( Ga_Helper::should_create_sharethis_property() ) {
26
+ $domain = parse_url( get_site_url(), PHP_URL_HOST );
27
+ $query_params = array( 'domain' => $domain );
28
+ $response = $api_client->call( 'ga_api_create_sharethis_property', array(
29
+ $query_params
30
+ ) );
31
+ $sharethis_options = self::get_sharethis_options( $response );
32
+ if ( !empty( $sharethis_options[ 'id' ] ) ) {
33
+ add_option( Ga_Admin::GA_SHARETHIS_PROPERTY_ID, $sharethis_options[ 'id' ] );
34
+ }
35
+ if ( !empty( $sharethis_options[ 'secret' ] ) ) {
36
+ add_option( Ga_Admin::GA_SHARETHIS_PROPERTY_SECRET, $sharethis_options[ 'secret' ] );
37
+ }
38
+ }
39
+
40
+ return $data;
41
+ }
42
+
43
+ public static function get_sharethis_options( $response ) {
44
+ $body = self::get_body( $response );
45
+ $options = array();
46
+ if ( !empty( $body ) ) {
47
+ foreach ( $body as $key => $value ) {
48
+ if ( $key == '_id' ) {
49
+ $options[ 'id' ] = $value;
50
+ } else if ( $key == 'secret' ) {
51
+ $options[ 'secret' ] = $value;
52
+ } else if ( $key == 'error' ) {
53
+ $options[ 'error' ] = $value;
54
+ }
55
+ }
56
+ } else {
57
+ $options[ 'error' ] = self::GA_SHARETHIS_ALERTS_ERROR;
58
+ }
59
+ return $options;
60
+ }
61
+
62
+ public static function sharethis_installation_verification( $api_client ) {
63
+ if ( Ga_Helper::should_verify_sharethis_installation() ) {
64
+ $query_params = array(
65
+ 'id' => get_option( Ga_Admin::GA_SHARETHIS_PROPERTY_ID ),
66
+ 'secret' => get_option( Ga_Admin::GA_SHARETHIS_PROPERTY_SECRET )
67
+ );
68
+ $response = $api_client->call( 'ga_api_sharethis_installation_verification', array(
69
+ $query_params
70
+ ) );
71
+ $result = self::get_verification_result( $response );
72
+ if ( !empty( $result ) ) {
73
+ add_option( Ga_Admin::GA_SHARETHIS_VERIFICATION_RESULT, true );
74
+ }
75
+ }
76
+ }
77
+
78
+ public static function get_verification_result( $response ) {
79
+ $body = self::get_body( $response );
80
+ if ( !empty( $body->{"status"} ) ) {
81
+ return true;
82
+ }
83
+ return false;
84
+ }
85
+
86
+ public static function load_sharethis_trending_alerts( $api_client ) {
87
+ if ( Ga_Helper::should_load_trending_alerts() ) {
88
+ $query_params = array(
89
+ 'id' => get_option( Ga_Admin::GA_SHARETHIS_PROPERTY_ID ),
90
+ 'secret' => get_option( Ga_Admin::GA_SHARETHIS_PROPERTY_SECRET )
91
+ );
92
+ $response = $api_client->call( 'ga_api_sharethis_get_trending_alerts', array(
93
+ $query_params
94
+ ) );
95
+ return self::get_alerts( $response );
96
+ }
97
+ }
98
+
99
+ public static function get_alerts( $response ) {
100
+ $body = self::get_body( $response );
101
+ if ( !empty( $body ) ) {
102
+ if ( !empty( $body[ 'error' ] ) ) {
103
+ return (object) array( 'error' => self::GA_SHARETHIS_ALERTS_ERROR );
104
+ }
105
+
106
+ return $body;
107
+ } else {
108
+ return array();
109
+ }
110
+ }
111
+
112
+ }
class/Ga_Stats.php CHANGED
@@ -42,17 +42,17 @@ class Ga_Stats {
42
  * @return array Sources query
43
  */
44
  public static function sources_query( $id_view ) {
45
- $reports_requests = array();
46
- $reports_requests[] = array(
47
- 'viewId' => $id_view,
48
- 'dateRanges' => self::set_date_ranges( '7daysAgo', 'yesterday' ),
49
- 'metrics' => self::set_metrics( array( 'ga:pageviews' ) ),
50
- 'includeEmptyRows' => true,
51
- 'pageSize' => 5,
52
- 'dimensions' => self::set_dimensions( 'ga:sourceMedium' ),
53
- 'orderBys' => self::set_order_bys( 'ga:pageviews', 'DESCENDING' ),
54
  );
55
- $query = array(
56
  'reportRequests' => $reports_requests
57
  );
58
 
@@ -68,11 +68,11 @@ class Ga_Stats {
68
  * @return array Dashboard boxes query
69
  */
70
  public static function dashboard_boxes_query( $id_view, $date_range ) {
71
- $reports_requests = array();
72
- $reports_requests[] = array(
73
- 'viewId' => $id_view,
74
- 'dateRanges' => self::set_date_ranges( $date_range, 'yesterday' ),
75
- 'metrics' => self::set_metrics( array(
76
  'ga:sessions',
77
  'ga:pageviews',
78
  'ga:pageviewsPerSession',
@@ -80,10 +80,10 @@ class Ga_Stats {
80
  'ga:avgTimeOnPage',
81
  'ga:percentNewSessions',
82
  ) ),
83
- 'includeEmptyRows' => true,
84
- 'dimensions' => self::set_dimensions( 'ga:date' )
85
  );
86
- $query = array(
87
  'reportRequests' => $reports_requests
88
  );
89
 
@@ -98,20 +98,20 @@ class Ga_Stats {
98
  * @return array Boxes query
99
  */
100
  public static function boxes_query( $id_view ) {
101
- $reports_requests = array();
102
- $reports_requests[] = array(
103
- 'viewId' => $id_view,
104
- 'dateRanges' => self::set_date_ranges( '7daysAgo', 'yesterday', '14daysAgo', '8daysAgo' ),
105
- 'metrics' => self::set_metrics( array(
106
  'ga:users',
107
  'ga:pageviews',
108
  'ga:pageviewsPerSession',
109
  'ga:BounceRate'
110
  ) ),
111
- 'includeEmptyRows' => true,
112
- 'dimensions' => self::set_dimensions( 'ga:date' )
113
  );
114
- $query = array(
115
  'reportRequests' => $reports_requests
116
  );
117
 
@@ -140,15 +140,15 @@ class Ga_Stats {
140
  $metric = 'ga:' . $metric;
141
  }
142
 
143
- $reports_requests = array();
144
- $reports_requests[] = array(
145
- 'viewId' => $id_view,
146
- 'dateRanges' => $date_ranges,
147
- 'metrics' => self::set_metrics( $metric ),
148
- 'includeEmptyRows' => true,
149
- 'dimensions' => self::set_dimensions( 'ga:date' )
150
  );
151
- $query = array(
152
  'reportRequests' => $reports_requests
153
  );
154
 
@@ -164,10 +164,10 @@ class Ga_Stats {
164
  * @return array OrderBys
165
  */
166
  public static function set_order_bys( $name, $sort ) {
167
- $order = array();
168
  $order[] = array(
169
- 'fieldName' => $name,
170
- 'sortOrder' => $sort,
171
  );
172
 
173
  return $order;
@@ -205,8 +205,8 @@ class Ga_Stats {
205
  * @return array Dimensions
206
  */
207
  public static function set_dimensions( $name ) {
208
- $dimensions = array();
209
- $dimensions[] = array(
210
  'name' => $name
211
  );
212
 
@@ -224,15 +224,15 @@ class Ga_Stats {
224
  * @return array Date ranges
225
  */
226
  public static function set_date_ranges( $start_date, $end_date, $prev_start_date = '', $prev_end_date = '' ) {
227
- $date_danges = array();
228
- $date_danges[] = array(
229
- 'startDate' => $start_date,
230
- 'endDate' => $end_date
231
  );
232
- if ( ! empty( $prev_start_date ) and ! empty( $prev_end_date ) ) {
233
  $date_danges[] = array(
234
- 'startDate' => $prev_start_date,
235
- 'endDate' => $prev_end_date
236
  );
237
  }
238
 
@@ -247,14 +247,14 @@ class Ga_Stats {
247
  * @return array Response rows
248
  */
249
  public static function prepare_response( $data ) {
250
- $data = self::get_reports_from_response( $data );
251
  self::handle_more_reports( $data );
252
- $report = self::get_single_report( $data );
253
  self::get_report_column_header( $report );
254
  $report_data = self::get_report_data( $report );
255
  self::get_totals( $report_data );
256
  self::get_row_count( $report_data );
257
- $rows = self::get_rows( $report_data );
258
 
259
  return $rows;
260
  }
@@ -267,8 +267,8 @@ class Ga_Stats {
267
  * @return array Dimensions
268
  */
269
  public static function get_dimensions( $row ) {
270
- if ( ! empty( $row['dimensions'] ) ) {
271
- return $row['dimensions'];
272
  }
273
 
274
  return false;
@@ -282,8 +282,8 @@ class Ga_Stats {
282
  * @return array Metrics
283
  */
284
  public static function get_metrics( $row ) {
285
- if ( ! empty( $row['metrics'] ) ) {
286
- return $row['metrics'];
287
  }
288
 
289
  return false;
@@ -297,8 +297,8 @@ class Ga_Stats {
297
  * @return array Rows
298
  */
299
  public static function get_rows( $report_data ) {
300
- if ( ! empty( $report_data['rows'] ) ) {
301
- return $report_data['rows'];
302
  }
303
 
304
  return false;
@@ -312,8 +312,8 @@ class Ga_Stats {
312
  * @return array Row count
313
  */
314
  public static function get_row_count( $report_data ) {
315
- if ( ! empty( $report_data['rowCount'] ) ) {
316
- return $report_data['rowCount'];
317
  }
318
 
319
  return false;
@@ -327,8 +327,8 @@ class Ga_Stats {
327
  * @return array Totals
328
  */
329
  public static function get_totals( $report_data ) {
330
- if ( ! empty( $report_data['totals'] ) ) {
331
- return $report_data['totals'];
332
  }
333
 
334
  return false;
@@ -342,8 +342,8 @@ class Ga_Stats {
342
  * @return array Reports
343
  */
344
  public static function get_reports_from_response( $data ) {
345
- if ( ! empty( $data['reports'] ) ) {
346
- return $data['reports'];
347
  }
348
 
349
  return false;
@@ -381,9 +381,9 @@ class Ga_Stats {
381
  * @return array Report
382
  */
383
  public static function get_single_report( $data ) {
384
- if ( ! empty( $data ) ) {
385
  foreach ( $data as $report ) {
386
- if ( ! empty( $report ) ) {
387
  return $report;
388
  }
389
  }
@@ -400,9 +400,9 @@ class Ga_Stats {
400
  * @return array Row
401
  */
402
  public static function get_single_row( $rows ) {
403
- if ( ! empty( $rows ) ) {
404
  foreach ( $rows as $row ) {
405
- if ( ! empty( $row ) ) {
406
  return $row;
407
  }
408
  }
@@ -419,8 +419,8 @@ class Ga_Stats {
419
  * @return array Column header
420
  */
421
  public static function get_report_column_header( $data ) {
422
- if ( ! empty( $data['columnHeader'] ) ) {
423
- return $data['columnHeader'];
424
  }
425
 
426
  return false;
@@ -434,8 +434,8 @@ class Ga_Stats {
434
  * @return array data
435
  */
436
  public static function get_report_data( $data ) {
437
- if ( ! empty( $data['data'] ) ) {
438
- return $data['data'];
439
  }
440
 
441
  return false;
@@ -450,18 +450,18 @@ class Ga_Stats {
450
  */
451
  public static function get_chart( $response_data ) {
452
  $chart_data = array();
453
- if ( ! empty( $response_data ) ) {
454
- $data = ( ! empty( $response_data['reports'] ) && ! empty( $response_data['reports'][0] ) && ! empty( $response_data['reports'][0]['data'] ) ) ? $response_data['reports'][0]['data'] : array();
455
- $rows = ( ! empty( $data['rows'] ) ) ? $data['rows'] : array();
456
- if ( ! empty( $rows ) ) {
457
  foreach ( $rows as $key => $row ) {
458
  if ( $key < 7 ) {
459
- $chart_data[ $key ]['previous'] = ! empty( $row['metrics'][1]['values'][0] ) ? $row['metrics'][1]['values'][0] : 0;
460
- $chart_data[ $key ]['previous-day'] = date( 'M j', strtotime( $row['dimensions'][0] ) );
461
  } else {
462
- $chart_data[ $key - 7 ]['day'] = date( 'M j', strtotime( $row['dimensions'][0] ) );
463
- $chart_data[ $key - 7 ]['current'] = ! empty( $row['metrics'][0]['values'][0] ) ? $row['metrics'][0]['values'][0] : 0;
464
- $chart_data['date'] = strtotime( $row['dimensions'][0] );
465
  }
466
  }
467
  }
@@ -479,14 +479,14 @@ class Ga_Stats {
479
  */
480
  public static function get_dashboard_chart( $response_data ) {
481
  $chart_data = array();
482
- if ( ! empty( $response_data ) ) {
483
- $data = ( ! empty( $response_data['reports'] ) && ! empty( $response_data['reports'][0] ) && ! empty( $response_data['reports'][0]['data'] ) ) ? $response_data['reports'][0]['data'] : array();
484
- $rows = ( ! empty( $data['rows'] ) ) ? $data['rows'] : array();
485
- if ( ! empty( $rows ) ) {
486
  foreach ( $rows as $row ) {
487
  $chart_data[] = array(
488
- 'day' => date( 'M j', strtotime( $row['dimensions'][0] ) ),
489
- 'current' => ! empty( $row['metrics'][0]['values'][0] ) ? $row['metrics'][0]['values'][0] : 0
490
  );
491
  }
492
  }
@@ -503,13 +503,13 @@ class Ga_Stats {
503
  * @return array boxes data
504
  */
505
  public static function get_boxes( $data ) {
506
- if ( ! empty( $data ) ) {
507
- $data = self::get_reports_from_response( $data );
508
  self::handle_more_reports( $data );
509
- $report = self::get_single_report( $data );
510
  self::get_report_column_header( $report );
511
  $report_data = self::get_report_data( $report );
512
- $totals = self::get_totals( $report_data );
513
 
514
  return self::get_boxes_from_totals( $totals );
515
  }
@@ -523,19 +523,19 @@ class Ga_Stats {
523
  * @return array boxes data
524
  */
525
  public static function get_boxes_from_totals( $totals ) {
526
- if ( ! empty( $totals ) ) {
527
  $boxes_data = array();
528
  foreach ( $totals as $key => $total ) {
529
  if ( $key == 0 ) {
530
- $boxes_data['Users']['current'] = $total['values'][0];
531
- $boxes_data['Pageviews']['current'] = $total['values'][1];
532
- $boxes_data['PageviewsPerSession']['current'] = $total['values'][2];
533
- $boxes_data['BounceRate']['current'] = round( $total['values'][3], 2 );
534
  } else {
535
- $boxes_data['Users']['previous'] = $total['values'][0];
536
- $boxes_data['Pageviews']['previous'] = $total['values'][1];
537
- $boxes_data['PageviewsPerSession']['previous'] = $total['values'][2];
538
- $boxes_data['BounceRate']['previous'] = round( $total['values'][3], 2 );
539
  }
540
  }
541
 
@@ -553,38 +553,30 @@ class Ga_Stats {
553
  * @return array boxes data
554
  */
555
  public static function prepare_boxes( $boxes_data ) {
556
- $boxes_data['Users']['diff'] = ( $boxes_data['Users']['previous'] > 0 ) ? round( ( $boxes_data['Users']['current'] - $boxes_data['Users']['previous'] ) / $boxes_data['Users']['previous'] * 100,
557
- 2 ) : 100;
558
- $boxes_data['Pageviews']['diff'] = ( $boxes_data['Pageviews']['previous'] > 0 ) ? round( ( $boxes_data['Pageviews']['current'] - $boxes_data['Pageviews']['previous'] ) / $boxes_data['Pageviews']['previous'] * 100,
559
- 2 ) : 100;
560
- $boxes_data['PageviewsPerSession']['diff'] = ( $boxes_data['PageviewsPerSession']['previous'] > 0 ) ? round( ( $boxes_data['PageviewsPerSession']['current'] - $boxes_data['PageviewsPerSession']['previous'] ) / $boxes_data['PageviewsPerSession']['previous'] * 100,
561
- 2 ) : 100;
562
- $boxes_data['BounceRate']['diff'] = ( $boxes_data['BounceRate']['previous'] > 0 ) ? round( ( $boxes_data['BounceRate']['current'] - $boxes_data['BounceRate']['previous'] ) / $boxes_data['BounceRate']['previous'] * 100,
563
- 2 ) : 100;
564
- $boxes_data['Users']['diff'] = ( $boxes_data['Users']['previous'] == 0 && $boxes_data['Users']['current'] == 0 ) ? 0 : $boxes_data['Users']['diff'];
565
- $boxes_data['Pageviews']['diff'] = ( $boxes_data['Pageviews']['previous'] == 0 && $boxes_data['Pageviews']['current'] == 0 ) ? 0 : $boxes_data['Pageviews']['diff'];
566
- $boxes_data['PageviewsPerSession']['diff'] = ( $boxes_data['PageviewsPerSession']['previous'] == 0 && $boxes_data['PageviewsPerSession']['current'] == 0 ) ? 0 : $boxes_data['PageviewsPerSession']['diff'];
567
- $boxes_data['BounceRate']['diff'] = ( $boxes_data['BounceRate']['previous'] == 0 && $boxes_data['BounceRate']['current'] == 0 ) ? 0 : $boxes_data['BounceRate']['diff'];
568
- $boxes_data['Users']['label'] = 'Users';
569
- $boxes_data['Pageviews']['label'] = 'Pageviews';
570
- $boxes_data['PageviewsPerSession']['label'] = 'Pages / Session';
571
- $boxes_data['BounceRate']['label'] = 'Bounce Rate';
572
- $boxes_data['Users']['comparison'] = $boxes_data['Users']['current'] . ' vs ' . $boxes_data['Users']['previous'];
573
- $boxes_data['Pageviews']['comparison'] = $boxes_data['Pageviews']['current'] . ' vs ' . $boxes_data['Pageviews']['previous'];
574
- $boxes_data['PageviewsPerSession']['comparison'] = self::number_format_clean( $boxes_data['PageviewsPerSession']['current'],
575
- 2, '.', ',' ) . ' vs ' . self::number_format_clean( $boxes_data['PageviewsPerSession']['previous'], 2,
576
- '.', ',' );
577
- $boxes_data['BounceRate']['comparison'] = self::number_format_clean( $boxes_data['BounceRate']['current'],
578
- 2, '.', ',' ) . '% vs ' . self::number_format_clean( $boxes_data['BounceRate']['previous'], 2, '.',
579
- ',' ) . '%';
580
- $boxes_data['Users']['color'] = ( $boxes_data['Users']['diff'] > 0 ) ? 'green' : 'red';
581
- $boxes_data['Pageviews']['color'] = ( $boxes_data['Pageviews']['diff'] > 0 ) ? 'green' : 'red';
582
- $boxes_data['PageviewsPerSession']['color'] = ( $boxes_data['PageviewsPerSession']['diff'] > 0 ) ? 'green' : 'red';
583
- $boxes_data['BounceRate']['color'] = ( $boxes_data['BounceRate']['diff'] > 0 ) ? 'red' : 'green';
584
- $boxes_data['Users']['color'] = ( $boxes_data['Users']['diff'] != 0 ) ? $boxes_data['Users']['color'] : 'black';
585
- $boxes_data['Pageviews']['color'] = ( $boxes_data['Pageviews']['diff'] != 0 ) ? $boxes_data['Pageviews']['color'] : 'black';
586
- $boxes_data['PageviewsPerSession']['color'] = ( $boxes_data['PageviewsPerSession']['diff'] != 0 ) ? $boxes_data['PageviewsPerSession']['color'] : 'black';
587
- $boxes_data['BounceRate']['color'] = ( $boxes_data['BounceRate']['diff'] != 0 ) ? $boxes_data['BounceRate']['color'] : 'black';
588
 
589
  return $boxes_data;
590
  }
@@ -620,39 +612,37 @@ class Ga_Stats {
620
  * @return array sources data
621
  */
622
  public static function get_sources( $data ) {
623
- if ( ! empty( $data ) ) {
624
- $data = self::get_reports_from_response( $data );
625
  self::handle_more_reports( $data );
626
- $report = self::get_single_report( $data );
627
  self::get_report_column_header( $report );
628
  $report_data = self::get_report_data( $report );
629
- $rows = self::get_rows( $report_data );
630
- $totals = self::get_totals( $report_data );
631
- $totalCount = array();
632
- if ( ! empty( $totals ) ) {
633
  foreach ( $totals as $key => $total ) {
634
- $totalCount = $total['values'][0];
635
  }
636
  }
637
  $sources = array(
638
- 'total' => $totalCount,
639
- 'sum' => 0,
640
- 'rows' => array(),
641
  );
642
- if ( ! empty( $rows ) ) {
643
  $i = 1;
644
  foreach ( $rows as $row ) {
645
- if ( ! empty( $row ) ) {
646
  foreach ( $row as $key => $value ) {
647
  if ( $key == 'dimensions' ) {
648
- $sources['rows'][ $i ]['name'] = $value[0];
649
- $sources['rows'][ $i ]['url'] = 'http://' . substr( $value[0], 0,
650
- strpos( $value[0], '/' ) - 1 );
651
  } elseif ( $key == 'metrics' ) {
652
- $sources['rows'][ $i ]['number'] = $value[0]['values'][0];
653
- $sources['rows'][ $i ]['percent'] = ( ! empty( $totalCount ) ) ? round( $value[0]['values'][0] / $totalCount * 100,
654
- 2 ) : 0;
655
- $sources['sum'] += $value[0]['values'][0];
656
  }
657
  }
658
  $i ++;
@@ -674,40 +664,41 @@ class Ga_Stats {
674
  * @return array dashboard boxes data
675
  */
676
  public static function get_dashboard_boxes_data( $data ) {
677
- if ( ! empty( $data ) ) {
678
- $data = self::get_reports_from_response( $data );
679
  self::handle_more_reports( $data );
680
- $report = self::get_single_report( $data );
681
  self::get_report_column_header( $report );
682
- $report_data = self::get_report_data( $report );
683
- $totals = self::get_totals( $report_data );
684
- $boxes_data = array();
685
- $boxes_data['Sessions'] = array(
686
- 'label' => 'Visits',
687
- 'value' => $totals[0]['values'][0],
688
  );
689
- $boxes_data['Pageviews'] = array(
690
- 'label' => 'Pageviews',
691
- 'value' => $totals[0]['values'][1],
692
  );
693
- $boxes_data['pageviewsPerSession'] = array(
694
- 'label' => 'Pages / Visit',
695
- 'value' => self::number_format_clean( $totals[0]['values'][2], 2, '.', ',' ),
696
  );
697
- $boxes_data['BounceRate'] = array(
698
- 'label' => 'Bounce Rate',
699
- 'value' => self::number_format_clean( $totals[0]['values'][3], 2, '.', ',' ) . '%',
700
  );
701
- $boxes_data['avgTimeOnPage'] = array(
702
- 'label' => 'Avg. Time on Site',
703
- 'value' => gmdate( "H:i:s", $totals[0]['values'][4] ),
704
  );
705
- $boxes_data['percentNewSessions'] = array(
706
- 'label' => '% of New Visits',
707
- 'value' => self::number_format_clean( $totals[0]['values'][5], 2, '.', ',' ),
708
  );
709
 
710
  return $boxes_data;
711
  }
712
  }
 
713
  }
42
  * @return array Sources query
43
  */
44
  public static function sources_query( $id_view ) {
45
+ $reports_requests = array();
46
+ $reports_requests[] = array(
47
+ 'viewId' => $id_view,
48
+ 'dateRanges' => self::set_date_ranges( '7daysAgo', 'yesterday' ),
49
+ 'metrics' => self::set_metrics( array( 'ga:pageviews' ) ),
50
+ 'includeEmptyRows' => true,
51
+ 'pageSize' => 5,
52
+ 'dimensions' => self::set_dimensions( 'ga:sourceMedium' ),
53
+ 'orderBys' => self::set_order_bys( 'ga:pageviews', 'DESCENDING' ),
54
  );
55
+ $query = array(
56
  'reportRequests' => $reports_requests
57
  );
58
 
68
  * @return array Dashboard boxes query
69
  */
70
  public static function dashboard_boxes_query( $id_view, $date_range ) {
71
+ $reports_requests = array();
72
+ $reports_requests[] = array(
73
+ 'viewId' => $id_view,
74
+ 'dateRanges' => self::set_date_ranges( $date_range, 'yesterday' ),
75
+ 'metrics' => self::set_metrics( array(
76
  'ga:sessions',
77
  'ga:pageviews',
78
  'ga:pageviewsPerSession',
80
  'ga:avgTimeOnPage',
81
  'ga:percentNewSessions',
82
  ) ),
83
+ 'includeEmptyRows' => true,
84
+ 'dimensions' => self::set_dimensions( 'ga:date' )
85
  );
86
+ $query = array(
87
  'reportRequests' => $reports_requests
88
  );
89
 
98
  * @return array Boxes query
99
  */
100
  public static function boxes_query( $id_view ) {
101
+ $reports_requests = array();
102
+ $reports_requests[] = array(
103
+ 'viewId' => $id_view,
104
+ 'dateRanges' => self::set_date_ranges( '7daysAgo', 'yesterday', '14daysAgo', '8daysAgo' ),
105
+ 'metrics' => self::set_metrics( array(
106
  'ga:users',
107
  'ga:pageviews',
108
  'ga:pageviewsPerSession',
109
  'ga:BounceRate'
110
  ) ),
111
+ 'includeEmptyRows' => true,
112
+ 'dimensions' => self::set_dimensions( 'ga:date' )
113
  );
114
+ $query = array(
115
  'reportRequests' => $reports_requests
116
  );
117
 
140
  $metric = 'ga:' . $metric;
141
  }
142
 
143
+ $reports_requests = array();
144
+ $reports_requests[] = array(
145
+ 'viewId' => $id_view,
146
+ 'dateRanges' => $date_ranges,
147
+ 'metrics' => self::set_metrics( $metric ),
148
+ 'includeEmptyRows' => true,
149
+ 'dimensions' => self::set_dimensions( 'ga:date' )
150
  );
151
+ $query = array(
152
  'reportRequests' => $reports_requests
153
  );
154
 
164
  * @return array OrderBys
165
  */
166
  public static function set_order_bys( $name, $sort ) {
167
+ $order = array();
168
  $order[] = array(
169
+ 'fieldName' => $name,
170
+ 'sortOrder' => $sort,
171
  );
172
 
173
  return $order;
205
  * @return array Dimensions
206
  */
207
  public static function set_dimensions( $name ) {
208
+ $dimensions = array();
209
+ $dimensions[] = array(
210
  'name' => $name
211
  );
212
 
224
  * @return array Date ranges
225
  */
226
  public static function set_date_ranges( $start_date, $end_date, $prev_start_date = '', $prev_end_date = '' ) {
227
+ $date_danges = array();
228
+ $date_danges[] = array(
229
+ 'startDate' => $start_date,
230
+ 'endDate' => $end_date
231
  );
232
+ if ( !empty( $prev_start_date ) and ! empty( $prev_end_date ) ) {
233
  $date_danges[] = array(
234
+ 'startDate' => $prev_start_date,
235
+ 'endDate' => $prev_end_date
236
  );
237
  }
238
 
247
  * @return array Response rows
248
  */
249
  public static function prepare_response( $data ) {
250
+ $data = self::get_reports_from_response( $data );
251
  self::handle_more_reports( $data );
252
+ $report = self::get_single_report( $data );
253
  self::get_report_column_header( $report );
254
  $report_data = self::get_report_data( $report );
255
  self::get_totals( $report_data );
256
  self::get_row_count( $report_data );
257
+ $rows = self::get_rows( $report_data );
258
 
259
  return $rows;
260
  }
267
  * @return array Dimensions
268
  */
269
  public static function get_dimensions( $row ) {
270
+ if ( !empty( $row[ 'dimensions' ] ) ) {
271
+ return $row[ 'dimensions' ];
272
  }
273
 
274
  return false;
282
  * @return array Metrics
283
  */
284
  public static function get_metrics( $row ) {
285
+ if ( !empty( $row[ 'metrics' ] ) ) {
286
+ return $row[ 'metrics' ];
287
  }
288
 
289
  return false;
297
  * @return array Rows
298
  */
299
  public static function get_rows( $report_data ) {
300
+ if ( !empty( $report_data[ 'rows' ] ) ) {
301
+ return $report_data[ 'rows' ];
302
  }
303
 
304
  return false;
312
  * @return array Row count
313
  */
314
  public static function get_row_count( $report_data ) {
315
+ if ( !empty( $report_data[ 'rowCount' ] ) ) {
316
+ return $report_data[ 'rowCount' ];
317
  }
318
 
319
  return false;
327
  * @return array Totals
328
  */
329
  public static function get_totals( $report_data ) {
330
+ if ( !empty( $report_data[ 'totals' ] ) ) {
331
+ return $report_data[ 'totals' ];
332
  }
333
 
334
  return false;
342
  * @return array Reports
343
  */
344
  public static function get_reports_from_response( $data ) {
345
+ if ( !empty( $data[ 'reports' ] ) ) {
346
+ return $data[ 'reports' ];
347
  }
348
 
349
  return false;
381
  * @return array Report
382
  */
383
  public static function get_single_report( $data ) {
384
+ if ( !empty( $data ) ) {
385
  foreach ( $data as $report ) {
386
+ if ( !empty( $report ) ) {
387
  return $report;
388
  }
389
  }
400
  * @return array Row
401
  */
402
  public static function get_single_row( $rows ) {
403
+ if ( !empty( $rows ) ) {
404
  foreach ( $rows as $row ) {
405
+ if ( !empty( $row ) ) {
406
  return $row;
407
  }
408
  }
419
  * @return array Column header
420
  */
421
  public static function get_report_column_header( $data ) {
422
+ if ( !empty( $data[ 'columnHeader' ] ) ) {
423
+ return $data[ 'columnHeader' ];
424
  }
425
 
426
  return false;
434
  * @return array data
435
  */
436
  public static function get_report_data( $data ) {
437
+ if ( !empty( $data[ 'data' ] ) ) {
438
+ return $data[ 'data' ];
439
  }
440
 
441
  return false;
450
  */
451
  public static function get_chart( $response_data ) {
452
  $chart_data = array();
453
+ if ( !empty( $response_data ) ) {
454
+ $data = (!empty( $response_data[ 'reports' ] ) && !empty( $response_data[ 'reports' ][ 0 ] ) && !empty( $response_data[ 'reports' ][ 0 ][ 'data' ] ) ) ? $response_data[ 'reports' ][ 0 ][ 'data' ] : array();
455
+ $rows = (!empty( $data[ 'rows' ] ) ) ? $data[ 'rows' ] : array();
456
+ if ( !empty( $rows ) ) {
457
  foreach ( $rows as $key => $row ) {
458
  if ( $key < 7 ) {
459
+ $chart_data[ $key ][ 'previous' ] = !empty( $row[ 'metrics' ][ 1 ][ 'values' ][ 0 ] ) ? $row[ 'metrics' ][ 1 ][ 'values' ][ 0 ] : 0;
460
+ $chart_data[ $key ][ 'previous-day' ] = date( 'M j', strtotime( $row[ 'dimensions' ][ 0 ] ) );
461
  } else {
462
+ $chart_data[ $key - 7 ][ 'day' ] = date( 'M j', strtotime( $row[ 'dimensions' ][ 0 ] ) );
463
+ $chart_data[ $key - 7 ][ 'current' ] = !empty( $row[ 'metrics' ][ 0 ][ 'values' ][ 0 ] ) ? $row[ 'metrics' ][ 0 ][ 'values' ][ 0 ] : 0;
464
+ $chart_data[ 'date' ] = strtotime( $row[ 'dimensions' ][ 0 ] );
465
  }
466
  }
467
  }
479
  */
480
  public static function get_dashboard_chart( $response_data ) {
481
  $chart_data = array();
482
+ if ( !empty( $response_data ) ) {
483
+ $data = (!empty( $response_data[ 'reports' ] ) && !empty( $response_data[ 'reports' ][ 0 ] ) && !empty( $response_data[ 'reports' ][ 0 ][ 'data' ] ) ) ? $response_data[ 'reports' ][ 0 ][ 'data' ] : array();
484
+ $rows = (!empty( $data[ 'rows' ] ) ) ? $data[ 'rows' ] : array();
485
+ if ( !empty( $rows ) ) {
486
  foreach ( $rows as $row ) {
487
  $chart_data[] = array(
488
+ 'day' => date( 'M j', strtotime( $row[ 'dimensions' ][ 0 ] ) ),
489
+ 'current' => !empty( $row[ 'metrics' ][ 0 ][ 'values' ][ 0 ] ) ? $row[ 'metrics' ][ 0 ][ 'values' ][ 0 ] : 0
490
  );
491
  }
492
  }
503
  * @return array boxes data
504
  */
505
  public static function get_boxes( $data ) {
506
+ if ( !empty( $data ) ) {
507
+ $data = self::get_reports_from_response( $data );
508
  self::handle_more_reports( $data );
509
+ $report = self::get_single_report( $data );
510
  self::get_report_column_header( $report );
511
  $report_data = self::get_report_data( $report );
512
+ $totals = self::get_totals( $report_data );
513
 
514
  return self::get_boxes_from_totals( $totals );
515
  }
523
  * @return array boxes data
524
  */
525
  public static function get_boxes_from_totals( $totals ) {
526
+ if ( !empty( $totals ) ) {
527
  $boxes_data = array();
528
  foreach ( $totals as $key => $total ) {
529
  if ( $key == 0 ) {
530
+ $boxes_data[ 'Users' ][ 'current' ] = $total[ 'values' ][ 0 ];
531
+ $boxes_data[ 'Pageviews' ][ 'current' ] = $total[ 'values' ][ 1 ];
532
+ $boxes_data[ 'PageviewsPerSession' ][ 'current' ] = $total[ 'values' ][ 2 ];
533
+ $boxes_data[ 'BounceRate' ][ 'current' ] = round( $total[ 'values' ][ 3 ], 2 );
534
  } else {
535
+ $boxes_data[ 'Users' ][ 'previous' ] = $total[ 'values' ][ 0 ];
536
+ $boxes_data[ 'Pageviews' ][ 'previous' ] = $total[ 'values' ][ 1 ];
537
+ $boxes_data[ 'PageviewsPerSession' ][ 'previous' ] = $total[ 'values' ][ 2 ];
538
+ $boxes_data[ 'BounceRate' ][ 'previous' ] = round( $total[ 'values' ][ 3 ], 2 );
539
  }
540
  }
541
 
553
  * @return array boxes data
554
  */
555
  public static function prepare_boxes( $boxes_data ) {
556
+ $boxes_data[ 'Users' ][ 'diff' ] = ( $boxes_data[ 'Users' ][ 'previous' ] > 0 ) ? round( ( $boxes_data[ 'Users' ][ 'current' ] - $boxes_data[ 'Users' ][ 'previous' ] ) / $boxes_data[ 'Users' ][ 'previous' ] * 100, 2 ) : 100;
557
+ $boxes_data[ 'Pageviews' ][ 'diff' ] = ( $boxes_data[ 'Pageviews' ][ 'previous' ] > 0 ) ? round( ( $boxes_data[ 'Pageviews' ][ 'current' ] - $boxes_data[ 'Pageviews' ][ 'previous' ] ) / $boxes_data[ 'Pageviews' ][ 'previous' ] * 100, 2 ) : 100;
558
+ $boxes_data[ 'PageviewsPerSession' ][ 'diff' ] = ( $boxes_data[ 'PageviewsPerSession' ][ 'previous' ] > 0 ) ? round( ( $boxes_data[ 'PageviewsPerSession' ][ 'current' ] - $boxes_data[ 'PageviewsPerSession' ][ 'previous' ] ) / $boxes_data[ 'PageviewsPerSession' ][ 'previous' ] * 100, 2 ) : 100;
559
+ $boxes_data[ 'BounceRate' ][ 'diff' ] = ( $boxes_data[ 'BounceRate' ][ 'previous' ] > 0 ) ? round( ( $boxes_data[ 'BounceRate' ][ 'current' ] - $boxes_data[ 'BounceRate' ][ 'previous' ] ) / $boxes_data[ 'BounceRate' ][ 'previous' ] * 100, 2 ) : 100;
560
+ $boxes_data[ 'Users' ][ 'diff' ] = ( $boxes_data[ 'Users' ][ 'previous' ] == 0 && $boxes_data[ 'Users' ][ 'current' ] == 0 ) ? 0 : $boxes_data[ 'Users' ][ 'diff' ];
561
+ $boxes_data[ 'Pageviews' ][ 'diff' ] = ( $boxes_data[ 'Pageviews' ][ 'previous' ] == 0 && $boxes_data[ 'Pageviews' ][ 'current' ] == 0 ) ? 0 : $boxes_data[ 'Pageviews' ][ 'diff' ];
562
+ $boxes_data[ 'PageviewsPerSession' ][ 'diff' ] = ( $boxes_data[ 'PageviewsPerSession' ][ 'previous' ] == 0 && $boxes_data[ 'PageviewsPerSession' ][ 'current' ] == 0 ) ? 0 : $boxes_data[ 'PageviewsPerSession' ][ 'diff' ];
563
+ $boxes_data[ 'BounceRate' ][ 'diff' ] = ( $boxes_data[ 'BounceRate' ][ 'previous' ] == 0 && $boxes_data[ 'BounceRate' ][ 'current' ] == 0 ) ? 0 : $boxes_data[ 'BounceRate' ][ 'diff' ];
564
+ $boxes_data[ 'Users' ][ 'label' ] = 'Users';
565
+ $boxes_data[ 'Pageviews' ][ 'label' ] = 'Pageviews';
566
+ $boxes_data[ 'PageviewsPerSession' ][ 'label' ] = 'Pages / Session';
567
+ $boxes_data[ 'BounceRate' ][ 'label' ] = 'Bounce Rate';
568
+ $boxes_data[ 'Users' ][ 'comparison' ] = $boxes_data[ 'Users' ][ 'current' ] . ' vs ' . $boxes_data[ 'Users' ][ 'previous' ];
569
+ $boxes_data[ 'Pageviews' ][ 'comparison' ] = $boxes_data[ 'Pageviews' ][ 'current' ] . ' vs ' . $boxes_data[ 'Pageviews' ][ 'previous' ];
570
+ $boxes_data[ 'PageviewsPerSession' ][ 'comparison' ] = self::number_format_clean( $boxes_data[ 'PageviewsPerSession' ][ 'current' ], 2, '.', ',' ) . ' vs ' . self::number_format_clean( $boxes_data[ 'PageviewsPerSession' ][ 'previous' ], 2, '.', ',' );
571
+ $boxes_data[ 'BounceRate' ][ 'comparison' ] = self::number_format_clean( $boxes_data[ 'BounceRate' ][ 'current' ], 2, '.', ',' ) . '% vs ' . self::number_format_clean( $boxes_data[ 'BounceRate' ][ 'previous' ], 2, '.', ',' ) . '%';
572
+ $boxes_data[ 'Users' ][ 'color' ] = ( $boxes_data[ 'Users' ][ 'diff' ] > 0 ) ? 'green' : 'red';
573
+ $boxes_data[ 'Pageviews' ][ 'color' ] = ( $boxes_data[ 'Pageviews' ][ 'diff' ] > 0 ) ? 'green' : 'red';
574
+ $boxes_data[ 'PageviewsPerSession' ][ 'color' ] = ( $boxes_data[ 'PageviewsPerSession' ][ 'diff' ] > 0 ) ? 'green' : 'red';
575
+ $boxes_data[ 'BounceRate' ][ 'color' ] = ( $boxes_data[ 'BounceRate' ][ 'diff' ] > 0 ) ? 'red' : 'green';
576
+ $boxes_data[ 'Users' ][ 'color' ] = ( $boxes_data[ 'Users' ][ 'diff' ] != 0 ) ? $boxes_data[ 'Users' ][ 'color' ] : 'black';
577
+ $boxes_data[ 'Pageviews' ][ 'color' ] = ( $boxes_data[ 'Pageviews' ][ 'diff' ] != 0 ) ? $boxes_data[ 'Pageviews' ][ 'color' ] : 'black';
578
+ $boxes_data[ 'PageviewsPerSession' ][ 'color' ] = ( $boxes_data[ 'PageviewsPerSession' ][ 'diff' ] != 0 ) ? $boxes_data[ 'PageviewsPerSession' ][ 'color' ] : 'black';
579
+ $boxes_data[ 'BounceRate' ][ 'color' ] = ( $boxes_data[ 'BounceRate' ][ 'diff' ] != 0 ) ? $boxes_data[ 'BounceRate' ][ 'color' ] : 'black';
 
 
 
 
 
 
 
 
580
 
581
  return $boxes_data;
582
  }
612
  * @return array sources data
613
  */
614
  public static function get_sources( $data ) {
615
+ if ( !empty( $data ) ) {
616
+ $data = self::get_reports_from_response( $data );
617
  self::handle_more_reports( $data );
618
+ $report = self::get_single_report( $data );
619
  self::get_report_column_header( $report );
620
  $report_data = self::get_report_data( $report );
621
+ $rows = self::get_rows( $report_data );
622
+ $totals = self::get_totals( $report_data );
623
+ $totalCount = array();
624
+ if ( !empty( $totals ) ) {
625
  foreach ( $totals as $key => $total ) {
626
+ $totalCount = $total[ 'values' ][ 0 ];
627
  }
628
  }
629
  $sources = array(
630
+ 'total' => $totalCount,
631
+ 'sum' => 0,
632
+ 'rows' => array(),
633
  );
634
+ if ( !empty( $rows ) ) {
635
  $i = 1;
636
  foreach ( $rows as $row ) {
637
+ if ( !empty( $row ) ) {
638
  foreach ( $row as $key => $value ) {
639
  if ( $key == 'dimensions' ) {
640
+ $sources[ 'rows' ][ $i ][ 'name' ] = $value[ 0 ];
641
+ $sources[ 'rows' ][ $i ][ 'url' ] = 'http://' . substr( $value[ 0 ], 0, strpos( $value[ 0 ], '/' ) - 1 );
 
642
  } elseif ( $key == 'metrics' ) {
643
+ $sources[ 'rows' ][ $i ][ 'number' ] = $value[ 0 ][ 'values' ][ 0 ];
644
+ $sources[ 'rows' ][ $i ][ 'percent' ] = (!empty( $totalCount ) ) ? round( $value[ 0 ][ 'values' ][ 0 ] / $totalCount * 100, 2 ) : 0;
645
+ $sources[ 'sum' ] += $value[ 0 ][ 'values' ][ 0 ];
 
646
  }
647
  }
648
  $i ++;
664
  * @return array dashboard boxes data
665
  */
666
  public static function get_dashboard_boxes_data( $data ) {
667
+ if ( !empty( $data ) ) {
668
+ $data = self::get_reports_from_response( $data );
669
  self::handle_more_reports( $data );
670
+ $report = self::get_single_report( $data );
671
  self::get_report_column_header( $report );
672
+ $report_data = self::get_report_data( $report );
673
+ $totals = self::get_totals( $report_data );
674
+ $boxes_data = array();
675
+ $boxes_data[ 'Sessions' ] = array(
676
+ 'label' => 'Visits',
677
+ 'value' => $totals[ 0 ][ 'values' ][ 0 ],
678
  );
679
+ $boxes_data[ 'Pageviews' ] = array(
680
+ 'label' => 'Pageviews',
681
+ 'value' => $totals[ 0 ][ 'values' ][ 1 ],
682
  );
683
+ $boxes_data[ 'pageviewsPerSession' ] = array(
684
+ 'label' => 'Pages / Visit',
685
+ 'value' => self::number_format_clean( $totals[ 0 ][ 'values' ][ 2 ], 2, '.', ',' ),
686
  );
687
+ $boxes_data[ 'BounceRate' ] = array(
688
+ 'label' => 'Bounce Rate',
689
+ 'value' => self::number_format_clean( $totals[ 0 ][ 'values' ][ 3 ], 2, '.', ',' ) . '%',
690
  );
691
+ $boxes_data[ 'avgTimeOnPage' ] = array(
692
+ 'label' => 'Avg. Time on Site',
693
+ 'value' => gmdate( "H:i:s", $totals[ 0 ][ 'values' ][ 4 ] ),
694
  );
695
+ $boxes_data[ 'percentNewSessions' ] = array(
696
+ 'label' => '% of New Visits',
697
+ 'value' => self::number_format_clean( $totals[ 0 ][ 'values' ][ 5 ], 2, '.', ',' ),
698
  );
699
 
700
  return $boxes_data;
701
  }
702
  }
703
+
704
  }
class/controller/Ga_Admin_Controller.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Manages actions in the admin area.
5
+ *
6
+ * Created by PhpStorm.
7
+ * User: mdn
8
+ * Date: 2017-01-25
9
+ * Time: 09:50
10
+ */
11
+ class Ga_Admin_Controller extends Ga_Controller_Core {
12
+
13
+ const ACTION_SHARETHIS_INVITE = 'ga_action_sharethis_invite';
14
+
15
+ /**
16
+ * Redirects to Google oauth authentication endpoint.
17
+ */
18
+ public static function ga_action_auth() {
19
+ if ( Ga_Helper::are_features_enabled() ) {
20
+ header( 'Location:' . Ga_Admin::api_client()->create_auth_url() );
21
+ } else {
22
+ wp_die( Ga_Helper::ga_oauth_notice( __( 'Please accept the terms to use this feature' ) ) );
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Handle Sharethis invite action
28
+ */
29
+ public static function ga_action_sharethis_invite() {
30
+
31
+ if ( self::verify_nonce( self::ACTION_SHARETHIS_INVITE ) ) {
32
+ $msg = Ga_Helper::create_url_msg( _( 'Invalid request.' ), Ga_Admin::NOTICE_ERROR );
33
+ } else {
34
+ $email = !empty( $_POST[ 'sharethis_invite_email' ] ) ? $_POST[ 'sharethis_invite_email' ] : null;
35
+ $response = null;
36
+ if ( !empty( $email ) ) {
37
+ $data = array(
38
+ 'id' => get_option( Ga_Admin::GA_SHARETHIS_PROPERTY_ID ),
39
+ 'secret' => get_option( Ga_Admin::GA_SHARETHIS_PROPERTY_SECRET ),
40
+ 'product' => 'viral-notifications',
41
+ 'role' => 'admin', // array_shift(Ga_Helper::get_user_roles())
42
+ 'email' => $email
43
+ );
44
+
45
+ $response = Ga_Admin::api_client( Ga_Admin::GA_SHARETHIS_API_ALIAS )->call( 'ga_api_sharethis_user_invite', array( $data ) );
46
+ $errors = Ga_Admin::api_client( Ga_Admin::GA_SHARETHIS_API_ALIAS )->get_errors();
47
+
48
+ if ( !empty( $errors ) ) {
49
+ $msg = '';
50
+ foreach ( $errors as $error ) {
51
+ $msg .= $error[ 'message' ];
52
+ }
53
+ $msg = Ga_Helper::create_url_msg( $msg, Ga_Admin::NOTICE_ERROR );
54
+ } else {
55
+ $msg = Ga_Helper::create_url_msg( _( 'An invite was sent to this email' ), Ga_Admin::NOTICE_SUCCESS );
56
+ }
57
+ }
58
+ }
59
+
60
+ wp_redirect( admin_url( Ga_Helper::create_url( Ga_Helper::GA_TRENDING_PAGE_URL, array( 'ga_msg' => $msg ) ) ) );
61
+ }
62
+
63
+ /**
64
+ * Sets accept terms option to TRUE.
65
+ */
66
+ public static function ga_action_update_terms() {
67
+ update_option( Ga_Admin::GA_SHARETHIS_TERMS_OPTION_NAME, true );
68
+
69
+ wp_redirect( admin_url( Ga_Helper::GA_SETTINGS_PAGE_URL ) );
70
+ }
71
+
72
+ /**
73
+ * Enables all features option.
74
+ */
75
+ public static function ga_action_enable_all_features() {
76
+ Ga_Helper::update_option( Ga_Admin::GA_DISABLE_ALL_FEATURES, false );
77
+
78
+ $url = !empty( $_GET[ 'page' ] ) ? Ga_Helper::create_url( admin_url( 'admin.php' ), array( 'page' => $_GET[ 'page' ] ) ) : admin_url( Ga_Helper::create_url( Ga_Helper::GA_SETTINGS_PAGE_URL ) );
79
+
80
+ wp_redirect( $url );
81
+ }
82
+
83
+ /**
84
+ * Disables all features option.
85
+ */
86
+ public static function ga_action_disable_all_features() {
87
+ Ga_Helper::update_option( Ga_Admin::GA_DISABLE_ALL_FEATURES, true );
88
+
89
+ $url = !empty( $_GET[ 'page' ] ) ? Ga_Helper::create_url( admin_url( 'admin.php' ), array( 'page' => $_GET[ 'page' ] ) ) : admin_url( Ga_Helper::create_url( Ga_Helper::GA_SETTINGS_PAGE_URL ) );
90
+
91
+ wp_redirect( $url );
92
+ }
93
+
94
+ }
class/controller/Ga_Frontend_Controller.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Created by PhpStorm.
5
+ * User: mdn
6
+ * Date: 2017-02-01
7
+ * Time: 09:46
8
+ */
9
+ class Ga_Frontend_Controller extends Ga_Controller_Core {
10
+
11
+ public static function googleanalytics_get_script() {
12
+ if ( !empty( $_SERVER[ 'HTTP_X_REQUESTED_WITH' ] ) && strtolower( $_SERVER[ 'HTTP_X_REQUESTED_WITH' ] ) == 'xmlhttprequest' ) {
13
+ $web_property_id = Ga_Frontend::get_web_property_id();
14
+ if ( Ga_Helper::should_load_ga_javascript( $web_property_id ) ) {
15
+ $javascript = Ga_View_Core::load( 'ga_code', array(
16
+ 'data' => array(
17
+ Ga_Admin::GA_WEB_PROPERTY_ID_OPTION_NAME => $web_property_id
18
+ )
19
+ ), true );
20
+ echo strip_tags( $javascript );
21
+ }
22
+ } else {
23
+ wp_redirect( home_url() );
24
+ }
25
+ exit();
26
+ }
27
+
28
+ }
class/core/Ga_Controller_Core.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Created by PhpStorm.
5
+ * User: mdn
6
+ * Date: 2017-02-01
7
+ * Time: 09:46
8
+ */
9
+ class Ga_Controller_Core {
10
+
11
+ const GA_NONCE_FIELD_NAME = '_gawpnonce';
12
+ const ACTION_PARAM_NAME = 'ga_action';
13
+
14
+ /**
15
+ * Runs particular action.
16
+ */
17
+ public function handle_actions() {
18
+ $action = !empty( $_REQUEST[ self::ACTION_PARAM_NAME ] ) ? $_REQUEST[ self::ACTION_PARAM_NAME ] : null;
19
+
20
+ if ( $action ) {
21
+ $class = get_class( $this );
22
+ if ( is_callable( array(
23
+ $class,
24
+ $action
25
+ ) ) ) {
26
+ call_user_func( $class . '::' . $action );
27
+ }
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Verifies nonce for given acction.
33
+ *
34
+ * @param $action
35
+ * @return bool
36
+ */
37
+ protected static function verify_nonce( $action ) {
38
+ return !isset( $_POST[ self::GA_NONCE_FIELD_NAME ] ) || !wp_verify_nonce( $_POST[ self::GA_NONCE_FIELD_NAME ], $action );
39
+ }
40
+ }
class/core/Ga_View_Core.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Ga_View_Core {
4
+
5
+ /**
6
+ * Name of the view folder.
7
+ */
8
+ const PATH = 'view';
9
+
10
+ /**
11
+ * Loads given view file and it's data.
12
+ * Displays view or returns HTML code.
13
+ *
14
+ * @param string $view Filename
15
+ * @param array $data Data array
16
+ * @param bool $html Whether to display or return HTML code.
17
+ *
18
+ * @return string
19
+ */
20
+ public static function load( $view, $data_array = array(), $html = false ) {
21
+ if ( !empty( $view ) ) {
22
+ foreach ( $data_array as $k => $v ) {
23
+ $$k = $v;
24
+ }
25
+ ob_start();
26
+ include GA_PLUGIN_DIR . "/" . self::PATH . "/" . $view . ".php";
27
+ if ( $html ) {
28
+ return ob_get_clean();
29
+ } else {
30
+ echo ob_get_clean();
31
+ }
32
+ }
33
+ }
34
+
35
+ }
css/ga_additional.css CHANGED
@@ -1,14 +1,13 @@
1
  @-ms-viewport {
2
  width: device-width;
3
  }
4
-
5
  .ga-table {
6
  border-collapse: collapse;
7
  border-spacing: 0;
8
  background-color: transparent;
9
  width: 100%;
10
  max-width: 100%;
11
- margin-bottom: 20px;
12
  border: 1px solid #dddddd;
13
  }
14
 
@@ -19,13 +18,11 @@
19
  vertical-align: top;
20
  border: 1px solid #dddddd;
21
  }
22
-
23
  .ga-table col[class*="col-"] {
24
  position: static;
25
  float: none;
26
  display: table-column;
27
  }
28
-
29
  .ga-table td[class*="col-"],
30
  .ga-table th[class*="col-"] {
31
  position: static;
@@ -33,6 +30,26 @@
33
  display: table-cell;
34
  }
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  .progress {
37
  overflow: hidden;
38
  height: 20px;
@@ -42,7 +59,6 @@
42
  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
43
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
44
  }
45
-
46
  .progress-bar {
47
  float: left;
48
  width: 0%;
@@ -58,7 +74,6 @@
58
  -o-transition: width 0.6s ease;
59
  transition: width 0.6s ease;
60
  }
61
-
62
  .progress.active .progress-bar,
63
  .progress-bar.active {
64
  -webkit-animation: progress-bar-stripes 2s linear infinite;
@@ -74,18 +89,15 @@
74
  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
75
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
76
  }
77
-
78
  .ga-panel-body {
79
  padding: 15px;
80
  }
81
-
82
  .ga-panel-heading {
83
  padding: 10px 15px;
84
  border-bottom: 1px solid transparent;
85
  border-top-right-radius: 3px;
86
  border-top-left-radius: 3px;
87
  }
88
-
89
  .ga-panel-heading > .dropdown .dropdown-toggle {
90
  color: inherit;
91
  }
@@ -107,12 +119,12 @@
107
  border-top-right-radius: 3px;
108
  border-top-left-radius: 3px;
109
  }
110
-
111
  .ga-panel > .ga-table:first-child > tbody:first-child > tr:first-child {
112
  border-top-left-radius: 3px;
113
  border-top-right-radius: 3px;
114
  }
115
 
 
116
  .ga-panel > .ga-table:first-child > tbody:first-child > tr:first-child td:first-child {
117
  border-top-left-radius: 3px;
118
  border-top-right-radius: 3px;
@@ -122,36 +134,30 @@
122
  border-bottom-right-radius: 3px;
123
  border-bottom-left-radius: 3px;
124
  }
125
-
126
  .ga-panel > .ga-table:last-child > tbody:last-child > tr:last-child {
127
  border-bottom-left-radius: 3px;
128
  border-bottom-right-radius: 3px;
129
  }
130
-
131
  .ga-panel > .ga-table:last-child > tbody:last-child > tr:last-child td:first-child,
132
  .ga-panel > .ga-table:last-child > tbody:last-child > tr:last-child th:first-child {
133
  border-bottom-left-radius: 3px;
134
- border-bottom-right-radius: 3px;
135
  }
136
-
137
  .ga-panel > .ga-panel-body + .ga-table,
138
  .ga-panel > .ga-table + .ga-panel-body {
139
  border-top: 1px solid #dddddd;
140
  }
141
-
142
  .ga-panel > .ga-table > tbody:first-child > tr:first-child th,
143
  .ga-panel > .ga-table > tbody:first-child > tr:first-child td {
144
  border-top: 0;
145
  }
146
-
147
- .ga-panel > .ga-table {
148
  border: 0;
149
  }
150
 
151
  .ga-panel-default {
152
  border-color: #dddddd;
153
  }
154
-
155
  .ga-panel-default > .ga-panel-heading {
156
  color: #333333;
157
  background-color: #dcdcdc;
@@ -164,18 +170,16 @@
164
  padding-left: 15px;
165
  padding-right: 15px;
166
  }
167
-
168
- .ga-col-name {
169
  width: 20%;
170
- overflow: hidden;
171
  text-overflow: ellipsis;
172
  word-wrap: break-word;
173
  }
174
-
175
  .ga-row:before,
176
  .ga-row:after,
177
  .ga-panel-body:before,
178
- .ga-panel-body:after {
179
  content: " ";
180
  display: table;
181
  }
@@ -193,78 +197,64 @@
193
  .ga-col-pageviews, .ga-box, .ga-col-progressbar {
194
  float: left;
195
  }
196
-
197
  .ga-col-pageviews {
198
  width: 16.66666667%;
199
  }
200
-
201
  .ga-col-progressbar {
202
  width: 41.66666667%;
203
  }
204
-
205
- .ga-box-diff {
206
  font-size: 16px;
207
  }
208
-
209
- .ga-box-comparison {
210
  color: grey;
211
  font-size: 12px;
212
- overflow: hidden;
213
  text-overflow: ellipsis;
214
- white-space: nowrap;
215
  }
216
-
217
- .ga-box-label {
218
  font-size: 14px;
219
- overflow: hidden;
220
  text-overflow: ellipsis;
221
  white-space: nowrap;
222
  }
223
-
224
- .ga-box {
225
  width: 140px;
226
  box-sizing: border-box;
227
  }
228
-
229
  @media (min-width: 600px) {
230
  .ga-box {
231
  width: 25%;
232
  }
233
  }
234
-
235
  @media (min-width: 760px) {
236
- .ga-box-diff {
237
  font-size: 24px;
238
  }
239
-
240
- .ga-box-comparison {
241
  font-size: 16px
242
- }
243
-
244
- .ga-box-label {
245
  font-size: 16px
246
  }
247
 
248
  }
249
-
250
- @media screen and (orientation: portrait) and (-webkit-device-pixel-ratio: 3) {
251
- .ga-col-name {
252
  max-width: 100px;
253
  }
254
-
255
  .ga-chart {
256
- width: 300px;
257
- overflow: hidden;
258
- text-overflow: ellipsis;
259
  }
260
  }
261
-
262
- .ga-source-name {
263
  color: #337ab7;
264
  text-decoration: none;
265
  word-wrap: break-word;
266
  }
267
-
268
  .ga-alert {
269
  padding: 15px;
270
  margin-bottom: 20px;
@@ -277,4 +267,72 @@
277
  background-color: #fcf8e3;
278
  border-color: #faebcc;
279
  max-width: 95%;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
  }
1
  @-ms-viewport {
2
  width: device-width;
3
  }
 
4
  .ga-table {
5
  border-collapse: collapse;
6
  border-spacing: 0;
7
  background-color: transparent;
8
  width: 100%;
9
  max-width: 100%;
10
+ margin-bottom: 20px;
11
  border: 1px solid #dddddd;
12
  }
13
 
18
  vertical-align: top;
19
  border: 1px solid #dddddd;
20
  }
 
21
  .ga-table col[class*="col-"] {
22
  position: static;
23
  float: none;
24
  display: table-column;
25
  }
 
26
  .ga-table td[class*="col-"],
27
  .ga-table th[class*="col-"] {
28
  position: static;
30
  display: table-cell;
31
  }
32
 
33
+ .ga-table-trending {
34
+ border: none;
35
+ }
36
+
37
+ .ga-table-trending > tbody > tr > th,
38
+ .ga-table-trending > tbody > tr > td {
39
+ border:none;
40
+ }
41
+
42
+ .ga-table-trending > tbody > tr > th {
43
+ border-bottom: 1px solid #dddddd;
44
+ }
45
+
46
+ .ga-ta-header > th {
47
+ padding: 8px;
48
+ line-height: 1.42857143;
49
+ vertical-align: top;
50
+ text-align: left;
51
+ }
52
+
53
  .progress {
54
  overflow: hidden;
55
  height: 20px;
59
  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
60
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
61
  }
 
62
  .progress-bar {
63
  float: left;
64
  width: 0%;
74
  -o-transition: width 0.6s ease;
75
  transition: width 0.6s ease;
76
  }
 
77
  .progress.active .progress-bar,
78
  .progress-bar.active {
79
  -webkit-animation: progress-bar-stripes 2s linear infinite;
89
  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
90
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
91
  }
 
92
  .ga-panel-body {
93
  padding: 15px;
94
  }
 
95
  .ga-panel-heading {
96
  padding: 10px 15px;
97
  border-bottom: 1px solid transparent;
98
  border-top-right-radius: 3px;
99
  border-top-left-radius: 3px;
100
  }
 
101
  .ga-panel-heading > .dropdown .dropdown-toggle {
102
  color: inherit;
103
  }
119
  border-top-right-radius: 3px;
120
  border-top-left-radius: 3px;
121
  }
 
122
  .ga-panel > .ga-table:first-child > tbody:first-child > tr:first-child {
123
  border-top-left-radius: 3px;
124
  border-top-right-radius: 3px;
125
  }
126
 
127
+
128
  .ga-panel > .ga-table:first-child > tbody:first-child > tr:first-child td:first-child {
129
  border-top-left-radius: 3px;
130
  border-top-right-radius: 3px;
134
  border-bottom-right-radius: 3px;
135
  border-bottom-left-radius: 3px;
136
  }
 
137
  .ga-panel > .ga-table:last-child > tbody:last-child > tr:last-child {
138
  border-bottom-left-radius: 3px;
139
  border-bottom-right-radius: 3px;
140
  }
 
141
  .ga-panel > .ga-table:last-child > tbody:last-child > tr:last-child td:first-child,
142
  .ga-panel > .ga-table:last-child > tbody:last-child > tr:last-child th:first-child {
143
  border-bottom-left-radius: 3px;
144
+ border-bottom-right-radius: 3px;
145
  }
 
146
  .ga-panel > .ga-panel-body + .ga-table,
147
  .ga-panel > .ga-table + .ga-panel-body {
148
  border-top: 1px solid #dddddd;
149
  }
 
150
  .ga-panel > .ga-table > tbody:first-child > tr:first-child th,
151
  .ga-panel > .ga-table > tbody:first-child > tr:first-child td {
152
  border-top: 0;
153
  }
154
+ .ga-panel > .ga-table{
 
155
  border: 0;
156
  }
157
 
158
  .ga-panel-default {
159
  border-color: #dddddd;
160
  }
 
161
  .ga-panel-default > .ga-panel-heading {
162
  color: #333333;
163
  background-color: #dcdcdc;
170
  padding-left: 15px;
171
  padding-right: 15px;
172
  }
173
+ .ga-col-name{
 
174
  width: 20%;
175
+ overflow: hidden;
176
  text-overflow: ellipsis;
177
  word-wrap: break-word;
178
  }
 
179
  .ga-row:before,
180
  .ga-row:after,
181
  .ga-panel-body:before,
182
+ .ga-panel-body:after{
183
  content: " ";
184
  display: table;
185
  }
197
  .ga-col-pageviews, .ga-box, .ga-col-progressbar {
198
  float: left;
199
  }
 
200
  .ga-col-pageviews {
201
  width: 16.66666667%;
202
  }
 
203
  .ga-col-progressbar {
204
  width: 41.66666667%;
205
  }
206
+ .ga-box-diff{
 
207
  font-size: 16px;
208
  }
209
+ .ga-box-comparison{
 
210
  color: grey;
211
  font-size: 12px;
212
+ overflow: hidden;
213
  text-overflow: ellipsis;
214
+ white-space: nowrap;
215
  }
216
+ .ga-box-label{
 
217
  font-size: 14px;
218
+ overflow: hidden;
219
  text-overflow: ellipsis;
220
  white-space: nowrap;
221
  }
222
+ .ga-box{
 
223
  width: 140px;
224
  box-sizing: border-box;
225
  }
 
226
  @media (min-width: 600px) {
227
  .ga-box {
228
  width: 25%;
229
  }
230
  }
 
231
  @media (min-width: 760px) {
232
+ .ga-box-diff{
233
  font-size: 24px;
234
  }
235
+ .ga-box-comparison{
 
236
  font-size: 16px
237
+ }
238
+ .ga-box-label{
 
239
  font-size: 16px
240
  }
241
 
242
  }
243
+ @media screen and (orientation: portrait) and (-webkit-device-pixel-ratio: 3){
244
+ .ga-col-name{
 
245
  max-width: 100px;
246
  }
 
247
  .ga-chart {
248
+ width:300px;
249
+ overflow: hidden;
250
+ text-overflow: ellipsis;
251
  }
252
  }
253
+ .ga-source-name{
 
254
  color: #337ab7;
255
  text-decoration: none;
256
  word-wrap: break-word;
257
  }
 
258
  .ga-alert {
259
  padding: 15px;
260
  margin-bottom: 20px;
267
  background-color: #fcf8e3;
268
  border-color: #faebcc;
269
  max-width: 95%;
270
+ }
271
+
272
+ .ga-alert-danger {
273
+ color: #a94442;
274
+ background-color: #f2dede;
275
+ border-color: #ebccd1;
276
+ max-width: 95%;
277
+ }
278
+
279
+ .ga-alert-link{
280
+ margin-left:10px;
281
+ }
282
+
283
+ .ga-switch {
284
+ position: relative;
285
+ display: inline-block;
286
+ width: 42px;
287
+ height: 14px;
288
+ }
289
+
290
+ .ga-switch input {display:none;}
291
+
292
+ .ga-slider {
293
+ position: absolute;
294
+ cursor: pointer;
295
+ top: 0;
296
+ left: 0;
297
+ right: 0;
298
+ bottom: 0;
299
+ background-color: #ccc;
300
+ -webkit-transition: .1s;
301
+ transition: .1s;
302
+ }
303
+
304
+ .ga-slider:before {
305
+ position: absolute;
306
+ content: "";
307
+ height: 20px;
308
+ width: 20px;
309
+ left: 0px;
310
+ bottom: -4px;
311
+ border:solid 1px gray;
312
+ background-color: white;
313
+ -webkit-transition: .1s;
314
+ transition: .1s;
315
+ }
316
+
317
+ input:checked + .ga-slider {
318
+ background-color: #0085ba;
319
+ }
320
+
321
+ input:focus + .ga-slider {
322
+ box-shadow: 0 0 1px #2196F3;
323
+ }
324
+
325
+ input:checked + .ga-slider:before {
326
+ -webkit-transform: translateX(20px);
327
+ -ms-transform: translateX(20px);
328
+ transform: translateX(20px);
329
+ }
330
+
331
+ /* Rounded sliders */
332
+ .ga-slider.round {
333
+ border-radius: 34px;
334
+ }
335
+
336
+ .ga-slider.round:before {
337
+ border-radius: 50%;
338
  }
css/ga_modal.css CHANGED
@@ -44,13 +44,12 @@
44
  }
45
 
46
  .ga-modal-footer {
47
- padding: 16px 16px 16px;
48
  background-color: #fff;
49
  color: #000;
50
  border: 1px solid #fff;
51
  border-bottom-left-radius: 4px;
52
  border-bottom-right-radius: 4px;
53
- border-top: 1px solid #cccccc;
54
  text-align: right;
55
  }
56
 
@@ -58,7 +57,7 @@
58
  .ga-close {
59
  color: #aaa;
60
  float: right;
61
- font-size: 24px;
62
  font-weight: bold;
63
  }
64
 
44
  }
45
 
46
  .ga-modal-footer {
47
+ padding: 2px 16px 16px;
48
  background-color: #fff;
49
  color: #000;
50
  border: 1px solid #fff;
51
  border-bottom-left-radius: 4px;
52
  border-bottom-right-radius: 4px;
 
53
  text-align: right;
54
  }
55
 
57
  .ga-close {
58
  color: #aaa;
59
  float: right;
60
+ font-size: 28px;
61
  font-weight: bold;
62
  }
63
 
css/ga_old_wp_support.css ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .notice {
2
+ background: #fff none repeat scroll 0 0;
3
+ border-left: 4px solid #fff;
4
+ box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
5
+ margin: 5px 0 15px;
6
+ padding: 1px 12px;
7
+ }
8
+ .notice-warning {
9
+ border-left-color: #ffb900;
10
+ }
11
+ .notice-success {
12
+ border-left-color: #46b450;
13
+ }
14
+ .notice-error{
15
+ border-left-color: #dc3232;
16
+ }
17
+ .notice p{
18
+ margin: 0.5em 0;
19
+ padding: 2px;
20
+ }
css/googleanalytics.css CHANGED
@@ -140,6 +140,11 @@ label.ga_checkbox_label {
140
  color: #ccc;
141
  }
142
 
 
 
 
 
 
143
  .ga-tooltip {
144
  position: relative;
145
  cursor: not-allowed;
@@ -148,7 +153,11 @@ label.ga_checkbox_label {
148
  .ga-tooltip input[disabled] {
149
  cursor: not-allowed;
150
  }
151
-
 
 
 
 
152
  .ga-tooltiptext {
153
  background-color: #ffe692;
154
  border: 1px solid #ffb900;
@@ -166,6 +175,11 @@ label.ga_checkbox_label {
166
  width: auto;
167
  z-index: 1;
168
  }
 
 
 
 
 
169
 
170
  .ga-tt-abs {
171
  display: inline-block;
@@ -175,4 +189,54 @@ label.ga_checkbox_label {
175
 
176
  .ga-tooltip:hover .ga-tooltiptext {
177
  visibility: visible;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  }
140
  color: #ccc;
141
  }
142
 
143
+ .trending-link, .trending-link:hover {
144
+ color: #47C2B6;
145
+ text-decoration: none;
146
+ }
147
+
148
  .ga-tooltip {
149
  position: relative;
150
  cursor: not-allowed;
153
  .ga-tooltip input[disabled] {
154
  cursor: not-allowed;
155
  }
156
+ .ga-tooltip .trending-link {
157
+ color: #ccc;
158
+ pointer-events: none;
159
+ cursor: not-allowed;
160
+ }
161
  .ga-tooltiptext {
162
  background-color: #ffe692;
163
  border: 1px solid #ffb900;
175
  width: auto;
176
  z-index: 1;
177
  }
178
+ .ga-tooltiptext-trending {
179
+ position: absolute;
180
+ margin-left: 200px;
181
+ margin-top: 30px;
182
+ }
183
 
184
  .ga-tt-abs {
185
  display: inline-block;
189
 
190
  .ga-tooltip:hover .ga-tooltiptext {
191
  visibility: visible;
192
+ }
193
+
194
+ .ga-trending-h2 {
195
+ font-size: 1.6em;
196
+ margin: 10px 0;
197
+ font-weight: bold;
198
+ }
199
+
200
+ .ga-trending-h3 {
201
+ font-size: 1.3em;
202
+ margin: 10px 0;
203
+ font-weight: normal;
204
+ }
205
+ .trending-table-container{
206
+ max-width: 1000px;
207
+ text-align:left;
208
+ }
209
+ .weight-normal{
210
+ font-weight: normal;
211
+ }
212
+
213
+ .trending-time {
214
+ width: 100px;
215
+ }
216
+
217
+ .ga-love-text {
218
+ display: block;
219
+ margin-top: 20px;
220
+ font-size: 10px;
221
+ font-weight: bold;
222
+ }
223
+
224
+ .ga-trending-loader {
225
+ margin: 50px 25px;
226
+ display: none;
227
+ width: 50%;
228
+ padding: 100px 50px;
229
+ }
230
+
231
+ .ga-trending-loader-wrapper {
232
+ float: left;
233
+ padding: 10px;
234
+ }
235
+
236
+ .ga-trending-loading-text {
237
+ color: black;
238
+ width: 200px;
239
+ font-size: 12pt;
240
+ height: 65px;
241
+ float: left;
242
  }
googleanalytics.php CHANGED
@@ -4,38 +4,39 @@
4
  * Plugin Name: Google Analytics
5
  * Plugin URI: http://wordpress.org/extend/plugins/googleanalytics/
6
  * Description: Use Google Analytics on your Wordpress site without touching any code, and view visitor reports right in your Wordpress admin dashboard!
7
- * Version: 2.0.5
8
  * Author: ShareThis
9
  * Author URI: http://sharethis.com
10
  */
11
- if ( ! defined( 'WP_CONTENT_URL' ) ) {
12
  define( 'WP_CONTENT_URL', get_option( 'siteurl' ) . '/wp-content' );
13
  }
14
- if ( ! defined( 'WP_CONTENT_DIR' ) ) {
15
  define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
16
  }
17
- if ( ! defined( 'WP_PLUGIN_URL' ) ) {
18
  define( 'WP_PLUGIN_URL', WP_CONTENT_URL . '/plugins' );
19
  }
20
- if ( ! defined( 'WP_PLUGIN_DIR' ) ) {
21
  define( 'WP_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins' );
22
  }
23
- if ( ! defined( 'GA_NAME' ) ) {
24
  define( 'GA_NAME', 'googleanalytics' );
25
  }
26
- if ( ! defined( 'GA_PLUGIN_DIR' ) ) {
27
  define( 'GA_PLUGIN_DIR', WP_PLUGIN_DIR . '/' . GA_NAME );
28
  }
29
- if ( ! defined( 'GA_PLUGIN_URL' ) ) {
30
  define( 'GA_PLUGIN_URL', WP_PLUGIN_URL . '/' . GA_NAME );
31
  }
32
- if ( ! defined( 'GA_MAIN_FILE_PATH' ) ) {
33
  define( 'GA_MAIN_FILE_PATH', __FILE__ );
34
  }
35
- if ( ! defined( 'GA_SHARETHIS_SCRIPTS_INCLUDED' ) ) {
36
  define( 'GA_SHARETHIS_SCRIPTS_INCLUDED', 0 );
37
  }
38
- define( 'GOOGLEANALYTICS_VERSION', '2.0.5' );
 
39
  include_once GA_PLUGIN_DIR . '/overwrite/ga_overwrite.php';
40
  include_once GA_PLUGIN_DIR . '/class/Ga_Autoloader.php';
41
  Ga_Autoloader::register();
@@ -43,5 +44,3 @@ Ga_Hook::add_hooks( GA_MAIN_FILE_PATH );
43
 
44
  add_action( 'plugins_loaded', 'Ga_Admin::loaded_googleanalytics' );
45
  add_action( 'init', 'Ga_Helper::init' );
46
-
47
- ?>
4
  * Plugin Name: Google Analytics
5
  * Plugin URI: http://wordpress.org/extend/plugins/googleanalytics/
6
  * Description: Use Google Analytics on your Wordpress site without touching any code, and view visitor reports right in your Wordpress admin dashboard!
7
+ * Version: 2.1
8
  * Author: ShareThis
9
  * Author URI: http://sharethis.com
10
  */
11
+ if ( !defined( 'WP_CONTENT_URL' ) ) {
12
  define( 'WP_CONTENT_URL', get_option( 'siteurl' ) . '/wp-content' );
13
  }
14
+ if ( !defined( 'WP_CONTENT_DIR' ) ) {
15
  define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
16
  }
17
+ if ( !defined( 'WP_PLUGIN_URL' ) ) {
18
  define( 'WP_PLUGIN_URL', WP_CONTENT_URL . '/plugins' );
19
  }
20
+ if ( !defined( 'WP_PLUGIN_DIR' ) ) {
21
  define( 'WP_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins' );
22
  }
23
+ if ( !defined( 'GA_NAME' ) ) {
24
  define( 'GA_NAME', 'googleanalytics' );
25
  }
26
+ if ( !defined( 'GA_PLUGIN_DIR' ) ) {
27
  define( 'GA_PLUGIN_DIR', WP_PLUGIN_DIR . '/' . GA_NAME );
28
  }
29
+ if ( !defined( 'GA_PLUGIN_URL' ) ) {
30
  define( 'GA_PLUGIN_URL', WP_PLUGIN_URL . '/' . GA_NAME );
31
  }
32
+ if ( !defined( 'GA_MAIN_FILE_PATH' ) ) {
33
  define( 'GA_MAIN_FILE_PATH', __FILE__ );
34
  }
35
+ if ( !defined( 'GA_SHARETHIS_SCRIPTS_INCLUDED' ) ) {
36
  define( 'GA_SHARETHIS_SCRIPTS_INCLUDED', 0 );
37
  }
38
+
39
+ define( 'GOOGLEANALYTICS_VERSION', '2.1' );
40
  include_once GA_PLUGIN_DIR . '/overwrite/ga_overwrite.php';
41
  include_once GA_PLUGIN_DIR . '/class/Ga_Autoloader.php';
42
  Ga_Autoloader::register();
44
 
45
  add_action( 'plugins_loaded', 'Ga_Admin::loaded_googleanalytics' );
46
  add_action( 'init', 'Ga_Helper::init' );
 
 
js/googleanalytics.js CHANGED
@@ -25,4 +25,14 @@
25
  }
26
  }
27
  };
 
 
 
 
 
 
 
 
 
 
28
  })(jQuery);
25
  }
26
  }
27
  };
28
+
29
+ ga_trending_loader = {
30
+ show: function() {
31
+ $('.ga-trending-loader').show();
32
+ ga_loader.show();
33
+ $(document).ready(function () {
34
+ $('.ga-trending-loader').hide();
35
+ });
36
+ }
37
+ };
38
  })(jQuery);
js/googleanalytics_page.js CHANGED
@@ -81,6 +81,41 @@ const GA_SAVE_ACCESS_CODE_BTN_ID = 'ga_save_access_code';
81
  }
82
  };
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  $(document).ready(function () {
85
  ga_events.initModalEvents();
86
  });
81
  }
82
  };
83
 
84
+ /**
85
+ * Handles "disable all features" switch button
86
+ * @type {{init: ga_switcher.init}}
87
+ */
88
+ ga_switcher = {
89
+ init: function (state) {
90
+ var checkbox = $("#ga-disable");
91
+
92
+ if (state) {
93
+ checkbox.prop('checked', 'checked');
94
+ } else {
95
+ checkbox.removeProp('checked');
96
+ }
97
+
98
+ $("#ga-slider").on("click", function (e) {
99
+ var manually_enter_not_checked = $('#ga_enter_code_manually').not(':checked');
100
+ if (checkbox.not(':checked').length > 0) {
101
+ if (confirm('This will disable Dashboards, Viral Alerts and Google API')) {
102
+ setTimeout(function () {
103
+ window.location.href = GA_DISABLE_FEATURE_URL;
104
+ }, 350);
105
+ } else {
106
+ setTimeout(function () {
107
+ checkbox.removeProp('checked');
108
+ }, 350);
109
+ }
110
+ } else { // disable
111
+ setTimeout(function () {
112
+ window.location.href = GA_ENABLE_FEATURE_URL;
113
+ }, 350);
114
+ }
115
+ });
116
+ }
117
+ };
118
+
119
  $(document).ready(function () {
120
  ga_events.initModalEvents();
121
  });
lib/Ga_Lib_Api_Client.php CHANGED
@@ -1,61 +1,12 @@
1
  <?php
2
 
3
- class Ga_Lib_Api_Client {
4
-
5
- const OAUTH2_REVOKE_ENDPOINT = 'https://accounts.google.com/o/oauth2/revoke';
6
-
7
- const OAUTH2_TOKEN_ENDPOINT = 'https://accounts.google.com/o/oauth2/token';
8
-
9
- const OAUTH2_AUTH_ENDPOINT = 'https://accounts.google.com/o/oauth2/auth';
10
-
11
- const OAUTH2_FEDERATED_SIGNON_CERTS_ENDPOINT = 'https://www.googleapis.com/oauth2/v1/certs';
12
-
13
- const GA_ACCOUNT_SUMMARIES_ENDPOINT = 'https://www.googleapis.com/analytics/v3/management/accountSummaries';
14
-
15
- const GA_DATA_ENDPOINT = 'https://analyticsreporting.googleapis.com/v4/reports:batchGet';
16
-
17
- const OAUTH2_CALLBACK_URI = 'urn:ietf:wg:oauth:2.0:oob';
18
-
19
- /**
20
- * Pre-defined API credentials.
21
- *
22
- * @var array
23
- */
24
- private $config = array(
25
- 'access_type' => 'offline',
26
- 'application_name' => 'Google Analytics',
27
- 'client_id' => '207216681371-433ldmujuv4l0743c1j7g8sci57cb51r.apps.googleusercontent.com',
28
- 'client_secret' => 'y0B-K-ODB1KZOam50aMEDhyc',
29
- 'scopes' => array( 'https://www.googleapis.com/auth/analytics.readonly' ),
30
- 'approval_prompt' => 'force'
31
- );
32
-
33
- /**
34
- * Keeps Access Token information.
35
- *
36
- * @var array
37
- */
38
- private $token;
39
 
40
  /**
41
  * Keeps error messages.
42
  * @var array
43
  */
44
- private $errors = array();
45
-
46
- /**
47
- * Returns API client instance.
48
- *
49
- * @return Ga_Lib_Api_Client|null
50
- */
51
- public static function get_instance() {
52
- static $instance = null;
53
- if ( $instance === null ) {
54
- $instance = new Ga_Lib_Api_Client();
55
- }
56
-
57
- return $instance;
58
- }
59
 
60
  /**
61
  * Returns errors array.
@@ -65,6 +16,16 @@ class Ga_Lib_Api_Client {
65
  return $this->errors;
66
  }
67
 
 
 
 
 
 
 
 
 
 
 
68
  /**
69
  * Calls api methods.
70
  *
@@ -75,20 +36,7 @@ class Ga_Lib_Api_Client {
75
  */
76
  public function call( $callback, $args = null ) {
77
  try {
78
- $callback = array( get_class( $this ), $callback );
79
- if ( is_callable( $callback ) ) {
80
- if ( ! empty( $args ) ) {
81
- if ( is_array( $args ) ) {
82
- return call_user_func_array( $callback, $args );
83
- } else {
84
- return call_user_func_array( $callback, array( $args ) );
85
- }
86
- } else {
87
- return call_user_func( $callback );
88
- }
89
- } else {
90
- throw new Ga_Lib_Api_Client_Exception( 'Unknown method: ' . $callback );
91
- }
92
  } catch ( Ga_Lib_Api_Client_Exception $e ) {
93
  $this->add_error( $e );
94
 
@@ -110,201 +58,16 @@ class Ga_Lib_Api_Client {
110
  * @param Exception $e
111
  *
112
  */
113
- private function add_error( Exception $e ) {
114
  $this->errors[ $e->getCode() ] = array( 'class' => get_class( $e ), 'message' => $e->getMessage() );
115
  }
116
 
117
- /**
118
- * Sets access token.
119
- *
120
- * @param $token
121
- */
122
- public function set_access_token( $token ) {
123
- $this->token = $token;
124
- }
125
-
126
- /**
127
- * Returns Google Oauth2 redirect URL.
128
- *
129
- * @return string
130
- */
131
- private function get_redirect_uri() {
132
- return self::OAUTH2_CALLBACK_URI;
133
- }
134
-
135
- /**
136
- * Creates Google Oauth2 authorization URL.
137
- *
138
- * @return string
139
- */
140
- public function create_auth_url() {
141
- $params = array(
142
- 'response_type' => 'code',
143
- 'redirect_uri' => $this->get_redirect_uri(),
144
- 'client_id' => urlencode( $this->config['client_id'] ),
145
- 'scope' => implode( " ", $this->config['scopes'] ),
146
- 'access_type' => urlencode( $this->config['access_type'] ),
147
- 'approval_prompt' => urlencode( $this->config['approval_prompt'] )
148
- );
149
-
150
- return self::OAUTH2_AUTH_ENDPOINT . "?" . http_build_query( $params );
151
- }
152
-
153
- /**
154
- * Sends request for Access Token during Oauth2 process.
155
- *
156
- * @param $access_code
157
- *
158
- * @return Ga_Lib_Api_Response Returns response object
159
- */
160
- private function ga_auth_get_access_token( $access_code ) {
161
- $request = array(
162
- 'code' => $access_code,
163
- 'grant_type' => 'authorization_code',
164
- 'redirect_uri' => $this->get_redirect_uri(),
165
- 'client_id' => $this->config['client_id'],
166
- 'client_secret' => $this->config['client_secret']
167
- );
168
-
169
- $response = Ga_Lib_Api_Request::get_instance()->make_request( self::OAUTH2_TOKEN_ENDPOINT, $request );
170
-
171
- return new Ga_Lib_Api_Response( $response );
172
- }
173
-
174
- private function ga_auth_refresh_access_token( $refresh_token ) {
175
- $request = array(
176
- 'refresh_token' => $refresh_token,
177
- 'grant_type' => 'refresh_token',
178
- 'client_id' => $this->config['client_id'],
179
- 'client_secret' => $this->config['client_secret']
180
- );
181
-
182
- $response = Ga_Lib_Api_Request::get_instance()->make_request( self::OAUTH2_TOKEN_ENDPOINT, $request );
183
-
184
- return new Ga_Lib_Api_Response( $response );
185
- }
186
-
187
- /**
188
- * Get list of the analytics accounts.
189
- *
190
- * @return Ga_Lib_Api_Response Returns response object
191
- */
192
- private function ga_api_account_summaries() {
193
- $request = Ga_Lib_Api_Request::get_instance();
194
- $request = $this->sign( $request );
195
- $response = $request->make_request( self::GA_ACCOUNT_SUMMARIES_ENDPOINT );
196
-
197
- return new Ga_Lib_Api_Response( $response );
198
- }
199
-
200
- /**
201
- * Sends request for Google Analytics data using given query parameters.
202
- *
203
- * @param $query_params
204
- *
205
- * @return Ga_Lib_Api_Response Returns response object
206
- */
207
- private function ga_api_data( $query_params ) {
208
- $request = Ga_Lib_Api_Request::get_instance();
209
- $request = $this->sign( $request );
210
- $current_user = wp_get_current_user();
211
- $quota_user_string = '';
212
- if ( !empty( $current_user ) ){
213
- $blogname = get_option( 'blogname' );
214
- $quota_user = md5( $blogname . $current_user->user_login );
215
- $quota_user_string = '?quotaUser=' . $quota_user;
216
- }
217
- $response = $request->make_request( self::GA_DATA_ENDPOINT.$quota_user_string, wp_json_encode( $query_params ), true );
218
-
219
- return new Ga_Lib_Api_Response( $response );
220
  }
221
 
222
- /**
223
- * Sign request with Access Token.
224
- * Adds Access Token to the request's headers.
225
- *
226
- * @param Ga_Lib_Api_Request $request
227
- *
228
- * @return Ga_Lib_Api_Request Returns response object
229
- * @throws Ga_Lib_Api_Client_Exception
230
- */
231
- private function sign( Ga_Lib_Api_Request $request ) {
232
- if ( empty( $this->token ) ) {
233
- throw new Ga_Lib_Api_Client_Exception( 'Access Token is not available. Please reauthenticate' );
234
- }
235
-
236
- // Check if the token is set to expire in the next 30 seconds
237
- // (or has already expired).
238
- $this->check_access_token();
239
-
240
- // Add the OAuth2 header to the request
241
- $request->set_request_headers( array( 'Authorization: Bearer ' . $this->token['access_token'] ) );
242
-
243
- return $request;
244
- }
245
-
246
- /**
247
- * Refresh and save refreshed Access Token.
248
- *
249
- * @param $refresh_token
250
- */
251
- public function refresh_access_token( $refresh_token ) {
252
- // Request for a new Access Token
253
- $response = $this->call( 'ga_auth_refresh_access_token', array( $refresh_token ) );
254
-
255
- Ga_Admin::save_access_token( $response, $refresh_token );
256
-
257
- // Set new access token
258
- $token = Ga_Helper::get_option( Ga_Admin::GA_OAUTH_AUTH_TOKEN_OPTION_NAME );
259
- $this->set_access_token( json_decode( $token, true ) );
260
- }
261
-
262
- /**
263
- * Checks if Access Token is valid.
264
- *
265
- * @return bool
266
- */
267
- public function is_authorized() {
268
- if ( ! empty( $this->token ) ) {
269
- try {
270
- $this->check_access_token();
271
- } catch ( Ga_Lib_Api_Client_Exception $e ) {
272
- $this->add_error( $e );
273
- } catch ( Exception $e ) {
274
- $this->add_error( $e );
275
- }
276
- }
277
-
278
- return ! empty( $this->token ) && ! $this->is_access_token_expired();
279
- }
280
-
281
- /**
282
- * Returns if the access_token is expired.
283
- * @return bool Returns True if the access_token is expired.
284
- */
285
- public function is_access_token_expired() {
286
- if ( null == $this->token ) {
287
- return true;
288
- }
289
- if ( ! empty( $this->token['error'] ) ) {
290
- return true;
291
- }
292
- // Check if the token is expired in the next 30 seconds.
293
- $expired = ( $this->token['created'] + ( $this->token['expires_in'] - 30 ) ) < time();
294
-
295
- return $expired;
296
- }
297
-
298
- private function check_access_token() {
299
- if ( $this->is_access_token_expired() ) {
300
- if ( empty( $this->token['refresh_token'] ) ) {
301
- throw new Ga_Lib_Api_Client_Exception( 'Refresh token is not available. Please re-authenticate.' );
302
- } else {
303
- $this->refresh_access_token( $this->token['refresh_token'] );
304
- }
305
- }
306
- }
307
  }
308
 
309
  class Ga_Lib_Api_Client_Exception extends Exception {
310
- }
 
1
  <?php
2
 
3
+ abstract class Ga_Lib_Api_Client {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  /**
6
  * Keeps error messages.
7
  * @var array
8
  */
9
+ protected $errors = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  /**
12
  * Returns errors array.
16
  return $this->errors;
17
  }
18
 
19
+ /**
20
+ * Calls private API method from context client.
21
+ *
22
+ * @param $callback
23
+ * @param $args
24
+ *
25
+ * @return Ga_Lib_Api_Response
26
+ */
27
+ abstract function call_api_method( $callback, $args );
28
+
29
  /**
30
  * Calls api methods.
31
  *
36
  */
37
  public function call( $callback, $args = null ) {
38
  try {
39
+ return $this->call_api_method( $callback, $args );
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  } catch ( Ga_Lib_Api_Client_Exception $e ) {
41
  $this->add_error( $e );
42
 
58
  * @param Exception $e
59
  *
60
  */
61
+ protected function add_error( Exception $e ) {
62
  $this->errors[ $e->getCode() ] = array( 'class' => get_class( $e ), 'message' => $e->getMessage() );
63
  }
64
 
65
+ public function add_own_error( $code, $message, $class = '' ) {
66
+ $this->errors[ $code ] = array( 'class' => $class, 'message' => $message );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  }
70
 
71
  class Ga_Lib_Api_Client_Exception extends Exception {
72
+
73
+ }
lib/Ga_Lib_Api_Request.php CHANGED
@@ -2,19 +2,24 @@
2
 
3
  class Ga_Lib_Api_Request {
4
 
5
- const HEADER_CONTENT_TYPE = "application/x-www-form-urlencoded";
6
 
 
7
  const HEADER_CONTENT_TYPE_JSON = "Content-type: application/json";
8
-
9
- const HEADER_ACCEPT = "Accept: application/json, text/javascript, */*; q=0.01";
10
-
11
- const TIMEOUT = 30;
12
-
13
- const USER_AGENT = 'googleanalytics-wordpress-plugin';
14
 
15
  private $headers = array();
16
 
17
- function __construct() {
 
 
 
 
 
 
 
18
  }
19
 
20
  /**
@@ -22,13 +27,12 @@ class Ga_Lib_Api_Request {
22
  *
23
  * @return Ga_Lib_Api_Request|null
24
  */
25
- public static function get_instance() {
26
- static $instance = null;
27
- if ( $instance === null ) {
28
- $instance = new Ga_Lib_Api_Request();
29
  }
30
 
31
- return $instance;
32
  }
33
 
34
  /**
@@ -49,13 +53,35 @@ class Ga_Lib_Api_Request {
49
  *
50
  * @param string $url URL address
51
  * @param string $rawPostBody
 
 
52
  *
53
  * @return string Response
54
  * @throws Exception
55
  */
56
- public function make_request( $url, $rawPostBody = null, $json = false ) {
57
- if ( ! function_exists( 'curl_init' ) ) {
58
- throw new Ga_Lib_Api_Request_Exception( _( 'cURL functions are not available' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  }
60
 
61
  // Set default headers
@@ -64,13 +90,13 @@ class Ga_Lib_Api_Request {
64
  self::HEADER_ACCEPT
65
  ) );
66
 
67
- $ch = curl_init( $url );
68
  $headers = $this->headers;
69
  curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
70
 
71
- $curl_timeout = self::TIMEOUT;
72
- $php_execution_time = ini_get( 'max_execution_time' );
73
- if ( ! empty( $php_execution_time ) && is_numeric( $php_execution_time ) ) {
74
  if ( $php_execution_time < 36 && $php_execution_time > 9 ) {
75
  $curl_timeout = $php_execution_time - 5;
76
  } elseif ( $php_execution_time < 10 ) {
@@ -104,7 +130,7 @@ class Ga_Lib_Api_Request {
104
  }
105
 
106
  // POST body
107
- if ( ! empty( $rawPostBody ) ) {
108
  curl_setopt( $ch, CURLOPT_POST, true );
109
  curl_setopt( $ch, CURLOPT_POSTFIELDS, ( $json ? $rawPostBody : http_build_query( $rawPostBody ) ) );
110
  }
@@ -115,23 +141,56 @@ class Ga_Lib_Api_Request {
115
  if ( $error = curl_error( $ch ) ) {
116
  $errno = curl_errno( $ch );
117
  curl_close( $ch );
 
 
 
 
 
 
 
 
 
118
  throw new Ga_Lib_Api_Client_Exception( $error . ' (' . $errno . ')' );
119
  } else {
120
- $httpCode = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
121
- $headerSize = curl_getinfo( $ch, CURLINFO_HEADER_SIZE );
122
- $header = substr( $response, 0, $headerSize );
123
- $body = substr( $response, $headerSize, strlen( $response ) );
124
-
125
  if ( preg_match( '/^(4|5)[0-9]{2}/', $httpCode ) ) {
126
- throw new Ga_Lib_Api_Request_Exception( _( 'There was an error while contacting Google API:' ) . ' ' . ( $httpCode == 404 ? _( 'Requested URL doesn\'t exists: ' . $url ) : $body ) );
 
 
 
 
 
 
 
 
 
127
  }
128
 
129
  curl_close( $ch );
130
 
131
- return array( $header, $body );
 
 
 
 
 
 
 
 
 
 
132
  }
133
  }
 
134
  }
135
 
136
  class Ga_Lib_Api_Request_Exception extends Exception {
137
- }
 
 
 
 
 
2
 
3
  class Ga_Lib_Api_Request {
4
 
5
+ static $instance = null;
6
 
7
+ const HEADER_CONTENT_TYPE = "application/x-www-form-urlencoded";
8
  const HEADER_CONTENT_TYPE_JSON = "Content-type: application/json";
9
+ const HEADER_ACCEPT = "Accept: application/json, text/javascript, */*; q=0.01";
10
+ const TIMEOUT = 5;
11
+ const USER_AGENT = 'googleanalytics-wordpress-plugin';
 
 
 
12
 
13
  private $headers = array();
14
 
15
+ // Whether to cache or not
16
+ private $cache = false;
17
+
18
+ private $appendix = '';
19
+
20
+ private function __construct( $cache = false, $appendix = '' ) {
21
+ $this->cache = $cache;
22
+ $this->appendix = $appendix;
23
  }
24
 
25
  /**
27
  *
28
  * @return Ga_Lib_Api_Request|null
29
  */
30
+ public static function get_instance( $cache = false, $appendix = '' ) {
31
+ if ( self::$instance === null ) {
32
+ self::$instance = new Ga_Lib_Api_Request( $cache, $appendix );
 
33
  }
34
 
35
+ return self::$instance;
36
  }
37
 
38
  /**
53
  *
54
  * @param string $url URL address
55
  * @param string $rawPostBody
56
+ * @param boolean $json Whether to append JSON content type
57
+ * @param boolean $force_no_cache Whether to force not to cache response data even if cache property is set to true
58
  *
59
  * @return string Response
60
  * @throws Exception
61
  */
62
+ public function make_request( $url, $rawPostBody = null, $json = false, $force_no_cache = false) {
63
+
64
+ // Return cached data if exist
65
+ if ( ! $force_no_cache ) {
66
+ if ( $this->cache ) {
67
+ $wp_transient_name = Ga_Cache::get_transient_name( $url, $rawPostBody, $this->appendix );
68
+
69
+ if ( $cached = Ga_Cache::get_cached_result( $wp_transient_name ) ) {
70
+ if ( ! Ga_Cache::is_data_cache_outdated( $wp_transient_name, $this->appendix ) ) {
71
+ return $cached;
72
+ }
73
+ }
74
+
75
+ // Check if the next request after error is allowed
76
+ if ( false === Ga_Cache::is_next_request_allowed( $wp_transient_name ) ) {
77
+ throw new Ga_Lib_Api_Client_Exception( _( 'There are temporary connection issues, please try again later.' ) );
78
+ }
79
+ }
80
+ }
81
+
82
+
83
+ if ( !function_exists( 'curl_init' ) ) {
84
+ throw new Ga_Lib_Api_Client_Exception( _( 'cURL functions are not available' ) );
85
  }
86
 
87
  // Set default headers
90
  self::HEADER_ACCEPT
91
  ) );
92
 
93
+ $ch = curl_init( $url );
94
  $headers = $this->headers;
95
  curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
96
 
97
+ $curl_timeout = self::TIMEOUT;
98
+ $php_execution_time = ini_get( 'max_execution_time' );
99
+ if ( !empty( $php_execution_time ) && is_numeric( $php_execution_time ) ) {
100
  if ( $php_execution_time < 36 && $php_execution_time > 9 ) {
101
  $curl_timeout = $php_execution_time - 5;
102
  } elseif ( $php_execution_time < 10 ) {
130
  }
131
 
132
  // POST body
133
+ if ( !empty( $rawPostBody ) ) {
134
  curl_setopt( $ch, CURLOPT_POST, true );
135
  curl_setopt( $ch, CURLOPT_POSTFIELDS, ( $json ? $rawPostBody : http_build_query( $rawPostBody ) ) );
136
  }
141
  if ( $error = curl_error( $ch ) ) {
142
  $errno = curl_errno( $ch );
143
  curl_close( $ch );
144
+
145
+ // Store last cache time when unsuccessful
146
+ if ( false === $force_no_cache ) {
147
+ if ( true === $this->cache ) {
148
+ Ga_Cache::set_last_cache_time( $wp_transient_name );
149
+ Ga_Cache::set_last_time_attempt();
150
+ }
151
+ }
152
+
153
  throw new Ga_Lib_Api_Client_Exception( $error . ' (' . $errno . ')' );
154
  } else {
155
+ $httpCode = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
156
+ $headerSize = curl_getinfo( $ch, CURLINFO_HEADER_SIZE );
157
+ $header = substr( $response, 0, $headerSize );
158
+ $body = substr( $response, $headerSize, strlen( $response ) );
 
159
  if ( preg_match( '/^(4|5)[0-9]{2}/', $httpCode ) ) {
160
+
161
+ // Store last cache time when unsuccessful
162
+ if ( false === $force_no_cache ) {
163
+ if ( true === $this->cache ) {
164
+ Ga_Cache::set_last_cache_time( $wp_transient_name );
165
+ Ga_Cache::set_last_time_attempt();
166
+ }
167
+ }
168
+
169
+ throw new Ga_Lib_Api_Request_Exception( ( $httpCode == 404 ? _( 'Requested URL doesn\'t exists: ' . $url ) : $body ) );
170
  }
171
 
172
  curl_close( $ch );
173
 
174
+ $response_data = array( $header, $body );
175
+
176
+ // Cache result
177
+ if ( false === $force_no_cache ) {
178
+ if (true === $this->cache) {
179
+ Ga_Cache::set_cache( $wp_transient_name, $response_data );
180
+ }
181
+ }
182
+
183
+
184
+ return $response_data;
185
  }
186
  }
187
+
188
  }
189
 
190
  class Ga_Lib_Api_Request_Exception extends Exception {
191
+
192
+ public function __construct( $message ) {
193
+ parent::__construct( $message );
194
+ }
195
+
196
+ }
lib/Ga_Lib_Api_Response.php CHANGED
@@ -3,15 +3,16 @@
3
  class Ga_Lib_Api_Response {
4
 
5
  public static $empty_response = array( '', '' );
6
-
7
  private $header;
8
  private $body;
9
  private $data;
10
 
11
- function __construct( $raw_response ) {
12
- $this->setHeader( $raw_response[0] );
13
- $this->setBody( $raw_response[1] );
14
- $this->setData( json_decode( $raw_response[1], true ) );
 
 
15
  }
16
 
17
  public function setHeader( $header ) {
@@ -37,4 +38,5 @@ class Ga_Lib_Api_Response {
37
  public function getData() {
38
  return $this->data;
39
  }
40
- }
 
3
  class Ga_Lib_Api_Response {
4
 
5
  public static $empty_response = array( '', '' );
 
6
  private $header;
7
  private $body;
8
  private $data;
9
 
10
+ function __construct( $raw_response = null ) {
11
+ if (!empty($raw_response)) {
12
+ $this->setHeader( $raw_response[ 0 ] );
13
+ $this->setBody( $raw_response[ 1 ] );
14
+ $this->setData( json_decode( $raw_response[ 1 ], true ) );
15
+ }
16
  }
17
 
18
  public function setHeader( $header ) {
38
  public function getData() {
39
  return $this->data;
40
  }
41
+
42
+ }
lib/Ga_Lib_Google_Api_Client.php ADDED
@@ -0,0 +1,408 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Ga_Lib_Google_Api_Client extends Ga_Lib_Api_Client {
4
+
5
+ static $instance = null;
6
+
7
+ const OAUTH2_REVOKE_ENDPOINT = 'https://accounts.google.com/o/oauth2/revoke';
8
+ const OAUTH2_TOKEN_ENDPOINT = 'https://accounts.google.com/o/oauth2/token';
9
+ const OAUTH2_AUTH_ENDPOINT = 'https://accounts.google.com/o/oauth2/auth';
10
+ const OAUTH2_FEDERATED_SIGNON_CERTS_ENDPOINT = 'https://www.googleapis.com/oauth2/v1/certs';
11
+ const GA_ACCOUNT_SUMMARIES_ENDPOINT = 'https://www.googleapis.com/analytics/v3/management/accountSummaries';
12
+ const GA_DATA_ENDPOINT = 'https://analyticsreporting.googleapis.com/v4/reports:batchGet';
13
+ const OAUTH2_CALLBACK_URI = 'urn:ietf:wg:oauth:2.0:oob';
14
+
15
+ const USE_CACHE = true;
16
+
17
+ private $disable_cache = false;
18
+
19
+ /**
20
+ * Pre-defined API credentials.
21
+ *
22
+ * @var array
23
+ */
24
+ private $config = array(
25
+ 'access_type' => 'offline',
26
+ 'application_name' => 'Google Analytics',
27
+ 'client_id' => '207216681371-433ldmujuv4l0743c1j7g8sci57cb51r.apps.googleusercontent.com',
28
+ 'client_secret' => 'y0B-K-ODB1KZOam50aMEDhyc',
29
+ 'scopes' => array( 'https://www.googleapis.com/auth/analytics.readonly' ),
30
+ 'approval_prompt' => 'force'
31
+ );
32
+
33
+ /**
34
+ * Keeps Access Token information.
35
+ *
36
+ * @var array
37
+ */
38
+ private $token;
39
+
40
+ private function __construct() {
41
+ }
42
+
43
+ /**
44
+ * Returns API client instance.
45
+ *
46
+ * @return Ga_Lib_Api_Client|null
47
+ */
48
+ public static function get_instance() {
49
+ if ( self::$instance === null ) {
50
+ self::$instance = new Ga_Lib_Google_Api_Client();
51
+ }
52
+
53
+ return self::$instance;
54
+ }
55
+
56
+ public function set_disable_cache($value) {
57
+ $this->disable_cache = $value;
58
+ }
59
+
60
+ function call_api_method( $callback, $args ) {
61
+ $callback = array( get_class( $this ), $callback );
62
+ if ( is_callable( $callback ) ) {
63
+ try {
64
+ if ( ! empty( $args ) ) {
65
+ if ( is_array( $args ) ) {
66
+ return call_user_func_array( $callback, $args );
67
+ } else {
68
+ return call_user_func_array( $callback, array( $args ) );
69
+ }
70
+ } else {
71
+ return call_user_func( $callback );
72
+ }
73
+
74
+ } catch ( Ga_Lib_Api_Request_Exception $e ) {
75
+ throw new Ga_Lib_Google_Api_Client_Exception( $e->getMessage() );
76
+ }
77
+ } else {
78
+ throw new Ga_Lib_Google_Api_Client_Exception( '[' . get_class( $this ) . ']Unknown method: ' . print_r( $callback,
79
+ true ) );
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Sets access token.
85
+ *
86
+ * @param $token
87
+ */
88
+ public function set_access_token( $token ) {
89
+ $this->token = $token;
90
+ }
91
+
92
+ /**
93
+ * Returns Google Oauth2 redirect URL.
94
+ *
95
+ * @return string
96
+ */
97
+ private function get_redirect_uri() {
98
+ return self::OAUTH2_CALLBACK_URI;
99
+ }
100
+
101
+ /**
102
+ * Creates Google Oauth2 authorization URL.
103
+ *
104
+ * @return string
105
+ */
106
+ public function create_auth_url() {
107
+ $params = array(
108
+ 'response_type' => 'code',
109
+ 'redirect_uri' => $this->get_redirect_uri(),
110
+ 'client_id' => urlencode( $this->config['client_id'] ),
111
+ 'scope' => implode( " ", $this->config['scopes'] ),
112
+ 'access_type' => urlencode( $this->config['access_type'] ),
113
+ 'approval_prompt' => urlencode( $this->config['approval_prompt'] )
114
+ );
115
+
116
+ return self::OAUTH2_AUTH_ENDPOINT . "?" . http_build_query( $params );
117
+ }
118
+
119
+ /**
120
+ * Sends request for Access Token during Oauth2 process.
121
+ *
122
+ * @param $access_code
123
+ *
124
+ * @return Ga_Lib_Api_Response Returns response object
125
+ */
126
+ private function ga_auth_get_access_token( $access_code ) {
127
+ $request = array(
128
+ 'code' => $access_code,
129
+ 'grant_type' => 'authorization_code',
130
+ 'redirect_uri' => $this->get_redirect_uri(),
131
+ 'client_id' => $this->config['client_id'],
132
+ 'client_secret' => $this->config['client_secret']
133
+ );
134
+ try {
135
+ $response = Ga_Lib_Api_Request::get_instance()->make_request( self::OAUTH2_TOKEN_ENDPOINT,
136
+ $request, false, true);
137
+ } catch ( Ga_Lib_Api_Request_Exception $e ) {
138
+ throw new Ga_Lib_Google_Api_Client_AuthCode_Exception( $e->getMessage() );
139
+ }
140
+
141
+ return new Ga_Lib_Api_Response( $response );
142
+ }
143
+
144
+ /**
145
+ * Sends request to refresh Access Token.
146
+ *
147
+ * @param $refresh_token
148
+ *
149
+ * @return Ga_Lib_Api_Response
150
+ */
151
+ private function ga_auth_refresh_access_token( $refresh_token ) {
152
+ $request = array(
153
+ 'refresh_token' => $refresh_token,
154
+ 'grant_type' => 'refresh_token',
155
+ 'client_id' => $this->config['client_id'],
156
+ 'client_secret' => $this->config['client_secret']
157
+ );
158
+
159
+ try {
160
+ $response = Ga_Lib_Api_Request::get_instance()->make_request( self::OAUTH2_TOKEN_ENDPOINT,
161
+ $request, false, true );
162
+ } catch (Ga_Lib_Api_Request_Exception $e) {
163
+ throw new Ga_Lib_Google_Api_Client_RefreshToken_Exception( $e->getMessage() );
164
+ }
165
+
166
+ return new Ga_Lib_Api_Response( $response );
167
+ }
168
+
169
+ /**
170
+ * Get list of the analytics accounts.
171
+ *
172
+ * @return Ga_Lib_Api_Response Returns response object
173
+ */
174
+ private function ga_api_account_summaries() {
175
+ $request = Ga_Lib_Api_Request::get_instance();
176
+ $request = $this->sign( $request );
177
+ try {
178
+ $response = $request->make_request( self::GA_ACCOUNT_SUMMARIES_ENDPOINT, null, false, true );
179
+ } catch (Ga_Lib_Api_Request_Exception $e) {
180
+ throw new Ga_Lib_Google_Api_Client_AccountSummaries_Exception( $e->getMessage() );
181
+ }
182
+
183
+ return new Ga_Lib_Api_Response( $response );
184
+ }
185
+
186
+ /**
187
+ * Sends request for Google Analytics data using given query parameters.
188
+ *
189
+ * @param $query_params
190
+ *
191
+ * @return Ga_Lib_Api_Response Returns response object
192
+ */
193
+ private function ga_api_data( $query_params ) {
194
+ $request = Ga_Lib_Api_Request::get_instance( $this->is_cache_enabled(), Ga_Helper::get_account_id() );
195
+ $request = $this->sign( $request );
196
+ $current_user = wp_get_current_user();
197
+ $quota_user_string = '';
198
+ if ( ! empty( $current_user ) ) {
199
+ $blogname = get_option( 'blogname' );
200
+ $quota_user = md5( $blogname . $current_user->user_login );
201
+ $quota_user_string = '?quotaUser=' . $quota_user;
202
+ }
203
+ try {
204
+ $response = $request->make_request( self::GA_DATA_ENDPOINT . $quota_user_string,
205
+ wp_json_encode( $query_params ), true );
206
+ } catch ( Ga_Lib_Api_Request_Exception $e ) {
207
+ throw new Ga_Lib_Google_Api_Client_Data_Exception( $e->getMessage() );
208
+ }
209
+
210
+ return new Ga_Lib_Api_Response( $response );
211
+ }
212
+
213
+ /**
214
+ * Sign request with Access Token.
215
+ * Adds Access Token to the request's headers.
216
+ *
217
+ * @param Ga_Lib_Api_Request $request
218
+ *
219
+ * @return Ga_Lib_Api_Request Returns response object
220
+ * @throws Ga_Lib_Api_Client_Exception
221
+ */
222
+ private function sign( Ga_Lib_Api_Request $request ) {
223
+ if ( empty( $this->token ) ) {
224
+ throw new Ga_Lib_Api_Client_Exception( 'Access Token is not available. Please reauthenticate' );
225
+ }
226
+
227
+ // Check if the token is set to expire in the next 30 seconds
228
+ // (or has already expired).
229
+ $this->check_access_token();
230
+
231
+ // Add the OAuth2 header to the request
232
+ $request->set_request_headers( array( 'Authorization: Bearer ' . $this->token['access_token'] ) );
233
+
234
+ return $request;
235
+ }
236
+
237
+ /**
238
+ * Refresh and save refreshed Access Token.
239
+ *
240
+ * @param $refresh_token
241
+ */
242
+ public function refresh_access_token( $refresh_token ) {
243
+ // Request for a new Access Token
244
+ $response = $this->call_api_method( 'ga_auth_refresh_access_token', array( $refresh_token ) );
245
+
246
+ Ga_Admin::save_access_token( $response, $refresh_token );
247
+
248
+ // Set new access token
249
+ $token = Ga_Helper::get_option( Ga_Admin::GA_OAUTH_AUTH_TOKEN_OPTION_NAME );
250
+ $this->set_access_token( json_decode( $token, true ) );
251
+ }
252
+
253
+ /**
254
+ * Checks if Access Token is valid.
255
+ *
256
+ * @return bool
257
+ */
258
+ public function is_authorized() {
259
+ if ( ! empty( $this->token ) ) {
260
+ try {
261
+ $this->check_access_token();
262
+ } catch ( Ga_Lib_Api_Client_Exception $e ) {
263
+ $this->add_error( $e );
264
+ } catch ( Exception $e ) {
265
+ $this->add_error( $e );
266
+ }
267
+ }
268
+
269
+ return ! empty( $this->token ) && ! $this->is_access_token_expired();
270
+ }
271
+
272
+ /**
273
+ * Returns if the access_token is expired.
274
+ * @return bool Returns True if the access_token is expired.
275
+ */
276
+ public function is_access_token_expired() {
277
+ if ( null == $this->token ) {
278
+ return true;
279
+ }
280
+ if ( ! empty( $this->token['error'] ) ) {
281
+ return true;
282
+ }
283
+ // Check if the token is expired in the next 30 seconds.
284
+ $expired = ( $this->token['created'] + ( $this->token['expires_in'] - 30 ) ) < time();
285
+
286
+ return $expired;
287
+ }
288
+
289
+ private function check_access_token() {
290
+ if ( $this->is_access_token_expired() ) {
291
+ if ( empty( $this->token['refresh_token'] ) ) {
292
+ throw new Ga_Lib_Api_Client_Exception( _( 'Refresh token is not available. Please re-authenticate.' ) );
293
+ } else {
294
+ $this->refresh_access_token( $this->token['refresh_token'] );
295
+ }
296
+ }
297
+ }
298
+
299
+ /**
300
+ * @return bool
301
+ */
302
+ public function is_cache_enabled() {
303
+ return self::USE_CACHE && ! $this->disable_cache;
304
+ }
305
+
306
+ }
307
+
308
+ class Ga_Lib_Google_Api_Client_Exception extends Ga_Lib_Api_Client_Exception {
309
+
310
+ private $google_error_response = null;
311
+
312
+ function __construct( $msg ) {
313
+ $this->set_google_error_response( $msg );
314
+ $data = $this->get_error_response_data( $msg );
315
+ parent::__construct( $data['error']['message'], $data['error']['code'] );
316
+ }
317
+
318
+ /**
319
+ * Sets google JSON response.
320
+ * Response structure:
321
+ * {
322
+ *"error": {
323
+ *"code": 403,
324
+ *"message": "User does not have sufficient permissions for this profile.",
325
+ *"status": "PERMISSION_DENIED",
326
+ *"details": [
327
+ *{
328
+ *"@type": "type.googleapis.com/google.rpc.DebugInfo",
329
+ *"detail": "[ORIGINAL ERROR] generic::permission_denied: User does not have sufficient permissions for this profile.
330
+ * [google.rpc.error_details_ext] { message: \"User does not have sufficient permissions for this profile.\" }"
331
+ *}
332
+ *]
333
+ *}
334
+ *}
335
+ */
336
+ public function set_google_error_response( $response ) {
337
+ $this->google_error_response = $response;
338
+ }
339
+
340
+ public function get_google_error_response() {
341
+ return $this->google_error_response;
342
+ }
343
+
344
+ /**
345
+ * Decodes JSON response
346
+ *
347
+ * @param $response
348
+ *
349
+ * @return array
350
+ */
351
+ protected function get_error_response_data( $response ) {
352
+ $data = json_decode( $response, true );
353
+ if ( ! empty( $data['error'] ) && ! empty( $data['error']['message'] ) && ! empty( $data['error']['code'] ) ) {
354
+ return $data;
355
+ } else {
356
+ return array(
357
+ 'error' => array(
358
+ 'message' => _( 'Google Reporting API - unknown error.' ),
359
+ 'code' => 500
360
+ )
361
+ );
362
+ }
363
+ }
364
+
365
+ }
366
+
367
+ class Ga_Lib_Google_Api_Client_AuthCode_Exception extends Ga_Lib_Google_Api_Client_Exception {
368
+ function __construct( $msg ) {
369
+ parent::__construct( $msg );
370
+ }
371
+
372
+ protected function get_error_response_data( $response ) {
373
+ $data = json_decode( $response, true );
374
+ if ( ! empty( $data['error'] ) && ! empty( $data['error_description'] ) ) {
375
+ return array(
376
+ 'error' => array(
377
+ 'message' => '[' . $data['error'] . ']' . $data['error_description'],
378
+ 'code' => 500
379
+ )
380
+ );
381
+ } else {
382
+ return array(
383
+ 'error' => array(
384
+ 'message' => 'Google API - uknown error.',
385
+ 'code' => 500
386
+ )
387
+ );
388
+ }
389
+ }
390
+ }
391
+
392
+ class Ga_Lib_Google_Api_Client_Data_Exception extends Ga_Lib_Google_Api_Client_Exception {
393
+ function __construct( $msg ) {
394
+ parent::__construct( $msg );
395
+ }
396
+ }
397
+
398
+ class Ga_Lib_Google_Api_Client_RefreshToken_Exception extends Ga_Lib_Google_Api_Client_Exception {
399
+ function __construct( $msg ) {
400
+ parent::__construct( $msg );
401
+ }
402
+ }
403
+
404
+ class Ga_Lib_Google_Api_Client_AccountSummaries_Exception extends Ga_Lib_Google_Api_Client_Exception {
405
+ function __construct( $msg ) {
406
+ parent::__construct( $msg );
407
+ }
408
+ }
lib/Ga_Lib_Sharethis_Api_Client.php ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Ga_Lib_Sharethis_Api_Client extends Ga_Lib_Api_Client {
4
+
5
+ static $instance = null;
6
+
7
+ const GA_SHARETHIS_ENDPOINT = 'platform-api.sharethis.com/v1.0/property';
8
+
9
+ const USE_CACHE = false;
10
+
11
+ private function __construct() {}
12
+
13
+ /**
14
+ * Returns API client instance.
15
+ *
16
+ * @return Ga_Lib_Api_Client|null
17
+ */
18
+ public static function get_instance() {
19
+ if ( self::$instance === null ) {
20
+ self::$instance = new Ga_Lib_Sharethis_Api_Client();
21
+ }
22
+
23
+ return self::$instance;
24
+ }
25
+
26
+ function call_api_method( $callback, $args ) {
27
+ $callback = array( get_class( $this ), $callback );
28
+ if ( is_callable( $callback ) ) {
29
+ try {
30
+ if ( !empty( $args ) ) {
31
+ if ( is_array( $args ) ) {
32
+ return call_user_func_array( $callback, $args );
33
+ } else {
34
+ return call_user_func_array( $callback, array( $args ) );
35
+ }
36
+ } else {
37
+ return call_user_func( $callback );
38
+ }
39
+ } catch ( Ga_Lib_Api_Request_Exception $e ) {
40
+ throw new Ga_Lib_Sharethis_Api_Client_Exception( $e->getMessage() );
41
+ }
42
+ } else {
43
+ throw new Ga_Lib_Sharethis_Api_Client_Exception( wp_json_encode( array( 'error' => '[' . get_class( $this ) . ']Unknown method: ' . $callback ) ) );
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Sends request for Sharethis api
49
+ *
50
+ * @param $query_params
51
+ *
52
+ * @return Ga_Lib_Api_Response Returns response object
53
+ */
54
+ private function ga_api_create_sharethis_property( $query_params ) {
55
+ $request = Ga_Lib_Api_Request::get_instance(self::USE_CACHE);
56
+ try {
57
+ $response = $request->make_request( $this->add_protocol( self::GA_SHARETHIS_ENDPOINT ), wp_json_encode( $query_params ), true );
58
+ } catch ( Ga_Lib_Api_Request_Exception $e ) {
59
+ throw new Ga_Lib_Sharethis_Api_Client_InvalidDomain_Exception( $e->getMessage() );
60
+ }
61
+
62
+ return new Ga_Lib_Api_Response( $response );
63
+ }
64
+
65
+ private function ga_api_sharethis_installation_verification( $query_params ) {
66
+ $request = Ga_Lib_Api_Request::get_instance(self::USE_CACHE);
67
+ try {
68
+ $response = $request->make_request( 'https://' . self::GA_SHARETHIS_ENDPOINT . '/verify', wp_json_encode( $query_params ), true );
69
+ } catch ( Ga_Lib_Api_Request_Exception $e ) {
70
+ throw new Ga_Lib_Sharethis_Api_Client_Verify_Exception( $e->getMessage() );
71
+ }
72
+
73
+ return new Ga_Lib_Api_Response( $response );
74
+ }
75
+
76
+ private function ga_api_sharethis_get_trending_alerts( $query_params ) {
77
+ $url = $this->add_protocol( add_query_arg( $query_params, self::GA_SHARETHIS_ENDPOINT . '/notifications' ) );
78
+ $request = Ga_Lib_Api_Request::get_instance(self::USE_CACHE);
79
+ try {
80
+ $response = $request->make_request( $url, null, true );
81
+ } catch ( Ga_Lib_Api_Request_Exception $e ) {
82
+ throw new Ga_Lib_Sharethis_Api_Client_Alerts_Exception( $e->getMessage() );
83
+ }
84
+
85
+ return new Ga_Lib_Api_Response( $response );
86
+ }
87
+
88
+ private function ga_api_sharethis_user_invite( $query_params ) {
89
+ $request = Ga_Lib_Api_Request::get_instance(self::USE_CACHE);
90
+ try {
91
+ $response = $request->make_request( 'https://' . self::GA_SHARETHIS_ENDPOINT . '/user/join', wp_json_encode( $query_params ), true );
92
+ } catch ( Ga_Lib_Api_Request_Exception $e ) {
93
+ throw new Ga_Lib_Sharethis_Api_Client_Invite_Exception( $e->getMessage() );
94
+ }
95
+
96
+ return new Ga_Lib_Api_Response( $response );
97
+ }
98
+
99
+ private function add_protocol( $url ) {
100
+ return ( is_ssl() ) ? 'https://' . $url : 'http://' . $url;
101
+ }
102
+
103
+ }
104
+
105
+ class Ga_Lib_Sharethis_Api_Client_Exception extends Ga_Lib_Api_Client_Exception {
106
+
107
+ function __construct( $msg ) {
108
+ $data = json_decode( $msg, true );
109
+ parent::__construct( !empty( $data[ 'error' ] ) ? $data[ 'error' ] : $msg );
110
+ }
111
+
112
+ }
113
+
114
+ class Ga_Lib_Sharethis_Api_Client_InvalidDomain_Exception extends Ga_Lib_Sharethis_Api_Client_Exception {
115
+
116
+ function __construct( $msg ) {
117
+ parent::__construct( $msg );
118
+ }
119
+
120
+ }
121
+
122
+ class Ga_Lib_Sharethis_Api_Client_Invite_Exception extends Ga_Lib_Sharethis_Api_Client_Exception {
123
+
124
+ function __construct( $msg ) {
125
+ parent::__construct( $msg );
126
+ }
127
+
128
+ }
129
+
130
+ class Ga_Lib_Sharethis_Api_Client_Alerts_Exception extends Ga_Lib_Sharethis_Api_Client_Exception {
131
+
132
+ function __construct( $msg ) {
133
+ parent::__construct( $msg );
134
+ }
135
+
136
+ }
137
+
138
+ class Ga_Lib_Sharethis_Api_Client_Verify_Exception extends Ga_Lib_Sharethis_Api_Client_Exception {
139
+
140
+ function __construct( $msg ) {
141
+ parent::__construct( $msg );
142
+ }
143
+
144
+ }
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: ShareThis
3
  Tags: analytics, dashboard, google, google analytics, google analytics plugin, javascript, marketing, pageviews, statistics, stats, tracking, visits, web stats, widget, analytics dashboard, google analytics dashboard, google analytics widget, google analytics dashboard
4
  Requires at least: 3.8
5
- Tested up to: 4.7.1
6
- Stable tag: 2.0.5
7
 
8
  Use Google Analytics on your Wordpress site without touching any code, and view visitor reports right in your Wordpress admin dashboard!
9
 
@@ -11,18 +11,20 @@ Use Google Analytics on your Wordpress site without touching any code, and view
11
 
12
  Google Analytics plugin from ShareThis is the best way to add GA tracking code to your website without modifying any files. Just log in with Google right from your WP admin dashboard and choose which website you want to link. Then you can disable GA tracking of specific users, so that when you are browsing your own site it won't affect your analytics.
13
 
14
- Also, you will be able to see Google Analytics reports in the same interface you already us every day to write and manage your posts - in your Wordpress dashboard. Now you can stay informed on how your website is doing without having to log into a separate tool.
15
 
16
- But wait, there's more! All feature of the Google Analytics plugin are free, with no subscriptions fees or add-ons!
17
 
18
- **Features:**
19
 
 
20
  * Simple setup - Adds latest version of Google Analytics javascript to every page
21
  * Account linking - no need to copy and paste any code or know your GA ID, just log in with Google, select the required website and it will automatically include the appropriate code
22
  * Visitor trends - Shows a summary dashboard with page views, users, pages per session and bounce rate for the past 7 days as compared to the previous 7 days
23
  * Traffic sources - Shows top 5 traffic sources so you know where your visitors are coming from
24
- * Only track real visitors - Allows you to disable tracking for Admins, Editors, Authors, Contributors, and/or
25
- * Subscribers so your analytics represent real visitors
 
26
  * Mobile - Fully optimized for mobile, so you can view your dashboards on any device
27
  * More updates coming - Continually updated and supported by a team of top Wordpress developers
28
 
@@ -30,17 +32,32 @@ If you don't have a Google Analytics account, you can sign up for free here: htt
30
 
31
  By downloading and installing this plugin you are agreeing to the <a href="http://www.sharethis.com/privacy/" target="_blank">Privacy Policy</a> and <a href="http://www.sharethis.com/publisher-terms-of-use/" target="_blank">Terms of Service</a>.
32
 
 
 
 
33
  == Installation ==
34
 
35
  1. Install Google Analytics either via WordPress.org plugin repository or directly by uploading the files to your server
36
  2. Activate the plugin through the Plugins menu in your WordPress dashboard
37
- 3. Navigate to the Plugin settings in the WordPress sidebar
38
  4. Authenticate via Google, copy and paste the access code and choose your property from the dropdown. You can also add the web property ID from Google Analytics manually but dashboards won't show up in this case.
 
39
 
40
  == Frequently Asked Questions ==
 
 
 
 
 
 
 
 
41
 
42
- = How I can get support? =
43
- We have a Plugin support forum here (https://googleanalytics.zendesk.com/hc/en-us) where you can always message our team if you have any questions.
 
 
 
44
 
45
  == Screenshots ==
46
 
@@ -49,16 +66,22 @@ We have a Plugin support forum here (https://googleanalytics.zendesk.com/hc/en-u
49
  3. Directly authenticate Google Analytics, and exclude sets of logged in users
50
  4. Just click to authenticate, then copy the API key and add it to the plugin
51
  5. View different time ranges and key metrics in the Wordpress Google Analytics widget
 
52
 
53
  == Changelog ==
54
 
 
 
 
 
 
 
55
  = 2.0.5 =
56
- * Better compatability with the Google API quotas
57
- * Undefined variable fix, thanks to @charlesstpierre
58
 
59
  = 2.0.4 =
60
- * Replaced Bootstrap, should fix most of the issues with Google Sign in
61
- * Fixed occasional black screen on GA sign
62
 
63
  = 2.0.3 =
64
  * Reliability improvements for Google Analytics access
2
  Contributors: ShareThis
3
  Tags: analytics, dashboard, google, google analytics, google analytics plugin, javascript, marketing, pageviews, statistics, stats, tracking, visits, web stats, widget, analytics dashboard, google analytics dashboard, google analytics widget, google analytics dashboard
4
  Requires at least: 3.8
5
+ Tested up to: 4.7.2
6
+ Stable tag: 2.1
7
 
8
  Use Google Analytics on your Wordpress site without touching any code, and view visitor reports right in your Wordpress admin dashboard!
9
 
11
 
12
  Google Analytics plugin from ShareThis is the best way to add GA tracking code to your website without modifying any files. Just log in with Google right from your WP admin dashboard and choose which website you want to link. Then you can disable GA tracking of specific users, so that when you are browsing your own site it won't affect your analytics.
13
 
14
+ Also, you will be able to see Google Analytics reports in the same interface you already use every day to write and manage your posts - in your WordPress dashboard. Now you can stay informed on how your website is doing without having to log into a separate tool.
15
 
16
+ This Google Analytics plugin has a unique feature called Trending Content. It learns about your traffic patterns and shows you a list of content that is performing significantly better than average, so that you know what resonates with your audience the most. You can even sign up to receive alerts via email or Slack when content is taking off!
17
 
18
+ One more thing - unlike other plugins, Google Analytics for WordPress has no monthly fees, and no paid upgrades. All the features are totally free.
19
 
20
+ = Features: =
21
  * Simple setup - Adds latest version of Google Analytics javascript to every page
22
  * Account linking - no need to copy and paste any code or know your GA ID, just log in with Google, select the required website and it will automatically include the appropriate code
23
  * Visitor trends - Shows a summary dashboard with page views, users, pages per session and bounce rate for the past 7 days as compared to the previous 7 days
24
  * Traffic sources - Shows top 5 traffic sources so you know where your visitors are coming from
25
+ * Trending Content - Shows a history of content that is performing better than average, so at any given time you know what content resonates with your audience the most
26
+ * Alerts - Sign up for alerts via email or Slack when your content is taking off
27
+ * Only track real visitors - Allows you to disable tracking for any role like Admins, or Editors so your analytics represent real visitors
28
  * Mobile - Fully optimized for mobile, so you can view your dashboards on any device
29
  * More updates coming - Continually updated and supported by a team of top Wordpress developers
30
 
32
 
33
  By downloading and installing this plugin you are agreeing to the <a href="http://www.sharethis.com/privacy/" target="_blank">Privacy Policy</a> and <a href="http://www.sharethis.com/publisher-terms-of-use/" target="_blank">Terms of Service</a>.
34
 
35
+ = Support =
36
+ If you have any questions please let us know directly at support@googleanalytics.zendesk.com or create a new topic within our support portal here: (https://googleanalytics.zendesk.com/hc/en-us/community/posts/new)
37
+
38
  == Installation ==
39
 
40
  1. Install Google Analytics either via WordPress.org plugin repository or directly by uploading the files to your server
41
  2. Activate the plugin through the Plugins menu in your WordPress dashboard
42
+ 3. Navigate to Google Analytics in the WordPress sidebar
43
  4. Authenticate via Google, copy and paste the access code and choose your property from the dropdown. You can also add the web property ID from Google Analytics manually but dashboards won't show up in this case.
44
+ 5. When any of your content takes off you will see the URLs inside the Trending Content section
45
 
46
  == Frequently Asked Questions ==
47
+ = Do I need to touch any code to add Google Analytics? =
48
+ Nope, just sign in with google, choose your website, and our plugin will automatically add Google analytics code to all pages.
49
+
50
+ = How do I make sure Google Analytics is properly installed on all pages? =
51
+ If you signed it with google and selected your website (or manually added the property ID) the Google Analytics javascript will be added to all pages. To check what UA code it is adding, just open any page of your website in Chrome, right click to select Inspect, navigate to Network tab, reload the page and search for googleanalytics, you will see the google code with your UA ID. <a href=”https://cl.ly/1q3o2q26261V/[e5b08a5ae1c09684a56ba14c36e6fa5c]_Screen%2520Shot%25202017-02-06%2520at%25201.57.34%2520PM.png” title=”Google Analytics code on the page example”>See example here.</a>
52
+
53
+ = I see broken formatting inside the plugin, for example some buttons are not aligned? =
54
+ This is likely caused by AdBlocker that is blocking anything related to "google analytics". Please disable AdBlocker for your own website or add it to exceptions if you are using Opera.
55
 
56
+ = How does that cool "Trending Content" feature work? =
57
+ It learns about your traffic patterns to spot "spikes" of visitors and then sends an alert. If your website doesn't have good amount of visitors you might not see any Trending Content Alerts because the algorithm needs more data to see "trends".
58
+
59
+ = I have other questions, where I can get support or provide feedback? =
60
+ If you have any questions please let us know directly at support@googleanalytics.zendesk.com or create a new topic within our support portal here: (https://googleanalytics.zendesk.com/hc/en-us/community/posts/new) We are always happy to help.
61
 
62
  == Screenshots ==
63
 
66
  3. Directly authenticate Google Analytics, and exclude sets of logged in users
67
  4. Just click to authenticate, then copy the API key and add it to the plugin
68
  5. View different time ranges and key metrics in the Wordpress Google Analytics widget
69
+ 6. Trending Content shows a list of alerts, article URLs, pageviews and time notified
70
 
71
  == Changelog ==
72
 
73
+ = 2.1 =
74
+ * NEW: Trending Content - trending content shows you a list of content that is performing better than average
75
+ * NEW: Alerts - option to sign up for alerts via email or Slack when your content is taking off
76
+ * Additional caching to always show Google Analytics dashboards
77
+ * User interface improvements
78
+
79
  = 2.0.5 =
80
+ * Better compatibility with the Google API quotas
81
+ * Undefined variable fix, thanks to charlesstpierre
82
 
83
  = 2.0.4 =
84
+ * Replaced Bootstrap with own scripts
 
85
 
86
  = 2.0.3 =
87
  * Reliability improvements for Google Analytics access
screenshot-6.png ADDED
Binary file
tools/Ga_Cache.php ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Handles request caching.
5
+ *
6
+ * Created by PhpStorm.
7
+ * User: mdn
8
+ * Date: 2017-01-27
9
+ * Time: 10:31
10
+ */
11
+ class Ga_Cache {
12
+
13
+ /**
14
+ * Time until expiration in seconds
15
+ */
16
+ const GA_DATA_EXPIRATION_TIME = 86400;// 60 * 60 * 24 = 86400; // 24h
17
+
18
+ const GA_TRANSIENT_PREFIX = 'googleanalytics_cache_';
19
+
20
+ const GA_LAST_CACHE_OPTION_NAME = 'googleanalytics_cache_last_cache_time';
21
+
22
+ const GA_LAST_TIME_ATTEMPT_OPTION_NAME = 'googleanalytics_cache_last_time_attempt';
23
+
24
+ const GA_BUFFER_CACHE_OPTION_NAME = 'googleanalytics_cache_buffer';
25
+
26
+ const GA_WAIT_AFTER_ERROR_TIME = 300; // 60 * 5 = 5 min
27
+
28
+ public static function add_cache_options() {
29
+ add_option( self::GA_LAST_CACHE_OPTION_NAME );
30
+ add_option( self::GA_BUFFER_CACHE_OPTION_NAME );
31
+ add_option( self::GA_LAST_TIME_ATTEMPT_OPTION_NAME );
32
+ }
33
+
34
+ public static function delete_cache_options() {
35
+ delete_option( self::GA_LAST_CACHE_OPTION_NAME );
36
+ delete_option( self::GA_BUFFER_CACHE_OPTION_NAME );
37
+ delete_option( self::GA_LAST_TIME_ATTEMPT_OPTION_NAME );
38
+ }
39
+
40
+ /**
41
+ * Generates transient name.
42
+ *
43
+ * @param $rest_url
44
+ * @param $query_params
45
+ * @param string $apendix
46
+ *
47
+ * @return string
48
+ */
49
+ public static function get_transient_name( $rest_url, $query_params, $apendix = '' ) {
50
+
51
+ if (is_array($query_params)) {
52
+ $query_params = wp_json_encode($query_params);
53
+ }
54
+
55
+ $name = md5( $rest_url . $query_params );
56
+
57
+ return self::GA_TRANSIENT_PREFIX . $name . '_' . $apendix;
58
+ }
59
+
60
+ /**
61
+ * Gets cached data.
62
+ *
63
+ * @param $name
64
+ *
65
+ * @return bool|mixed
66
+ */
67
+ public static function get_cached_result( $name ) {
68
+
69
+ $data = get_option( self::GA_BUFFER_CACHE_OPTION_NAME );
70
+
71
+ // Check if cache exists
72
+ if ( ! empty( $data[ $name ] ) ) { // Cache exists
73
+ return $data[ $name ];
74
+ } else {
75
+ return false;
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Sets ne cache value.
81
+ *
82
+ * @param $name
83
+ * @param $result
84
+ */
85
+ public static function set_cache( $name, $result ) {
86
+ if ( ! empty( $result ) ) {
87
+ self::set_last_cache_time( $name );
88
+ self::set_cache_buffer( $name, $result );
89
+ self::delete_last_time_attempt();
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Updates the time the response was cached.
95
+ *
96
+ * @param $name
97
+ */
98
+ public static function set_last_cache_time( $name ) {
99
+ $data = get_option( self::GA_LAST_CACHE_OPTION_NAME );
100
+
101
+ if ( empty( $data ) ) {
102
+ $data = array();
103
+ $data[ $name ] = time();
104
+ } else {
105
+ $data = array_merge( $data, array( $name => time() ) );
106
+ }
107
+
108
+ update_option( self::GA_LAST_CACHE_OPTION_NAME, $data );
109
+ }
110
+
111
+ /**
112
+ * Sets or update data cache.
113
+ *
114
+ * @param $name
115
+ * @param $result
116
+ */
117
+ public static function set_cache_buffer( $name, $result ) {
118
+ $data = get_option( self::GA_BUFFER_CACHE_OPTION_NAME );
119
+
120
+ if ( empty( $data ) ) {
121
+ $data = array();
122
+ $data[ $name ] = $result;
123
+ } else {
124
+ $data = array_merge( $data, array( $name => $result ) );
125
+ }
126
+
127
+ update_option( self::GA_BUFFER_CACHE_OPTION_NAME, $data );
128
+ }
129
+
130
+ /**
131
+ * Sets last time attempt option
132
+ */
133
+ public static function set_last_time_attempt() {
134
+ update_option( self::GA_LAST_TIME_ATTEMPT_OPTION_NAME, time());
135
+ }
136
+
137
+ /**
138
+ * Deletes last time attepmt option
139
+ */
140
+ public static function delete_last_time_attempt() {
141
+ delete_option( self::GA_LAST_TIME_ATTEMPT_OPTION_NAME );
142
+ }
143
+
144
+ /**
145
+ * Checks if the next rest API request is allowed.
146
+ *
147
+ * Next api request is allowed when there was an unsuccessful attempt and data_cache is empty.
148
+ *
149
+ * @param $name
150
+ *
151
+ * @return bool
152
+ */
153
+ public static function is_next_request_allowed( $name ) {
154
+ $last_time_attempt = get_option( self::GA_LAST_TIME_ATTEMPT_OPTION_NAME );
155
+ $outdated_last_attempt_time = true;
156
+
157
+ if ( empty( $last_time_attempt ) ) {
158
+ // If there is no last_time_attempt then return true
159
+ return true;
160
+ } elseif (!empty($last_time_attempt)) {
161
+ $outdated_last_attempt_time = ( $last_time_attempt + self::GA_WAIT_AFTER_ERROR_TIME ) < time();
162
+ }
163
+
164
+ return ( ! self::get_cached_result( $name ) && $outdated_last_attempt_time );
165
+ }
166
+
167
+ /**
168
+ * Checks whether data cache is outdated.
169
+ * @param string $name
170
+ * @param string $appendix
171
+ *
172
+ * @return bool
173
+ */
174
+ public static function is_data_cache_outdated($name = '', $appendix = '') {
175
+ $last_time = get_option( self::GA_LAST_CACHE_OPTION_NAME );
176
+ $outdated = 0;
177
+ if (!empty($last_time)) {
178
+
179
+ // Validate cache for given rest name
180
+ if ( ! empty( $name ) ) {
181
+
182
+ // if appendix is set then check only that cache which concerns given appendix
183
+ if ( ! empty( $appendix ) ) {
184
+ return ( ! empty( $appendix ) && preg_match( '/' . $appendix . '/',
185
+ $name ) && ( $last_time[ $name ] + self::GA_DATA_EXPIRATION_TIME ) < time() );
186
+ } else {
187
+ return ! empty( $last_time[ $name ] ) && ( $last_time[ $name ] + self::GA_DATA_EXPIRATION_TIME ) < time();
188
+ }
189
+
190
+ } else { // Validate cache for all requests
191
+
192
+ // If any of existing caches is outdated
193
+ foreach ( $last_time as $item => $time ) {
194
+ // if appendix is set then check only entries concerns given appendix
195
+ if ( ! empty( $appendix ) ) {
196
+ if ( ! empty( $appendix ) && preg_match( '/' . $appendix . '/', $item ) && ( $time + self::GA_DATA_EXPIRATION_TIME ) < time() ) {
197
+ $outdated ++;
198
+ }
199
+ } else {
200
+ if ( ( $time + self::GA_DATA_EXPIRATION_TIME ) < time() ) {
201
+ $outdated ++;
202
+ }
203
+ }
204
+ }
205
+
206
+ return $outdated > 0;
207
+ }
208
+ }
209
+
210
+ return false;
211
+ }
212
+
213
+ }
view/ga_code.php CHANGED
@@ -1,4 +1,5 @@
1
  <script>
 
2
  (function (i, s, o, g, r, a, m) {
3
  i['GoogleAnalyticsObject'] = r;
4
  i[r] = i[r] || function () {
@@ -9,8 +10,9 @@
9
  a.async = 1;
10
  a.src = g;
11
  m.parentNode.insertBefore(a, m)
12
- })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
13
 
14
  ga('create', '<?php echo esc_attr( $data[ Ga_Admin::GA_WEB_PROPERTY_ID_OPTION_NAME ] ); ?>', 'auto');
15
  ga('send', 'pageview');
 
16
  </script>
1
  <script>
2
+ (function() {
3
  (function (i, s, o, g, r, a, m) {
4
  i['GoogleAnalyticsObject'] = r;
5
  i[r] = i[r] || function () {
10
  a.async = 1;
11
  a.src = g;
12
  m.parentNode.insertBefore(a, m)
13
+ })(window, document, 'script', 'https://google-analytics.com/analytics.js', 'ga');
14
 
15
  ga('create', '<?php echo esc_attr( $data[ Ga_Admin::GA_WEB_PROPERTY_ID_OPTION_NAME ] ); ?>', 'auto');
16
  ga('send', 'pageview');
17
+ })();
18
  </script>
view/ga_googleanalytics_loader.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <script>
2
+ jQuery(document).ready(function () {
3
+ jQuery.post('<?php echo esc_attr( $ajaxurl ); ?>', {action: 'googleanalytics_get_script'}, function(response) {
4
+ var F = new Function ( response );
5
+ return( F() );
6
+ });
7
+ });
8
+ </script>
view/ga_notice.php CHANGED
@@ -3,9 +3,7 @@
3
  <p>
4
  Google Analytics <?php echo esc_html( GOOGLEANALYTICS_VERSION ); ?> plugin <a
5
  href="http://www.sharethis.com/news/2016/12/sharethis-adds-analytics-plugin-to-suite-of-tools/"
6
- target="_blank">has joined the ShareThis family.</a> <strong>A host of new features</strong> has been
7
- added in this version, including Google Analytics dashboards and roles management, and the update requires
8
- agreeing to the <a href="http://www.sharethis.com/privacy/" target="_blank">privacy policy</a> and <a
9
  href="http://www.sharethis.com/publisher-terms-of-use/" target="_blank">terms of use</a> to enable them.
10
  <a href="<?php echo esc_url( $url ); ?>"><span class="button button-primary">I accept</span></a>
11
  </p>
3
  <p>
4
  Google Analytics <?php echo esc_html( GOOGLEANALYTICS_VERSION ); ?> plugin <a
5
  href="http://www.sharethis.com/news/2016/12/sharethis-adds-analytics-plugin-to-suite-of-tools/"
6
+ target="_blank">has joined the ShareThis family.</a> <strong>A host of new features</strong> has been added in this version, including Google Analytics dashboards, Trending Content, and Alerts. The update requires agreeing to the <a href="http://www.sharethis.com/privacy/" target="_blank">privacy policy</a> and <a
 
 
7
  href="http://www.sharethis.com/publisher-terms-of-use/" target="_blank">terms of use</a> to enable them.
8
  <a href="<?php echo esc_url( $url ); ?>"><span class="button button-primary">I accept</span></a>
9
  </p>
view/ga_wp_notice.php CHANGED
@@ -1,3 +1,9 @@
1
- <div class="notice notice-<?php echo $type; ?>">
2
- <?php echo $msg; ?>
 
 
 
 
 
 
3
  </div>
1
+ <div class="notice notice-<?php echo $type; ?> <?php echo( ! empty( $is_dismissable ) ? 'is-dismissible' : '' ); ?>">
2
+ <p><?php echo $msg; ?>
3
+ <?php if ( ! empty( $action ) ): ?>
4
+ &nbsp;
5
+ <button onclick="window.location.href='<?php echo $action['url']; ?>'"
6
+ class="button button-primary"><?php echo $action['label']; ?></button>
7
+ <?php endif; ?>
8
+ </p>
9
  </div>
view/page.php CHANGED
@@ -14,7 +14,7 @@
14
  </div>
15
  </div>
16
  <div class="ga-modal-footer">
17
- <button id="ga_btn_close" type="button" class="button"><?php _e( 'Close' ); ?></button>
18
  <button type="button" class="button-primary"
19
  id="ga_save_access_code"
20
  onclick="ga_popup.saveAccessCode( event )"><?php _e( 'Save Changes' ); ?></button>
@@ -37,21 +37,21 @@
37
  <tr valign="top">
38
  <?php if ( ! empty( $data['popup_url'] ) ): ?>
39
  <th scope="row">
40
- <label <?php echo ( ! Ga_Helper::are_terms_accepted() ) ? 'class="label-grey ga-tooltip"' : '' ?>><?php echo _e( 'Google Profile' ) ?>
41
  :
42
- <span class="ga-tooltiptext ga-tt-abs"><?php _e( 'Please accept the terms to use this feature' ); ?></span>
43
  </label>
44
  </th>
45
- <td <?php echo ( ! Ga_Helper::are_terms_accepted() ) ? 'class="ga-tooltip"' : ''; ?>>
46
  <button id="ga_authorize_with_google_button" class="button-primary"
47
- <?php if ( Ga_Helper::are_terms_accepted() ) : ?>
48
  onclick="ga_popup.authorize( event, '<?php echo esc_attr( $data['popup_url'] ); ?>' )"
49
  <?php endif; ?>
50
- <?php echo( ( esc_attr( $data[ Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME ] ) || ! Ga_Helper::are_terms_accepted() ) ? 'disabled="disabled"' : '' ); ?>
51
  ><?php _e( 'Authenticate
52
  with Google' ) ?>
53
  </button>
54
- <span class="ga-tooltiptext"><?php _e( 'Please accept the terms to use this feature' ); ?></span>
55
  <?php if ( ! empty( $data[ Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME ] ) ): ?>
56
  <div class="ga_warning">
57
  <strong><?php _e( 'Notice' ) ?></strong>:&nbsp;<?php _e( 'Please uncheck the "Manually enter Tracking ID" option to authenticate and view statistics.' ); ?>
@@ -71,22 +71,22 @@
71
 
72
  <th scope="row">
73
  <div class="checkbox">
74
- <label class="ga_checkbox_label <?php echo ( ! Ga_Helper::are_terms_accepted() ) ? 'label-grey ga-tooltip' : '' ?>"
75
  for="ga_enter_code_manually"> <input
76
- <?php if ( Ga_Helper::are_terms_accepted() ) : ?>
77
- onclick="ga_events.click( this, ga_events.codeManuallyCallback( <?php echo Ga_Helper::are_terms_accepted() ? 1 : 0; ?> ) )"
78
  <?php endif; ?>
79
  type="checkbox"
80
- <?php echo ( ! Ga_Helper::are_terms_accepted() ) ? 'disabled="disabled"' : ''; ?>
81
  name="<?php echo esc_attr( Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME ); ?>"
82
  id="ga_enter_code_manually"
83
  value="1"
84
  <?php echo( ( $data[ Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME ] || ! Ga_Helper::are_terms_accepted() ) ? 'checked="checked"' : '' ); ?>/>&nbsp;
85
  <?php _e( 'Manually enter Tracking ID' ) ?>
86
- <span class="ga-tooltiptext ga-tt-abs"><?php _e( 'Please accept the terms to use this feature' ); ?></span>
87
  </label>
88
- <?php if ( ! Ga_Helper::are_terms_accepted() ) : ?>
89
- <input id="ga_access_code" type="hidden"
90
  name="<?php echo esc_attr( Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME ); ?>"
91
  value="1"/>
92
  <?php endif; ?>
@@ -95,7 +95,7 @@
95
  <td></td>
96
  </tr>
97
  <tr valign="top"
98
- id="ga_manually_wrapper" <?php echo( ( $data[ Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME ] || ! Ga_Helper::are_terms_accepted() ) ? '' : 'style="display: none"' ); ?> >
99
 
100
  <th scope="row"><?php _e( 'Tracking ID' ) ?>:</th>
101
  <td>
@@ -112,11 +112,11 @@
112
 
113
  </tr>
114
 
115
- <tr valign="top">
116
  <th scope="row">
117
- <label <?php echo ( ! Ga_Helper::are_terms_accepted() ) ? 'class="label-grey ga-tooltip"' : '' ?>><?php _e( 'Exclude Tracking for Roles' ) ?>
118
  :
119
- <span class="ga-tooltiptext ga-tt-abs"><?php _e( 'Please accept the terms to use this feature' ); ?></span>
120
  </label>
121
  </th>
122
  <td>
@@ -128,15 +128,15 @@
128
  foreach ( $roles as $role ) {
129
  ?>
130
  <div class="checkbox">
131
- <label class="ga_checkbox_label <?php echo ( ! Ga_Helper::are_terms_accepted() ) ? 'label-grey ga-tooltip' : ''; ?>"
132
  for="checkbox_<?php echo $role['id']; ?>">
133
  <input id="checkbox_<?php echo $role['id']; ?>" type="checkbox"
134
- <?php echo ( ! Ga_Helper::are_terms_accepted() ) ? 'disabled="disabled"' : ''; ?>
135
  name="<?php echo esc_attr( Ga_Admin::GA_EXCLUDE_ROLES_OPTION_NAME . "[" . $role['id'] . "]" ); ?>"
136
  id="<?php echo esc_attr( $role['id'] ); ?>"
137
  <?php echo esc_attr( ( $role['checked'] ? 'checked="checked"' : '' ) ); ?> />&nbsp;
138
  <?php echo esc_html( $role['name'] ); ?>
139
- <span class="ga-tooltiptext"><?php _e( 'Please accept the terms to use this feature' ); ?></span>
140
  </label>
141
  </div>
142
  <?php
@@ -146,7 +146,16 @@
146
 
147
  </td>
148
  </tr>
149
-
 
 
 
 
 
 
 
 
 
150
  </table>
151
 
152
  <p class="submit">
@@ -155,4 +164,17 @@
155
  </p>
156
  </form>
157
  </div>
158
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  </div>
15
  </div>
16
  <div class="ga-modal-footer">
17
+ <button id="ga_btn_close" type="button" class="button">Close</button>
18
  <button type="button" class="button-primary"
19
  id="ga_save_access_code"
20
  onclick="ga_popup.saveAccessCode( event )"><?php _e( 'Save Changes' ); ?></button>
37
  <tr valign="top">
38
  <?php if ( ! empty( $data['popup_url'] ) ): ?>
39
  <th scope="row">
40
+ <label <?php echo ( ! Ga_Helper::are_features_enabled() ) ? 'class="label-grey ga-tooltip"' : '' ?>><?php echo _e( 'Google Profile' ) ?>
41
  :
42
+ <span class="ga-tooltiptext ga-tt-abs"><?php _e( $tooltip ); ?></span>
43
  </label>
44
  </th>
45
+ <td <?php echo ( ! Ga_Helper::are_features_enabled() ) ? 'class="ga-tooltip"' : ''; ?>>
46
  <button id="ga_authorize_with_google_button" class="button-primary"
47
+ <?php if ( Ga_Helper::are_features_enabled() ) : ?>
48
  onclick="ga_popup.authorize( event, '<?php echo esc_attr( $data['popup_url'] ); ?>' )"
49
  <?php endif; ?>
50
+ <?php echo( ( esc_attr( $data[ Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME ] ) || ! Ga_Helper::are_features_enabled() ) ? 'disabled="disabled"' : '' ); ?>
51
  ><?php _e( 'Authenticate
52
  with Google' ) ?>
53
  </button>
54
+ <span class="ga-tooltiptext"><?php _e( $tooltip ); ?></span>
55
  <?php if ( ! empty( $data[ Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME ] ) ): ?>
56
  <div class="ga_warning">
57
  <strong><?php _e( 'Notice' ) ?></strong>:&nbsp;<?php _e( 'Please uncheck the "Manually enter Tracking ID" option to authenticate and view statistics.' ); ?>
71
 
72
  <th scope="row">
73
  <div class="checkbox">
74
+ <label class="ga_checkbox_label <?php echo ( ! Ga_Helper::are_features_enabled() ) ? 'label-grey ga-tooltip' : '' ?>"
75
  for="ga_enter_code_manually"> <input
76
+ <?php if ( Ga_Helper::are_features_enabled() ) : ?>
77
+ onclick="ga_events.click( this, ga_events.codeManuallyCallback( <?php echo Ga_Helper::are_features_enabled() ? 1 : 0; ?> ) )"
78
  <?php endif; ?>
79
  type="checkbox"
80
+ <?php echo ( ! Ga_Helper::are_features_enabled() ) ? 'disabled="disabled"' : ''; ?>
81
  name="<?php echo esc_attr( Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME ); ?>"
82
  id="ga_enter_code_manually"
83
  value="1"
84
  <?php echo( ( $data[ Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME ] || ! Ga_Helper::are_terms_accepted() ) ? 'checked="checked"' : '' ); ?>/>&nbsp;
85
  <?php _e( 'Manually enter Tracking ID' ) ?>
86
+ <span class="ga-tooltiptext ga-tt-abs"><?php _e( $tooltip ); ?></span>
87
  </label>
88
+ <?php if ( ! Ga_Helper::are_features_enabled() ) : ?>
89
+ <input id="ga_enter_code_manually_hidden" type="hidden"
90
  name="<?php echo esc_attr( Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME ); ?>"
91
  value="1"/>
92
  <?php endif; ?>
95
  <td></td>
96
  </tr>
97
  <tr valign="top"
98
+ id="ga_manually_wrapper" <?php echo( ( $data[ Ga_Admin::GA_WEB_PROPERTY_ID_MANUALLY_OPTION_NAME ] || ! Ga_Helper::are_features_enabled() ) ? '' : 'style="display: none"' ); ?> >
99
 
100
  <th scope="row"><?php _e( 'Tracking ID' ) ?>:</th>
101
  <td>
112
 
113
  </tr>
114
 
115
+ <tr valign="top" id="ga_roles_wrapper">
116
  <th scope="row">
117
+ <label <?php echo ( ! Ga_Helper::are_features_enabled() ) ? 'class="label-grey ga-tooltip"' : '' ?>><?php _e( 'Exclude Tracking for Roles' ) ?>
118
  :
119
+ <span class="ga-tooltiptext ga-tt-abs"><?php _e( $tooltip ); ?></span>
120
  </label>
121
  </th>
122
  <td>
128
  foreach ( $roles as $role ) {
129
  ?>
130
  <div class="checkbox">
131
+ <label class="ga_checkbox_label <?php echo ( ! Ga_Helper::are_features_enabled() ) ? 'label-grey ga-tooltip' : ''; ?>"
132
  for="checkbox_<?php echo $role['id']; ?>">
133
  <input id="checkbox_<?php echo $role['id']; ?>" type="checkbox"
134
+ <?php echo ( ! Ga_Helper::are_features_enabled() ) ? 'disabled="disabled"' : ''; ?>
135
  name="<?php echo esc_attr( Ga_Admin::GA_EXCLUDE_ROLES_OPTION_NAME . "[" . $role['id'] . "]" ); ?>"
136
  id="<?php echo esc_attr( $role['id'] ); ?>"
137
  <?php echo esc_attr( ( $role['checked'] ? 'checked="checked"' : '' ) ); ?> />&nbsp;
138
  <?php echo esc_html( $role['name'] ); ?>
139
+ <span class="ga-tooltiptext"><?php _e( $tooltip ); ?></span>
140
  </label>
141
  </div>
142
  <?php
146
 
147
  </td>
148
  </tr>
149
+ <tr valign="top">
150
+ <th scope="row"><?php _e( 'Disable all features' ) ?>:</th>
151
+ <td>
152
+ <label class="ga-switch">
153
+ <input id="ga-disable" name="<?php echo Ga_Admin::GA_DISABLE_ALL_FEATURES; ?>"
154
+ type="checkbox">
155
+ <div id="ga-slider" class="ga-slider round"></div>
156
+ </label
157
+ </td>
158
+ </tr>
159
  </table>
160
 
161
  <p class="submit">
164
  </p>
165
  </form>
166
  </div>
167
+ <p class="ga-love-text"><?php _e( 'Experiencing a problem or have feedback for us?' ); ?> <a
168
+ href="https://googleanalytics.zendesk.com/hc/en-us"><?php _e( 'We\'d love to hear from you!' ); ?> </a>
169
+ </p>
170
+ <p class="ga-love-text"><?php _e( 'Love this plugin?' ); ?> <a
171
+ href="https://wordpress.org/support/plugin/googleanalytics/reviews/#new-post"><?php _e( ' Please help spread the word by leaving a 5-star review!' ); ?> </a>
172
+ </p>
173
+ </div>
174
+ <script type="text/javascript">
175
+ const GA_DISABLE_FEATURE_URL = '<?php echo Ga_Helper::create_url(admin_url(Ga_Helper::GA_SETTINGS_PAGE_URL), array(Ga_Controller_Core::ACTION_PARAM_NAME => 'ga_action_disable_all_features')); ?>';
176
+ const GA_ENABLE_FEATURE_URL = '<?php echo Ga_Helper::create_url(admin_url(Ga_Helper::GA_SETTINGS_PAGE_URL), array(Ga_Controller_Core::ACTION_PARAM_NAME => 'ga_action_enable_all_features')); ?>';
177
+ jQuery(document).ready(function () {
178
+ ga_switcher.init('<?php echo $data[ Ga_Admin::GA_DISABLE_ALL_FEATURES ]; ?>');
179
+ });
180
+ </script>
view/stats.php CHANGED
@@ -1,4 +1,5 @@
1
  <div class="wrap ga-wrap" id="ga-stats-container">
 
2
  <div class="ga-panel ga-panel-default">
3
  <div class="ga-panel-heading"><strong><?php _e( "Pageviews - Last 7 days vs previous 7 days" ) ?></strong></div>
4
  <div class="ga-panel-body ga-chart">
@@ -8,13 +9,14 @@
8
  </div>
9
  </div>
10
  </div>
 
11
 
 
12
  <div class="ga-panel ga-panel-default">
13
  <div class="ga-panel-heading"><strong><?php _e( "Comparison - Last 7 days vs previous 7 days" ) ?></strong>
14
  </div>
15
  <div class="ga-panel-body">
16
  <div class="ga-row">
17
- <?php if ( ! empty( $boxes ) ) : ?>
18
  <?php foreach ( $boxes as $box ) : ?>
19
  <div class="ga-box">
20
  <div class="ga-panel ga-panel-default">
@@ -27,10 +29,11 @@
27
  </div>
28
  </div>
29
  <?php endforeach; ?>
30
- <?php endif; ?>
31
  </div>
32
  </div>
33
  </div>
 
 
34
  <?php if ( ! empty( $sources ) ) : ?>
35
  <div class="ga-panel ga-panel-default">
36
  <div class="ga-panel-heading"><strong><?php _e( "Top 5 Traffic Sources for the past 7 days" ) ?></strong>
1
  <div class="wrap ga-wrap" id="ga-stats-container">
2
+ <?php if ( ! empty( $chart ) ) : ?>
3
  <div class="ga-panel ga-panel-default">
4
  <div class="ga-panel-heading"><strong><?php _e( "Pageviews - Last 7 days vs previous 7 days" ) ?></strong></div>
5
  <div class="ga-panel-body ga-chart">
9
  </div>
10
  </div>
11
  </div>
12
+ <?php endif; ?>
13
 
14
+ <?php if ( ! empty( $boxes ) ) : ?>
15
  <div class="ga-panel ga-panel-default">
16
  <div class="ga-panel-heading"><strong><?php _e( "Comparison - Last 7 days vs previous 7 days" ) ?></strong>
17
  </div>
18
  <div class="ga-panel-body">
19
  <div class="ga-row">
 
20
  <?php foreach ( $boxes as $box ) : ?>
21
  <div class="ga-box">
22
  <div class="ga-panel ga-panel-default">
29
  </div>
30
  </div>
31
  <?php endforeach; ?>
 
32
  </div>
33
  </div>
34
  </div>
35
+ <?php endif; ?>
36
+
37
  <?php if ( ! empty( $sources ) ) : ?>
38
  <div class="ga-panel ga-panel-default">
39
  <div class="ga-panel-heading"><strong><?php _e( "Top 5 Traffic Sources for the past 7 days" ) ?></strong>
view/trending.php ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wrap ga-wrap">
2
+ <h3 class="ga-trending-h3">Google Analytics</h3>
3
+ <h2 class="ga-trending-h2"><?php _e( 'Trending content' ); ?></h2>
4
+ <div class="ga_container <?php echo ( ! Ga_Helper::are_features_enabled() ) ? 'label-grey ga-tooltip' : '' ?>"
5
+ id="exTab2">
6
+ <?php if ( ! empty( $data['error_message'] ) ) : ?>
7
+ <?php echo $data['error_message']; ?>
8
+ <?php endif; ?>
9
+ <?php if ( ! empty( $data['ga_msg'] ) ) : ?>
10
+ <?php echo $data['ga_msg']; ?>
11
+ <?php endif; ?>
12
+ <span class="ga-tooltiptext ga-tooltiptext-trending"><?php _e( $tooltip ); ?></span>
13
+ <div class="ga-trending-loader">
14
+ <div class="ga-trending-loader-wrapper">
15
+ <div class="ga-loader"></div>
16
+ </div>
17
+ <div class="ga-trending-loading-text"><?php _e( 'Please wait. Trending Content Alerts are loading.' ); ?></div>
18
+ </div>
19
+ <?php if ( Ga_Helper::are_features_enabled() && empty( $errors ) ) : ?>
20
+ <?php if ( ! empty( $alerts ) && empty( $alerts->error ) ) : ?>
21
+ <div class="trending-table-container">
22
+ <table class="ga-table ga-table-trending">
23
+ <tr>
24
+ <th>
25
+ <?php _e( 'Top 5 Recent alerts' ); ?>
26
+ </th>
27
+ <th class="weight-normal">
28
+ <?php _e( 'Views' ); ?>
29
+ </th>
30
+ <th class="weight-normal trending-time">
31
+ <?php _e( 'Time Notified' ); ?>
32
+ </th>
33
+ </tr>
34
+ <?php foreach ( $alerts as $key => $alert ) : ?>
35
+ <tr>
36
+ <td>
37
+ <a class="trending-link"
38
+ href="<?php echo $alert->{"url"} ?>"><?php echo $alert->{"url"} ?></a>
39
+ </td>
40
+ <td><?php echo ( property_exists( $alert, "pageviews" ) ) ? $alert->{"pageviews"} : '0' ?></td>
41
+ <td><?php echo date( 'F jS, g:ia', strtotime( $alert->{"sent_at"} ) ) ?></td>
42
+ </tr>
43
+ <?php if ( $key >= 4 ) {
44
+ break;
45
+ } ?>
46
+ <?php endforeach; ?>
47
+ </table>
48
+ </div>
49
+ <?php elseif ( ! empty( $alerts->error ) ) : ?>
50
+ <div class="ga-alert ga-alert-danger">
51
+ <?php _e( $alerts->error ) ?>
52
+ </div>
53
+ <?php else : ?>
54
+ <div class="ga-alert ga-alert-warning">
55
+ <?php _e( 'You will see a history of trending content here once the first article takes off.' ) ?>
56
+ <a class="ga-alert-link" href="http://tiny.cc/trending/"><?php _e( 'Click here to learn more' ) ?></a>
57
+ </div>
58
+ <?php endif; ?>
59
+ <?php endif; ?>
60
+ <div>
61
+ <form method="post">
62
+ <?php wp_nonce_field(Ga_Admin_Controller::ACTION_SHARETHIS_INVITE, Ga_Admin_Controller::GA_NONCE_FIELD_NAME); ?>
63
+ <input type="hidden" name="<?php echo Ga_Controller_Core::ACTION_PARAM_NAME; ?>"
64
+ value="<?php echo Ga_Admin_Controller::ACTION_SHARETHIS_INVITE; ?>">
65
+ <table>
66
+ <tr class="ga-ta-header">
67
+ <th>
68
+ <?php _e( 'Trending alerts' ); ?>
69
+ </th>
70
+ </tr>
71
+ <tr>
72
+ <td>
73
+ <?php _e( 'Connect your site to the Social Optimization Platform and receive these alerts via slack or email.' ); ?>
74
+ </td>
75
+ </tr>
76
+ <tr>
77
+ <td><?php _e( 'Enter your email to receive an invite' ); ?> <input name="sharethis_invite_email"
78
+ type="email" value=""
79
+ <?php echo ( ! Ga_Helper::are_features_enabled() ) ? 'disabled="disabled"' : ''; ?>
80
+ placeholder="Your email address">
81
+ <button <?php echo ( ! Ga_Helper::are_features_enabled() ) ? 'disabled="disabled"' : ''; ?>
82
+ type="submit" class="button button-primary"><?php _e( 'Send' ); ?></button>
83
+ </td>
84
+ </tr>
85
+ </table>
86
+ </form>
87
+ </div>
88
+ </div>
89
+ </div>
90
+
91
+ <script type="text/javascript">
92
+ <?php if( Ga_Helper::are_features_enabled() ) : ?>
93
+ ga_trending_loader.show();
94
+ <?php endif; ?>
95
+ </script>