In the first part of our series, we introduced the Google Analytics API, including the basic usage. In this part, we will continue creating our demo and see how we can extend it with more functionality.
Google Analytics API
Management API
As we discussed in the first part, the Management API is responsible for getting user accounts, properties, views… for our first example we will retrieve the list of accounts available for our authenticated user.
// app/src/GA_Service.php
public function accounts(){
if( !$this->isLoggedIn() ){
//login
}
$service = new Google_AnalyticsService($this->client);
$man_accounts = $service->management_accounts->listManagementAccounts();
$accounts = [];
foreach ($man_accounts['items'] as $account) {
$accounts[] = [ 'id' => $account['id'], 'name' => $account['name'] ];
}
return $accounts;
}//accounts
// app/controllers/HomeController.php
public function accounts(){
$accounts = $this->ga->accounts();
return $accounts;
}//accounts
// app/routes.php
Route::get('/accounts', 'HomeController@accounts');
Inside GA_Service::accounts
we create a new Google_AnalyticsService
with our authorized client and then query the API for the list of accounts.
In this case the result is an array, but the API also makes use of objects, we just need to specify that inside our GA_Service::init
function. In the following examples, I’m going to use array results.
$this->client->setUseObjects(true);
The listManagementAccounts
function returns an array containing:
{
kind: "analytics#accounts",
username: "me@mail.com",
totalResults: 3,
startIndex: 1,
itemsPerPage: 1000,
items: [
{
id: "4449308",
kind: "analytics#account",
selfLink: "https://www.googleapis.com/analytics/v3/management/accounts/4449308",
name: "me@mail.com",
permissions: {
effective: [
"COLLABORATE",
"EDIT",
"MANAGE_USERS",
"READ_AND_ANALYZE"
]
},
created: "2013-10-01T11:04:28.478Z",
updated: "2013-10-01T11:04:28.478Z",
childLink: {
type: "analytics#webproperties",
href: "https://www.googleapis.com/analytics/v3/management/accounts/4449308/webproperties"
}
}
]
}
Note that when you return an array as a response, Laravel automatically encodes the result as a JSON response and sends it to the browser.
The result contains information about the total results and some pagination info as well. The items
column contains the list of accounts with their IDs, permissions, etc., but we looped through items
to extract only the id
and name
from the accounts.
If you would like to have result pagination, you can always pass more options to listManagementAccount
:
$service->management_accounts->listManagementAccounts( [ 'max-results' => $max_results, 'start-index' => $start_index ] );
Let’s assume that we’re going to show our users their list of accounts, and when they select one, we load the list of properties associated with it.
// app/src/GA_Service.php
public function properties( $account_id ){
if( !$this->isLoggedIn() ){
//login
}
try {
$service = new Google_AnalyticsService($this->client);
$man_properties = $service->management_webproperties->listManagementWebproperties($account_id);
$properties = [];
foreach ($man_properties['items'] as $property) {
$properties[] = [ 'id' => $property['id'], 'name' => $property['name'] ];
}//foreach
return json_encode($properties);
} catch (Google_ServiceException $e) {
return Response::json([
'status' => 0,
'code' => 3,
'message' => $e->getMessage()
]);
}//catch
}//properties
// app/controllers/HomeController.php
public function properties( $account_id ){
$properties = $this->ga->properties( $account_id );
return $properties;
}//properties
// app/routes.php
Route::get( '/properties/{account_id}', [ 'uses' => 'HomeController@properties' ] )->where('account_id', '\d+');
The GA_Service::properties
accepts an account ID, and returns the list of properties for that account. We basically have the same process, like retrieving accounts.
[
{
id: "UA-52317977-1",
name: "Prop1"
},
{
id: "UA-52317977-2",
name: "Prop1"
}
]
Every property has a subset of views. By default, Google adds a view called All Web Site Data
for every new property.
Using an ID from the list of properties and the account ID grabbed from the first part, we will query Google Analytics API for the list of available views for a given account property.
// app/src/GA_Service.php
public function views( $account_id, $property_id ){
if( !$this->isLoggedIn() ){
//login
}
try {
$service = new Google_AnalyticsService($this->client);
$man_views = $service->management_profiles->listManagementProfiles( $account_id, $property_id );
$views = [];
foreach ($man_views['items'] as $view) {
$views[] = [ 'id' => $view['id'], 'name' => $view['name'] ];
}//foreach
return json_encode($views);
} catch (Google_ServiceException $e) {
return Response::json([
'status' => 0,
'code' => 3,
'message' => $e->getMessage()
]);
}//catch
}//views
// app/controllers/HomeController.php
public function views( $account_id, $property_id ){
$views = $this->ga->views( $account_id ,$property_id );
return $views;
}//properties
// app/routes.php
Route::get( '/views/{account_id}/{property_id}', [ 'uses' => 'HomeController@views' ] )->where([ 'account_id', '\d+', 'property_id', '\d+' ]);
In the browser, when hitting /views/{account_id}/{property_id}
route, we should get something similar to:
// http://localhost:8000/views/44493065/UA-44493083
[
{
id: "77278619",
name: "All Web Site Data"
}
]
Metadata API
To query some statistics from Google Analytics we need to provide a set of dimensions and metrics.
- Metrics: metrics are the individual measurements of user activity on your property, such as sessions and pageviews..
- Dimensions: dimensions break down metrics across some common criteria, such as country or browser.
To grab the list of available metadata you can simply use curl
to query data from the following url https://www.googleapis.com/analytics/v3/metadata/ga/columns
.
Google Analytics gives us an etag
attribute that can be used for caching the response so that we don’t have to query the API on every request.
$gcurl = new Google_CurlIO;
$response = $gcurl->makeRequest(
new Google_HttpRequest(
"https://www.googleapis.com/analytics/v3/metadata/ga/columns"
));
Google_CurlIO
: a class wrapped with somecurl
utilities for dealing with caching, authentication, etc – by using this class we ensure the response is cached using theetag
attribute.Google_HttpRequest
: is a class representing a single HTTP request.
The makeRequest
method returns a Google_HttpRequest
instance, and we can use the getResponseBody
to get our metadata response.
// app/src/GA_Service.php
public function metadata(){
$gcurl = new Google_CurlIO;
$response = $gcurl->makeRequest(
new Google_HttpRequest( "https://www.googleapis.com/analytics/v3/metadata/ga/columns" )
);
//verify returned data
$data = json_decode($response->getResponseBody());
$items = $data->items;
$data_items = [];
$dimensions_data = [];
$metrics_data = [];
foreach( $items as $item ){
if( $item->attributes->status == 'DEPRECATED' )
continue;
if( $item->attributes->type == 'DIMENSION' )
$dimensions_data[ $item->attributes->group ][] = $item;
if( $item->attributes->type == 'METRIC' )
$metrics_data[ $item->attributes->group ][] = $item;
}//foreach
$data_items['dimensions'] = $dimensions_data;
$data_items['metrics'] = $metrics_data;
return $data_items;
}//metadata
// app/controllers/HomeController.php
public function metadata(){
$metadata = $this->ga->metadata();
return $metadata;
}//metadata
// app/routes.php
Route::get('/metadata', 'HomeController@metadata');
Now, when accessing the /metadata
route in your browser you should get an array of dimensions and another one for metrics, and each one of them contains a list of grouped elements.
{
dimensions: {
User: [
{
id: "ga:userType",
kind: "analytics#column",
attributes: {
type: "DIMENSION",
dataType: "STRING",
group: "User",
status: "PUBLIC",
uiName: "User Type",
description: "A boolean indicating if a user is new or returning. Possible values: New Visitor, Returning Visitor.",
allowedInSegments: "true"
}
},
...
]
},
metrics: {
...
}
}
To speed up the process we will use bootsnipp. If the user is logged in, we will show the home page.
We need to update our HomeController@index
to show the home page view.
// app/controllers/HomeController.php
public function index(){
if( $this->ga->isLoggedIn() ){
$metadata = $this->metadata();
$dimensions = $metadata['dimensions'];
$metrics = $metadata['metrics'];
return View::make('home', [
'dimensions' => $dimensions,
'metrics' => $metrics
]);
}//if
else{
$url = $this->ga->getLoginUrl();
return View::make('login', [ 'url' => $url ]);
}
}//index
As you can see from the screenshot, when the user selects an account we asynchronously change the property and the view accordingly. To achieve that, I wrote some simple JS which you can check in the final repo.
Reporting API
By providing the selected view, metrics and dimensions we can get detailed statistics about users and interactions. The result after the user submission will be something similar to:
array(3) {
["items"]=>
array(10) {
[0]=>
array(2) {
[0]=>
string(9) "Argentina"
[1]=>
string(1) "2"
}
[1]=>
array(2) {
[0]=>
string(6) "Brazil"
[1]=>
string(2) "31"
}
[2]=>
array(2) {
[0]=>
string(6) "France"
[1]=>
string(1) "1"
}
[3]=>
array(2) {
[0]=>
string(7) "Germany"
[1]=>
string(1) "1"
}
[4]=>
array(2) {
[0]=>
string(6) "Greece"
[1]=>
string(1) "1"
}
//...
}
["columnHeaders"]=>
array(2) {
[0]=>
array(3) {
["name"]=>
string(10) "ga:country"
["columnType"]=>
string(9) "DIMENSION"
["dataType"]=>
string(6) "STRING"
}
[1]=>
array(3) {
["name"]=>
string(12) "ga:pageviews"
["columnType"]=>
string(6) "METRIC"
["dataType"]=>
string(7) "INTEGER"
}
}
["totalResults"]=>
int(15)
}
Our GA_Service::report
accepts four arguments: a view ID, a start and end date and an array of metrics.
Google can’t return all your legacy data – instead we provide a start and end date. In my example, I queried the last month’s results.
The third parameter is the list of metrics which we already have from the user selection.
The fourth optional parameter is an array of options.
– max-results
: the maximum number of results. (we used 10 to speed up the response).
– dimensions
: a comma separated list of values. (ga:country,ga:city
)
– filters
: a comma separated list of rules to be appilied to the result .(ga:country!=usa,ga:pageviews>100
)
In this example we excluded USA from the list of dimensions and only showed pageviews that are greater than 100.
– segment
: advanced segment ID to be applied to the data.
– sort
: order results by dimensions or metrics. Can combine multiple dimensions and metrics. (ga:country,-ga:pageviews
= order by ga:country
ascending, and by ga:pageviews
descending.
– start-index
: can be used for pagination.
// app/src/GA_Service.php
public function report( $view, $dimensions, $metrics ){
// to make the request quicker
$max_results = 10;
// query the last month analytics
$now = new DateTime();
$end_date = $now->format('Y-m-d');
$start_date = $now->modify('-1 month')->format('Y-m-d');
// if( !is_array( $dimensions ) )
// $dimensions = array( $dimensions );
$dimensions = implode( ",", $dimensions );
$metrics = implode( ",", $metrics );
try{
$analytics = new Google_AnalyticsService($this->client);
$options = [];
$options['dimensions'] = $dimensions;
$options['max-results'] = $max_results;
$data = $analytics->data_ga->get( $view, $start_date, $end_date, $metrics,
$options
);
$res = [
'items' => isset($data['rows']) ? $data['rows'] : [],
'columnHeaders' => $data['columnHeaders'],
'totalResults' => $data['totalResults']
];
}catch( Google_ServiceException $ex ){
return Response::json([
'status' => 0,
'code' => 2,
'message' => 'Google analytics internal server error: (Technical details) ' . $ex->getErrors()[0]['message']
]);
}//catch
return $res;
}//report
// app/controller/HomeController.php
public function report(){
if( !$this->ga->isLoggedIn() )
return Response::json([
'status' => 0,
'code' => 1,
'message' => 'Login required'
]);
if( !Input::has('dimensions') || !Input::has('metrics') || !Input::has('view') )
return Response::json([
'status' => 0,
'code' => 1,
'message' => 'Invalid request parametter'
]);
$view = 'ga:' . Input::get('view');
$dimensions = Input::get('dimensions');
$metrics = Input::get('metrics');
$report = $this->ga->report( $view, $dimensions, $metrics );
return View::make('report', [ 'columns' => $report['columnHeaders'], 'items' => $report['items'], 'totalResults' => $report['totalResults' ] ]);
}//metadata
// app/routes.php
Route::post('/report', 'HomeController@report');
After calling the get Google_AnalyticsService::get
method, we use the list of result items, column headers, and total results to output the result as a table.
Extending The Demo
Now let’s see how we can extend our demo with filters, sorting and segments.
Filters
Filters are a way to exclude some data from the returned result. They take the following form:
ga:column operator value
ga:column
: dimension or metric id (Ex:ga:country
)operator
: the operator depends on the choice of metric or dimension column id, check the docs for the list of operators.value
: the value can be a number, a string, or a regex.
You can combine multiple filters: you can use comma (,) as an OR operator and a semi-colon (;) as an AND operator.
Segments
By default Google Analytics group all your data in one group called All Sessions
. However, you can always choose from the built in segments or create a new one depending on your needs. You can group data by referral, device type, age, gender, etc.
You can extend the demo by adding a new select element with the available segment list, and pass the ID to the get
method as discussed previously.
// app/src/GA_Service.php
public function segments(){
if( !$this->isLoggedIn() ){
//login
}
$service = new Google_AnalyticsService($this->client);
$segments = $service->management_segments->listManagementSegments();
return $segments;
}//segments
// app/controllers/HomeController.php
public function segments(){
$segments = $this->ga->segments();
return $segments;
}//segments
// app/routes.php
Route::get('/segments', 'HomeController@segments');
You can visit the /segments
page to see the list of available segments with their IDs, and you can of course use this as an option as we saw earlier.
Wrapping up
The Google Analytics API is very flexible and provides a lot of features, but the documentation is not complete yet, and doesn’t provide good examples of use. You get a lot more by digging into the source code and testing possibilities and limits.
In this series, we focused on the basic usage of Google Analytics, but you can extend the demo with options from the Google Analytics dashboard.
You can check the final repo for the source code of this tutorial.
Questions? Comments? Let me know!
Frequently Asked Questions (FAQs) about Using Google Analytics API v3 with PHP
How can I get started with Google Analytics API v3 with PHP?
To get started with Google Analytics API v3 with PHP, you first need to create a project in the Google Developers Console. After creating the project, enable the Google Analytics API for it. Then, create credentials for the API. You will receive a client ID and client secret, which you will use to authenticate your application with Google. After that, you can start making requests to the API using PHP.
What are the prerequisites for using Google Analytics API v3 with PHP?
Before you can use Google Analytics API v3 with PHP, you need to have a Google account and access to the Google Analytics data you want to retrieve. You also need to have PHP installed on your server and a basic understanding of PHP programming.
How can I authenticate my application with Google using PHP?
To authenticate your application with Google using PHP, you need to use the client ID and client secret you received when you created your API credentials. You can use these credentials to obtain an access token, which you can then use to authenticate your API requests.
How can I retrieve data from Google Analytics using PHP?
To retrieve data from Google Analytics using PHP, you need to make a GET request to the Google Analytics API. You can specify the metrics, dimensions, and filters you want to apply in the request parameters. The API will return the requested data in JSON format, which you can then parse and use in your application.
How can I handle errors when using Google Analytics API v3 with PHP?
When using Google Analytics API v3 with PHP, errors can occur for various reasons, such as invalid request parameters or authentication issues. You can handle these errors by checking the HTTP status code and error message returned by the API. This will give you information about what went wrong and how to fix it.
Can I use Google Analytics API v3 with PHP to track real-time data?
Yes, you can use Google Analytics API v3 with PHP to track real-time data. The API provides a Real Time Reporting API that you can use to retrieve real-time data such as the number of active users on your site.
How can I filter data when using Google Analytics API v3 with PHP?
You can filter data when using Google Analytics API v3 with PHP by specifying filter parameters in your API request. These parameters allow you to restrict the data returned by the API to meet specific criteria.
Can I use Google Analytics API v3 with PHP to retrieve data from multiple Google Analytics accounts?
Yes, you can use Google Analytics API v3 with PHP to retrieve data from multiple Google Analytics accounts. You just need to authenticate with each account separately and make separate API requests for each account.
How can I paginate results when using Google Analytics API v3 with PHP?
You can paginate results when using Google Analytics API v3 with PHP by using the ‘start-index’ and ‘max-results’ parameters in your API request. These parameters allow you to specify the range of results you want to retrieve.
How can I sort data when using Google Analytics API v3 with PHP?
You can sort data when using Google Analytics API v3 with PHP by specifying sort parameters in your API request. These parameters allow you to order the data returned by the API based on specific metrics or dimensions.
Younes is a freelance web developer, technical writer and a blogger from Morocco. He's worked with JAVA, J2EE, JavaScript, etc., but his language of choice is PHP. You can learn more about him on his website.