This guide will show you how to access the Google Analytics API with Ruby, using the OAuth 2.0 flow for web applications.
Step 1: Setup your project
First you’ll need to sign in to the Google Developers Console and register your app:
- Start by creating a new project, and enabling the Google Analytics API on the “APIs” page.
- Set the name of your application and your support email address on the “OAuth consent screen” page. The consent screen is shown to users when they authenticate with Google and agree to their data being shared with you.
- Create a new client on the “Credentials” page. Choose “Web application” as the application type (it should be selected by default), and edit the “Authorized redirect URIs” list to make sure the callback URL you’ll be using in development is included. This is the URL in your application that Google will redirect back to, for example:
http://localhost:5000/oauth2callback
. - Copy & paste the “Client ID” and “Client secret” values associated with the new client–your application will need these to access the API.
You can find these pages under the “APIs & auth” menu item, and you can come back and tweak all these settings before you deploy to staging or production environments.
Step 2: Install the google-api-client gem
Add the google-api-client gem to your Gemfile:
gem 'google-api-client', '~> 0.9', require: 'google/apis/analytics_v3'
Then run bundle. The gem has a lot of dependencies, but will save you from having to write any low level HTTP client code to call the API.
Step 3: Obtain an authorization code
The first step in the OAuth 2.0 flow is to redirect the user to Google so they can sign in and consent to the access you are requesting.
If you’re using Rails your controller action might look something like this:
def redirect
client = Signet::OAuth2::Client.new({
client_id: ENV.fetch('GOOGLE_API_CLIENT_ID'),
client_secret: ENV.fetch('GOOGLE_API_CLIENT_SECRET'),
authorization_uri: 'https://accounts.google.com/o/oauth2/auth',
scope: Google::Apis::AnalyticsV3::AUTH_ANALYTICS_READONLY,
redirect_uri: url_for(:action => :callback)
})
redirect_to client.authorization_uri.to_s
end
There’s a lot going on here, so let’s go through some of the details:
- Signet is the underlying implementation of OAuth 2.0 that Google uses.
- The
client_id
andclient_secret
parameters are the values you copied/pasted from earlier when setting up your project. As with any other secrets it’s important not to commit these values to version control, but for testing purposes you might find it easier just to hardcode them into the code above instead of using environment variables. - The
redirect_uri
value should match the URL in your application that you specified in the “Authorized redirect URIs” list earlier. - You can test this step by running your app and hitting the redirect action. If everything is configured correctly you should see the Google “consent screen” requesting access to view your analytics data. If you accept Google will redirect you back to the URL that you provided with a temporary authorization code.
Step 4: Obtain an access token
The next step in the OAuth 2.0 flow is to handle the callback and exchange the temporary authorization code for an access token. If you’re using Rails your controller action might look something like this:
def callback
client = Signet::OAuth2::Client.new({
client_id: ENV.fetch('GOOGLE_API_CLIENT_ID'),
client_secret: ENV.fetch('GOOGLE_API_CLIENT_SECRET'),
token_credential_uri: 'https://accounts.google.com/o/oauth2/token',
redirect_uri: url_for(:action => :callback),
code: params[:code]
})
response = client.fetch_access_token!
session[:access_token] = response['access_token']
redirect_to url_for(:action => :analytics)
end
Initialization of the client object is similar to before, and includes the temporary authorization code from the request params.
The call to #fetch_access_token!
exchanges the authorization code for an access token, which is then put into the session to persist it between requests.
Step 5: Call the Google Analytics API
Now that you have an access token you can call the Google Analytics API itself–finally!
The callback action in the previous step finishes by redirecting to an analytics action, which you can implement like this:
def analytics
client = Signet::OAuth2::Client.new(access_token: session[:access_token])
service = Google::Apis::AnalyticsV3::AnalyticsService.new
service.authorization = client
@account_summaries = service.list_account_summaries
end
This time the client object is initialized with the access token from the session. The service object provides methods for making calls to the Analytics API. This example calls the Management API to get a list of the analytics properties the user has access to. The API response is assigned to an instance variable so it can be accessed from the view.
You can then add in a basic view to list the web properties and their profiles like this:
<ul>
<% @account_summaries.items.each do |item| %>
<li><%= item.name %> (<%= item.id %>)
<ul>
<% item.web_properties.each do |property| %>
<li><%= property.name %> (<%= property.id %>)
<ul>
<% property.profiles.each do |profile| %>
<li><%= profile.name %> (<%= profile.id %>)</li>
<% end %>
</ul>
</li>
<% end %>
</ul>
</li>
<% end %>
</ul>
You should now be able to test the complete flow end-to-end by starting at the redirect action. If everything is configured correctly the callback action should fetch the access token and redirect to the analytics action to display a list of your properties and profiles.
Calling the Core Reporting API
Using the Management API to get the account summaries will allow you to get the ids of the profiles you’re interested in reporting on, but you’re probably more interested in getting analytics data. For this you’ll need the Core Reporting API. For example, here’s how you would query for the number of sessions by date in a given month:
profile_id = 'ga:123456'
start_date = '2015-10-01'
end_date = '2015-10-31'
metrics = 'ga:sessions'
service.get_ga_data(profile_id, start_date, end_date, metrics, {
dimensions: 'ga:date'
})
Note that the profile id needs to be prefixed and parameters need to be strings. There are some common queries listed in the developer docs which might be useful.
Things to consider
The examples above implement the “happy path”, and don’t handle errors or exceptions which you should code for in a production ready application. Some common failure scenarios you might want to implement:
- If the user cancels at the consent screen Google will redirect back to the callback action with an
error
parameter instead of thecode
parameter. - Calling the API will fail if the access token has expired (access tokens are only valid for an hour). When obtaining the access token Google will also return a
refresh_token
value which you can use to re-request access tokens directly without having to re-authorize. - Calling the API might fail for other reasons, so you might also want to handle other response errors (
Google::Apis::ClientError
exceptions for example).
The code examples above contain some duplication in setting up the signet client. To reduce this you can either use some of the classes included in the google-api-client gem (Google::APIClient::ClientSecrets
and Google::APIClient::InstalledAppFlow
), or you can refactor and reorganize it as you would any other code.
You might want to consider storing the tokens in some kind of datastore instead of the session, depending on the needs of your application.