├── README.md ├── config └── gapi.php ├── controllers └── Example.php ├── libraries └── Gapi.php └── views └── example_view.php /README.md: -------------------------------------------------------------------------------- 1 | # Google Analytics API with Codeigniter # 2 | 3 | Works with [gapi-google-analytics-php-interface](https://github.com/erebusnz/gapi-google-analytics-php-interface) 4 | 5 | **config/gapi.php** 6 | 7 | ``` 8 | $config['account_email'] = '847834925186-siheminq2k5rk84a03enev9jin2m3aq6@developer.gserviceaccount.com'; 9 | ``` 10 | 11 | This is the email address of your Google Project's service account. 12 | 13 | ``` 14 | $config['p12_key'] = 'assets/admin/Analytics-ef0175d30222.p12'; 15 | ``` 16 | 17 | This is the .p12 key file's location. 18 | 19 | ``` 20 | $config['ga_profile_id'] = '54982801'; 21 | ``` 22 | 23 | Profile ID of your website on Google Anaytics. 24 | 25 | For Turkish documentation [Click Here!](http://www.turankaratug.com/blog/php/3-codeigniter-ile-google-analytics-verilerini-cekmek) -------------------------------------------------------------------------------- /config/gapi.php: -------------------------------------------------------------------------------- 1 | load->config('gapi'); 14 | $params = [ 'client_email' => $this->config->item('account_email'), 'key_file' => $this->config->item('p12_key') ]; 15 | $this->load->library('gapi', $params); 16 | 17 | $this->gapi->requestReportData($this->config->item('ga_profile_id'), array('day'), array('sessions','users','pageviews','organicSearches','bounceRate'), 'day', '', date('Y-m-01'), date('Y-m-d'), 1, 500); 18 | $data['totalSessions'] = $this->gapi->getSessions(); 19 | $data['totalUsers'] = $this->gapi->getUsers(); 20 | $data['totalPageViews'] = $this->gapi->getPageviews(); 21 | $data['totalOrganik'] = $this->gapi->getOrganicSearches(); 22 | $data['totalBounce'] = $this->gapi->getBounceRate(); 23 | 24 | $this->load->view('exampla_view',$data); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /libraries/Gapi.php: -------------------------------------------------------------------------------- 1 | . 22 | * 23 | * @author Stig Manning 24 | * @author Joel Kitching 25 | * @author Cliff Gordon 26 | * @version 2.0 27 | * 28 | */ 29 | 30 | class gapi { 31 | const account_data_url = 'https://www.googleapis.com/analytics/v3/management/accountSummaries'; 32 | const report_data_url = 'https://www.googleapis.com/analytics/v3/data/ga'; 33 | const interface_name = 'GAPI-2.0'; 34 | const dev_mode = false; 35 | 36 | private $auth_method = null; 37 | private $account_entries = array(); 38 | private $report_aggregate_metrics = array(); 39 | private $report_root_parameters = array(); 40 | private $results = array(); 41 | 42 | private $client_email = null; 43 | private $key_file = null; 44 | 45 | /** 46 | * Constructor function for new gapi instances 47 | * 48 | * @param string $client_email Email of OAuth2 service account (XXXXX@developer.gserviceaccount.com) 49 | * @param string $key_file Location/filename of .p12 key file 50 | * @param string $delegate_email Optional email of account to impersonate 51 | * @return gapi 52 | */ 53 | public function __construct($login_params = array(), $delegate_email = null) { 54 | if (version_compare(PHP_VERSION, '5.3.0') < 0) { 55 | throw new Exception('GAPI: PHP version ' . PHP_VERSION . ' is below minimum required 5.3.0.'); 56 | } 57 | $this->client_email = $login_params['client_email']; 58 | $this->key_file = $login_params['key_file']; 59 | $this->auth_method = new gapiOAuth2(); 60 | $this->auth_method->fetchToken($this->client_email, $this->key_file, $delegate_email); 61 | } 62 | 63 | /** 64 | * Return the auth token string retrieved by Google 65 | * 66 | * @return String 67 | */ 68 | public function getToken() { 69 | return $this->auth_method->getToken(); 70 | } 71 | 72 | /** 73 | * Return the auth token information from the Google service 74 | * 75 | * @return Array 76 | */ 77 | public function getTokenInfo() { 78 | return $this->auth_method->getTokenInfo(); 79 | } 80 | 81 | /** 82 | * Revoke the current auth token, rendering it invalid for future requests 83 | * 84 | * @return Boolean 85 | */ 86 | public function revokeToken() { 87 | return $this->auth_method->revokeToken(); 88 | } 89 | 90 | /** 91 | * Request account data from Google Analytics 92 | * 93 | * @param Int $start_index OPTIONAL: Start index of results 94 | * @param Int $max_results OPTIONAL: Max results returned 95 | */ 96 | public function requestAccountData($start_index=1, $max_results=1000) { 97 | $get_variables = array( 98 | 'start-index' => $start_index, 99 | 'max-results' => $max_results, 100 | ); 101 | $url = new gapiRequest(gapi::account_data_url); 102 | $response = $url->get($get_variables, $this->auth_method->generateAuthHeader()); 103 | 104 | if (substr($response['code'], 0, 1) == '2') { 105 | return $this->accountObjectMapper($response['body']); 106 | } else { 107 | throw new Exception('GAPI: Failed to request account data. Error: "' . strip_tags($response['body']) . '"'); 108 | } 109 | } 110 | 111 | /** 112 | * Request report data from Google Analytics 113 | * 114 | * $report_id is the Google report ID for the selected account 115 | * 116 | * $parameters should be in key => value format 117 | * 118 | * @param String $report_id 119 | * @param Array $dimensions Google Analytics dimensions e.g. array('browser') 120 | * @param Array $metrics Google Analytics metrics e.g. array('pageviews') 121 | * @param Array $sort_metric OPTIONAL: Dimension or dimensions to sort by e.g.('-visits') 122 | * @param String $filter OPTIONAL: Filter logic for filtering results 123 | * @param String $start_date OPTIONAL: Start of reporting period 124 | * @param String $end_date OPTIONAL: End of reporting period 125 | * @param Int $start_index OPTIONAL: Start index of results 126 | * @param Int $max_results OPTIONAL: Max results returned 127 | */ 128 | public function requestReportData($report_id, $dimensions=null, $metrics, $sort_metric=null, $filter=null, $start_date=null, $end_date=null, $start_index=1, $max_results=10000) { 129 | $parameters = array('ids'=>'ga:' . $report_id); 130 | 131 | if (is_array($dimensions)) { 132 | $dimensions_string = ''; 133 | foreach ($dimensions as $dimesion) { 134 | $dimensions_string .= ',ga:' . $dimesion; 135 | } 136 | $parameters['dimensions'] = substr($dimensions_string, 1); 137 | } elseif ($dimensions !== null) { 138 | $parameters['dimensions'] = 'ga:'.$dimensions; 139 | } 140 | 141 | if (is_array($metrics)) { 142 | $metrics_string = ''; 143 | foreach ($metrics as $metric) { 144 | $metrics_string .= ',ga:' . $metric; 145 | } 146 | $parameters['metrics'] = substr($metrics_string, 1); 147 | } else { 148 | $parameters['metrics'] = 'ga:'.$metrics; 149 | } 150 | 151 | if ($sort_metric==null&&isset($parameters['metrics'])) { 152 | $parameters['sort'] = $parameters['metrics']; 153 | } elseif (is_array($sort_metric)) { 154 | $sort_metric_string = ''; 155 | 156 | foreach ($sort_metric as $sort_metric_value) { 157 | //Reverse sort - Thanks Nick Sullivan 158 | if (substr($sort_metric_value, 0, 1) == "-") { 159 | $sort_metric_string .= ',-ga:' . substr($sort_metric_value, 1); // Descending 160 | } 161 | else { 162 | $sort_metric_string .= ',ga:' . $sort_metric_value; // Ascending 163 | } 164 | } 165 | 166 | $parameters['sort'] = substr($sort_metric_string, 1); 167 | } else { 168 | if (substr($sort_metric, 0, 1) == "-") { 169 | $parameters['sort'] = '-ga:' . substr($sort_metric, 1); 170 | } else { 171 | $parameters['sort'] = 'ga:' . $sort_metric; 172 | } 173 | } 174 | 175 | if ($filter!=null) { 176 | $filter = $this->processFilter($filter); 177 | if ($filter!==false) { 178 | $parameters['filters'] = $filter; 179 | } 180 | } 181 | 182 | if ($start_date==null) { 183 | // Use the day that Google Analytics was released (1 Jan 2005). 184 | $start_date = '2005-01-01'; 185 | } elseif (is_int($start_date)) { 186 | // Perhaps we are receiving a Unix timestamp. 187 | $start_date = date('Y-m-d', $start_date); 188 | } 189 | 190 | $parameters['start-date'] = $start_date; 191 | 192 | if ($end_date==null) { 193 | $end_date = date('Y-m-d'); 194 | } elseif (is_int($end_date)) { 195 | // Perhaps we are receiving a Unix timestamp. 196 | $end_date = date('Y-m-d', $end_date); 197 | } 198 | 199 | $parameters['end-date'] = $end_date; 200 | 201 | 202 | $parameters['start-index'] = $start_index; 203 | $parameters['max-results'] = $max_results; 204 | 205 | $parameters['prettyprint'] = gapi::dev_mode ? 'true' : 'false'; 206 | 207 | $url = new gapiRequest(gapi::report_data_url); 208 | $response = $url->get($parameters, $this->auth_method->generateAuthHeader()); 209 | 210 | //HTTP 2xx 211 | if (substr($response['code'], 0, 1) == '2') { 212 | return $this->reportObjectMapper($response['body']); 213 | } else { 214 | throw new Exception('GAPI: Failed to request report data. Error: "' . $this->cleanErrorResponse($response['body']) . '"'); 215 | } 216 | } 217 | 218 | /** 219 | * Clean error message from Google API 220 | * 221 | * @param String $error Error message HTML or JSON from Google API 222 | */ 223 | private function cleanErrorResponse($error) { 224 | if (strpos($error, ']*>[^<]*<\/(style|title|script)>/i', '', $error); 226 | return trim(preg_replace('/\s+/', ' ', strip_tags($error))); 227 | } 228 | else 229 | { 230 | $json = json_decode($error); 231 | return isset($json->error->message) ? strval($json->error->message) : $error; 232 | } 233 | } 234 | 235 | /** 236 | * Process filter string, clean parameters and convert to Google Analytics 237 | * compatible format 238 | * 239 | * @param String $filter 240 | * @return String Compatible filter string 241 | */ 242 | protected function processFilter($filter) { 243 | $valid_operators = '(!~|=~|==|!=|>|<|>=|<=|=@|!@)'; 244 | 245 | $filter = preg_replace('/\s\s+/', ' ', trim($filter)); //Clean duplicate whitespace 246 | $filter = str_replace(array(',', ';'), array('\,', '\;'), $filter); //Escape Google Analytics reserved characters 247 | $filter = preg_replace('/(&&\s*|\|\|\s*|^)([a-z0-9]+)(\s*' . $valid_operators . ')/i','$1ga:$2$3',$filter); //Prefix ga: to metrics and dimensions 248 | $filter = preg_replace('/[\'\"]/i', '', $filter); //Clear invalid quote characters 249 | $filter = preg_replace(array('/\s*&&\s*/','/\s*\|\|\s*/','/\s*' . $valid_operators . '\s*/'), array(';', ',', '$1'), $filter); //Clean up operators 250 | 251 | if (strlen($filter) > 0) { 252 | return urlencode($filter); 253 | } 254 | else { 255 | return false; 256 | } 257 | } 258 | 259 | /** 260 | * Report Account Mapper to convert the JSON to array of useful PHP objects 261 | * 262 | * @param String $json_string 263 | * @return Array of gapiAccountEntry objects 264 | */ 265 | protected function accountObjectMapper($json_string) { 266 | $json = json_decode($json_string, true); 267 | $results = array(); 268 | 269 | foreach ($json['items'] as $item) { 270 | foreach ($item['webProperties'] as $property) { 271 | if (isset($property['profiles'][0]['id'])) { 272 | $property['ProfileId'] = $property['profiles'][0]['id']; 273 | } 274 | $results[] = new gapiAccountEntry($property); 275 | } 276 | } 277 | 278 | $this->account_entries = $results; 279 | 280 | return $results; 281 | } 282 | 283 | /** 284 | * Report Object Mapper to convert the JSON to array of useful PHP objects 285 | * 286 | * @param String $json_string 287 | * @return Array of gapiReportEntry objects 288 | */ 289 | protected function reportObjectMapper($json_string) { 290 | $json = json_decode($json_string, true); 291 | 292 | $this->results = null; 293 | $results = array(); 294 | 295 | $report_aggregate_metrics = array(); 296 | 297 | //Load root parameters 298 | 299 | // Start with elements from the root level of the JSON that aren't themselves arrays. 300 | $report_root_parameters = array_filter($json, function($var){ 301 | return !is_array($var); 302 | }); 303 | 304 | // Get the items from the 'query' object, and rename them slightly. 305 | foreach($json['query'] as $index => $value) { 306 | $new_index = lcfirst(str_replace(' ', '', ucwords(str_replace('-', ' ', $index)))); 307 | $report_root_parameters[$new_index] = $value; 308 | } 309 | 310 | // Now merge in the profileInfo, as this is also mostly useful. 311 | array_merge($report_root_parameters, $json['profileInfo']); 312 | 313 | //Load result aggregate metrics 314 | 315 | foreach($json['totalsForAllResults'] as $index => $metric_value) { 316 | //Check for float, or value with scientific notation 317 | if (preg_match('/^(\d+\.\d+)|(\d+E\d+)|(\d+.\d+E\d+)$/', $metric_value)) { 318 | $report_aggregate_metrics[str_replace('ga:', '', $index)] = floatval($metric_value); 319 | } else { 320 | $report_aggregate_metrics[str_replace('ga:', '', $index)] = intval($metric_value); 321 | } 322 | } 323 | 324 | //Load result entries 325 | if(isset($json['rows'])){ 326 | foreach($json['rows'] as $row) { 327 | $metrics = array(); 328 | $dimensions = array(); 329 | foreach($json['columnHeaders'] as $index => $header) { 330 | switch($header['columnType']) { 331 | case 'METRIC': 332 | $metric_value = $row[$index]; 333 | 334 | //Check for float, or value with scientific notation 335 | if(preg_match('/^(\d+\.\d+)|(\d+E\d+)|(\d+.\d+E\d+)$/',$metric_value)) { 336 | $metrics[str_replace('ga:', '', $header['name'])] = floatval($metric_value); 337 | } else { 338 | $metrics[str_replace('ga:', '', $header['name'])] = intval($metric_value); 339 | } 340 | break; 341 | case 'DIMENSION': 342 | $dimensions[str_replace('ga:', '', $header['name'])] = strval($row[$index]); 343 | break; 344 | default: 345 | throw new Exception("GAPI: Unrecognized columnType '{$header['columnType']}' for columnHeader '{$header['name']}'"); 346 | } 347 | } 348 | $results[] = new gapiReportEntry($metrics, $dimensions); 349 | } 350 | } 351 | 352 | $this->report_root_parameters = $report_root_parameters; 353 | $this->report_aggregate_metrics = $report_aggregate_metrics; 354 | $this->results = $results; 355 | 356 | return $results; 357 | } 358 | 359 | /** 360 | * Get current analytics results 361 | * 362 | * @return Array 363 | */ 364 | public function getResults() { 365 | return is_array($this->results) ? $this->results : false; 366 | } 367 | 368 | /** 369 | * Get current account data 370 | * 371 | * @return Array 372 | */ 373 | public function getAccounts() { 374 | return is_array($this->account_entries) ? $this->account_entries : false; 375 | } 376 | 377 | /** 378 | * Get an array of the metrics and the matching 379 | * aggregate values for the current result 380 | * 381 | * @return Array 382 | */ 383 | public function getMetrics() { 384 | return $this->report_aggregate_metrics; 385 | } 386 | 387 | /** 388 | * Call method to find a matching root parameter or 389 | * aggregate metric to return 390 | * 391 | * @param $name String name of function called 392 | * @return String 393 | * @throws Exception if not a valid parameter or aggregate 394 | * metric, or not a 'get' function 395 | */ 396 | public function __call($name, $parameters) { 397 | if (!preg_match('/^get/', $name)) { 398 | throw new Exception('No such function "' . $name . '"'); 399 | } 400 | 401 | $name = preg_replace('/^get/', '', $name); 402 | 403 | $parameter_key = gapi::ArrayKeyExists($name, $this->report_root_parameters); 404 | 405 | if ($parameter_key) { 406 | return $this->report_root_parameters[$parameter_key]; 407 | } 408 | 409 | $aggregate_metric_key = gapi::ArrayKeyExists($name, $this->report_aggregate_metrics); 410 | 411 | if ($aggregate_metric_key) { 412 | return $this->report_aggregate_metrics[$aggregate_metric_key]; 413 | } 414 | 415 | throw new Exception('No valid root parameter or aggregate metric called "' . $name . '"'); 416 | } 417 | 418 | /** 419 | * Case insensitive array_key_exists function, also returns 420 | * matching key. 421 | * 422 | * @param String $key 423 | * @param Array $search 424 | * @return String Matching array key 425 | */ 426 | public static function ArrayKeyExists($key, $search) { 427 | if (array_key_exists($key, $search)) { 428 | return $key; 429 | } 430 | if (!(is_string($key) && is_array($search))) { 431 | return false; 432 | } 433 | $key = strtolower($key); 434 | foreach ($search as $k => $v) { 435 | if (strtolower($k) == $key) { 436 | return $k; 437 | } 438 | } 439 | return false; 440 | } 441 | } 442 | 443 | /** 444 | * Storage for individual gapi account entries 445 | * 446 | */ 447 | class gapiAccountEntry { 448 | private $properties = array(); 449 | 450 | /** 451 | * Constructor function for all new gapiAccountEntry instances 452 | * 453 | * @param Array $properties 454 | * @return gapiAccountEntry 455 | */ 456 | public function __construct($properties) { 457 | $this->properties = $properties; 458 | } 459 | 460 | /** 461 | * toString function to return the name of the account 462 | * 463 | * @return String 464 | */ 465 | public function __toString() { 466 | return isset($this->properties['name']) ? 467 | $this->properties['name']: ''; 468 | } 469 | 470 | /** 471 | * Get an associative array of the properties 472 | * and the matching values for the current result 473 | * 474 | * @return Array 475 | */ 476 | public function getProperties() { 477 | return $this->properties; 478 | } 479 | 480 | /** 481 | * Call method to find a matching parameter to return 482 | * 483 | * @param $name String name of function called 484 | * @return String 485 | * @throws Exception if not a valid parameter, or not a 'get' function 486 | */ 487 | public function __call($name, $parameters) { 488 | if (!preg_match('/^get/', $name)) { 489 | throw new Exception('No such function "' . $name . '"'); 490 | } 491 | 492 | $name = preg_replace('/^get/', '', $name); 493 | 494 | $property_key = gapi::ArrayKeyExists($name, $this->properties); 495 | 496 | if ($property_key) { 497 | return $this->properties[$property_key]; 498 | } 499 | 500 | throw new Exception('No valid property called "' . $name . '"'); 501 | } 502 | } 503 | 504 | /** 505 | * Storage for individual gapi report entries 506 | * 507 | */ 508 | class gapiReportEntry { 509 | private $metrics = array(); 510 | private $dimensions = array(); 511 | 512 | /** 513 | * Constructor function for all new gapiReportEntry instances 514 | * 515 | * @param Array $metrics 516 | * @param Array $dimensions 517 | * @return gapiReportEntry 518 | */ 519 | public function __construct($metrics, $dimensions) { 520 | $this->metrics = $metrics; 521 | $this->dimensions = $dimensions; 522 | } 523 | 524 | /** 525 | * toString function to return the name of the result 526 | * this is a concatented string of the dimensions chosen 527 | * 528 | * For example: 529 | * 'Firefox 3.0.10' from browser and browserVersion 530 | * 531 | * @return String 532 | */ 533 | public function __toString() { 534 | return is_array($this->dimensions) ? 535 | implode(' ', $this->dimensions) : ''; 536 | } 537 | 538 | /** 539 | * Get an associative array of the dimensions 540 | * and the matching values for the current result 541 | * 542 | * @return Array 543 | */ 544 | public function getDimensions() { 545 | return $this->dimensions; 546 | } 547 | 548 | /** 549 | * Get an array of the metrics and the matchning 550 | * values for the current result 551 | * 552 | * @return Array 553 | */ 554 | public function getMetrics() { 555 | return $this->metrics; 556 | } 557 | 558 | /** 559 | * Call method to find a matching metric or dimension to return 560 | * 561 | * @param String $name name of function called 562 | * @param Array $parameters 563 | * @return String 564 | * @throws Exception if not a valid metric or dimensions, or not a 'get' function 565 | */ 566 | public function __call($name, $parameters) { 567 | if (!preg_match('/^get/', $name)) { 568 | throw new Exception('No such function "' . $name . '"'); 569 | } 570 | 571 | $name = preg_replace('/^get/', '', $name); 572 | 573 | $metric_key = gapi::ArrayKeyExists($name, $this->metrics); 574 | 575 | if ($metric_key) { 576 | return $this->metrics[$metric_key]; 577 | } 578 | 579 | $dimension_key = gapi::ArrayKeyExists($name, $this->dimensions); 580 | 581 | if ($dimension_key) { 582 | return $this->dimensions[$dimension_key]; 583 | } 584 | 585 | throw new Exception('No valid metric or dimesion called "' . $name . '"'); 586 | } 587 | } 588 | 589 | /** 590 | * OAuth2 Google API authentication 591 | * 592 | */ 593 | class gapiOAuth2 { 594 | const scope_url = 'https://www.googleapis.com/auth/analytics.readonly'; 595 | const request_url = 'https://www.googleapis.com/oauth2/v3/token'; 596 | const grant_type = 'urn:ietf:params:oauth:grant-type:jwt-bearer'; 597 | const header_alg = 'RS256'; 598 | const header_typ = 'JWT'; 599 | 600 | private function base64URLEncode($data) { 601 | return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); 602 | } 603 | 604 | private function base64URLDecode($data) { 605 | return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT)); 606 | } 607 | 608 | /** 609 | * Authenticate Google Account with OAuth2 610 | * 611 | * @param String $client_email 612 | * @param String $key_file 613 | * @param String $delegate_email 614 | * @return String Authentication token 615 | */ 616 | public function fetchToken($client_email, $key_file, $delegate_email = null) { 617 | $header = array( 618 | "alg" => self::header_alg, 619 | "typ" => self::header_typ, 620 | ); 621 | 622 | $claimset = array( 623 | "iss" => $client_email, 624 | "scope" => self::scope_url, 625 | "aud" => self::request_url, 626 | "exp" => time() + (60 * 60), 627 | "iat" => time(), 628 | ); 629 | 630 | if(!empty($delegate_email)) { 631 | $claimset["sub"] = $delegate_email; 632 | } 633 | 634 | $data = $this->base64URLEncode(json_encode($header)) . '.' . $this->base64URLEncode(json_encode($claimset)); 635 | 636 | if (!file_exists($key_file)) { 637 | if ( !file_exists(__DIR__ . DIRECTORY_SEPARATOR . $key_file) ) { 638 | throw new Exception('GAPI: Failed load key file "' . $key_file . '". File could not be found.'); 639 | } else { 640 | $key_file = __DIR__ . DIRECTORY_SEPARATOR . $key_file; 641 | } 642 | } 643 | 644 | $key_data = file_get_contents($key_file); 645 | 646 | if (empty($key_data)) { 647 | throw new Exception('GAPI: Failed load key file "' . $key_file . '". File could not be opened or is empty.'); 648 | } 649 | 650 | openssl_pkcs12_read($key_data, $certs, 'notasecret'); 651 | 652 | if (!isset($certs['pkey'])) { 653 | throw new Exception('GAPI: Failed load key file "' . $key_file . '". Unable to load pkcs12 check if correct p12 format.'); 654 | } 655 | 656 | openssl_sign($data, $signature, openssl_pkey_get_private($certs['pkey']), "sha256"); 657 | 658 | $post_variables = array( 659 | 'grant_type' => self::grant_type, 660 | 'assertion' => $data . '.' . $this->base64URLEncode($signature), 661 | ); 662 | 663 | $url = new gapiRequest(self::request_url); 664 | $response = $url->post(null, $post_variables); 665 | $auth_token = json_decode($response['body'], true); 666 | 667 | if (substr($response['code'], 0, 1) != '2' || !is_array($auth_token) || empty($auth_token['access_token'])) { 668 | throw new Exception('GAPI: Failed to authenticate user. Error: "' . strip_tags($response['body']) . '"'); 669 | } 670 | 671 | $this->auth_token = $auth_token['access_token']; 672 | 673 | return $this->auth_token; 674 | } 675 | 676 | /** 677 | * Return the auth token string retrieved from Google 678 | * 679 | * @return String 680 | */ 681 | public function getToken() { 682 | return $this->auth_token; 683 | } 684 | 685 | /** 686 | * Generate authorization token header for all requests 687 | * 688 | * @param String $token 689 | * @return Array 690 | */ 691 | public function generateAuthHeader($token=null) { 692 | if ($token == null) 693 | $token = $this->auth_token; 694 | return array('Authorization' => 'Bearer ' . $token); 695 | } 696 | } 697 | 698 | /** 699 | * Google Analytics API request 700 | * 701 | */ 702 | class gapiRequest { 703 | const http_interface = 'auto'; //'auto': autodetect, 'curl' or 'fopen' 704 | const interface_name = gapi::interface_name; 705 | 706 | private $url = null; 707 | 708 | public function __construct($url) { 709 | $this->url = $url; 710 | } 711 | 712 | /** 713 | * Return the URL to be requested, optionally adding GET variables 714 | * 715 | * @param Array $get_variables 716 | * @return String 717 | */ 718 | public function getUrl($get_variables=null) { 719 | if (is_array($get_variables)) { 720 | $get_variables = '?' . str_replace('&', '&', urldecode(http_build_query($get_variables, '', '&'))); 721 | } else { 722 | $get_variables = null; 723 | } 724 | 725 | return $this->url . $get_variables; 726 | } 727 | 728 | /** 729 | * Perform http POST request 730 | * 731 | * 732 | * @param Array $get_variables 733 | * @param Array $post_variables 734 | * @param Array $headers 735 | */ 736 | public function post($get_variables=null, $post_variables=null, $headers=null) { 737 | return $this->request($get_variables, $post_variables, $headers); 738 | } 739 | 740 | /** 741 | * Perform http GET request 742 | * 743 | * 744 | * @param Array $get_variables 745 | * @param Array $headers 746 | */ 747 | public function get($get_variables=null, $headers=null) { 748 | return $this->request($get_variables, null, $headers); 749 | } 750 | 751 | /** 752 | * Perform http request 753 | * 754 | * 755 | * @param Array $get_variables 756 | * @param Array $post_variables 757 | * @param Array $headers 758 | */ 759 | public function request($get_variables=null, $post_variables=null, $headers=null) { 760 | $interface = self::http_interface; 761 | 762 | if (self::http_interface == 'auto') 763 | $interface = function_exists('curl_exec') ? 'curl' : 'fopen'; 764 | 765 | switch ($interface) { 766 | case 'curl': 767 | return $this->curlRequest($get_variables, $post_variables, $headers); 768 | case 'fopen': 769 | return $this->fopenRequest($get_variables, $post_variables, $headers); 770 | default: 771 | throw new Exception('Invalid http interface defined. No such interface "' . self::http_interface . '"'); 772 | } 773 | } 774 | 775 | /** 776 | * HTTP request using PHP CURL functions 777 | * Requires curl library installed and configured for PHP 778 | * 779 | * @param Array $get_variables 780 | * @param Array $post_variables 781 | * @param Array $headers 782 | */ 783 | private function curlRequest($get_variables=null, $post_variables=null, $headers=null) { 784 | $ch = curl_init(); 785 | 786 | if (is_array($get_variables)) { 787 | $get_variables = '?' . str_replace('&', '&', urldecode(http_build_query($get_variables, '', '&'))); 788 | } else { 789 | $get_variables = null; 790 | } 791 | 792 | curl_setopt($ch, CURLOPT_URL, $this->url . $get_variables); 793 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 794 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //CURL doesn't like google's cert 795 | 796 | if (is_array($post_variables)) { 797 | curl_setopt($ch, CURLOPT_POST, true); 798 | curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_variables, '', '&')); 799 | } 800 | 801 | if (is_array($headers)) { 802 | $string_headers = array(); 803 | foreach ($headers as $key => $value) { 804 | $string_headers[] = "$key: $value"; 805 | } 806 | curl_setopt($ch, CURLOPT_HTTPHEADER, $string_headers); 807 | } 808 | 809 | $response = curl_exec($ch); 810 | $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); 811 | 812 | curl_close($ch); 813 | 814 | return array('body' => $response, 'code' => $code); 815 | } 816 | 817 | /** 818 | * HTTP request using native PHP fopen function 819 | * Requires PHP openSSL 820 | * 821 | * @param Array $get_variables 822 | * @param Array $post_variables 823 | * @param Array $headers 824 | */ 825 | private function fopenRequest($get_variables=null, $post_variables=null, $headers=null) { 826 | $http_options = array('method'=>'GET', 'timeout'=>3); 827 | 828 | $string_headers = ''; 829 | if (is_array($headers)) { 830 | foreach ($headers as $key => $value) { 831 | $string_headers .= "$key: $value\r\n"; 832 | } 833 | } 834 | 835 | if (is_array($get_variables)) { 836 | $get_variables = '?' . str_replace('&', '&', urldecode(http_build_query($get_variables, '', '&'))); 837 | } 838 | else { 839 | $get_variables = null; 840 | } 841 | 842 | if (is_array($post_variables)) { 843 | $post_variables = str_replace('&', '&', urldecode(http_build_query($post_variables, '', '&'))); 844 | $http_options['method'] = 'POST'; 845 | $string_headers = "Content-type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($post_variables) . "\r\n" . $string_headers; 846 | $http_options['header'] = $string_headers; 847 | $http_options['content'] = $post_variables; 848 | } 849 | else { 850 | $post_variables = ''; 851 | $http_options['header'] = $string_headers; 852 | } 853 | 854 | $context = stream_context_create(array('http'=>$http_options)); 855 | $response = @file_get_contents($this->url . $get_variables, null, $context); 856 | 857 | return array('body'=>$response!==false?$response:'Request failed, consider using php5-curl module for more information.', 'code'=>$response!==false?'200':'400'); 858 | } 859 | } -------------------------------------------------------------------------------- /views/example_view.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Codeigniter Google Analytics API 6 | 7 | 8 |

9 |

10 |

11 |

12 | 13 | --------------------------------------------------------------------------------