Published on: 18 October, 2017

Google Analytics API Tutorial using JavaScript

Posted by andy | 295 views 0 likes 0 favourites 2 comments
Tumblr Digg Google Plus

In this tutorial, you will learn how to access Google Analytics API using javascript. We will use Oauth2 to access user account analytics and a combination of Google Analytics version 3 to get the list of account summaries and version 4 to query the analytics accounts such as a number of visitors, sessions, bounce rates etc.

To start with, we need to go to the following url to get the Oauth Client ID for our project.

https://console.developers.google.com

If you do not have a Google Account, you will need to register it first. Once registered you can go to above link and create a new project. You can name it, for example, Web Analytics. Once the project has been created, you will need to enable Google Analytics Reporting and Analytics API. If you go to Dashboard menu, there should be an option for you to enable APIs. Simply perform a search and type in Analytics.

Once those have been enabled, you can now create a credential. Go to the Credentials menu and select the OAuth Client ID type.

It will pop up a selection of application type for you to choose. In this example, we are going to select Web Application. If you have not set the consent screen, simply click the Configure consent screen to proceed further. Just make sure in the product name you do not include any keyword Google as it will violate the Google's terms.

Once this has been set up, you should be able to select your application type. In the Authorized Javascript Origins, make sure you type in the correct URL path. In this example, as I am showing the example on my site, so I entered http://bytutorial.com. If you test in your local computer, usually it will be http://localhost. Then click the Create button.

You should see the created Oauth 2 Client ID like below.

Let starts with the codes now. I have divided the tutorial into 3 files. They are:

  • google-analytics-api-tutorial.html
  • google-analytics.js
  • style.css

Here is the full code of the html page.

<!DOCTYPE html>
<html>
<head>
<title>Google Analytics API Tutorial< using Javascript</title>
 <meta name="description" content="Learn how to query Google Analytics API using Javascript - ByTutorial.com">
<link href="style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="transparent-wrapper">
	<div id="wait-box">
		<div><img src="images/loading-bubble.gif"/></div>
		<div>Please wait....</div>
	</div>
	
</div>
<div id="login-box" class="hidden">
	<p>Please login on your google account.</p>
	<button id="btnLogin" onclick="byTutorialAnalytics.handleAuthClick()" class="button">Login</button>
</div>

<div id="account-panel" class="hidden">
	<h1>Google Analytics Panel</h1>
	<table class="tbl" cellpadding="0" cellspacing="0">
		<tr>
			<td>Site: </td>
			<td><select id="cboAccount"></select></td>
		</tr>
		<tr>
			<td>Period: </td>
			<td><select id="cboPeriod">
					<option value="today">Today</option>
					<option value="yesterday">Yesterday</option>
					<option value="7daysago">Last Week</option>
					<option value="14daysago">Last Two Weeks</option>
					<option value="28daysago"">Last Four Weeks</option>
				</select>
			</td>
		</tr>
		<tr>
			<td>Data Type: </td>
			<td>
				<div><input type="checkbox" data-id="ga:users" class="chk-data" checked="true"/> ga:users</div>
				<div><input type="checkbox" data-id="ga:newUsers" class="chk-data" checked="true"/> ga:newUsers</div>
				<div><input type="checkbox" data-id="ga:hits" class="chk-data" checked="true"/> ga:hits</div>
				<div><input type="checkbox" data-id="ga:sessions" class="chk-data" checked="true"/> ga:sessions</div>
				<div><input type="checkbox" data-id="ga:visits" class="chk-data" checked="true"/> ga:visits</div>
				<div><input type="checkbox" data-id="ga:bounces" class="chk-data" checked="true"/> ga:bounces</div>
			</td>
		</tr>
		<tr>
			<td></td>
			<td><button id="btnQuery" onclick="byTutorialAnalytics.queryAnalytics()" class="button">Query</button> <button id="btnReset" onclick="byTutorialAnalytics.reset()" class="button">Reset</button> <button id="btnLogout" onclick="byTutorialAnalytics.handleSignoutClick()" class="button">Log off</button></td>
		</tr>
		<tr>
			<td></td>
			<td></td>
		</tr>
	</table>
	
	<div id="result" class="hidden">
		<h2>Query Result</h2>
		<div id="query-result" class="result-box"></div>
		
		<h2>JSON Result</h2>
		<div id="json-result" class="result-box"></div>
	</div>
	
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="google-analytics.js"></script>
<script async defer src="https://apis.google.com/js/api.js" 
      onload="this.onload=function(){};byTutorialAnalytics.handleClientLoad()" 
      onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body>
</html>

If you see above HTML code, you will notice at the end of the last script which points to https://apis.google.com, you will notice it will called a function called handleClientLoad. This function will load the Google API library and check if the user has already given an access permission. If it has not then, it will display a login box otherwise it will display the analytics panel like below.

I have added a list of data types available such as ga:users, ga:newUsers, ga:hits, etc. For more information about the list of metric expression available, you can check on the following link.

https://developers.google.com/analytics/devguides/reporting/core/dimsmets

In addition, I have included a filter parameter for report periods such as today, yesterday, last week etc. You can find more information about start date and end date filter in the following link.

https://developers.google.com/analytics/devguides/reporting/core/v3/reference

Here is the javascript code. I have included some comments and hopefully it is clear enough and feel free to post a comment if you have any question.

/******************** GLOBAL VARIABLES ********************/
var SCOPES = ['https://www.googleapis.com/auth/analytics.readonly'];
var CLIENT_ID = 'REPLACE_WITH_YOUR_CLIENT_ID.apps.googleusercontent.com';
var API_KEY = '';

var byTutorialAnalytics = {
	
	/******************** AUTHENTICATION ********************/
	handleClientLoad: function() {
		// Load the API client and auth2 library
		gapi.load('client:auth2', byTutorialAnalytics.initClient);
	},

	//authorize apps
	initClient: function() {
		gapi.client.init({
			//apiKey: API_KEY, //THIS IS OPTIONAL AND WE DONT ACTUALLY NEED THIS, BUT I INCLUDE THIS AS EXAMPLE
			clientId: CLIENT_ID,
			scope: SCOPES.join(' ')
		}).then(function () {
		  // Listen for sign-in state changes.
		  gapi.auth2.getAuthInstance().isSignedIn.listen(byTutorialAnalytics.updateSigninStatus);
		  // Handle the initial sign-in state.
		  byTutorialAnalytics.updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
		});
	},

	//check the return authentication of the login is successful, we display the account panel box and hide the login box.
	updateSigninStatus: function(isSignedIn) {
		if (isSignedIn) {
			$("#login-box").hide();
			$("#account-panel").removeClass("hidden").show();
			byTutorialAnalytics.queryAccounts();
		} else {
			$("#login-box").removeClass("hidden").show();
		}
	},

	handleAuthClick: function(event) {
		gapi.auth2.getAuthInstance().signIn();
	},

	handleSignoutClick: function(event) {
		if(confirm("Are you sure you want to logout?")){
			gapi.auth2.getAuthInstance().signOut();
			$("#account-panel, #result").hide();
			$(".result-box").html("");
		}
	},
	/******************** END AUTHENTICATION ********************/
	
	//function to query google analytics account
	queryAccounts: function () {
		byTutorialAnalytics.showLoading();
		// Load the Google Analytics client library.
		gapi.client.load('analytics', 'v3').then(function() {
			// Get a list of all Google Analytics accounts for this user
			var request = gapi.client.analytics.management.accountSummaries.list();
			request.execute(byTutorialAnalytics.handleAccountSummaryResponse);
		});
	},
	
	//handle the response of account summary
	handleAccountSummaryResponse: function (response) {
	  if (response && !response.error) {
		if (response.items) {
		  byTutorialAnalytics.buildAccountSummariesCombo(response.items);
		}
	  } else {
		console.log('There was an error: ' + response.message);
		byTutorialAnalytics.hideLoading();
	  }
	},
	
	//build the account summaries combo box
	buildAccountSummariesCombo: function(accounts) {
	  for (var i = 0, account; account = accounts[i]; i++) {
		if(account.webProperties.length > 0 && account.webProperties[0].profiles.length > 0){
			$("#cboAccount").append("<option value='" + account.webProperties[0].profiles[0].id + "'>" + account.name + "</option>");
		}
	  }
	  $("#account-panel").removeClass("hidden").show();
	  byTutorialAnalytics.hideLoading()
	},
	
	//function to query google analytics data 
	queryAnalytics: function () {
		var id = $("#cboAccount").val();
		var expressions = [];
		
		//we loop through the checkbox and append it to expression array
		$(".chk-data").each(function(item,index){
			if($(this).is(":checked")){
				var expressionData = {
					expression: $(this).attr("data-id")
				}
				expressions.push(expressionData);
			}
		});
		
		//get the report query by passing the period time and expression daa.
		byTutorialAnalytics.showLoading();
		//if it is yesterday comparison, we have to set end date to yesterday otherwise it will combine today and yesteray
		var toDate = $("#cboPeriod").val() != "yesterday" ? "today" : "yesterday";
		
		byTutorialAnalytics.getReportQuery(id, $("#cboPeriod").val(), toDate, expressions).then(function(response){
			var formattedJson = JSON.stringify(response.result, null, 2);
			$('#json-result').html(formattedJson);
			$("#result").removeClass("hidden").show();
			
			//show result in table
			if(response.result.reports.length > 0){
				var sb = "<table cellpadding='0' cellspacing='0' class='tbl'>";
				for(var i = 0; i < response.result.reports[0].columnHeader.metricHeader.metricHeaderEntries.length; i++){
					sb += "<tr>";
					sb += "<td>" + response.result.reports[0].columnHeader.metricHeader.metricHeaderEntries[i].name + "</td>";
					sb += "<td>" + response.result.reports[0].data.rows[0].metrics[0].values[i] + "</td>";
					sb += "</tr>";
				}
				sb += "</table>";
				$("#query-result").html(sb);
			}
			byTutorialAnalytics.hideLoading();
		});
	},

	reset: function(){
		$(".result-box").html("");
		$("#result").hide();
	},
	
	//get the analytics query reports, we are using version 4.0
	getReportQuery: function (id, sDate, eDate, dataMetrics){
		return new Promise(function(resolve, reject){
			gapi.client.request({
			  path: '/v4/reports:batchGet',
			  root: 'https://analyticsreporting.googleapis.com/',
			  method: 'POST',
			  body: {
				reportRequests: [
				  {
					viewId: id,
					dateRanges: [
					  {
						startDate: sDate,
						endDate: eDate
					  }
					],
					metrics: dataMetrics
				  }
				]
			  }
			}).then(function(response){
				if(response != null){
					resolve(response);
				}else{
					reject(Error("Error getting the data"));
				}
			})
		});
	},

	//show the transparent waiting progress wrapper
	showLoading: function (){
		$("#transparent-wrapper").show();
	},
	
	//hide the transparent waiting progress wrapper
	hideLoading: function(){
		$("#transparent-wrapper").hide();
	}
}

Just a note, when querying account summaries list, you have to use version 3, as version 4 does not support this functionality yet at the time this article is written.

And finally, here is the stylesheet css code.

/* remove the html and body margin and padding and align the body content to centre. */
html, body{
	margin:0;
	padding:0;
	font-family: Arial, Helvetica;
	font-size:15px;
	text-align:center;
}
button, select{
	padding:5px;
	border-radius:5px;
}

/* transparent loading wrapper background */
#transparent-wrapper
{
    display: none; 
    position: fixed;
    top: 0%; 
    left: 0%; 
    width: 100%; 
    height: 100%; 
    background-color: #000; 
    z-index: 1001;
    -moz-opacity: 0.35; 
    opacity: .35; 
    filter: alpha(opacity=35);
}

#wait-box{
	z-index:1002;
	position:absolute;
	top:50%;
	left:50%;
	width:400px;
	height:200px;
	margin-top:-100px;
	margin-left:-200px;
	text-align:center;
	background:#fff;
	border:solid 1px #cc;
	border-radius:3px;
}

/* content wrapper, we align back the content to left */
#account-panel{
	width:980px;
	text-align:left;
	margin:0 auto;
	padding:20px;
	margin-top:20px;
	border:solid 1px #ccc;
	border-radius:5px;
}

/* class for hide an object */
.hidden{
	display:none;
}

/* center the login box */
#login-box{
	width:250px;
	text-align:center;
	margin:0 auto;
	margin-top:50px;
	border:solid 1px #ccc;
	padding:20px;
	border-radius:5px;
	background:#e2ecfb;
}

button{
	cursor:pointer;
}

table.tbl td{
	padding:5px 10px;
}

.result-box{
	background:#d8e5fa;
	padding:20px;
	border:solid 1px #264984;
	border-radius:5px;
}

.result-box table.tbl{
	border-left:solid 1px #ccc;
	border-top:solid 1px #ccc;
}

.result-box table.tbl td{
	border-bottom:solid 1px #ccc;
	border-right:solid 1px #ccc;
}

Example of Query result

You can see the example of screenshot of my bytutorial.com analytics.

See in action.

You can see how the Google Analytics API works by clicking on this demo link.

Demo Files

You can download the example demo files in here.

Download

If you have any question about above codes, feel free to post your comment below.

Comments
EB
Commented on: 24 Nov, 2017 11:36:16 PM
Hello Andy, Thanks for this concise tutorial. Is there a way to use this to display the number of visits on a site? I need to get the number of views on our site but I don't want to get the login prompt to the visitor.
andy
Commented on: 30 Nov, 2017 09:19:16 AM
Hi EB, When you say the number of visits, did you mean live visitors? There is an option called ga:visits there in the checkbox list. Please see the following reference to use. https://developers.google.com/analytics/devguides/reporting/core/dimsmets#cats=user,session,traffic_sources
Write Comment
0 characters entered. Maximum characters allowed are 1000 characters.
Share your article with us and add your own google adsense account to earn extra money. Plus, you can promote a link back to your site.
Related Articles
Related Tutorials