Google Analytics - Version 3.1.0

Version Description

  • Fix chart starting at 0.
  • Enable GA4 for public use.
Download this release

Release Info

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

Code changes from version 3.0.0 to 3.1.0

class/class-ga-admin.php CHANGED
@@ -322,10 +322,6 @@ class Ga_Admin {
322
  )
323
  );
324
 
325
- if ( Ga_Cache::is_data_cache_outdated( '', Ga_Helper::get_account_id() ) ) {
326
- self::api_client()->add_own_error( '1', __( 'Saved data is shown, it will be refreshed soon' ), 'Ga_Data_Outdated_Exception' );
327
- }
328
-
329
  self::display_api_errors();
330
  }
331
 
@@ -736,7 +732,7 @@ class Ga_Admin {
736
  * Adds GA dashboard widget only for administrators.
737
  */
738
  public static function add_dashboard_device_widget() {
739
- if ( true === Ga_Helper::is_administrator() ) {
740
  wp_add_dashboard_widget(
741
  'ga-dashboard-widget',
742
  __( 'Google Analytics Dashboard' ),
@@ -1363,8 +1359,6 @@ class Ga_Admin {
1363
  $client->setScopes(
1364
  [
1365
  'https://www.googleapis.com/auth/analytics.readonly',
1366
- 'https://www.googleapis.com/auth/analytics.edit',
1367
- 'https://www.googleapis.com/auth/analytics',
1368
  ]
1369
  );
1370
  $client->setAuthConfig(GOOGLE_APPLICATION_CREDENTIALS);
322
  )
323
  );
324
 
 
 
 
 
325
  self::display_api_errors();
326
  }
327
 
732
  * Adds GA dashboard widget only for administrators.
733
  */
734
  public static function add_dashboard_device_widget() {
735
+ if (true === Ga_Helper::is_administrator() && true === Ga_Helper::is_dashboard_page()) {
736
  wp_add_dashboard_widget(
737
  'ga-dashboard-widget',
738
  __( 'Google Analytics Dashboard' ),
1359
  $client->setScopes(
1360
  [
1361
  'https://www.googleapis.com/auth/analytics.readonly',
 
 
1362
  ]
1363
  );
1364
  $client->setAuthConfig(GOOGLE_APPLICATION_CREDENTIALS);
class/class-ga-helper.php CHANGED
@@ -14,8 +14,8 @@ class Ga_Helper {
14
  const GA_DEFAULT_WEB_ID = 'UA-0000000-0';
15
  const GA_STATISTICS_PAGE_URL = 'admin.php?page=googleanalytics';
16
  const GA_SETTINGS_PAGE_URL = 'admin.php?page=googleanalytics/settings';
17
- const DASHBOARD_PAGE_NAME = 'dashboard';
18
- const PHP_VERSION_REQUIRED = '5.2.17';
19
  const GA_WP_MODERN_VERSION = '4.1';
20
  const GA_TOOLTIP_TERMS_NOT_ACCEPTED = 'Please accept the terms to use this feature.';
21
  const GA_TOOLTIP_FEATURES_DISABLED = 'Click the Enable button at the top to start using this feature.';
14
  const GA_DEFAULT_WEB_ID = 'UA-0000000-0';
15
  const GA_STATISTICS_PAGE_URL = 'admin.php?page=googleanalytics';
16
  const GA_SETTINGS_PAGE_URL = 'admin.php?page=googleanalytics/settings';
17
+ const DASHBOARD_PAGE_NAME = 'admin.php?page=googleanalytics';
18
+ const PHP_VERSION_REQUIRED = '7.4';
19
  const GA_WP_MODERN_VERSION = '4.1';
20
  const GA_TOOLTIP_TERMS_NOT_ACCEPTED = 'Please accept the terms to use this feature.';
21
  const GA_TOOLTIP_FEATURES_DISABLED = 'Click the Enable button at the top to start using this feature.';
class/class-ga-stats.php CHANGED
@@ -15,1069 +15,1074 @@
15
  */
16
  class Ga_Stats {
17
 
18
- /**
19
- * Profile object.
20
- *
21
- * @var array Profile.
22
- */
23
- private $profile = array();
24
-
25
- /**
26
- * Primary class constructor.
27
- *
28
- * @access public
29
- * @since 7.0.0
30
- */
31
- public function __construct() {
32
- }
33
-
34
- /**
35
- * Preparing query to get Analytics data
36
- *
37
- * @param string $query Query type.
38
- * @param int $id_view The Analytics view ID from which to retrieve data.
39
- * @param string $date_range The start date for the query in the format YYYY-MM-DD or '7daysAgo'.
40
- * @param string $metric A metric expression.
41
- * @param bool $old Use old query style.
42
- *
43
- * @return array Request query
44
- */
45
- public static function get_query( $query, $id_view, $date_range = null, $metric = null, $old = false ) {
46
- if ( 'main_chart' === $query ) {
47
- return $old ? self::main_chart_query_old( $id_view, $date_range, $metric ) : self::main_chart_query(
48
- $id_view,
49
- $date_range,
50
- $metric
51
- );
52
- } elseif ( 'gender' === $query ) {
53
- return self::gender_chart_query( $id_view, $date_range, $metric );
54
- } elseif ( 'device' === $query ) {
55
- return self::device_chart_query( $id_view, $date_range, $metric );
56
- } elseif ( 'age' === $query ) {
57
- return self::age_chart_query( $id_view, $date_range, $metric );
58
- } elseif ( 'boxes' === $query ) {
59
- return self::boxes_query( $id_view );
60
- } elseif ( 'dashboard_boxes' === $query ) {
61
- return $old ? self::dashboard_boxes_query_old( $id_view, $date_range ) :
62
- self::dashboard_boxes_query( $id_view, $date_range );
63
- } elseif ( 'sources' === $query ) {
64
- return self::sources_query( $id_view, $date_range );
65
- } else {
66
- return array();
67
- }
68
- }
69
-
70
- /**
71
- * Preparing query for top traffic sources table
72
- *
73
- * @param int $id_view The Analytics view ID from which to retrieve data.
74
- * @param array $date_ranges An array representing the date ranges that will be passed to chart query.
75
- *
76
- * @return array Sources query
77
- */
78
- public static function sources_query( $id_view, $date_ranges ) {
79
- $reports_requests = array();
80
-
81
- $ts = filter_input( INPUT_GET, 'ts', FILTER_SANITIZE_STRING );
82
-
83
- if ( false === empty( $ts ) ) {
84
- $reports_requests[] = array(
85
- 'viewId' => $id_view,
86
- 'dateRanges' => $date_ranges,
87
- 'metrics' => self::set_metrics( array( 'ga:pageviews' ) ),
88
- 'includeEmptyRows' => true,
89
- 'pageSize' => 10,
90
- 'dimensions' => self::set_dimensions( 'ga:sourceMedium' ),
91
- 'orderBys' => self::set_order_bys( 'ga:pageviews', 'DESCENDING' ),
92
- );
93
- } else {
94
- $reports_requests[] = array(
95
- 'viewId' => $id_view,
96
- 'dateRanges' => $date_ranges,
97
- 'metrics' => self::set_metrics(
98
- array(
99
- 'ga:pageviews',
100
- 'ga:uniquePageviews',
101
- 'ga:timeOnPage',
102
- 'ga:bounces',
103
- 'ga:entrances',
104
- 'ga:exits',
105
- )
106
- ),
107
- 'includeEmptyRows' => true,
108
- 'pageSize' => 10,
109
- 'dimensions' => self::set_dimensions( 'ga:pagePath' ),
110
- 'orderBys' => self::set_order_bys( 'ga:pageviews', 'DESCENDING' ),
111
- );
112
- }
113
-
114
- $query = array(
115
- 'reportRequests' => $reports_requests,
116
- );
117
-
118
- return $query;
119
- }
120
-
121
- /**
122
- * Preparing query for dashboard boxes
123
- *
124
- * @param int $id_view The Analytics view ID from which to retrieve data.
125
- * @param array $date_ranges An array representing the date ranges that will be passed to chart query.
126
- *
127
- * @return array Dashboard boxes query
128
- */
129
- public static function dashboard_boxes_query( $id_view, $date_ranges ) {
130
- $reports_requests = array();
131
-
132
- $ts = filter_input( INPUT_GET, 'ts', FILTER_SANITIZE_STRING );
133
-
134
- if ( false === empty( $ts ) ) {
135
- $reports_requests[] = array(
136
- 'viewId' => $id_view,
137
- 'dateRanges' => $date_ranges,
138
- 'metrics' => self::set_metrics( array( 'ga:pageviews' ) ),
139
- 'includeEmptyRows' => true,
140
- 'pageSize' => 10,
141
- 'dimensions' => self::set_dimensions( 'ga:sourceMedium' ),
142
- 'orderBys' => self::set_order_bys( 'ga:pageviews', 'DESCENDING' ),
143
- );
144
- } else {
145
- $reports_requests[] = array(
146
- 'viewId' => $id_view,
147
- 'dateRanges' => $date_ranges,
148
- 'metrics' => self::set_metrics(
149
- array(
150
- 'ga:pageviews',
151
- 'ga:uniquePageviews',
152
- 'ga:timeOnPage',
153
- 'ga:bounces',
154
- 'ga:entrances',
155
- 'ga:exits',
156
- )
157
- ),
158
- 'includeEmptyRows' => true,
159
- 'pageSize' => 10,
160
- 'dimensions' => self::set_dimensions( 'ga:pagePath' ),
161
- 'orderBys' => self::set_order_bys( 'ga:pageviews', 'DESCENDING' ),
162
- );
163
- }
164
- $query = array(
165
- 'reportRequests' => $reports_requests,
166
- );
167
-
168
- return $query;
169
- }
170
-
171
- /**
172
- * Preparing query for dashboard boxes
173
- *
174
- * @param int $id_view The Analytics view ID from which to retrieve data.
175
- * @param string $date_range The start date for the query in the format YYYY-MM-DD or '7daysAgo'.
176
- *
177
- * @return array Dashboard boxes query
178
- * @deprecated
179
- */
180
- public static function dashboard_boxes_query_old( $id_view, $date_range ) {
181
- $reports_requests = array();
182
-
183
- $th = filter_input( INPUT_GET, 'th', FILTER_SANITIZE_STRING );
184
- $ts = filter_input( INPUT_GET, 'ts', FILTER_SANITIZE_STRING );
185
-
186
- $days_ago = false === empty( $th ) ? '30daysAgo' : '7daysAgo';
187
-
188
- if ( false === empty( $ts ) ) {
189
- $reports_requests[] = array(
190
- 'viewId' => $id_view,
191
- 'dateRanges' => self::set_date_ranges( $days_ago, 'yesterday' ),
192
- 'metrics' => self::set_metrics( array( 'ga:pageviews' ) ),
193
- 'includeEmptyRows' => true,
194
- 'pageSize' => 10,
195
- 'dimensions' => self::set_dimensions( 'ga:sourceMedium' ),
196
- 'orderBys' => self::set_order_bys( 'ga:pageviews', 'DESCENDING' ),
197
- );
198
- } else {
199
- $reports_requests[] = array(
200
- 'viewId' => $id_view,
201
- 'dateRanges' => self::set_date_ranges( $days_ago, 'yesterday' ),
202
- 'metrics' => self::set_metrics(
203
- array(
204
- 'ga:pageviews',
205
- 'ga:uniquePageviews',
206
- 'ga:timeOnPage',
207
- 'ga:bounces',
208
- 'ga:entrances',
209
- 'ga:exits',
210
- )
211
- ),
212
- 'includeEmptyRows' => true,
213
- 'pageSize' => 10,
214
- 'dimensions' => self::set_dimensions( 'ga:pagePath' ),
215
- 'orderBys' => self::set_order_bys( 'ga:pageviews', 'DESCENDING' ),
216
- );
217
- }
218
- $query = array(
219
- 'reportRequests' => $reports_requests,
220
- );
221
-
222
- return $query;
223
- }
224
-
225
- /**
226
- * Preparing query for stats boxes
227
- *
228
- * @param int $id_view The Analytics view ID from which to retrieve data.
229
- *
230
- * @return array Boxes query
231
- */
232
- public static function boxes_query( $id_view ) {
233
- $th = filter_input( INPUT_GET, 'th', FILTER_SANITIZE_STRING );
234
-
235
- $range = false === empty( $th ) ? '30daysAgo' : '7daysAgo';
236
- $range_s_prev = false === empty( $th ) ? '60daysAgo' : '14daysAgo';
237
- $range_e_prev = false === empty( $th ) ? '31daysAgo' : '8daysAgo';
238
- $reports_requests = array();
239
- $reports_requests[] = array(
240
- 'viewId' => $id_view,
241
- 'dateRanges' => self::set_date_ranges( $range, 'yesterday', $range_s_prev, $range_e_prev ),
242
- 'metrics' => self::set_metrics(
243
- array(
244
- 'ga:users',
245
- 'ga:pageviews',
246
- 'ga:pageviewsPerSession',
247
- 'ga:BounceRate',
248
- )
249
- ),
250
- 'includeEmptyRows' => true,
251
- 'dimensions' => self::set_dimensions( 'ga:date' ),
252
- );
253
- $query = array(
254
- 'reportRequests' => $reports_requests,
255
- );
256
-
257
- return $query;
258
- }
259
-
260
- /**
261
- * Preparing query for chart
262
- *
263
- * @param int $id_view The Analytics view ID from which to retrieve data.
264
- * @param array $date_ranges An array representing the date ranges that will be passed to chart query.
265
- * @param string $metric A metric expression.
266
- *
267
- * @return array Chart query
268
- */
269
- public static function main_chart_query( $id_view, $date_ranges = null, $metric = null ) {
270
- if ( true === empty( $metric ) ) {
271
- $metric = 'ga:pageviews';
272
- } else {
273
- $metric = 'ga:' . $metric;
274
- }
275
-
276
- $reports_requests = array();
277
- $reports_requests[] = array(
278
- 'viewId' => $id_view,
279
- 'dateRanges' => $date_ranges,
280
- 'metrics' => self::set_metrics( $metric ),
281
- 'includeEmptyRows' => true,
282
- 'dimensions' => self::set_dimensions( 'ga:date' ),
283
- );
284
- $query = array(
285
- 'reportRequests' => $reports_requests,
286
- );
287
-
288
- return $query;
289
- }
290
-
291
- /**
292
- * Preparing query for chart
293
- *
294
- * @param int $id_view The Analytics view ID from which to retrieve data.
295
- * @param string $date_range The start date for the query in the format YYYY-MM-DD or '7daysAgo'.
296
- * @param string $metric A metric expression.
297
- *
298
- * @return array Chart query
299
- * @deprecated
300
- */
301
- public static function main_chart_query_old( $id_view, $date_range = null, $metric = null ) {
302
- if ( empty( $date_range ) ) {
303
- $date_ranges = self::set_date_ranges( '7daysAgo', 'yesterday', '14daysAgo', '8daysAgo' );
304
- } else {
305
- $date_ranges = self::set_date_ranges( $date_range, 'yesterday', '14daysAgo', '8daysAgo' );
306
- }
307
-
308
- if ( empty( $metric ) ) {
309
- $metric = 'ga:pageviews';
310
- } else {
311
- $metric = 'ga:' . $metric;
312
- }
313
-
314
- $reports_requests = array();
315
- $reports_requests[] = array(
316
- 'viewId' => $id_view,
317
- 'dateRanges' => $date_ranges,
318
- 'metrics' => self::set_metrics( $metric ),
319
- 'includeEmptyRows' => true,
320
- 'dimensions' => self::set_dimensions( 'ga:date' ),
321
- );
322
- $query = array(
323
- 'reportRequests' => $reports_requests,
324
- );
325
-
326
- return $query;
327
- }
328
-
329
- /**
330
- * Preparing query for gender chart
331
- *
332
- * @param int $id_view The Analytics view ID from which to retrieve data.
333
- * @param array $date_ranges An array representing the date ranges that will be passed to chart query.
334
- * @param string $metric A metric expression.
335
- *
336
- * @return array Chart query
337
- */
338
- public static function gender_chart_query( $id_view, $date_ranges = null, $metric = null ) {
339
- if ( true === empty( $date_ranges ) ) {
340
- $date_ranges = self::set_date_ranges( '7daysAgo', 'yesterday', '14daysAgo', '8daysAgo' );
341
- }
342
-
343
- $reports_requests = array();
344
- $reports_requests[] = array(
345
- 'viewId' => $id_view,
346
- 'dateRanges' => $date_ranges,
347
- 'metrics' => self::set_metrics( 'ga:sessions' ),
348
- 'includeEmptyRows' => true,
349
- 'dimensions' => self::set_dimensions( 'ga:userGender' ),
350
- );
351
- $query = array(
352
- 'reportRequests' => $reports_requests,
353
- );
354
-
355
- return $query;
356
- }
357
-
358
- /**
359
- * Preparing query for device chart.
360
- *
361
- * @param int $id_view The Analytics view ID from which to retrieve data.
362
- * @param array $date_ranges An array representing the date ranges that will be passed to chart query.
363
- * @param string $metric A metric expression.
364
- *
365
- * @return array Chart query
366
- * @since 2.5.2
367
- */
368
- public static function device_chart_query( $id_view, $date_ranges = null, $metric = null ) {
369
- return array(
370
- 'reportRequests' => array(
371
- array(
372
- 'viewId' => $id_view,
373
- 'dateRanges' => $date_ranges,
374
- 'metrics' => self::set_metrics( 'ga:sessions' ),
375
- 'includeEmptyRows' => true,
376
- 'dimensions' => self::set_dimensions( 'ga:deviceCategory' ),
377
- ),
378
- ),
379
- );
380
- }
381
-
382
- /**
383
- * Preparing query for age chart
384
- *
385
- * @param int $id_view The Analytics view ID from which to retrieve data.
386
- * @param array $date_ranges An array representing the date ranges that will be passed to chart query.
387
- * @param string $metric A metric expression.
388
- *
389
- * @return array Chart query
390
- */
391
- public static function age_chart_query( $id_view, $date_ranges = null, $metric = null ) {
392
- if ( true === empty( $date_ranges ) ) {
393
- $date_ranges = self::set_date_ranges( '7daysAgo', 'yesterday', '14daysAgo', '8daysAgo' );
394
- }
395
-
396
- $reports_requests = array();
397
- $reports_requests[] = array(
398
- 'viewId' => $id_view,
399
- 'dateRanges' => $date_ranges,
400
- 'metrics' => self::set_metrics( 'ga:sessions' ),
401
- 'includeEmptyRows' => true,
402
- 'dimensions' => self::set_dimensions( 'ga:userAgeBracket' ),
403
- );
404
- $query = array(
405
- 'reportRequests' => $reports_requests,
406
- );
407
-
408
- return $query;
409
- }
410
-
411
- /**
412
- * Setting order for requests
413
- *
414
- * @param string $name The field which to sort by. The default sort order is ascending. Example: ga:browser.
415
- * @param string $sort The sorting order for the field. 'ASCENDING' or 'DESCENDING'.
416
- *
417
- * @return array OrderBys
418
- */
419
- public static function set_order_bys( $name, $sort ) {
420
- $order = array();
421
- $order[] = array(
422
- 'fieldName' => $name,
423
- 'sortOrder' => $sort,
424
- );
425
-
426
- return $order;
427
- }
428
-
429
- /**
430
- * Setting metrics for requests
431
- *
432
- * @param mixed $expression A metric expression or array of expressions.
433
- *
434
- * @return array Metrics
435
- */
436
- public static function set_metrics( $expression ) {
437
- $metrics = array();
438
- if ( is_array( $expression ) ) {
439
- foreach ( $expression as $exp ) {
440
- $metrics[] = array(
441
- 'expression' => $exp,
442
- );
443
- }
444
- } else {
445
- $metrics[] = array(
446
- 'expression' => $expression,
447
- );
448
- }
449
-
450
- return $metrics;
451
- }
452
-
453
- /**
454
- * Setting dimensions for requests
455
- *
456
- * @param string $name Name of the dimension to fetch, for example ga:browser.
457
- *
458
- * @return array Dimensions
459
- */
460
- public static function set_dimensions( $name ) {
461
- $dimensions = array();
462
- $dimensions[] = array(
463
- 'name' => $name,
464
- );
465
-
466
- return $dimensions;
467
- }
468
-
469
- /**
470
- * Setting date ranges for requests
471
- *
472
- * @param string $start_date The start date for the query in the format YYYY-MM-DD.
473
- * @param string $end_date The end date for the query in the format YYYY-MM-DD.
474
- * @param string $prev_start_date The start date (second range) for the query in the format YYYY-MM-DD.
475
- * @param string $prev_end_date The start date (second range) for the query in the format YYYY-MM-DD.
476
- *
477
- * @return array Date ranges
478
- */
479
- public static function set_date_ranges( $start_date, $end_date, $prev_start_date = '', $prev_end_date = '' ) {
480
- $date_danges = array();
481
- $date_danges[] = array(
482
- 'startDate' => $start_date,
483
- 'endDate' => $end_date,
484
- );
485
- if ( false === empty( $prev_start_date ) && false === empty( $prev_end_date ) ) {
486
- $date_danges[] = array(
487
- 'startDate' => $prev_start_date,
488
- 'endDate' => $prev_end_date,
489
- );
490
- }
491
-
492
- return $date_danges;
493
- }
494
-
495
- /**
496
- * Preparing response for data received from analytics
497
- *
498
- * @param array $data Analytics response.
499
- *
500
- * @return array Response rows
501
- */
502
- public static function prepare_response( $data ) {
503
- $data = self::get_reports_from_response( $data );
504
- self::handle_more_reports( $data );
505
- $report = self::get_single_report( $data );
506
- self::get_report_column_header( $report );
507
- $report_data = self::get_report_data( $report );
508
- self::get_totals( $report_data );
509
- self::get_row_count( $report_data );
510
- $rows = self::get_rows( $report_data );
511
-
512
- return $rows;
513
- }
514
-
515
- /**
516
- * Get dimensions from response row
517
- *
518
- * @param array $row Analytics response row.
519
- *
520
- * @return array|bool Dimensions
521
- */
522
- public static function get_dimensions( $row ) {
523
- if ( false === empty( $row['dimensions'] ) ) {
524
- return $row['dimensions'];
525
- }
526
-
527
- return false;
528
- }
529
-
530
- /**
531
- * Get metrics from response row
532
- *
533
- * @param array $row Analytics response row.
534
- *
535
- * @return array|bool Metrics
536
- */
537
- public static function get_metrics( $row ) {
538
- if ( false === empty( $row['metrics'] ) ) {
539
- return $row['metrics'];
540
- }
541
-
542
- return false;
543
- }
544
-
545
- /**
546
- * Get row from response report data
547
- *
548
- * @param array $report_data Analytics response report data.
549
- *
550
- * @return array|bool Rows
551
- */
552
- public static function get_rows( $report_data ) {
553
- if ( false === empty( $report_data['rows'] ) ) {
554
- return $report_data['rows'];
555
- }
556
-
557
- return false;
558
- }
559
-
560
- /**
561
- * Get row count from response report data
562
- *
563
- * @param array $report_data Analytics response report data.
564
- *
565
- * @return array|bool Row count
566
- */
567
- public static function get_row_count( $report_data ) {
568
- if ( false === empty( $report_data['rowCount'] ) ) {
569
- return $report_data['rowCount'];
570
- }
571
-
572
- return false;
573
- }
574
-
575
- /**
576
- * Get totals from response report data
577
- *
578
- * @param array $report_data Analytics response report data.
579
- *
580
- * @return array|bool Totals
581
- */
582
- public static function get_totals( $report_data ) {
583
- if ( false === empty( $report_data['totals'] ) ) {
584
- return $report_data['totals'];
585
- }
586
-
587
- return false;
588
- }
589
-
590
- /**
591
- * Get reports from response data
592
- *
593
- * @param array $data Analytics response data.
594
- *
595
- * @return array|bool Reports
596
- */
597
- public static function get_reports_from_response( $data ) {
598
- if ( false === empty( $data['reports'] ) ) {
599
- return $data['reports'];
600
- }
601
-
602
- return false;
603
- }
604
-
605
- /**
606
- * Show info for multiple data
607
- *
608
- * @param array $data Analytics response data.
609
- */
610
- public static function handle_more_reports( $data ) {
611
- if ( count( $data ) > 1 ) {
612
- echo 'more than one report';
613
- }
614
- }
615
-
616
- /**
617
- * Show info for multiple rows
618
- *
619
- * @param array $rows Analytics response rows.
620
- */
621
- public static function handle_more_rows( $rows ) {
622
- if ( count( $rows ) > 1 ) {
623
- echo 'more than one row';
624
- }
625
- }
626
-
627
- /**
628
- * Get single report from response data
629
- *
630
- * @param array $data Analytics response data.
631
- *
632
- * @return array|bool Report
633
- */
634
- public static function get_single_report( $data ) {
635
- if ( false === empty( $data ) ) {
636
- foreach ( $data as $report ) {
637
- if ( false === empty( $report ) ) {
638
- return $report;
639
- }
640
- }
641
- }
642
-
643
- return false;
644
- }
645
-
646
- /**
647
- * Get single row from response data rows
648
- *
649
- * @param array $rows Analytics response data rows.
650
- *
651
- * @return array|bool Row
652
- */
653
- public static function get_single_row( $rows ) {
654
- if ( false === empty( $rows ) ) {
655
- foreach ( $rows as $row ) {
656
- if ( false === empty( $row ) ) {
657
- return $row;
658
- }
659
- }
660
- }
661
-
662
- return false;
663
- }
664
-
665
- /**
666
- * Get column header from response data
667
- *
668
- * @param array $data Analytics response data.
669
- *
670
- * @return array Column header
671
- */
672
- public static function get_report_column_header( $data ) {
673
- if ( false === empty( $data['columnHeader'] ) ) {
674
- return $data['columnHeader'];
675
- }
676
-
677
- return false;
678
- }
679
-
680
- /**
681
- * Get report data from response data
682
- *
683
- * @param array $data Analytics response data.
684
- *
685
- * @return array|bool data
686
- */
687
- public static function get_report_data( $data ) {
688
- if ( false === empty( $data['data'] ) ) {
689
- return $data['data'];
690
- }
691
-
692
- return false;
693
- }
694
-
695
- /**
696
- * Get chart from response data
697
- *
698
- * @param array $response_data Analytics response data.
699
- * @param int $period_in_days Period in days (default = 7).
700
- *
701
- * @return array chart data
702
- */
703
- public static function get_chart( $response_data, $period_in_days = 7 ) {
704
- $chart_data = array();
705
- if ( false === empty( $response_data ) ) {
706
- $data = (
707
- false === empty( $response_data['reports'] )
708
- && false === empty( $response_data['reports'][0] )
709
- && false === empty( $response_data['reports'][0]['data'] )
710
- )
711
- ? $response_data['reports'][0]['data'] : array();
712
- $rows = ( false === empty( $data['rows'] ) ) ? $data['rows'] : array();
713
- if ( false === empty( $rows ) ) {
714
- foreach ( $rows as $key => $row ) {
715
- if ( $key < $period_in_days ) {
716
- $chart_data[ $key ]['previous'] = false === empty( $row['metrics'][1]['values'][0] ) ? $row['metrics'][1]['values'][0] : 0;
717
- $chart_data[ $key ]['previous-day'] = gmdate( 'M j', strtotime( $row['dimensions'][0] ) );
718
- } else {
719
- $chart_data[ $key - $period_in_days ]['day'] = gmdate( 'M j', strtotime( $row['dimensions'][0] ) );
720
- $chart_data[ $key - $period_in_days ]['current'] = false === empty( $row['metrics'][0]['values'][0] ) ? $row['metrics'][0]['values'][0] : 0;
721
- $chart_data['date'] = strtotime( $row['dimensions'][0] );
722
- }
723
- }
724
- }
725
- }
726
-
727
- return $chart_data;
728
- }
729
-
730
- /**
731
- * Get gender chart from response data
732
- *
733
- * @param array $response_data Analytics response data.
734
- *
735
- * @return array chart data
736
- */
737
- public static function get_gender_chart( $response_data ) {
738
- $chart_data = array();
739
- if ( false === empty( $response_data ) ) {
740
- $data = ( false === empty( $response_data['reports'] ) && false === empty( $response_data['reports'][0] ) && false === empty( $response_data['reports'][0]['data'] ) ) ? $response_data['reports'][0]['data'] : array();
741
- $rows = ( false === empty( $data['rows'] ) ) ? $data['rows'] : array();
742
- if ( false === empty( $rows ) ) {
743
- foreach ( $rows as $key => $row ) {
744
- $chart_data[ $row['dimensions'][0] ] = self::get_metric_value( $row['metrics'] );
745
- }
746
- }
747
- }
748
-
749
- return $chart_data;
750
- }
751
-
752
- /**
753
- * Get device chart from response data.
754
- *
755
- * @param array $response_data Analytics response data array.
756
- *
757
- * @return array Chart data array.
758
- */
759
- public static function get_device_chart( $response_data ) {
760
- $chart_data = array();
761
- if ( false === empty( $response_data ) ) {
762
- $data = ( false === empty( $response_data['reports'] ) && false === empty( $response_data['reports'][0] ) && false === empty( $response_data['reports'][0]['data'] ) ) ? $response_data['reports'][0]['data'] : array();
763
- $rows = ( false === empty( $data['rows'] ) ) ? $data['rows'] : array();
764
- if ( false === empty( $rows ) ) {
765
- foreach ( $rows as $row ) {
766
- $chart_data[ $row['dimensions'][0] ] = self::get_metric_value( $row['metrics'] );
767
- }
768
- }
769
- }
770
-
771
- return $chart_data;
772
- }
773
-
774
- /**
775
- * Get the value of metric data response.
776
- *
777
- * @param array $metrics Metrics array.
778
- *
779
- * @return mixed
780
- */
781
- private static function get_metric_value( $metrics ) {
782
- if ( is_array( $metrics ) ) {
783
- foreach ( $metrics as $metric ) {
784
- $values[] = $metric['values'][0];
785
- }
786
- }
787
-
788
- return $values[0];
789
- }
790
-
791
- /**
792
- * Get gender chart from response data
793
- *
794
- * @param array $response_data Analytics response data.
795
- *
796
- * @return array chart data
797
- */
798
- public static function get_age_chart( $response_data ) {
799
- $chart_data = array();
800
- if ( false === empty( $response_data ) ) {
801
- $data = ( false === empty( $response_data['reports'] ) && false === empty( $response_data['reports'][0] ) && false === empty( $response_data['reports'][0]['data'] ) ) ? $response_data['reports'][0]['data'] : array();
802
- $rows = ( false === empty( $data['rows'] ) ) ? $data['rows'] : array();
803
- if ( false === empty( $rows ) ) {
804
- foreach ( $rows as $key => $row ) {
805
- $chart_data[ $row['dimensions'][0] ] = self::get_metric_value( $row['metrics'] );
806
- }
807
- }
808
- }
809
-
810
- return $chart_data;
811
- }
812
-
813
- /**
814
- * Get dasboard chart from response data
815
- *
816
- * @param array $response_data Analytics response data.
817
- *
818
- * @return array dashboard chart data
819
- */
820
- public static function get_dashboard_chart( $response_data ) {
821
- $chart_data = array();
822
- if ( false === empty( $response_data ) ) {
823
- $data = (
824
- false === empty( $response_data['reports'] )
825
- && false === empty( $response_data['reports'][0] )
826
- && false === empty( $response_data['reports'][0]['data'] )
827
- ) ? $response_data['reports'][0]['data'] : array();
828
-
829
- $rows = ( false === empty( $data['rows'] ) ) ? $data['rows'] : array();
830
- if ( false === empty( $rows ) ) {
831
- foreach ( $rows as $row ) {
832
- $chart_data[] = array(
833
- 'day' => gmdate( 'M j', strtotime( $row['dimensions'][0] ) ),
834
- 'current' => false === empty( $row['metrics'][0]['values'][0] ) ? $row['metrics'][0]['values'][0] : 0,
835
- );
836
- }
837
- }
838
- }
839
-
840
- return $chart_data;
841
- }
842
-
843
- /**
844
- * Get boxes from response data
845
- *
846
- * @param array $data Analytics response data.
847
- *
848
- * @return array boxes data
849
- */
850
- public static function get_boxes( $data ) {
851
- if ( false === empty( $data ) ) {
852
- $data = self::get_reports_from_response( $data );
853
- self::handle_more_reports( $data );
854
- $report = self::get_single_report( $data );
855
- self::get_report_column_header( $report );
856
- $report_data = self::get_report_data( $report );
857
- $totals = self::get_totals( $report_data );
858
-
859
- return self::get_boxes_from_totals( $totals );
860
- }
861
- }
862
-
863
- /**
864
- * Get boxes from totals
865
- *
866
- * @param array $totals Analytics response totals.
867
- *
868
- * @return array|bool boxes data
869
- */
870
- public static function get_boxes_from_totals( $totals ) {
871
- if ( false === empty( $totals ) ) {
872
- $boxes_data = array();
873
- foreach ( $totals as $key => $total ) {
874
- if ( 0 === $key ) {
875
- $boxes_data['Users']['current'] = $total['values'][0];
876
- $boxes_data['Pageviews']['current'] = $total['values'][1];
877
- $boxes_data['PageviewsPerSession']['current'] = $total['values'][2];
878
- $boxes_data['BounceRate']['current'] = round( $total['values'][3], 2 );
879
- } else {
880
- $boxes_data['Users']['previous'] = $total['values'][0];
881
- $boxes_data['Pageviews']['previous'] = $total['values'][1];
882
- $boxes_data['PageviewsPerSession']['previous'] = $total['values'][2];
883
- $boxes_data['BounceRate']['previous'] = round( $total['values'][3], 2 );
884
- }
885
- }
886
-
887
- return self::prepare_boxes( $boxes_data );
888
- }
889
-
890
- return false;
891
- }
892
-
893
- /**
894
- * Prepare boxes data
895
- *
896
- * @param array $boxes_data Boxes data.
897
- *
898
- * @return array boxes data
899
- */
900
- public static function prepare_boxes( $boxes_data ) {
901
- $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;
902
- $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;
903
- $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;
904
- $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;
905
- $boxes_data['Users']['diff'] = ( 0 === $boxes_data['Users']['previous'] && 0 === $boxes_data['Users']['current'] ) ? 0 : $boxes_data['Users']['diff'];
906
- $boxes_data['Pageviews']['diff'] = ( 0 === $boxes_data['Pageviews']['previous'] && 0 === $boxes_data['Pageviews']['current'] ) ? 0 : $boxes_data['Pageviews']['diff'];
907
- $boxes_data['PageviewsPerSession']['diff'] = ( 0 === $boxes_data['PageviewsPerSession']['previous'] && 0 === $boxes_data['PageviewsPerSession']['current'] ) ? 0 : $boxes_data['PageviewsPerSession']['diff'];
908
- $boxes_data['BounceRate']['diff'] = ( 0 === $boxes_data['BounceRate']['previous'] && 0 === $boxes_data['BounceRate']['current'] ) ? 0 : $boxes_data['BounceRate']['diff'];
909
- $boxes_data['Users']['label'] = 'Users';
910
- $boxes_data['Pageviews']['label'] = 'Pageviews';
911
- $boxes_data['PageviewsPerSession']['label'] = 'Pages / Session';
912
- $boxes_data['BounceRate']['label'] = 'Bounce Rate';
913
- $boxes_data['Users']['comparison'] = $boxes_data['Users']['current'] . ' vs ' . $boxes_data['Users']['previous'];
914
- $boxes_data['Pageviews']['comparison'] = $boxes_data['Pageviews']['current'] . ' vs ' . $boxes_data['Pageviews']['previous'];
915
- $boxes_data['PageviewsPerSession']['comparison'] = self::number_format_clean( $boxes_data['PageviewsPerSession']['current'], 2, '.', ',' ) . ' vs ' . self::number_format_clean( $boxes_data['PageviewsPerSession']['previous'], 2, '.', ',' );
916
- $boxes_data['BounceRate']['comparison'] = self::number_format_clean( $boxes_data['BounceRate']['current'], 2, '.', ',' ) . '% vs ' . self::number_format_clean( $boxes_data['BounceRate']['previous'], 2, '.', ',' ) . '%';
917
- $boxes_data['Users']['color'] = ( $boxes_data['Users']['diff'] > 0 ) ? 'green' : 'red';
918
- $boxes_data['Pageviews']['color'] = ( $boxes_data['Pageviews']['diff'] > 0 ) ? 'green' : 'red';
919
- $boxes_data['PageviewsPerSession']['color'] = ( $boxes_data['PageviewsPerSession']['diff'] > 0 ) ? 'green' : 'red';
920
- $boxes_data['BounceRate']['color'] = ( $boxes_data['BounceRate']['diff'] > 0 ) ? 'red' : 'green';
921
- $boxes_data['Users']['color'] = ( 0 !== $boxes_data['Users']['diff'] ) ? $boxes_data['Users']['color'] : 'black';
922
- $boxes_data['Pageviews']['color'] = ( 0 !== $boxes_data['Pageviews']['diff'] ) ? $boxes_data['Pageviews']['color'] : 'black';
923
- $boxes_data['PageviewsPerSession']['color'] = ( 0 !== $boxes_data['PageviewsPerSession']['diff'] ) ? $boxes_data['PageviewsPerSession']['color'] : 'black';
924
- $boxes_data['BounceRate']['color'] = ( 0 !== $boxes_data['BounceRate']['diff'] ) ? $boxes_data['BounceRate']['color'] : 'black';
925
-
926
- return $boxes_data;
927
- }
928
-
929
- /**
930
- * Number format for boxes
931
- *
932
- * @param float $number Number to format.
933
- * @param int $precision Precision.
934
- * @param string $dec_point Decimal point.
935
- * @param string $thousands_sep Thousands Separator.
936
- *
937
- * @return string clean number format
938
- */
939
- public static function number_format_clean( $number, $precision = 0, $dec_point = '.', $thousands_sep = ',' ) {
940
- if ( 0 === $number ) {
941
- return 0;
942
- } else {
943
- $format = number_format( $number, $precision, $dec_point, $thousands_sep );
944
- if ( '.00' === substr( $format, 2 ) ) {
945
- return substr( $format, 0, - 3 );
946
- }
947
-
948
- return $format;
949
- }
950
- }
951
-
952
- /**
953
- * Get sources from analytics response data
954
- *
955
- * @param array $data Analytics response data.
956
- *
957
- * @return array|bool sources data
958
- */
959
- public static function get_sources( $data ) {
960
- if ( false === empty( $data ) ) {
961
- $data = self::get_reports_from_response( $data );
962
- self::handle_more_reports( $data );
963
- $report = self::get_single_report( $data );
964
- self::get_report_column_header( $report );
965
- $report_data = self::get_report_data( $report );
966
- $rows = self::get_rows( $report_data );
967
- $totals = self::get_totals( $report_data );
968
- $total_count = array();
969
- if ( false === empty( $totals ) ) {
970
- foreach ( $totals as $key => $total ) {
971
- $total_count = $total['values'][0];
972
- }
973
- }
974
- $sources = array(
975
- 'total' => $total_count,
976
- 'sum' => 0,
977
- 'rows' => array(),
978
- );
979
- if ( false === empty( $rows ) ) {
980
- $i = 1;
981
- foreach ( $rows as $row ) {
982
- if ( false === empty( $row ) ) {
983
- foreach ( $row as $key => $value ) {
984
- if ( 'dimensions' === $key ) {
985
- $sources['rows'][ $i ]['name'] = $value[0];
986
- $sources['rows'][ $i ]['url'] = $value[0];
987
- } elseif ( 'metrics' === $key ) {
988
- $sources['rows'][ $i ]['number'] = $value[0]['values'][0];
989
- $sources['rows'][ $i ]['percent'] = ( false === empty( $total_count ) ) ? round( $value[0]['values'][0] / $total_count * 100, 2 ) : 0;
990
- $sources['sum'] += $value[0]['values'][0];
991
- }
992
- }
993
- $i ++;
994
- }
995
- }
996
- }
997
-
998
- return $sources;
999
- }
1000
-
1001
- return false;
1002
- }
1003
-
1004
- /**
1005
- * Get dashboard boxes data from analytics response data
1006
- *
1007
- * @param array $data Analytics response data.
1008
- *
1009
- * @return array dashboard boxes data
1010
- */
1011
- public static function get_dashboard_boxes_data( $data ) {
1012
- if ( false === empty( $data ) ) {
1013
- $data = self::get_reports_from_response( $data );
1014
- self::handle_more_reports( $data );
1015
- $report = self::get_single_report( $data );
1016
- self::get_report_column_header( $report );
1017
- $report_data = self::get_report_data( $report );
1018
- $totals = self::get_totals( $report_data );
1019
- $boxes_data = array();
1020
- $boxes_data['Sessions'] = array(
1021
- 'label' => 'Visits',
1022
- 'value' => $totals[0]['values'][0],
1023
- );
1024
- $boxes_data['Pageviews'] = array(
1025
- 'label' => 'Pageviews',
1026
- 'value' => $totals[0]['values'][1],
1027
- );
1028
- $boxes_data['pageviewsPerSession'] = array(
1029
- 'label' => 'Pages / Visit',
1030
- 'value' => self::number_format_clean( $totals[0]['values'][2], 2, '.', ',' ),
1031
- );
1032
- $boxes_data['BounceRate'] = array(
1033
- 'label' => 'Bounce Rate',
1034
- 'value' => self::number_format_clean( $totals[0]['values'][3], 2, '.', ',' ) . '%',
1035
- );
1036
- $boxes_data['avgTimeOnPage'] = array(
1037
- 'label' => 'Avg. Time on Site',
1038
- 'value' => gmdate( 'H:i:s', $totals[0]['values'][4] ),
1039
- );
1040
- $boxes_data['percentNewSessions'] = array(
1041
- 'label' => '% of New Visits',
1042
- 'value' => self::number_format_clean( $totals[0]['values'][5], 2, '.', ',' ),
1043
- );
1044
-
1045
- return $boxes_data;
1046
- }
1047
- }
1048
-
1049
- /**
1050
- * Get Empty Boxes Structure.
1051
- *
1052
- * @return array Array of empty boxes structure values.
1053
- */
1054
- public static function get_empty_boxes_structure() {
1055
- $boxes_data = array();
1056
- $boxes_data['Sessions'] = array(
1057
- 'label' => 'Visits',
1058
- 'value' => 0,
1059
- );
1060
- $boxes_data['Pageviews'] = array(
1061
- 'label' => 'Pageviews',
1062
- 'value' => 0,
1063
- );
1064
- $boxes_data['pageviewsPerSession'] = array(
1065
- 'label' => 'Pages / Visit',
1066
- 'value' => self::number_format_clean( 0, 2, '.', ',' ),
1067
- );
1068
- $boxes_data['BounceRate'] = array(
1069
- 'label' => 'Bounce Rate',
1070
- 'value' => self::number_format_clean( 0, 2, '.', ',' ) . '%',
1071
- );
1072
- $boxes_data['avgTimeOnPage'] = array(
1073
- 'label' => 'Avg. Time on Site',
1074
- 'value' => gmdate( 'H:i:s', 0 ),
1075
- );
1076
- $boxes_data['percentNewSessions'] = array(
1077
- 'label' => '% of New Visits',
1078
- 'value' => self::number_format_clean( 0, 2, '.', ',' ),
1079
- );
1080
-
1081
- return $boxes_data;
1082
- }
 
 
 
 
 
1083
  }
15
  */
16
  class Ga_Stats {
17
 
18
+ /**
19
+ * Profile object.
20
+ *
21
+ * @var array Profile.
22
+ */
23
+ private $profile = array();
24
+
25
+ /**
26
+ * Primary class constructor.
27
+ *
28
+ * @access public
29
+ * @since 7.0.0
30
+ */
31
+ public function __construct() {
32
+ }
33
+
34
+ /**
35
+ * Preparing query to get Analytics data
36
+ *
37
+ * @param string $query Query type.
38
+ * @param int $id_view The Analytics view ID from which to retrieve data.
39
+ * @param string $date_range The start date for the query in the format YYYY-MM-DD or '7daysAgo'.
40
+ * @param string $metric A metric expression.
41
+ * @param bool $old Use old query style.
42
+ *
43
+ * @return array Request query
44
+ */
45
+ public static function get_query( $query, $id_view, $date_range = null, $metric = null, $old = false ) {
46
+ if ( 'main_chart' === $query ) {
47
+ return $old ? self::main_chart_query_old( $id_view, $date_range, $metric ) : self::main_chart_query(
48
+ $id_view,
49
+ $date_range,
50
+ $metric
51
+ );
52
+ } elseif ( 'gender' === $query ) {
53
+ return self::gender_chart_query( $id_view, $date_range, $metric );
54
+ } elseif ( 'device' === $query ) {
55
+ return self::device_chart_query( $id_view, $date_range, $metric );
56
+ } elseif ( 'age' === $query ) {
57
+ return self::age_chart_query( $id_view, $date_range, $metric );
58
+ } elseif ( 'boxes' === $query ) {
59
+ return self::boxes_query( $id_view );
60
+ } elseif ( 'dashboard_boxes' === $query ) {
61
+ return $old ? self::dashboard_boxes_query_old( $id_view, $date_range ) :
62
+ self::dashboard_boxes_query( $id_view, $date_range );
63
+ } elseif ( 'sources' === $query ) {
64
+ return self::sources_query( $id_view, $date_range );
65
+ } else {
66
+ return array();
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Preparing query for top traffic sources table
72
+ *
73
+ * @param int $id_view The Analytics view ID from which to retrieve data.
74
+ * @param array $date_ranges An array representing the date ranges that will be passed to chart query.
75
+ *
76
+ * @return array Sources query
77
+ */
78
+ public static function sources_query( $id_view, $date_ranges ) {
79
+ $reports_requests = array();
80
+
81
+ $ts = filter_input( INPUT_GET, 'ts', FILTER_SANITIZE_STRING );
82
+
83
+ if ( false === empty( $ts ) ) {
84
+ $reports_requests[] = array(
85
+ 'viewId' => $id_view,
86
+ 'dateRanges' => $date_ranges,
87
+ 'metrics' => self::set_metrics( array( 'ga:pageviews' ) ),
88
+ 'includeEmptyRows' => true,
89
+ 'pageSize' => 10,
90
+ 'dimensions' => self::set_dimensions( 'ga:sourceMedium' ),
91
+ 'orderBys' => self::set_order_bys( 'ga:pageviews', 'DESCENDING' ),
92
+ );
93
+ } else {
94
+ $reports_requests[] = array(
95
+ 'viewId' => $id_view,
96
+ 'dateRanges' => $date_ranges,
97
+ 'metrics' => self::set_metrics(
98
+ array(
99
+ 'ga:pageviews',
100
+ 'ga:uniquePageviews',
101
+ 'ga:timeOnPage',
102
+ 'ga:bounces',
103
+ 'ga:entrances',
104
+ 'ga:exits',
105
+ )
106
+ ),
107
+ 'includeEmptyRows' => true,
108
+ 'pageSize' => 10,
109
+ 'dimensions' => self::set_dimensions( 'ga:pagePath' ),
110
+ 'orderBys' => self::set_order_bys( 'ga:pageviews', 'DESCENDING' ),
111
+ );
112
+ }
113
+
114
+ $query = array(
115
+ 'reportRequests' => $reports_requests,
116
+ );
117
+
118
+ return $query;
119
+ }
120
+
121
+ /**
122
+ * Preparing query for dashboard boxes
123
+ *
124
+ * @param int $id_view The Analytics view ID from which to retrieve data.
125
+ * @param array $date_ranges An array representing the date ranges that will be passed to chart query.
126
+ *
127
+ * @return array Dashboard boxes query
128
+ */
129
+ public static function dashboard_boxes_query( $id_view, $date_ranges ) {
130
+ $reports_requests = array();
131
+
132
+ $ts = filter_input( INPUT_GET, 'ts', FILTER_SANITIZE_STRING );
133
+
134
+ if ( false === empty( $ts ) ) {
135
+ $reports_requests[] = array(
136
+ 'viewId' => $id_view,
137
+ 'dateRanges' => $date_ranges,
138
+ 'metrics' => self::set_metrics( array( 'ga:pageviews' ) ),
139
+ 'includeEmptyRows' => true,
140
+ 'pageSize' => 10,
141
+ 'dimensions' => self::set_dimensions( 'ga:sourceMedium' ),
142
+ 'orderBys' => self::set_order_bys( 'ga:pageviews', 'DESCENDING' ),
143
+ );
144
+ } else {
145
+ $reports_requests[] = array(
146
+ 'viewId' => $id_view,
147
+ 'dateRanges' => $date_ranges,
148
+ 'metrics' => self::set_metrics(
149
+ array(
150
+ 'ga:pageviews',
151
+ 'ga:uniquePageviews',
152
+ 'ga:timeOnPage',
153
+ 'ga:bounces',
154
+ 'ga:entrances',
155
+ 'ga:exits',
156
+ )
157
+ ),
158
+ 'includeEmptyRows' => true,
159
+ 'pageSize' => 10,
160
+ 'dimensions' => self::set_dimensions( 'ga:pagePath' ),
161
+ 'orderBys' => self::set_order_bys( 'ga:pageviews', 'DESCENDING' ),
162
+ );
163
+ }
164
+ $query = array(
165
+ 'reportRequests' => $reports_requests,
166
+ );
167
+
168
+ return $query;
169
+ }
170
+
171
+ /**
172
+ * Preparing query for dashboard boxes
173
+ *
174
+ * @param int $id_view The Analytics view ID from which to retrieve data.
175
+ * @param string $date_range The start date for the query in the format YYYY-MM-DD or '7daysAgo'.
176
+ *
177
+ * @return array Dashboard boxes query
178
+ * @deprecated
179
+ */
180
+ public static function dashboard_boxes_query_old( $id_view, $date_range ) {
181
+ $reports_requests = array();
182
+
183
+ $th = filter_input( INPUT_GET, 'th', FILTER_SANITIZE_STRING );
184
+ $ts = filter_input( INPUT_GET, 'ts', FILTER_SANITIZE_STRING );
185
+
186
+ $days_ago = false === empty( $th ) ? '30daysAgo' : '7daysAgo';
187
+
188
+ if ( false === empty( $ts ) ) {
189
+ $reports_requests[] = array(
190
+ 'viewId' => $id_view,
191
+ 'dateRanges' => self::set_date_ranges( $days_ago, 'yesterday' ),
192
+ 'metrics' => self::set_metrics( array( 'ga:pageviews' ) ),
193
+ 'includeEmptyRows' => true,
194
+ 'pageSize' => 10,
195
+ 'dimensions' => self::set_dimensions( 'ga:sourceMedium' ),
196
+ 'orderBys' => self::set_order_bys( 'ga:pageviews', 'DESCENDING' ),
197
+ );
198
+ } else {
199
+ $reports_requests[] = array(
200
+ 'viewId' => $id_view,
201
+ 'dateRanges' => self::set_date_ranges( $days_ago, 'yesterday' ),
202
+ 'metrics' => self::set_metrics(
203
+ array(
204
+ 'ga:pageviews',
205
+ 'ga:uniquePageviews',
206
+ 'ga:timeOnPage',
207
+ 'ga:bounces',
208
+ 'ga:entrances',
209
+ 'ga:exits',
210
+ )
211
+ ),
212
+ 'includeEmptyRows' => true,
213
+ 'pageSize' => 10,
214
+ 'dimensions' => self::set_dimensions( 'ga:pagePath' ),
215
+ 'orderBys' => self::set_order_bys( 'ga:pageviews', 'DESCENDING' ),
216
+ );
217
+ }
218
+ $query = array(
219
+ 'reportRequests' => $reports_requests,
220
+ );
221
+
222
+ return $query;
223
+ }
224
+
225
+ /**
226
+ * Preparing query for stats boxes
227
+ *
228
+ * @param int $id_view The Analytics view ID from which to retrieve data.
229
+ *
230
+ * @return array Boxes query
231
+ */
232
+ public static function boxes_query( $id_view ) {
233
+ $th = filter_input( INPUT_GET, 'th', FILTER_SANITIZE_STRING );
234
+
235
+ $range = false === empty( $th ) ? '30daysAgo' : '7daysAgo';
236
+ $range_s_prev = false === empty( $th ) ? '60daysAgo' : '14daysAgo';
237
+ $range_e_prev = false === empty( $th ) ? '31daysAgo' : '8daysAgo';
238
+ $reports_requests = array();
239
+ $reports_requests[] = array(
240
+ 'viewId' => $id_view,
241
+ 'dateRanges' => self::set_date_ranges( $range, 'yesterday', $range_s_prev, $range_e_prev ),
242
+ 'metrics' => self::set_metrics(
243
+ array(
244
+ 'ga:users',
245
+ 'ga:pageviews',
246
+ 'ga:pageviewsPerSession',
247
+ 'ga:BounceRate',
248
+ )
249
+ ),
250
+ 'includeEmptyRows' => true,
251
+ 'dimensions' => self::set_dimensions( 'ga:date' ),
252
+ );
253
+ $query = array(
254
+ 'reportRequests' => $reports_requests,
255
+ );
256
+
257
+ return $query;
258
+ }
259
+
260
+ /**
261
+ * Preparing query for chart
262
+ *
263
+ * @param int $id_view The Analytics view ID from which to retrieve data.
264
+ * @param array $date_ranges An array representing the date ranges that will be passed to chart query.
265
+ * @param string $metric A metric expression.
266
+ *
267
+ * @return array Chart query
268
+ */
269
+ public static function main_chart_query( $id_view, $date_ranges = null, $metric = null ) {
270
+ if ( true === empty( $metric ) ) {
271
+ $metric = 'ga:pageviews';
272
+ } else {
273
+ $metric = 'ga:' . $metric;
274
+ }
275
+
276
+ $reports_requests = array();
277
+ $reports_requests[] = array(
278
+ 'viewId' => $id_view,
279
+ 'dateRanges' => $date_ranges,
280
+ 'metrics' => self::set_metrics( $metric ),
281
+ 'includeEmptyRows' => true,
282
+ 'dimensions' => self::set_dimensions( 'ga:date' ),
283
+ );
284
+ $query = array(
285
+ 'reportRequests' => $reports_requests,
286
+ );
287
+
288
+ return $query;
289
+ }
290
+
291
+ /**
292
+ * Preparing query for chart
293
+ *
294
+ * @param int $id_view The Analytics view ID from which to retrieve data.
295
+ * @param string $date_range The start date for the query in the format YYYY-MM-DD or '7daysAgo'.
296
+ * @param string $metric A metric expression.
297
+ *
298
+ * @return array Chart query
299
+ * @deprecated
300
+ */
301
+ public static function main_chart_query_old( $id_view, $date_range = null, $metric = null ) {
302
+ if ( empty( $date_range ) ) {
303
+ $date_ranges = self::set_date_ranges( '7daysAgo', 'yesterday', '14daysAgo', '8daysAgo' );
304
+ } else {
305
+ $date_ranges = self::set_date_ranges( $date_range, 'yesterday', '14daysAgo', '8daysAgo' );
306
+ }
307
+
308
+ if ( empty( $metric ) ) {
309
+ $metric = 'ga:pageviews';
310
+ } else {
311
+ $metric = 'ga:' . $metric;
312
+ }
313
+
314
+ $reports_requests = array();
315
+ $reports_requests[] = array(
316
+ 'viewId' => $id_view,
317
+ 'dateRanges' => $date_ranges,
318
+ 'metrics' => self::set_metrics( $metric ),
319
+ 'includeEmptyRows' => true,
320
+ 'dimensions' => self::set_dimensions( 'ga:date' ),
321
+ );
322
+ $query = array(
323
+ 'reportRequests' => $reports_requests,
324
+ );
325
+
326
+ return $query;
327
+ }
328
+
329
+ /**
330
+ * Preparing query for gender chart
331
+ *
332
+ * @param int $id_view The Analytics view ID from which to retrieve data.
333
+ * @param array $date_ranges An array representing the date ranges that will be passed to chart query.
334
+ * @param string $metric A metric expression.
335
+ *
336
+ * @return array Chart query
337
+ */
338
+ public static function gender_chart_query( $id_view, $date_ranges = null, $metric = null ) {
339
+ if ( true === empty( $date_ranges ) ) {
340
+ $date_ranges = self::set_date_ranges( '7daysAgo', 'yesterday', '14daysAgo', '8daysAgo' );
341
+ }
342
+
343
+ $reports_requests = array();
344
+ $reports_requests[] = array(
345
+ 'viewId' => $id_view,
346
+ 'dateRanges' => $date_ranges,
347
+ 'metrics' => self::set_metrics( 'ga:sessions' ),
348
+ 'includeEmptyRows' => true,
349
+ 'dimensions' => self::set_dimensions( 'ga:userGender' ),
350
+ );
351
+ $query = array(
352
+ 'reportRequests' => $reports_requests,
353
+ );
354
+
355
+ return $query;
356
+ }
357
+
358
+ /**
359
+ * Preparing query for device chart.
360
+ *
361
+ * @param int $id_view The Analytics view ID from which to retrieve data.
362
+ * @param array $date_ranges An array representing the date ranges that will be passed to chart query.
363
+ * @param string $metric A metric expression.
364
+ *
365
+ * @return array Chart query
366
+ * @since 2.5.2
367
+ */
368
+ public static function device_chart_query( $id_view, $date_ranges = null, $metric = null ) {
369
+ return array(
370
+ 'reportRequests' => array(
371
+ array(
372
+ 'viewId' => $id_view,
373
+ 'dateRanges' => $date_ranges,
374
+ 'metrics' => self::set_metrics( 'ga:sessions' ),
375
+ 'includeEmptyRows' => true,
376
+ 'dimensions' => self::set_dimensions( 'ga:deviceCategory' ),
377
+ ),
378
+ ),
379
+ );
380
+ }
381
+
382
+ /**
383
+ * Preparing query for age chart
384
+ *
385
+ * @param int $id_view The Analytics view ID from which to retrieve data.
386
+ * @param array $date_ranges An array representing the date ranges that will be passed to chart query.
387
+ * @param string $metric A metric expression.
388
+ *
389
+ * @return array Chart query
390
+ */
391
+ public static function age_chart_query( $id_view, $date_ranges = null, $metric = null ) {
392
+ if ( true === empty( $date_ranges ) ) {
393
+ $date_ranges = self::set_date_ranges( '7daysAgo', 'yesterday', '14daysAgo', '8daysAgo' );
394
+ }
395
+
396
+ $reports_requests = array();
397
+ $reports_requests[] = array(
398
+ 'viewId' => $id_view,
399
+ 'dateRanges' => $date_ranges,
400
+ 'metrics' => self::set_metrics( 'ga:sessions' ),
401
+ 'includeEmptyRows' => true,
402
+ 'dimensions' => self::set_dimensions( 'ga:userAgeBracket' ),
403
+ );
404
+ $query = array(
405
+ 'reportRequests' => $reports_requests,
406
+ );
407
+
408
+ return $query;
409
+ }
410
+
411
+ /**
412
+ * Setting order for requests
413
+ *
414
+ * @param string $name The field which to sort by. The default sort order is ascending. Example: ga:browser.
415
+ * @param string $sort The sorting order for the field. 'ASCENDING' or 'DESCENDING'.
416
+ *
417
+ * @return array OrderBys
418
+ */
419
+ public static function set_order_bys( $name, $sort ) {
420
+ $order = array();
421
+ $order[] = array(
422
+ 'fieldName' => $name,
423
+ 'sortOrder' => $sort,
424
+ );
425
+
426
+ return $order;
427
+ }
428
+
429
+ /**
430
+ * Setting metrics for requests
431
+ *
432
+ * @param mixed $expression A metric expression or array of expressions.
433
+ *
434
+ * @return array Metrics
435
+ */
436
+ public static function set_metrics( $expression ) {
437
+ $metrics = array();
438
+ if ( is_array( $expression ) ) {
439
+ foreach ( $expression as $exp ) {
440
+ $metrics[] = array(
441
+ 'expression' => $exp,
442
+ );
443
+ }
444
+ } else {
445
+ $metrics[] = array(
446
+ 'expression' => $expression,
447
+ );
448
+ }
449
+
450
+ return $metrics;
451
+ }
452
+
453
+ /**
454
+ * Setting dimensions for requests
455
+ *
456
+ * @param string $name Name of the dimension to fetch, for example ga:browser.
457
+ *
458
+ * @return array Dimensions
459
+ */
460
+ public static function set_dimensions( $name ) {
461
+ $dimensions = array();
462
+ $dimensions[] = array(
463
+ 'name' => $name,
464
+ );
465
+
466
+ return $dimensions;
467
+ }
468
+
469
+ /**
470
+ * Setting date ranges for requests
471
+ *
472
+ * @param string $start_date The start date for the query in the format YYYY-MM-DD.
473
+ * @param string $end_date The end date for the query in the format YYYY-MM-DD.
474
+ * @param string $prev_start_date The start date (second range) for the query in the format YYYY-MM-DD.
475
+ * @param string $prev_end_date The start date (second range) for the query in the format YYYY-MM-DD.
476
+ *
477
+ * @return array Date ranges
478
+ */
479
+ public static function set_date_ranges( $start_date, $end_date, $prev_start_date = '', $prev_end_date = '' ) {
480
+ $date_danges = array();
481
+ $date_danges[] = array(
482
+ 'startDate' => $start_date,
483
+ 'endDate' => $end_date,
484
+ );
485
+ if ( false === empty( $prev_start_date ) && false === empty( $prev_end_date ) ) {
486
+ $date_danges[] = array(
487
+ 'startDate' => $prev_start_date,
488
+ 'endDate' => $prev_end_date,
489
+ );
490
+ }
491
+
492
+ return $date_danges;
493
+ }
494
+
495
+ /**
496
+ * Preparing response for data received from analytics
497
+ *
498
+ * @param array $data Analytics response.
499
+ *
500
+ * @return array Response rows
501
+ */
502
+ public static function prepare_response( $data ) {
503
+ $data = self::get_reports_from_response( $data );
504
+ self::handle_more_reports( $data );
505
+ $report = self::get_single_report( $data );
506
+ self::get_report_column_header( $report );
507
+ $report_data = self::get_report_data( $report );
508
+ self::get_totals( $report_data );
509
+ self::get_row_count( $report_data );
510
+ $rows = self::get_rows( $report_data );
511
+
512
+ return $rows;
513
+ }
514
+
515
+ /**
516
+ * Get dimensions from response row
517
+ *
518
+ * @param array $row Analytics response row.
519
+ *
520
+ * @return array|bool Dimensions
521
+ */
522
+ public static function get_dimensions( $row ) {
523
+ if ( false === empty( $row['dimensions'] ) ) {
524
+ return $row['dimensions'];
525
+ }
526
+
527
+ return false;
528
+ }
529
+
530
+ /**
531
+ * Get metrics from response row
532
+ *
533
+ * @param array $row Analytics response row.
534
+ *
535
+ * @return array|bool Metrics
536
+ */
537
+ public static function get_metrics( $row ) {
538
+ if ( false === empty( $row['metrics'] ) ) {
539
+ return $row['metrics'];
540
+ }
541
+
542
+ return false;
543
+ }
544
+
545
+ /**
546
+ * Get row from response report data
547
+ *
548
+ * @param array $report_data Analytics response report data.
549
+ *
550
+ * @return array|bool Rows
551
+ */
552
+ public static function get_rows( $report_data ) {
553
+ if ( false === empty( $report_data['rows'] ) ) {
554
+ return $report_data['rows'];
555
+ }
556
+
557
+ return false;
558
+ }
559
+
560
+ /**
561
+ * Get row count from response report data
562
+ *
563
+ * @param array $report_data Analytics response report data.
564
+ *
565
+ * @return array|bool Row count
566
+ */
567
+ public static function get_row_count( $report_data ) {
568
+ if ( false === empty( $report_data['rowCount'] ) ) {
569
+ return $report_data['rowCount'];
570
+ }
571
+
572
+ return false;
573
+ }
574
+
575
+ /**
576
+ * Get totals from response report data
577
+ *
578
+ * @param array $report_data Analytics response report data.
579
+ *
580
+ * @return array|bool Totals
581
+ */
582
+ public static function get_totals( $report_data ) {
583
+ if ( false === empty( $report_data['totals'] ) ) {
584
+ return $report_data['totals'];
585
+ }
586
+
587
+ return false;
588
+ }
589
+
590
+ /**
591
+ * Get reports from response data
592
+ *
593
+ * @param array $data Analytics response data.
594
+ *
595
+ * @return array|bool Reports
596
+ */
597
+ public static function get_reports_from_response( $data ) {
598
+ if ( false === empty( $data['reports'] ) ) {
599
+ return $data['reports'];
600
+ }
601
+
602
+ return false;
603
+ }
604
+
605
+ /**
606
+ * Show info for multiple data
607
+ *
608
+ * @param array $data Analytics response data.
609
+ */
610
+ public static function handle_more_reports( $data ) {
611
+ if ( count( $data ) > 1 ) {
612
+ echo 'more than one report';
613
+ }
614
+ }
615
+
616
+ /**
617
+ * Show info for multiple rows
618
+ *
619
+ * @param array $rows Analytics response rows.
620
+ */
621
+ public static function handle_more_rows( $rows ) {
622
+ if ( count( $rows ) > 1 ) {
623
+ echo 'more than one row';
624
+ }
625
+ }
626
+
627
+ /**
628
+ * Get single report from response data
629
+ *
630
+ * @param array $data Analytics response data.
631
+ *
632
+ * @return array|bool Report
633
+ */
634
+ public static function get_single_report( $data ) {
635
+ if ( false === empty( $data ) ) {
636
+ foreach ( $data as $report ) {
637
+ if ( false === empty( $report ) ) {
638
+ return $report;
639
+ }
640
+ }
641
+ }
642
+
643
+ return false;
644
+ }
645
+
646
+ /**
647
+ * Get single row from response data rows
648
+ *
649
+ * @param array $rows Analytics response data rows.
650
+ *
651
+ * @return array|bool Row
652
+ */
653
+ public static function get_single_row( $rows ) {
654
+ if ( false === empty( $rows ) ) {
655
+ foreach ( $rows as $row ) {
656
+ if ( false === empty( $row ) ) {
657
+ return $row;
658
+ }
659
+ }
660
+ }
661
+
662
+ return false;
663
+ }
664
+
665
+ /**
666
+ * Get column header from response data
667
+ *
668
+ * @param array $data Analytics response data.
669
+ *
670
+ * @return array Column header
671
+ */
672
+ public static function get_report_column_header( $data ) {
673
+ if ( false === empty( $data['columnHeader'] ) ) {
674
+ return $data['columnHeader'];
675
+ }
676
+
677
+ return false;
678
+ }
679
+
680
+ /**
681
+ * Get report data from response data
682
+ *
683
+ * @param array $data Analytics response data.
684
+ *
685
+ * @return array|bool data
686
+ */
687
+ public static function get_report_data( $data ) {
688
+ if ( false === empty( $data['data'] ) ) {
689
+ return $data['data'];
690
+ }
691
+
692
+ return false;
693
+ }
694
+
695
+ /**
696
+ * Get chart from response data
697
+ *
698
+ * @param array $response_data Analytics response data.
699
+ * @param int $period_in_days Period in days (default = 7).
700
+ *
701
+ * @return array chart data
702
+ */
703
+ public static function get_chart( $response_data, $period_in_days = 7 ) {
704
+ $chart_data = array();
705
+ if ( false === empty( $response_data ) ) {
706
+ $data = (
707
+ false === empty( $response_data['reports'] )
708
+ && false === empty( $response_data['reports'][0] )
709
+ && false === empty( $response_data['reports'][0]['data'] )
710
+ )
711
+ ? $response_data['reports'][0]['data'] : array();
712
+ $rows = ( false === empty( $data['rows'] ) ) ? $data['rows'] : array();
713
+ if ( false === empty( $rows ) ) {
714
+ foreach ( $rows as $key => $row ) {
715
+ if ( $key < $period_in_days ) {
716
+ $chart_data[ $key ]['previous'] = false === empty( $row['metrics'][1]['values'][0] ) ? $row['metrics'][1]['values'][0] : 0;
717
+ $chart_data[ $key ]['previous-day'] = gmdate( 'M j', strtotime( $row['dimensions'][0] ) );
718
+ } else {
719
+ $chart_data[ $key - $period_in_days ]['day'] = gmdate( 'M j', strtotime( $row['dimensions'][0] ) );
720
+ $chart_data[ $key - $period_in_days ]['current'] = false === empty( $row['metrics'][0]['values'][0] ) ? $row['metrics'][0]['values'][0] : 0;
721
+
722
+ if (0 === $chart_data[ $key - $period_in_days ]['current']) {
723
+ $chart_data[ $key - $period_in_days ]['current'] = false === empty( $row['metrics'][1]['values'][0] ) ? $row['metrics'][1]['values'][0] : 0;
724
+ }
725
+
726
+ $chart_data['date'] = strtotime( $row['dimensions'][0] );
727
+ }
728
+ }
729
+ }
730
+ }
731
+
732
+ return $chart_data;
733
+ }
734
+
735
+ /**
736
+ * Get gender chart from response data
737
+ *
738
+ * @param array $response_data Analytics response data.
739
+ *
740
+ * @return array chart data
741
+ */
742
+ public static function get_gender_chart( $response_data ) {
743
+ $chart_data = array();
744
+ if ( false === empty( $response_data ) ) {
745
+ $data = ( false === empty( $response_data['reports'] ) && false === empty( $response_data['reports'][0] ) && false === empty( $response_data['reports'][0]['data'] ) ) ? $response_data['reports'][0]['data'] : array();
746
+ $rows = ( false === empty( $data['rows'] ) ) ? $data['rows'] : array();
747
+ if ( false === empty( $rows ) ) {
748
+ foreach ( $rows as $key => $row ) {
749
+ $chart_data[ $row['dimensions'][0] ] = self::get_metric_value( $row['metrics'] );
750
+ }
751
+ }
752
+ }
753
+
754
+ return $chart_data;
755
+ }
756
+
757
+ /**
758
+ * Get device chart from response data.
759
+ *
760
+ * @param array $response_data Analytics response data array.
761
+ *
762
+ * @return array Chart data array.
763
+ */
764
+ public static function get_device_chart( $response_data ) {
765
+ $chart_data = array();
766
+ if ( false === empty( $response_data ) ) {
767
+ $data = ( false === empty( $response_data['reports'] ) && false === empty( $response_data['reports'][0] ) && false === empty( $response_data['reports'][0]['data'] ) ) ? $response_data['reports'][0]['data'] : array();
768
+ $rows = ( false === empty( $data['rows'] ) ) ? $data['rows'] : array();
769
+ if ( false === empty( $rows ) ) {
770
+ foreach ( $rows as $row ) {
771
+ $chart_data[ $row['dimensions'][0] ] = self::get_metric_value( $row['metrics'] );
772
+ }
773
+ }
774
+ }
775
+
776
+ return $chart_data;
777
+ }
778
+
779
+ /**
780
+ * Get the value of metric data response.
781
+ *
782
+ * @param array $metrics Metrics array.
783
+ *
784
+ * @return mixed
785
+ */
786
+ private static function get_metric_value( $metrics ) {
787
+ if ( is_array( $metrics ) ) {
788
+ foreach ( $metrics as $metric ) {
789
+ $values[] = $metric['values'][0];
790
+ }
791
+ }
792
+
793
+ return $values[0];
794
+ }
795
+
796
+ /**
797
+ * Get gender chart from response data
798
+ *
799
+ * @param array $response_data Analytics response data.
800
+ *
801
+ * @return array chart data
802
+ */
803
+ public static function get_age_chart( $response_data ) {
804
+ $chart_data = array();
805
+ if ( false === empty( $response_data ) ) {
806
+ $data = ( false === empty( $response_data['reports'] ) && false === empty( $response_data['reports'][0] ) && false === empty( $response_data['reports'][0]['data'] ) ) ? $response_data['reports'][0]['data'] : array();
807
+ $rows = ( false === empty( $data['rows'] ) ) ? $data['rows'] : array();
808
+ if ( false === empty( $rows ) ) {
809
+ foreach ( $rows as $key => $row ) {
810
+ $chart_data[ $row['dimensions'][0] ] = self::get_metric_value( $row['metrics'] );
811
+ }
812
+ }
813
+ }
814
+
815
+ return $chart_data;
816
+ }
817
+
818
+ /**
819
+ * Get dasboard chart from response data
820
+ *
821
+ * @param array $response_data Analytics response data.
822
+ *
823
+ * @return array dashboard chart data
824
+ */
825
+ public static function get_dashboard_chart( $response_data ) {
826
+ $chart_data = array();
827
+ if ( false === empty( $response_data ) ) {
828
+ $data = (
829
+ false === empty( $response_data['reports'] )
830
+ && false === empty( $response_data['reports'][0] )
831
+ && false === empty( $response_data['reports'][0]['data'] )
832
+ ) ? $response_data['reports'][0]['data'] : array();
833
+
834
+ $rows = ( false === empty( $data['rows'] ) ) ? $data['rows'] : array();
835
+ if ( false === empty( $rows ) ) {
836
+ foreach ( $rows as $row ) {
837
+ $chart_data[] = array(
838
+ 'day' => gmdate( 'M j', strtotime( $row['dimensions'][0] ) ),
839
+ 'current' => false === empty( $row['metrics'][0]['values'][0] ) ? $row['metrics'][0]['values'][0] : 0,
840
+ );
841
+ }
842
+ }
843
+ }
844
+
845
+ return $chart_data;
846
+ }
847
+
848
+ /**
849
+ * Get boxes from response data
850
+ *
851
+ * @param array $data Analytics response data.
852
+ *
853
+ * @return array boxes data
854
+ */
855
+ public static function get_boxes( $data ) {
856
+ if ( false === empty( $data ) ) {
857
+ $data = self::get_reports_from_response( $data );
858
+ self::handle_more_reports( $data );
859
+ $report = self::get_single_report( $data );
860
+ self::get_report_column_header( $report );
861
+ $report_data = self::get_report_data( $report );
862
+ $totals = self::get_totals( $report_data );
863
+
864
+ return self::get_boxes_from_totals( $totals );
865
+ }
866
+ }
867
+
868
+ /**
869
+ * Get boxes from totals
870
+ *
871
+ * @param array $totals Analytics response totals.
872
+ *
873
+ * @return array|bool boxes data
874
+ */
875
+ public static function get_boxes_from_totals( $totals ) {
876
+ if ( false === empty( $totals ) ) {
877
+ $boxes_data = array();
878
+ foreach ( $totals as $key => $total ) {
879
+ if ( 0 === $key ) {
880
+ $boxes_data['Users']['current'] = $total['values'][0];
881
+ $boxes_data['Pageviews']['current'] = $total['values'][1];
882
+ $boxes_data['PageviewsPerSession']['current'] = $total['values'][2];
883
+ $boxes_data['BounceRate']['current'] = round( $total['values'][3], 2 );
884
+ } else {
885
+ $boxes_data['Users']['previous'] = $total['values'][0];
886
+ $boxes_data['Pageviews']['previous'] = $total['values'][1];
887
+ $boxes_data['PageviewsPerSession']['previous'] = $total['values'][2];
888
+ $boxes_data['BounceRate']['previous'] = round( $total['values'][3], 2 );
889
+ }
890
+ }
891
+
892
+ return self::prepare_boxes( $boxes_data );
893
+ }
894
+
895
+ return false;
896
+ }
897
+
898
+ /**
899
+ * Prepare boxes data
900
+ *
901
+ * @param array $boxes_data Boxes data.
902
+ *
903
+ * @return array boxes data
904
+ */
905
+ public static function prepare_boxes( $boxes_data ) {
906
+ $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;
907
+ $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;
908
+ $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;
909
+ $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;
910
+ $boxes_data['Users']['diff'] = ( 0 === $boxes_data['Users']['previous'] && 0 === $boxes_data['Users']['current'] ) ? 0 : $boxes_data['Users']['diff'];
911
+ $boxes_data['Pageviews']['diff'] = ( 0 === $boxes_data['Pageviews']['previous'] && 0 === $boxes_data['Pageviews']['current'] ) ? 0 : $boxes_data['Pageviews']['diff'];
912
+ $boxes_data['PageviewsPerSession']['diff'] = ( 0 === $boxes_data['PageviewsPerSession']['previous'] && 0 === $boxes_data['PageviewsPerSession']['current'] ) ? 0 : $boxes_data['PageviewsPerSession']['diff'];
913
+ $boxes_data['BounceRate']['diff'] = ( 0 === $boxes_data['BounceRate']['previous'] && 0 === $boxes_data['BounceRate']['current'] ) ? 0 : $boxes_data['BounceRate']['diff'];
914
+ $boxes_data['Users']['label'] = 'Users';
915
+ $boxes_data['Pageviews']['label'] = 'Pageviews';
916
+ $boxes_data['PageviewsPerSession']['label'] = 'Pages / Session';
917
+ $boxes_data['BounceRate']['label'] = 'Bounce Rate';
918
+ $boxes_data['Users']['comparison'] = $boxes_data['Users']['current'] . ' vs ' . $boxes_data['Users']['previous'];
919
+ $boxes_data['Pageviews']['comparison'] = $boxes_data['Pageviews']['current'] . ' vs ' . $boxes_data['Pageviews']['previous'];
920
+ $boxes_data['PageviewsPerSession']['comparison'] = self::number_format_clean( $boxes_data['PageviewsPerSession']['current'], 2, '.', ',' ) . ' vs ' . self::number_format_clean( $boxes_data['PageviewsPerSession']['previous'], 2, '.', ',' );
921
+ $boxes_data['BounceRate']['comparison'] = self::number_format_clean( $boxes_data['BounceRate']['current'], 2, '.', ',' ) . '% vs ' . self::number_format_clean( $boxes_data['BounceRate']['previous'], 2, '.', ',' ) . '%';
922
+ $boxes_data['Users']['color'] = ( $boxes_data['Users']['diff'] > 0 ) ? 'green' : 'red';
923
+ $boxes_data['Pageviews']['color'] = ( $boxes_data['Pageviews']['diff'] > 0 ) ? 'green' : 'red';
924
+ $boxes_data['PageviewsPerSession']['color'] = ( $boxes_data['PageviewsPerSession']['diff'] > 0 ) ? 'green' : 'red';
925
+ $boxes_data['BounceRate']['color'] = ( $boxes_data['BounceRate']['diff'] > 0 ) ? 'red' : 'green';
926
+ $boxes_data['Users']['color'] = ( 0 !== $boxes_data['Users']['diff'] ) ? $boxes_data['Users']['color'] : 'black';
927
+ $boxes_data['Pageviews']['color'] = ( 0 !== $boxes_data['Pageviews']['diff'] ) ? $boxes_data['Pageviews']['color'] : 'black';
928
+ $boxes_data['PageviewsPerSession']['color'] = ( 0 !== $boxes_data['PageviewsPerSession']['diff'] ) ? $boxes_data['PageviewsPerSession']['color'] : 'black';
929
+ $boxes_data['BounceRate']['color'] = ( 0 !== $boxes_data['BounceRate']['diff'] ) ? $boxes_data['BounceRate']['color'] : 'black';
930
+
931
+ return $boxes_data;
932
+ }
933
+
934
+ /**
935
+ * Number format for boxes
936
+ *
937
+ * @param float $number Number to format.
938
+ * @param int $precision Precision.
939
+ * @param string $dec_point Decimal point.
940
+ * @param string $thousands_sep Thousands Separator.
941
+ *
942
+ * @return string clean number format
943
+ */
944
+ public static function number_format_clean( $number, $precision = 0, $dec_point = '.', $thousands_sep = ',' ) {
945
+ if ( 0 === $number ) {
946
+ return 0;
947
+ } else {
948
+ $format = number_format( $number, $precision, $dec_point, $thousands_sep );
949
+ if ( '.00' === substr( $format, 2 ) ) {
950
+ return substr( $format, 0, - 3 );
951
+ }
952
+
953
+ return $format;
954
+ }
955
+ }
956
+
957
+ /**
958
+ * Get sources from analytics response data
959
+ *
960
+ * @param array $data Analytics response data.
961
+ *
962
+ * @return array|bool sources data
963
+ */
964
+ public static function get_sources( $data ) {
965
+ if ( false === empty( $data ) ) {
966
+ $data = self::get_reports_from_response( $data );
967
+ self::handle_more_reports( $data );
968
+ $report = self::get_single_report( $data );
969
+ self::get_report_column_header( $report );
970
+ $report_data = self::get_report_data( $report );
971
+ $rows = self::get_rows( $report_data );
972
+ $totals = self::get_totals( $report_data );
973
+ $total_count = array();
974
+ if ( false === empty( $totals ) ) {
975
+ foreach ( $totals as $key => $total ) {
976
+ $total_count = $total['values'][0];
977
+ }
978
+ }
979
+ $sources = array(
980
+ 'total' => $total_count,
981
+ 'sum' => 0,
982
+ 'rows' => array(),
983
+ );
984
+ if ( false === empty( $rows ) ) {
985
+ $i = 1;
986
+ foreach ( $rows as $row ) {
987
+ if ( false === empty( $row ) ) {
988
+ foreach ( $row as $key => $value ) {
989
+ if ( 'dimensions' === $key ) {
990
+ $sources['rows'][ $i ]['name'] = $value[0];
991
+ $sources['rows'][ $i ]['url'] = $value[0];
992
+ } elseif ( 'metrics' === $key ) {
993
+ $sources['rows'][ $i ]['number'] = $value[0]['values'][0];
994
+ $sources['rows'][ $i ]['percent'] = ( false === empty( $total_count ) ) ? round( $value[0]['values'][0] / $total_count * 100, 2 ) : 0;
995
+ $sources['sum'] += $value[0]['values'][0];
996
+ }
997
+ }
998
+ $i ++;
999
+ }
1000
+ }
1001
+ }
1002
+
1003
+ return $sources;
1004
+ }
1005
+
1006
+ return false;
1007
+ }
1008
+
1009
+ /**
1010
+ * Get dashboard boxes data from analytics response data
1011
+ *
1012
+ * @param array $data Analytics response data.
1013
+ *
1014
+ * @return array dashboard boxes data
1015
+ */
1016
+ public static function get_dashboard_boxes_data( $data ) {
1017
+ if ( false === empty( $data ) ) {
1018
+ $data = self::get_reports_from_response( $data );
1019
+ self::handle_more_reports( $data );
1020
+ $report = self::get_single_report( $data );
1021
+ self::get_report_column_header( $report );
1022
+ $report_data = self::get_report_data( $report );
1023
+ $totals = self::get_totals( $report_data );
1024
+ $boxes_data = array();
1025
+ $boxes_data['Sessions'] = array(
1026
+ 'label' => 'Visits',
1027
+ 'value' => $totals[0]['values'][0],
1028
+ );
1029
+ $boxes_data['Pageviews'] = array(
1030
+ 'label' => 'Pageviews',
1031
+ 'value' => $totals[0]['values'][1],
1032
+ );
1033
+ $boxes_data['pageviewsPerSession'] = array(
1034
+ 'label' => 'Pages / Visit',
1035
+ 'value' => self::number_format_clean( $totals[0]['values'][2], 2, '.', ',' ),
1036
+ );
1037
+ $boxes_data['BounceRate'] = array(
1038
+ 'label' => 'Bounce Rate',
1039
+ 'value' => self::number_format_clean( $totals[0]['values'][3], 2, '.', ',' ) . '%',
1040
+ );
1041
+ $boxes_data['avgTimeOnPage'] = array(
1042
+ 'label' => 'Avg. Time on Site',
1043
+ 'value' => gmdate( 'H:i:s', $totals[0]['values'][4] ),
1044
+ );
1045
+ $boxes_data['percentNewSessions'] = array(
1046
+ 'label' => '% of New Visits',
1047
+ 'value' => self::number_format_clean( $totals[0]['values'][5], 2, '.', ',' ),
1048
+ );
1049
+
1050
+ return $boxes_data;
1051
+ }
1052
+ }
1053
+
1054
+ /**
1055
+ * Get Empty Boxes Structure.
1056
+ *
1057
+ * @return array Array of empty boxes structure values.
1058
+ */
1059
+ public static function get_empty_boxes_structure() {
1060
+ $boxes_data = array();
1061
+ $boxes_data['Sessions'] = array(
1062
+ 'label' => 'Visits',
1063
+ 'value' => 0,
1064
+ );
1065
+ $boxes_data['Pageviews'] = array(
1066
+ 'label' => 'Pageviews',
1067
+ 'value' => 0,
1068
+ );
1069
+ $boxes_data['pageviewsPerSession'] = array(
1070
+ 'label' => 'Pages / Visit',
1071
+ 'value' => self::number_format_clean( 0, 2, '.', ',' ),
1072
+ );
1073
+ $boxes_data['BounceRate'] = array(
1074
+ 'label' => 'Bounce Rate',
1075
+ 'value' => self::number_format_clean( 0, 2, '.', ',' ) . '%',
1076
+ );
1077
+ $boxes_data['avgTimeOnPage'] = array(
1078
+ 'label' => 'Avg. Time on Site',
1079
+ 'value' => gmdate( 'H:i:s', 0 ),
1080
+ );
1081
+ $boxes_data['percentNewSessions'] = array(
1082
+ 'label' => '% of New Visits',
1083
+ 'value' => self::number_format_clean( 0, 2, '.', ',' ),
1084
+ );
1085
+
1086
+ return $boxes_data;
1087
+ }
1088
  }
googleanalytics.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: ShareThis Dashboard for Google Analytics
4
  * Plugin URI: http://wordpress.org/extend/plugins/googleanalytics/
5
  * Description: Use Google Analytics on your WordPress site without touching any code, and view visitor reports right in your WordPress admin dashboard!
6
- * Version: 3.0.0
7
  * Author: ShareThis
8
  * Author URI: http://sharethis.com
9
  *
@@ -59,7 +59,7 @@ if ( false === preg_match( '/(\/|\\\)' . GA_NAME . '(\/|\\\)/', realpath( __FILE
59
  die();
60
  }
61
 
62
- const GOOGLEANALYTICS_VERSION = '3.0.0';
63
 
64
  // Requires.
65
  require_once GA_PLUGIN_DIR . '/lib/analytics-admin/vendor/autoload.php';
@@ -68,8 +68,25 @@ require_once GA_PLUGIN_DIR . '/class/class-ga-autoloader.php';
68
  require_once GA_PLUGIN_DIR . '/class/class-ga-autoloader.php';
69
  require_once GA_PLUGIN_DIR . '/tools/class-ga-supportlogger.php';
70
 
71
- Ga_Autoloader::register();
72
- Ga_Hook::add_hooks( GA_MAIN_FILE_PATH );
 
73
 
74
- add_action( 'plugins_loaded', 'Ga_Admin::loaded_googleanalytics' );
75
- add_action( 'init', 'Ga_Helper::init' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  * Plugin Name: ShareThis Dashboard for Google Analytics
4
  * Plugin URI: http://wordpress.org/extend/plugins/googleanalytics/
5
  * Description: Use Google Analytics on your WordPress site without touching any code, and view visitor reports right in your WordPress admin dashboard!
6
+ * Version: 3.1.0
7
  * Author: ShareThis
8
  * Author URI: http://sharethis.com
9
  *
59
  die();
60
  }
61
 
62
+ const GOOGLEANALYTICS_VERSION = '3.1.0';
63
 
64
  // Requires.
65
  require_once GA_PLUGIN_DIR . '/lib/analytics-admin/vendor/autoload.php';
68
  require_once GA_PLUGIN_DIR . '/class/class-ga-autoloader.php';
69
  require_once GA_PLUGIN_DIR . '/tools/class-ga-supportlogger.php';
70
 
71
+ if ( version_compare( phpversion(), '7.4', '>=' ) ) {
72
+ Ga_Autoloader::register();
73
+ Ga_Hook::add_hooks( GA_MAIN_FILE_PATH );
74
 
75
+ add_action( 'plugins_loaded', 'Ga_Admin::loaded_googleanalytics' );
76
+ add_action( 'init', 'Ga_Helper::init' );
77
+ } else {
78
+ if ( defined( 'WP_CLI' ) ) {
79
+ WP_CLI::warning( _google_analytics_version_text() );
80
+ } else {
81
+ add_action( 'admin_notices', '_google_analytcis_php_version_error' );
82
+ }
83
+ }
84
+
85
+ /**
86
+ * String describing the minimum PHP version.
87
+ *
88
+ * @return string
89
+ */
90
+ function _google_analtyics_php_version_text() {
91
+ return __( 'ShareThis Dashboard for Google Analytics plugin error: Your version of PHP is too old to run this plugin. You must be running PHP 7.4 or higher.', 'googlanalytics' );
92
+ }
js/googleanalytics_dashboard.js CHANGED
@@ -15,15 +15,18 @@
15
  if (showLoader) {
16
  ga_loader.show();
17
  }
18
- google.charts.load( 'current', {'packages': ['corechart']} );
19
- google.charts.setOnLoadCallback(
20
- function () {
21
- if (dataArr) {
22
- ga_dashboard.drawChart( dataArr );
23
- ga_dashboard.setChartData( dataArr );
 
 
 
24
  }
25
- }
26
- );
27
  },
28
  events: function (data) {
29
  $( document ).ready(
15
  if (showLoader) {
16
  ga_loader.show();
17
  }
18
+
19
+ if ( google ) {
20
+ google.charts.load( 'current', { 'packages': [ 'corechart' ] } );
21
+ google.charts.setOnLoadCallback(
22
+ function () {
23
+ if ( dataArr ) {
24
+ ga_dashboard.drawChart( dataArr );
25
+ ga_dashboard.setChartData( dataArr );
26
+ }
27
  }
28
+ );
29
+ }
30
  },
31
  events: function (data) {
32
  $( document ).ready(
js/googleanalytics_page.js CHANGED
@@ -47,7 +47,6 @@ const GA_AUTHENTICATION_CODE_ERROR = 'That looks like your Google Analytics Trac
47
  if ( ga_popup.validateCode( e, ac_tmp ) ) {
48
  $( '#' + GA_ACCESS_CODE_ID ).val( ac_tmp );
49
  $( '#' + GA_FORM_ID ).submit();
50
- $( '#ga4_form' ).submit();
51
  }
52
  },
53
  validateCode: function( e, code ) {
@@ -1063,12 +1062,14 @@ const GA_AUTHENTICATION_CODE_ERROR = 'That looks like your Google Analytics Trac
1063
 
1064
  data = google.visualization.arrayToDataTable( data );
1065
 
1066
- var chart = new google.visualization.PieChart( document.getElementById( demoChartGenderContainer ) );
1067
- var options = {
1068
- title: 'Gender',
1069
- };
 
1070
 
1071
- chart.draw( data, options );
 
1072
  },
1073
  drawDemoDeviceChart: function( data, chartWidth ) {
1074
  if ( typeof chartWidth == 'undefined' ) {
@@ -1077,12 +1078,14 @@ const GA_AUTHENTICATION_CODE_ERROR = 'That looks like your Google Analytics Trac
1077
 
1078
  data = google.visualization.arrayToDataTable( data );
1079
 
1080
- var chart = new google.visualization.PieChart( document.getElementById( demoChartDeviceContainer ) );
1081
- var options = {
1082
- title: 'Device Breakdown',
1083
- };
 
1084
 
1085
- chart.draw( data, options );
 
1086
  },
1087
 
1088
  drawGa4DemoDeviceChart: function( data, chartWidth ) {
@@ -1092,12 +1095,14 @@ const GA_AUTHENTICATION_CODE_ERROR = 'That looks like your Google Analytics Trac
1092
 
1093
  data = google.visualization.arrayToDataTable( data );
1094
 
1095
- var chart = new google.visualization.PieChart( document.getElementById( demoGa4ChartDeviceContainer ) );
1096
- var options = {
1097
- title: 'Device Breakdown',
1098
- };
 
1099
 
1100
- chart.draw( data, options );
 
1101
  },
1102
 
1103
  drawDemoAgeChart: function( data, chartWidth ) {
@@ -1115,9 +1120,11 @@ const GA_AUTHENTICATION_CODE_ERROR = 'That looks like your Google Analytics Trac
1115
  },
1116
  };
1117
 
1118
- var chart = new google.visualization.BarChart( document.getElementById( demoChartAgeContainer ) );
 
1119
 
1120
- chart.draw( data, options );
 
1121
  },
1122
  drawDemoGenderGa4Chart: function( data, chartWidth ) {
1123
  if ( typeof chartWidth == 'undefined' ) {
@@ -1126,12 +1133,14 @@ const GA_AUTHENTICATION_CODE_ERROR = 'That looks like your Google Analytics Trac
1126
 
1127
  data = google.visualization.arrayToDataTable( data );
1128
 
1129
- var chart = new google.visualization.PieChart( document.getElementById( demoChartGenderGa4Container ) );
1130
- var options = {
1131
- title: 'Gender',
1132
- };
 
1133
 
1134
- chart.draw( data, options );
 
1135
  },
1136
  drawDemoAgeGa4Chart: function( data, chartWidth ) {
1137
  if ( typeof chartWidth == 'undefined' ) {
@@ -1148,9 +1157,11 @@ const GA_AUTHENTICATION_CODE_ERROR = 'That looks like your Google Analytics Trac
1148
  },
1149
  };
1150
 
1151
- var chart = new google.visualization.BarChart( document.getElementById( demoChartAgeGa4Container ) );
 
1152
 
1153
- chart.draw( data, options );
 
1154
  },
1155
  };
1156
  ga_debug = {
47
  if ( ga_popup.validateCode( e, ac_tmp ) ) {
48
  $( '#' + GA_ACCESS_CODE_ID ).val( ac_tmp );
49
  $( '#' + GA_FORM_ID ).submit();
 
50
  }
51
  },
52
  validateCode: function( e, code ) {
1062
 
1063
  data = google.visualization.arrayToDataTable( data );
1064
 
1065
+ if ( document.getElementById( demoChartGenderContainer ) ) {
1066
+ var chart = new google.visualization.PieChart( document.getElementById( demoChartGenderContainer ) );
1067
+ var options = {
1068
+ title: 'Gender',
1069
+ };
1070
 
1071
+ chart.draw( data, options );
1072
+ }
1073
  },
1074
  drawDemoDeviceChart: function( data, chartWidth ) {
1075
  if ( typeof chartWidth == 'undefined' ) {
1078
 
1079
  data = google.visualization.arrayToDataTable( data );
1080
 
1081
+ if ( document.getElementById( demoChartDeviceContainer ) ) {
1082
+ var chart = new google.visualization.PieChart( document.getElementById( demoChartDeviceContainer ) );
1083
+ var options = {
1084
+ title: 'Device Breakdown',
1085
+ };
1086
 
1087
+ chart.draw( data, options );
1088
+ }
1089
  },
1090
 
1091
  drawGa4DemoDeviceChart: function( data, chartWidth ) {
1095
 
1096
  data = google.visualization.arrayToDataTable( data );
1097
 
1098
+ if ( document.getElementById( demoGa4ChartDeviceContainer ) ) {
1099
+ var chart = new google.visualization.PieChart( document.getElementById( demoGa4ChartDeviceContainer ) );
1100
+ var options = {
1101
+ title: 'Device Breakdown',
1102
+ };
1103
 
1104
+ chart.draw( data, options );
1105
+ }
1106
  },
1107
 
1108
  drawDemoAgeChart: function( data, chartWidth ) {
1120
  },
1121
  };
1122
 
1123
+ if ( document.getElementById( demoChartAgeContainer ) ) {
1124
+ var chart = new google.visualization.BarChart( document.getElementById( demoChartAgeContainer ) );
1125
 
1126
+ chart.draw( data, options );
1127
+ }
1128
  },
1129
  drawDemoGenderGa4Chart: function( data, chartWidth ) {
1130
  if ( typeof chartWidth == 'undefined' ) {
1133
 
1134
  data = google.visualization.arrayToDataTable( data );
1135
 
1136
+ if ( document.getElementById( demoChartGenderGa4Container ) ) {
1137
+ var chart = new google.visualization.PieChart( document.getElementById( demoChartGenderGa4Container ) );
1138
+ var options = {
1139
+ title: 'Gender',
1140
+ };
1141
 
1142
+ chart.draw( data, options );
1143
+ }
1144
  },
1145
  drawDemoAgeGa4Chart: function( data, chartWidth ) {
1146
  if ( typeof chartWidth == 'undefined' ) {
1157
  },
1158
  };
1159
 
1160
+ if ( document.getElementById( demoChartAgeGa4Container ) ) {
1161
+ var chart = new google.visualization.BarChart( document.getElementById( demoChartAgeGa4Container ) );
1162
 
1163
+ chart.draw( data, options );
1164
+ }
1165
  },
1166
  };
1167
  ga_debug = {
readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: sharethis, scottstorebloom, scottmweaver
3
  Tags: analytics, google analytics, google analytics plugin, google analytics widget, google analytics dashboard
4
  Requires at least: 5.2
5
- Tested up to: 6.0.1
6
- Stable tag: 3.0.0
7
- Version: 3.0.0
8
 
9
  Use Google Analytics on your WordPress site without touching any code, and view visitor reports right in your WordPress admin dashboard!
10
 
@@ -18,7 +18,7 @@ Unlike other plugins, there are no monthly fees or paid upgrades for this plugin
18
 
19
  Get started in less than 10 minutes. Installation is quick and easy, no developers required.
20
 
21
- Simply download the plugin, log into Google, select the required website, and it will automatically include the appropriate code.
22
 
23
  **GOOGLE ANALYTICS DASHBOARD**
24
 
@@ -27,21 +27,22 @@ Start making data-driven decisions with real time stats including:
27
  * Visitor trends – Dive deeper into your website’s page views, users, pages per session, and bounce rate for the past 7 days as compared to the previous 7 days
28
  * Traffic sources – Discover which 5 traffic sources are driving the most visitors to your website
29
  * Top pages – Stay updated on your 10 most viewed pages
30
- * New! Demographics - Get age and gender data in your dashboard.
31
- * New! GDPR Compliance Tool - For all your EU Compliance, we've integrated the ShareThis GDPR Compliance Tool into our plugin!
32
 
33
  With our mobile-optimized plugin, you’ll be able to stay informed and get actionable insights on any device. For more accurate stats, you also have the option to disable tracking for any role like Admins or Editors so your analytics represent real visitors.
34
 
35
- If you don’t have a Google Analytics account, you can sign up for free here: [https://www.google.com/analytics/](https://www.google.com/analytics/)
36
 
37
- **LOOKING FOR MORE WAYS TO GROW YOUR WEBSITE?**
38
 
39
- [Share buttons](https://wordpress.org/plugins/sharethis-share-buttons/) - Enable one-click sharing to start scaling your site traffic today.
40
 
41
- [Follow buttons](https://wordpress.org/plugins/sharethis-follow-buttons/) - Expand your social following across 20+ social channels including Facebook, Twitter, WhatsApp, and Pinterest.
42
 
43
- [Reaction buttons](https://wordpress.org/plugins/sharethis-reaction-buttons/) - Give your audience a fun and easy way to react to your content.
44
 
 
45
 
46
  **SUPPORT**
47
 
@@ -49,7 +50,6 @@ If you have any questions, please contact us at [support@sharethis.com](mailto:s
49
 
50
  By downloading and installing this plugin, you are agreeing to the [Privacy Policy](http://www.sharethis.com/privacy/) and [Terms of Service](http://www.sharethis.com/publisher-terms-of-use/).
51
 
52
-
53
  **USEFUL GOOGLE ANALYTICS & SEO RESOURCES**
54
 
55
  Check out these helpful tutorials and resources for getting the most out of Google Analytics, driving more traffic to your website, and improving your WordPress website’s SEO:
@@ -106,15 +106,46 @@ When the General Data Protection Regulation (GDPR) was first introduced, website
106
  Fortunately, a number of useful compliance tools emerged to make compliance easier for publishers and businesses of all sizes. Consent Management Platforms (CMPs) are tools designed to inform visitors about the data a website or third-party tool is collecting about them and how that data will be used, provide an opt-in option for users to grant consent to have their data collected (as well as an opt-out option to decline), and communicate the consent status of users and cookies to other vendors operating within the IAB Framework. CMPs also offer transparency to users, providing granular information on the companies their data will be shared with and allowing them to monitor and control who receives their data. Finally, CMPs provide a centralized database for users to review the most up-to-date privacy policies and information related to their data collection.
107
  If you’re using Google Analytics on your WordPress website or a plugin like the Google Analytics Dashboard for WordPress, you must comply with GDPR. A CMP is the best way to manage the consent process for GDPR compliance. With ShareThis’ GDPR Compliance Tool built right in to the Google Analytics Dashboard for WordPress plugin, you can easily stay on top of getting consent to collect your visitors’ data and provide visitors with clear and valuable information. Our GDPR Compliance Tool is compliant with the IAB’s Transparency & Consent Framework v2.0, meaning it meets the latest standards for transparency in data collection and consent management. Check out our GDPR checklist for publishers & website owners to make sure you’re meeting the requirements or download our GDPR Compliance Guide for detailed information on GDPR compliance with ShareThis’ tools.
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  == Screenshots ==
110
 
111
  1. Overall site performance - the past 7/30 days
112
  2. The top 10 page views for the past 7/30 days
113
  3. Directly authenticate Google Analytics, and exclude sets of logged in users
114
  4. Just click to authenticate, then copy the API key and add it to the plugin
 
 
 
115
 
116
  == Changelog ==
117
 
 
 
 
 
118
  = 3.0.0 =
119
  * Add GA4 property auth.
120
  * Add GA4 specific dashboard graphs.
2
  Contributors: sharethis, scottstorebloom, scottmweaver
3
  Tags: analytics, google analytics, google analytics plugin, google analytics widget, google analytics dashboard
4
  Requires at least: 5.2
5
+ Tested up to: 6.0.2
6
+ Stable tag: 3.1.0
7
+ Version: 3.1.0
8
 
9
  Use Google Analytics on your WordPress site without touching any code, and view visitor reports right in your WordPress admin dashboard!
10
 
18
 
19
  Get started in less than 10 minutes. Installation is quick and easy, no developers required.
20
 
21
+ Simply download the plugin, log into Google, select the required website, and it will automatically include the appropriate code. This plugin is compatible with both Universal Analytics and Google Analytics 4 (GA4).
22
 
23
  **GOOGLE ANALYTICS DASHBOARD**
24
 
27
  * Visitor trends – Dive deeper into your website’s page views, users, pages per session, and bounce rate for the past 7 days as compared to the previous 7 days
28
  * Traffic sources – Discover which 5 traffic sources are driving the most visitors to your website
29
  * Top pages – Stay updated on your 10 most viewed pages
30
+ * Demographics Get device type and gender data in your dashboard
31
+ * GDPR Compliance Tool For EU Compliance, weve integrated the ShareThis GDPR Compliance Tool into our plugin.
32
 
33
  With our mobile-optimized plugin, you’ll be able to stay informed and get actionable insights on any device. For more accurate stats, you also have the option to disable tracking for any role like Admins or Editors so your analytics represent real visitors.
34
 
35
+ If you don’t have a Google Analytics account, you can sign up for free here:
36
 
37
+ [https://www.google.com/analytics/](https://www.google.com/analytics/)
38
 
39
+ **LOOKING FOR MORE WAYS TO GROW YOUR WEBSITE?**
40
 
41
+ [Share buttons](https://wordpress.org/plugins/sharethis-share-buttons/) Enable one-click sharing to start scaling your site traffic today.
42
 
43
+ [Follow buttons](https://wordpress.org/plugins/sharethis-follow-buttons/) Expand your social following across 20+ social channels including Facebook, Twitter, WhatsApp, and Pinterest.
44
 
45
+ [Reaction buttons](https://wordpress.org/plugins/sharethis-reaction-buttons/) – Give your audience a fun and easy way to react to your content.
46
 
47
  **SUPPORT**
48
 
50
 
51
  By downloading and installing this plugin, you are agreeing to the [Privacy Policy](http://www.sharethis.com/privacy/) and [Terms of Service](http://www.sharethis.com/publisher-terms-of-use/).
52
 
 
53
  **USEFUL GOOGLE ANALYTICS & SEO RESOURCES**
54
 
55
  Check out these helpful tutorials and resources for getting the most out of Google Analytics, driving more traffic to your website, and improving your WordPress website’s SEO:
106
  Fortunately, a number of useful compliance tools emerged to make compliance easier for publishers and businesses of all sizes. Consent Management Platforms (CMPs) are tools designed to inform visitors about the data a website or third-party tool is collecting about them and how that data will be used, provide an opt-in option for users to grant consent to have their data collected (as well as an opt-out option to decline), and communicate the consent status of users and cookies to other vendors operating within the IAB Framework. CMPs also offer transparency to users, providing granular information on the companies their data will be shared with and allowing them to monitor and control who receives their data. Finally, CMPs provide a centralized database for users to review the most up-to-date privacy policies and information related to their data collection.
107
  If you’re using Google Analytics on your WordPress website or a plugin like the Google Analytics Dashboard for WordPress, you must comply with GDPR. A CMP is the best way to manage the consent process for GDPR compliance. With ShareThis’ GDPR Compliance Tool built right in to the Google Analytics Dashboard for WordPress plugin, you can easily stay on top of getting consent to collect your visitors’ data and provide visitors with clear and valuable information. Our GDPR Compliance Tool is compliant with the IAB’s Transparency & Consent Framework v2.0, meaning it meets the latest standards for transparency in data collection and consent management. Check out our GDPR checklist for publishers & website owners to make sure you’re meeting the requirements or download our GDPR Compliance Guide for detailed information on GDPR compliance with ShareThis’ tools.
108
 
109
+ = What is Universal Analytics? =
110
+ Universal Analytics is Google’s legacy Google Analytics. The code line will normally look like so: UA-XXXXXXX. This is the product that we have been using on your behalf to collect data for your Google Analytics.
111
+
112
+ = What is GA4 =
113
+ Google Analytics 4 (GA4) is the latest update from Google Analytic’s platform. GA4's biggest update is allowing you to track both websites and apps under one account. There are also many new reporting features and it provides deeper insights into how users interact with your content.
114
+
115
+ On the back end, the way data is maintained is a little bit different, which will ultimately provide all of us new ways to track, measure and eventually analyze traffic.
116
+
117
+ = Do I have to use GA4? =
118
+ In theory, you don’t have to set up GA4 if you do not want to.
119
+ Our ShareThis Google Analytics plugin will continue working with UA and support it as long as possible. However, like all new products that are brought to market, Google will only release new features that support GA4 moving forward.
120
+ We highly suggest setting up a GA4 property even if you do not plan on using it for the moment. That way, when you do decide to make the cross over, you’ll have access to historical data as soon as possible.
121
+
122
+ Our plugin will collect data at the same time for UA and GA4. Setting up a GA4 property is very easy and we provide the ability to connect through your Wordpress admin section.
123
+
124
+ = What happens to my data? =
125
+ Nothing will happen to your existing data! Your UA property will be kept as is.
126
+ If you do decide to start using GA4, a new property will be created in Google Analytics. As with all new properties, it means there won’t be any data (you start from scratch).
127
+
128
+ Luckily we’ve allowed you to use both UA and GA4 properties and view both analytics on the same dashboard.
129
+
130
+ = When will Google switch to GA4? =
131
+ Google has already switched to supporting Google Analytics 4. However, you can still use your UA code and it will continue to collect data.
132
+
133
  == Screenshots ==
134
 
135
  1. Overall site performance - the past 7/30 days
136
  2. The top 10 page views for the past 7/30 days
137
  3. Directly authenticate Google Analytics, and exclude sets of logged in users
138
  4. Just click to authenticate, then copy the API key and add it to the plugin
139
+ 5. GA4 dashboard graphs
140
+ 6. GA4 Top 10 pages and new users by page view
141
+ 7. UA and GA4 tabs for settings
142
 
143
  == Changelog ==
144
 
145
+ = 3.1.0 =
146
+ * Fix chart starting at 0.
147
+ * Enable GA4 for public use.
148
+
149
  = 3.0.0 =
150
  * Add GA4 property auth.
151
  * Add GA4 specific dashboard graphs.
view/ga-ga4-settings.php CHANGED
@@ -122,6 +122,7 @@ $ga4_exclude_roles = true === is_array($ga4_exclude_roles) ? $ga4_exclude_roles
122
  </div>
123
  </div>
124
 
 
125
  <div style="margin-top: 0;<?php echo true === $setup_done ? '' : ' display: none;'; ?>" class="ga4_container ga_container">
126
  <?php if ( false === empty( $data['error_message'] ) ) : ?>
127
  <?php echo wp_kses_post( $data['error_message'] ); ?>
@@ -251,3 +252,4 @@ $ga4_exclude_roles = true === is_array($ga4_exclude_roles) ? $ga4_exclude_roles
251
  </p>
252
  </form>
253
  </div>
 
122
  </div>
123
  </div>
124
 
125
+ <?php if (true === $setup_done) : ?>
126
  <div style="margin-top: 0;<?php echo true === $setup_done ? '' : ' display: none;'; ?>" class="ga4_container ga_container">
127
  <?php if ( false === empty( $data['error_message'] ) ) : ?>
128
  <?php echo wp_kses_post( $data['error_message'] ); ?>
252
  </p>
253
  </form>
254
  </div>
255
+ <?php endif; ?>
view/page.php CHANGED
@@ -15,8 +15,6 @@ $plugin_dir = plugin_dir_path( __FILE__ );
15
  $plugin_uri = trailingslashit( get_home_url() ) . 'wp-content/plugins/googleanalytics/';
16
  $has_code = filter_input(INPUT_GET, 'code');
17
  $has_code = isset($has_code) ? $has_code : false;
18
- $show_ga4 = filter_input(INPUT_GET, 'ga4');
19
- $show_ga4 = false === empty($show_ga4);
20
  $has_property = get_option('googleanalytics-ga4-property');
21
  $has_property = isset($has_property) ? $has_property : false;
22
  $ga4_optimize = get_option('googleanalytics-ga4-optimize');
@@ -83,26 +81,22 @@ $setup_done = false !== $has_property &&
83
  <?php echo wp_kses_post( $data['debug_modal'] ); ?>
84
  <div class="wrap ga-wrap do-flex">
85
  <div class="setting-tabs">
86
- <?php if (true === $show_ga4) : ?>
87
- <div class="setting-tabs__tab ga4<?php echo false !== $has_code || true === $show_ga4 ? ' engage' : ''; ?>">
88
  <?php esc_html_e('Google Analytics 4', 'googleanalytics'); ?>
89
  </div>
90
- <?php endif; ?>
91
- <div class="ua setting-tabs__tab<?php echo false === $has_code && false === $show_ga4 ? ' engage' : ''; ?>">
92
  <?php esc_html_e('Universal Analytics Settings', 'googleanalytics'); ?>
93
  </div>
94
  </div>
95
- <?php if (true === $show_ga4) : ?>
96
  <div class="ga4-settings-wrap setting-tab-content st-notice-there
97
  <?php echo true === $setup_done ? ' normal-settings' : '';
98
- echo false !== $has_code || true === $show_ga4 ? ' engage' : '';
99
  ?>">
100
  <?php include 'ga-ga4-settings.php'; ?>
101
  </div>
102
- <?php endif; ?>
103
- <div class="ua-settings-wrap setting-tab-content<?php echo false === $has_code && false === $show_ga4 ? ' engage' : ''; ?>">
104
  <h1>Universal Analytics - <?php esc_html_e( 'Settings', 'googleanalytics' ); ?></h1>
105
- <?php if (false === $setup_done && true === $show_ga4) : ?>
106
  <button class="open-ga4">Setup Google Analytics 4</button>
107
  <?php endif; ?>
108
  <div style="margin-top: 0;" class="ga_container">
15
  $plugin_uri = trailingslashit( get_home_url() ) . 'wp-content/plugins/googleanalytics/';
16
  $has_code = filter_input(INPUT_GET, 'code');
17
  $has_code = isset($has_code) ? $has_code : false;
 
 
18
  $has_property = get_option('googleanalytics-ga4-property');
19
  $has_property = isset($has_property) ? $has_property : false;
20
  $ga4_optimize = get_option('googleanalytics-ga4-optimize');
81
  <?php echo wp_kses_post( $data['debug_modal'] ); ?>
82
  <div class="wrap ga-wrap do-flex">
83
  <div class="setting-tabs">
84
+ <div class="setting-tabs__tab ga4<?php echo false !== $has_code ? ' engage' : ''; ?>">
 
85
  <?php esc_html_e('Google Analytics 4', 'googleanalytics'); ?>
86
  </div>
87
+ <div class="ua setting-tabs__tab<?php echo false === $has_code ? ' engage' : ''; ?>">
 
88
  <?php esc_html_e('Universal Analytics Settings', 'googleanalytics'); ?>
89
  </div>
90
  </div>
 
91
  <div class="ga4-settings-wrap setting-tab-content st-notice-there
92
  <?php echo true === $setup_done ? ' normal-settings' : '';
93
+ echo false !== $has_code ? ' engage' : '';
94
  ?>">
95
  <?php include 'ga-ga4-settings.php'; ?>
96
  </div>
97
+ <div class="ua-settings-wrap setting-tab-content<?php echo false === $has_code ? ' engage' : ''; ?>">
 
98
  <h1>Universal Analytics - <?php esc_html_e( 'Settings', 'googleanalytics' ); ?></h1>
99
+ <?php if (false === $setup_done) : ?>
100
  <button class="open-ga4">Setup Google Analytics 4</button>
101
  <?php endif; ?>
102
  <div style="margin-top: 0;" class="ga_container">
view/templates/ga4-dashboard.php CHANGED
@@ -303,6 +303,31 @@ $x = 1;
303
  } );
304
  </script>
305
  <div class="dashboard-title">GA4 Dashboard</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
  <div id="page_session_chart_div"></div>
307
 
308
  <?php require plugin_dir_path( __FILE__ ) . 'ga4-demographic-chart.php'; ?>
@@ -375,4 +400,5 @@ $x = 1;
375
  </div>
376
  </div>
377
  </div>
 
378
  <div id="user_chart_div"></div>
303
  } );
304
  </script>
305
  <div class="dashboard-title">GA4 Dashboard</div>
306
+
307
+ <?php
308
+ if (true === empty($page_list_count_data)) :
309
+ echo wp_kses(
310
+ Ga_Helper::ga_wp_notice(
311
+ __( 'You don\'t appear to have enough page view data. Please come back at a later date once you do.' ),
312
+ 'warning',
313
+ false,
314
+ array(
315
+
316
+ )
317
+ ),
318
+ array(
319
+ 'button' => array(
320
+ 'class' => array(),
321
+ 'onclick' => array(),
322
+ ),
323
+ 'div' => array(
324
+ 'class' => array(),
325
+ ),
326
+ 'p' => array(),
327
+ )
328
+ );
329
+ else :
330
+ ?>
331
  <div id="page_session_chart_div"></div>
332
 
333
  <?php require plugin_dir_path( __FILE__ ) . 'ga4-demographic-chart.php'; ?>
400
  </div>
401
  </div>
402
  </div>
403
+ <?php endif; ?>
404
  <div id="user_chart_div"></div>