PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 1.17
Independent Analytics – WordPress Analytics Plugin v1.17
2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / IAWP / queries / views.php
independent-analytics / IAWP / queries Last commit date
campaigns.php 3 years ago current_traffic_finder.php 3 years ago geos.php 3 years ago range_query.php 3 years ago referrers.php 3 years ago reset_database.php 3 years ago resources.php 3 years ago view.php 3 years ago views.php 3 years ago visitors_over_time_finder.php 3 years ago
views.php
234 lines
1 <?php
2
3 namespace IAWP;
4
5 class Views extends Range_Query
6 {
7 const REFERRERS = 'REFERRERS';
8 const RESOURCES = 'RESOURCES';
9 const GEO = 'GEO';
10 const CAMPAIGNS = 'CAMPAIGNS';
11 private $views;
12 private $prev_period_views;
13 private $daily_views;
14 private $visitors;
15 private $prev_period_visitors;
16 private $daily_visitors;
17
18 public function __construct($type, $ids = null, $start = null, $end = null)
19 {
20 parent::__construct([
21 'start' => $start,
22 'end' => $end,
23 ]);
24 if ($type === self::RESOURCES || $type === self::REFERRERS || $type === self::GEO || $type === self::CAMPAIGNS) {
25 $this->query($type, $ids);
26 } else {
27 throw new \Exception('IAWP_Views: Unsupported type');
28 }
29 }
30
31 public function views()
32 {
33 return $this->views;
34 }
35
36 public function prev_period_views()
37 {
38 return $this->prev_period_views;
39 }
40
41 public function daily_views()
42 {
43 return $this->daily_views;
44 }
45
46 public function views_percentage_growth()
47 {
48 if ($this->views() === 0 || $this->prev_period_views() === 0) {
49 return 0;
50 } else {
51 return round((($this->views() / $this->prev_period_views()) - 1) * 100);
52 }
53 }
54
55 public function visitors()
56 {
57 return $this->visitors;
58 }
59
60 public function visitors_percentage_growth()
61 {
62 if ($this->visitors() === 0 || $this->prev_period_visitors() === 0) {
63 return 0;
64 } else {
65 return round((($this->visitors() / $this->prev_period_visitors()) - 1) * 100);
66 }
67 }
68
69 public function prev_period_visitors()
70 {
71 return $this->prev_period_visitors;
72 }
73
74 public function daily_visitors()
75 {
76 return $this->daily_visitors;
77 }
78
79 private function query($type, $ids)
80 {
81 global $wpdb;
82 $views_table = Query::get_table_name(Query::VIEWS);
83 $visitors_table = Query::get_table_name(Query::VISITORS);
84 $sessions_table = Query::get_table_name(Query::SESSIONS);
85
86 if (is_null($ids)) {
87 $skip_in = 1;
88 $ids = [0];
89 $in = '%s';
90 } elseif (count($ids) === 0) {
91 $skip_in = 0;
92 $ids = [0];
93 $in = '%s';
94 } else {
95 $skip_in = 0;
96 $in = implode(',', array_fill(0, count($ids), '%s'));
97 }
98
99 if ($type === self::RESOURCES) {
100 $column = 'views.resource_id';
101 } elseif ($type === self::REFERRERS) {
102 $column = 'sessions.referrer_id';
103 } elseif ($type === self::GEO) {
104 $column = 'sessions.visitor_id';
105 } elseif ($type === self::CAMPAIGNS) {
106 $column = 'sessions.campaign_id';
107 }
108
109 $has_null_id = false;
110 foreach ($ids as $id) {
111 if (is_null($id)) {
112 $has_null_id = true;
113 break;
114 }
115 }
116 $null_check = '';
117
118 if ($type === self::REFERRERS && $has_null_id) {
119 $null_check = "OR $column IS NULL";
120 }
121
122 $utc = Timezone::utc_offset();
123 $local_offset = Timezone::local_offset();
124 $query = $wpdb->prepare(
125 "
126 SELECT
127 DATE(CONVERT_TZ(views.viewed_at, '$utc', '$local_offset')) as date,
128 COUNT(*) as views,
129 COUNT(DISTINCT sessions.visitor_id) as visitors
130 FROM $views_table AS views
131 LEFT JOIN $sessions_table AS sessions ON views.session_id = sessions.session_id
132 LEFT JOIN $visitors_table AS visitors ON sessions.visitor_id = visitors.visitor_id
133 WHERE views.viewed_at BETWEEN %s AND %s
134 AND (%d = 1 OR $column IN ($in) $null_check)
135 AND ('$type' != 'GEO' OR visitors.country_code IS NOT NULL)
136 AND ('$type' != 'CAMPAIGNS' OR sessions.campaign_id IS NOT NULL)
137 GROUP BY DATE(CONVERT_TZ(views.viewed_at, '$utc', '$local_offset'))",
138 $this->formatted_start(),
139 $this->formatted_end(),
140 $skip_in,
141 ...$ids
142 );
143 $rows = $wpdb->get_results($query);
144
145 // This separate query for visitor counts is required
146 // Without it, visitors visiting on separate days are counted twice in the quick stats
147 $visitors_query = $wpdb->prepare(
148 "
149 SELECT
150 COUNT(DISTINCT sessions.visitor_id) as visitors
151 FROM $views_table AS views
152 LEFT JOIN $sessions_table AS sessions ON views.session_id = sessions.session_id
153 LEFT JOIN $visitors_table AS visitors ON sessions.visitor_id = visitors.visitor_id
154 WHERE views.viewed_at BETWEEN %s AND %s
155 AND (%d = 1 OR $column IN ($in) $null_check)
156 AND ('$type' != 'GEO' OR visitors.country_code IS NOT NULL)
157 AND ('$type' != 'CAMPAIGNS' OR sessions.campaign_id IS NOT NULL)
158 ",
159 $this->formatted_start(),
160 $this->formatted_end(),
161 $skip_in,
162 ...$ids
163 );
164 $visitors = intval($wpdb->get_var($visitors_query));
165
166 $prev_period_query = $wpdb->prepare(
167 "
168 SELECT
169 COUNT(*) as views,
170 COUNT(DISTINCT sessions.visitor_id) as visitors
171 FROM $views_table AS views
172 LEFT JOIN $sessions_table AS sessions ON views.session_id = sessions.session_id
173 LEFT JOIN $visitors_table AS visitors ON sessions.visitor_id = visitors.visitor_id
174 WHERE views.viewed_at BETWEEN %s AND %s
175 AND (%d = 1 OR $column IN ($in) $null_check)
176 AND ('$type' != 'GEO' OR visitors.country_code IS NOT NULL)
177 AND ('$type' != 'CAMPAIGNS' OR sessions.campaign_id IS NOT NULL)
178 ",
179 $this->prev_period_formatted_start(),
180 $this->prev_period_formatted_end(),
181 $skip_in,
182 ...$ids
183 );
184 $prev_period_results = $wpdb->get_row($prev_period_query);
185 $prev_period_views = intval($prev_period_results->views);
186 $prev_period_visitors = intval($prev_period_results->visitors);
187
188 $views = 0;
189 $daily_views = [];
190 $daily_visitors = [];
191
192 foreach ($rows as $row) {
193 $views += $row->views;
194 $daily_views[] = [$row->date, intval($row->views)];
195 $daily_visitors[] = [$row->date, intval($row->visitors)];
196 }
197
198 $this->views = $views;
199 $this->prev_period_views = $prev_period_views;
200 $this->visitors = $visitors;
201 $this->prev_period_visitors = $prev_period_visitors;
202 $this->daily_views = $this->fill_in_data_range($daily_views);
203 $this->daily_visitors = $this->fill_in_data_range($daily_visitors);
204 }
205
206 private function fill_in_data_range($partial_data)
207 {
208 $interval = new \DateInterval('P1D');
209 $start = clone $this->start();
210 $end = clone $this->end();
211 $user_timezone = new \DateTimeZone(Timezone::local_offset());
212 $start->setTimezone($user_timezone);
213 $end->setTimezone($user_timezone);
214
215 $date_range = new \DatePeriod($start, $interval, $end);
216 $new_data = [];
217
218 foreach ($date_range as $date) {
219 $views = 0;
220
221 foreach ($partial_data as $data_point) {
222 if ($date == (new \DateTime($data_point[0], $user_timezone))) {
223 $views = intval($data_point[1]);
224 break;
225 }
226 }
227
228 $new_data[] = [$date, $views];
229 }
230
231 return $new_data;
232 }
233 }
234