Commit 5de5ebaee0eb9523962d4a571c09ff8b157280e6
1 parent
c6c9c77e
фиксы по гуглу: множественные дименшины, сортировка, лимит, трансформер для графиков
Showing
3 changed files
with
342 additions
and
70 deletions
Show diff stats
app/library/App/Controllers/GaController.php
... | ... | @@ -10,12 +10,15 @@ namespace App\Controllers; |
10 | 10 | |
11 | 11 | |
12 | 12 | use App\Model\Project; |
13 | +use Codeception\Exception\ContentNotFound; | |
14 | +use DateTime; | |
13 | 15 | use Google_Client; |
14 | 16 | use Google_Service_AnalyticsReporting; |
15 | 17 | use Google_Service_AnalyticsReporting_DateRange; |
16 | 18 | use Google_Service_AnalyticsReporting_Dimension; |
17 | 19 | use Google_Service_AnalyticsReporting_GetReportsRequest; |
18 | 20 | use Google_Service_AnalyticsReporting_Metric; |
21 | +use Google_Service_AnalyticsReporting_OrderBy; | |
19 | 22 | use Google_Service_AnalyticsReporting_ReportRequest; |
20 | 23 | use PhalconRest\Mvc\Controllers\CrudResourceController; |
21 | 24 | |
... | ... | @@ -25,6 +28,11 @@ class GaController extends CrudResourceController { |
25 | 28 | const VIEW_ID = '119240817'; |
26 | 29 | const SCOPE = 'https://www.googleapis.com/auth/analytics.readonly'; |
27 | 30 | |
31 | + /** | |
32 | + * Main action for /ga request. Send it google report api. | |
33 | + * | |
34 | + * @return array | |
35 | + */ | |
28 | 36 | public function getAction() { |
29 | 37 | |
30 | 38 | /** user params **/ |
... | ... | @@ -38,22 +46,53 @@ class GaController extends CrudResourceController { |
38 | 46 | $get_start_date = $this->request->get('start') ?? '30daysAgo'; |
39 | 47 | $get_end_date = $this->request->get('end') ?? 'today'; |
40 | 48 | $filter_expression = $this->request->get('filter'); |
41 | - | |
42 | - | |
43 | - if (empty($view_id)) { | |
44 | - $result = []; | |
45 | - $projects = Project::find(['user_id' => $user_id]); | |
46 | - foreach ($projects as $project) { | |
47 | - $view_id = (string)$project->ga_view_id; | |
48 | - if (!empty($view_id)) { | |
49 | - $result[] = $this->sendGaRequest($project->name, $view_id, $get_metrics, $get_dimensions, $get_start_date, $get_end_date, $chart, $filter_expression); | |
49 | + $sort = $this->request->get('sort'); | |
50 | + $sort_type = $this->request->get('sort_type'); | |
51 | + $max_result = $this->request->get('max_result'); | |
52 | + | |
53 | + | |
54 | + /** if empty $_GET["view_id"] send request to all projects in user's model **/ | |
55 | + if (empty($view_id)) { | |
56 | + $result = []; | |
57 | + $projects = Project::find(['user_id' => $user_id]); | |
58 | + foreach ($projects as $project) { | |
59 | + $view_id = (string)$project->ga_view_id; | |
60 | + if (!empty($view_id)) { | |
61 | + $result[] = $this->sendGaRequest( | |
62 | + $project->name, | |
63 | + $view_id, | |
64 | + $get_metrics, | |
65 | + $get_dimensions, | |
66 | + $get_start_date, | |
67 | + $get_end_date, | |
68 | + $chart, | |
69 | + $filter_expression, | |
70 | + $sort, | |
71 | + $sort_type, | |
72 | + $max_result | |
73 | + ); | |
74 | + } | |
50 | 75 | } |
51 | 76 | } |
52 | - } | |
53 | - else { | |
54 | - $project = Project::findFirst(['ga_view_id' => $view_id]); | |
55 | - $result = $this->sendGaRequest($project->name , $view_id, $get_metrics, $get_dimensions, $get_start_date, $get_end_date, $chart, $filter_expression); | |
56 | - } | |
77 | + else { | |
78 | + $project = Project::findFirst([ | |
79 | + "ga_view_id = '$view_id'", | |
80 | + ]); | |
81 | + $result = $this->sendGaRequest( | |
82 | + $project->name, | |
83 | + $view_id, | |
84 | + $get_metrics, | |
85 | + $get_dimensions, | |
86 | + $get_start_date, | |
87 | + $get_end_date, | |
88 | + $chart, | |
89 | + $filter_expression, | |
90 | + $sort, | |
91 | + $sort_type, | |
92 | + $max_result | |
93 | + ); | |
94 | + } | |
95 | + /** --------------------------------------------------------------- **/ | |
57 | 96 | return $result; |
58 | 97 | |
59 | 98 | } |
... | ... | @@ -69,9 +108,12 @@ class GaController extends CrudResourceController { |
69 | 108 | * @param string $end |
70 | 109 | * @param bool $chart |
71 | 110 | * @param string $filter_expression |
111 | + * @param string $sort | |
112 | + * @param string $sort_type | |
113 | + * @param int $max_result | |
72 | 114 | * @return array |
73 | 115 | */ |
74 | - public function sendGaRequest($project_name, $view, $get_metrics, $get_dimensions, $start, $end, $chart = false, $filter_expression = null) { | |
116 | + public function sendGaRequest($project_name, $view, $get_metrics, $get_dimensions, $start, $end, $chart = false, $filter_expression = null, $sort = null, $sort_type = 'desc', $max_result = 50000) { | |
75 | 117 | |
76 | 118 | putenv('GOOGLE_APPLICATION_CREDENTIALS=/var/www/phalcon/'.self::SECRET_JSON); |
77 | 119 | $client = new Google_Client(); |
... | ... | @@ -80,57 +122,89 @@ class GaController extends CrudResourceController { |
80 | 122 | $analytics = new Google_Service_AnalyticsReporting($client); |
81 | 123 | |
82 | 124 | /** Create the DateRange object. **/ |
83 | - $dateRange = new Google_Service_AnalyticsReporting_DateRange(); | |
84 | - $dateRange->setStartDate($start); | |
85 | - $dateRange->setEndDate($end); | |
125 | + $dateRange = new Google_Service_AnalyticsReporting_DateRange(); | |
126 | + $dateRange->setStartDate($start); | |
127 | + $dateRange->setEndDate($end); | |
128 | + /** ---------------------------- **/ | |
86 | 129 | |
87 | 130 | /** Create the Metrics object. **/ |
88 | - $metrics = []; | |
89 | - $get_metrics = explode(',', $get_metrics); | |
90 | - foreach ($get_metrics as $metric) { | |
91 | - $metrics_obj = new Google_Service_AnalyticsReporting_Metric(); | |
92 | - $metrics_obj->setExpression('ga:'.$metric); | |
93 | - $metrics_obj->setAlias('ga:'.$metric); | |
94 | - $metrics[] = $metrics_obj; | |
95 | - } | |
131 | + $metrics = []; | |
132 | + $get_metrics = explode(',', $get_metrics); | |
133 | + foreach ($get_metrics as $metric) { | |
134 | + $metrics_obj = new Google_Service_AnalyticsReporting_Metric(); | |
135 | + $metrics_obj->setExpression('ga:'.$metric); | |
136 | + $metrics_obj->setAlias('ga:'.$metric); | |
137 | + $metrics[] = $metrics_obj; | |
138 | + } | |
139 | + /** -------------------------- **/ | |
96 | 140 | |
97 | 141 | /** Create the Dimensions object. **/ |
98 | - if (!empty($get_dimensions)) { | |
99 | - $dimensions = []; | |
100 | - $get_dimensions = explode(',', $get_dimensions); | |
101 | - foreach ($get_dimensions as $dimension) { | |
102 | - $dimension_obj = new Google_Service_AnalyticsReporting_Dimension(); | |
103 | - $dimension_obj->setName("ga:".$dimension); | |
104 | - $dimensions[] = $dimension_obj; | |
142 | + if (!empty($get_dimensions)) { | |
143 | + $dimensions = []; | |
144 | + $get_dimensions = explode(',', $get_dimensions); | |
145 | + foreach ($get_dimensions as $dimension) { | |
146 | + $dimension_obj = new Google_Service_AnalyticsReporting_Dimension(); | |
147 | + $dimension_obj->setName("ga:".$dimension); | |
148 | + $dimensions[] = $dimension_obj; | |
149 | + } | |
105 | 150 | } |
106 | - } | |
151 | + /** ----------------------------- **/ | |
107 | 152 | |
108 | 153 | /** Create the ReportRequest object. **/ |
109 | - $request = new Google_Service_AnalyticsReporting_ReportRequest(); | |
110 | - $request->setViewId($view); | |
111 | - $request->setDateRanges($dateRange); | |
112 | - $request->setIncludeEmptyRows(true); | |
113 | - if (!empty($dimensions)) { | |
114 | - $request->setDimensions(array($dimensions)); | |
115 | - } | |
116 | - $request->setMetrics(array($metrics)); | |
117 | - if (!empty($filter_expression)) { | |
118 | - $request->setFiltersExpression("ga:".$filter_expression); | |
119 | - } | |
154 | + $request = new Google_Service_AnalyticsReporting_ReportRequest(); | |
155 | + $request->setViewId($view); | |
156 | + $request->setPageSize($max_result); | |
157 | + $request->setDateRanges($dateRange); | |
158 | + $request->setIncludeEmptyRows(true); | |
159 | + /** Create the Ordering **/ | |
160 | + if (isset($sort)) { | |
161 | + $ordering = new Google_Service_AnalyticsReporting_OrderBy(); | |
162 | + $ordering->setFieldName("ga:".$sort); | |
163 | + $ordering->setOrderType("VALUE"); | |
164 | + $ordering->setSortOrder("DESCENDING"); | |
165 | + if ($sort_type == 'asc') { | |
166 | + $ordering->setSortOrder("ASCENDING"); | |
167 | + } | |
168 | + $request->setOrderBys($ordering); | |
169 | + } | |
170 | + /** --------------- **/ | |
171 | + if (!empty($dimensions)) { | |
172 | + $request->setDimensions(array($dimensions)); | |
173 | + } | |
174 | + $request->setMetrics(array($metrics)); | |
175 | + if (!empty($filter_expression)) { | |
176 | + $request->setFiltersExpression("ga:".$filter_expression); | |
177 | + } | |
178 | + /** compute days in request **/ | |
179 | + $request_date['start'] = new DateTime(date('d.m.Y', strtotime($request->getDateRanges()['startDate']))); | |
180 | + $request_date['end'] = new DateTime(date('d.m.Y', strtotime($request->getDateRanges()['endDate']))); | |
181 | + $request_days = (date_diff($request_date['start'], $request_date['end'])->days)+1; | |
182 | + /** ----------------------- **/ | |
183 | + $request_dim = $request->getDimensions(); | |
184 | + if (count($request_dim[0]) == 2) { | |
185 | + $request_dim = $request_dim[0][1]->name; | |
186 | + } | |
187 | + else { | |
188 | + $request_dim = $request_dim[0][0]->name; | |
189 | + } | |
190 | + $iterations = self::countIterations($request_dim, $request_days); | |
191 | + /** ---------------------------- **/ | |
120 | 192 | |
121 | 193 | $body = new Google_Service_AnalyticsReporting_GetReportsRequest(); |
122 | 194 | $body->setReportRequests(array($request)); |
123 | 195 | |
124 | 196 | $response = $analytics->reports->batchGet($body); |
125 | 197 | |
126 | - /** can be refactored (code below 2 rows) **/ | |
198 | + //can be refactored (code below, 2 rows) | |
127 | 199 | $response = $response->toSimpleObject(); |
128 | 200 | $response = $response->reports[0]['data']['rows']; |
129 | 201 | |
130 | 202 | if ($chart) { |
131 | - $result = self::responseChartTransform($response, $project_name); | |
203 | + //$result = self::responseChartTransform($response, $project_name); | |
204 | + $result = self::responseDataTransform($response, $iterations, $request_dim, $project_name); | |
205 | + $result = self::chartTransform($result); | |
132 | 206 | } else { |
133 | - $result = self::responseDataTransform($response, $project_name); | |
207 | + $result = self::responseDataTransform($response, $iterations, $request_dim, $project_name); | |
134 | 208 | } |
135 | 209 | |
136 | 210 | return $result; |
... | ... | @@ -141,29 +215,84 @@ class GaController extends CrudResourceController { |
141 | 215 | * Data-transformer for tables. Used by default. |
142 | 216 | * |
143 | 217 | * @param array $response |
218 | + * @param int $iterations | |
219 | + * @param string $request_dimension | |
144 | 220 | * @param string $project_name |
145 | 221 | * @return array |
146 | 222 | */ |
147 | - public static function responseDataTransform(array $response, $project_name) { | |
223 | + public static function responseDataTransform(array $response, $iterations, $request_dimension, $project_name) { | |
148 | 224 | |
149 | - $result = []; | |
225 | + $result = []; | |
226 | + $int_query = true; | |
227 | + $max_values = 0; | |
150 | 228 | |
151 | 229 | foreach ($response as $item) { |
152 | 230 | |
153 | 231 | $metric_val = $item['metrics'][0]['values']; |
154 | 232 | $dimension_val = $item['dimensions'][0]; |
233 | + $dimension_count = count($item['dimensions']); | |
234 | + | |
235 | + /** remove "0001" from dimension keys **/ | |
236 | + for ($i = 0; $i < $dimension_count; $i++) { | |
237 | + $current_value = $item['dimensions'][$i]; | |
238 | + if (ctype_digit(strval($current_value))) { | |
239 | + $item['dimensions'][$i] = (int)$current_value; | |
240 | + if ($i == 0) { | |
241 | + $dimension_val = (int)$current_value; | |
242 | + } | |
243 | + } | |
244 | + elseif ($i == 1) { | |
245 | + $int_query = false; | |
246 | + } | |
247 | + } | |
248 | + /** --------------------------------- **/ | |
155 | 249 | |
156 | - $result['name'] = $project_name; | |
157 | 250 | |
158 | - if (count($metric_val) > 1) { | |
159 | - for ($i = 0; $i < count($metric_val); $i++) { | |
160 | - $result[$dimension_val][] = $metric_val[$i]; | |
251 | + if ($dimension_count == 2) { | |
252 | + $dimension_val_2 = $item['dimensions'][1]; | |
253 | + if (count($metric_val) > 1) { | |
254 | + for ($i = 0; $i < count($metric_val); $i++) { | |
255 | + $result[$dimension_val][$dimension_val_2][] = (int)$metric_val[$i]; | |
256 | + } | |
257 | + } else { | |
258 | + $result[$dimension_val][$dimension_val_2] = (int)$metric_val[0]; | |
259 | + } | |
260 | + } | |
261 | + else { | |
262 | + if (count($metric_val) > 1) { | |
263 | + for ($i = 0; $i < count($metric_val); $i++) { | |
264 | + $result[$dimension_val][] = (int)$metric_val[$i]; | |
265 | + } | |
266 | + } else { | |
267 | + $result[$dimension_val] = (int)$metric_val[0]; | |
161 | 268 | } |
162 | - } else { | |
163 | - $result[$dimension_val] = $metric_val[0]; | |
164 | 269 | } |
270 | + | |
271 | + $dim_val_count = count($result[$dimension_val]); | |
272 | + if ($dim_val_count > $max_values) $max_values = $dim_val_count; | |
273 | + unset($dim_val_count); | |
274 | + | |
165 | 275 | } |
166 | 276 | |
277 | + $int_query = self::checkDimension($request_dimension); | |
278 | + | |
279 | + /** ------ filling missing data ------ **/ | |
280 | + if ($int_query) { | |
281 | + foreach ($result as $key => $item) { | |
282 | + if (!is_array($item)) break; | |
283 | + $iterations = $iterations ?? $max_values; | |
284 | + for ($i = 0; $i < $iterations; $i++) { | |
285 | + $result[$key][$i] = $item[$i] ?? 0; | |
286 | + } | |
287 | + ksort($result[$key]); | |
288 | + } | |
289 | + } | |
290 | + /** --------------------------------- **/ | |
291 | + | |
292 | + /** ----- add custom fields ------ **/ | |
293 | + $result['name'] = $project_name ?? 'Неизвестный проект'; | |
294 | + /** ------------------------------ **/ | |
295 | + | |
167 | 296 | return $result; |
168 | 297 | |
169 | 298 | } |
... | ... | @@ -171,6 +300,91 @@ class GaController extends CrudResourceController { |
171 | 300 | /** |
172 | 301 | * Data-transformer for charts, when query string contains "?chart=true" |
173 | 302 | * |
303 | + * @param array $data | |
304 | + * @return array | |
305 | + */ | |
306 | + public static function chartTransform(array $data) { | |
307 | + $result = []; | |
308 | + foreach ($data as $key => $value) { | |
309 | + if ($key === 'name') { | |
310 | + $result[$key] = $value; | |
311 | + } | |
312 | + else { | |
313 | + if (!is_array($value)) { | |
314 | + $result['data'][] = $value; | |
315 | + } | |
316 | + else { | |
317 | + foreach ($value as $v_key => $v_value) { | |
318 | + $result['data'][$key][$v_key] = $v_value; | |
319 | + } | |
320 | + ksort($result['data'][$key]); | |
321 | + } | |
322 | + } | |
323 | + } | |
324 | + | |
325 | + return $result; | |
326 | + } | |
327 | + | |
328 | + /** | |
329 | + * Deprecated | |
330 | + * | |
331 | + * @param array $data | |
332 | + * @return array | |
333 | + */ | |
334 | + public static function chartTransform1(array $data) { | |
335 | + | |
336 | + $result = []; | |
337 | + $max = 0; | |
338 | + | |
339 | + foreach ($data as $key => $value) { | |
340 | + if ($key == 'name') { | |
341 | + $result[$key] = $value; | |
342 | + continue; | |
343 | + } | |
344 | + | |
345 | + if (!is_array($value)) break; | |
346 | + | |
347 | + /** ------ check array keys for int values --- **/ | |
348 | + $count = count($value); | |
349 | + if ($count > $max) $max = $count; | |
350 | + $int_type = true; | |
351 | + foreach ($value as $inc_key => $inc_value) { | |
352 | + if (!preg_match('/\d+/', $inc_key)) { | |
353 | + $int_type = false; | |
354 | + break; | |
355 | + } | |
356 | + } | |
357 | + /** ------------------------------------------ **/ | |
358 | + | |
359 | + /** rewrites keys like "0001" to integer type **/ | |
360 | + if ($int_type) { | |
361 | + $bad_keys = array_keys($value); | |
362 | + for ($i = 0; $i < $count; $i++) { | |
363 | + $good_key = (int)$bad_keys[$i]; | |
364 | + $result[$key][$good_key] = $value[$bad_keys[$i]] ?? 0; | |
365 | + } | |
366 | + } | |
367 | + /** ------------------------------------------ **/ | |
368 | + | |
369 | + } | |
370 | + | |
371 | + /** ---------- filling missing data ---------- **/ | |
372 | + foreach ($result as $key => $value) { | |
373 | + if ($key == 'name') continue; | |
374 | + for ($i = 0; $i < $max; $i++) { | |
375 | + $result[$key][$i] = (int)$result[$key][$i] ?? 0; | |
376 | + } | |
377 | + ksort($result[$key]); | |
378 | + } | |
379 | + /** ------------------------------------------ **/ | |
380 | + | |
381 | + return $result; | |
382 | + | |
383 | + } | |
384 | + | |
385 | + /** | |
386 | + * Deprecated | |
387 | + * | |
174 | 388 | * @param array $response |
175 | 389 | * @param string $project_name |
176 | 390 | * @return array |
... | ... | @@ -181,15 +395,30 @@ class GaController extends CrudResourceController { |
181 | 395 | |
182 | 396 | foreach ($response as $item) { |
183 | 397 | |
184 | - $metric_val = $item['metrics'][0]['values']; | |
185 | 398 | $result['name'] = $project_name; |
186 | 399 | |
187 | - if (count($metric_val) > 1) { | |
188 | - for ($i = 0; $i < count($metric_val); $i++) { | |
189 | - $result['data'][] = (int)$metric_val[$i]; | |
400 | + $metric_val = $item['metrics'][0]['values']; | |
401 | + $dimension_val = $item['dimensions'][0]; | |
402 | + $dimension_count = count($item['dimensions']); | |
403 | + | |
404 | + if ($dimension_count == 2) { | |
405 | + $dimension_val_2 = $item['dimensions'][1]; | |
406 | + if (count($metric_val) > 1) { | |
407 | + for ($i = 0; $i < count($metric_val); $i++) { | |
408 | + $result['data'][$dimension_val][] = (int)$metric_val[$i]; | |
409 | + } | |
410 | + } else { | |
411 | + $result['data'][$dimension_val][] = (int)$metric_val[0]; | |
412 | + } | |
413 | + } | |
414 | + else { | |
415 | + if (count($metric_val) > 1) { | |
416 | + for ($i = 0; $i < count($metric_val); $i++) { | |
417 | + $result['data'][] = (int)$metric_val[$i]; | |
418 | + } | |
419 | + } else { | |
420 | + $result['data'][] = (int)$metric_val[0]; | |
190 | 421 | } |
191 | - } else { | |
192 | - $result['data'][] = (int)$metric_val[0]; | |
193 | 422 | } |
194 | 423 | } |
195 | 424 | |
... | ... | @@ -197,6 +426,49 @@ class GaController extends CrudResourceController { |
197 | 426 | |
198 | 427 | } |
199 | 428 | |
429 | + /** | |
430 | + * Compute count of fields | |
431 | + * | |
432 | + * @param string $request_dim | |
433 | + * @param int $request_days | |
434 | + * @return int | |
435 | + * @throws ContentNotFound if functions params is empty | |
436 | + */ | |
437 | + public static function countIterations($request_dim, $request_days) { | |
438 | + | |
439 | + if (empty($request_dim)) throw new ContentNotFound('PHP: request_dim not found'); | |
440 | + if (empty($request_days)) throw new ContentNotFound('PHP: request_days not found'); | |
441 | + switch ($request_dim) { | |
442 | + case 'ga:nthDay': | |
443 | + $iterations = $request_days*1; | |
444 | + break; | |
445 | + case 'ga:nthHour': | |
446 | + $iterations = $request_days*24; | |
447 | + break; | |
448 | + case 'ga:nthMinute': | |
449 | + $iterations = $request_days*24*60; | |
450 | + break; | |
451 | + default: | |
452 | + $iterations = null; | |
453 | + } | |
454 | + | |
455 | + return $iterations; | |
456 | + | |
457 | + } | |
458 | + | |
459 | + /** | |
460 | + * Boolean indicator for chart transformer | |
461 | + * | |
462 | + * @param string $dimension | |
463 | + * @return bool | |
464 | + */ | |
465 | + public static function checkDimension($dimension) { | |
466 | + | |
467 | + $nthArray = ['ga:nthMonth', 'ga:nthWeek', 'ga:nthDay', 'ga:nthMinute', 'ga:nthHour']; | |
468 | + | |
469 | + return in_array($dimension, $nthArray) ? true : false; | |
470 | + | |
471 | + } | |
200 | 472 | |
201 | 473 | /** |
202 | 474 | * without usage, from google docs. | ... | ... |
app/library/App/Controllers/UserController.php
app/library/App/Resources/GaResource.php
... | ... | @@ -21,7 +21,6 @@ class GaResource extends ApiResource { |
21 | 21 | $this |
22 | 22 | ->name('Google Analytics') |
23 | 23 | ->expectsJsonData() |
24 | - //->transformer(ModelTransformer::class) | |
25 | 24 | ->itemKey('ga') |
26 | 25 | ->collectionKey('ga') |
27 | 26 | ->deny(AclRoles::UNAUTHORIZED) |
... | ... | @@ -49,13 +48,15 @@ class GaResource extends ApiResource { |
49 | 48 | 'end' => 'ГГГГ-ММ-ДД/NdaysAgo, где N – целое положительное число(дата конца загрузки данных)' |
50 | 49 | ], |
51 | 50 | 'optional params' => [ |
52 | - 'user_id' => 'integer(id пользователя в системе)', | |
53 | - 'view_id' => 'integer(id представления проэкта с гугл аналитики)', | |
54 | - 'chart' => 'boolean(Задает структуру возвращаемых данных(true для графиков))', | |
55 | - 'filter' => 'expression(https://developers.google.com/analytics/devguides/reporting/core/v3/reference#filters)', | |
51 | + 'user_id' => 'integer(id пользователя в системе)', | |
52 | + 'view_id' => 'integer(id представления проэкта с гугл аналитики)', | |
53 | + 'chart' => 'boolean(Задает структуру возвращаемых данных(true для графиков))', | |
54 | + 'filter' => 'expression(https://developers.google.com/analytics/devguides/reporting/core/v3/reference#filters)', | |
55 | + 'sort' => 'string(параметр сортировки, metric либо dimension)', | |
56 | + 'sort_type' => 'enum(ans, desc)', | |
57 | + 'max_result' => 'integer(максимальное число строк в результате, по умолчанию 50,000)', | |
56 | 58 | ] |
57 | - ], | |
58 | - 'summary' => '/ga?view_id=119240817&metric=users,sessions&dimension=source,browser&filter=browser=~^Firef' | |
59 | + ] | |
59 | 60 | ]) |
60 | 61 | ) |
61 | 62 | ; | ... | ... |