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 https://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 call 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(); } }
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; }
Demo Files
You can download the example demo files in here.
If you have any question about above codes, feel free to post your comment below.