Server side integrates Google Analytics API with Ruby

Upgrading google-api-ruby-client from 0.8.x to 0.9 will probably break a lot of your code. Officially, there is a migration guide, but it does not give you much clue of how to pull Google Analytics stats via the API, neither does the documentation in Google developer platform.

The post is to focus on the integration with Google Analytics' Core Reporting API and authorisation with Ruby (on Rails) from server side. So the use case is, any user comes to authorise your application to access the data in his/her Google Analytics account, and then your server can pull the latest data at any time without a second time authorisation from the user.

Preparation

Before typing any code, please make sure you have got client_id and client_secret. If you don't have them like 44410190108-74nkm6jc5e3vvjqis803frkvmu88cu3a.apps.googleusercontent.com and X1NUhvO-rQr9sm8uUSMY8i7v respectively, please follow the Step 1 in Google Developers Guide, where the rest of steps are not for Ruby.

Authorization

Google API's authorisation suggests Signet to do OAuth2. That means there are two rounds of API communication, to get an authorisation code by client_id and client_secret, and then use the code to exchange for an access token.

Because we need to initialize Signet::OAuth2::Client for many times, I prefer to create another ruby class as a wrapper of it, such as a google_api.rb file (in your /lib folder if using rails).

#google_api.rb
require 'google/apis/analytics_v3'

class GoogleAPI  
  GOOGLE_API_CLIENT_ID = '44410190108-74nkm6jc5e3vvjqis803frkvmu88cu3a.apps.googleusercontent.com'
  GOOGLE_API_CLIENT_SECRET = 'X1NUhvO-rQr9sm8uUSMY8i7v'
  GOOGLE_OAUTH2_URL = 'https://accounts.google.com/o/oauth2/auth'
  GOOGLE_ACCESS_TOKEN_URL = 'https://www.googleapis.com/oauth2/v3/token'
  GOOGLE_CALLBACK_URL = 'http://yourhost/google/callback' #the url that Google will send authorisation codes to

  attr_accessor :client

  def initialize
    @client = Signet::OAuth2::Client.new(
        client_id: GOOGLE_API_CLIENT_ID,
        client_secret: GOOGLE_API_CLIENT_SECRET,
        authorization_uri: GOOGLE_OAUTH2_URL,
        scope: Google::Apis::AnalyticsV3::AUTH_ANALYTICS_READONLY,
        token_credential_uri: GOOGLE_ACCESS_TOKEN_URL,
        redirect_uri: GOOGLE_CALLBACK_URL
    )
  end
end  

Then to handle the request from users, just redirect to Google's authorisation uri in your controller.

#google_api.rb
class GoogleAPI  
  ...
  def authorization_uri
    @client.authorization_uri.to_s
  end
  ...
end

#google_controller.rb
class GoogleController < ApplicationController  
  def authorise
    redirect_to GoogleAPI.new.authorization_uri
  end
end  

After users click through the authorisation steps, Google will send you authorisation codes, with which you can request access tokens. The access token is ready for fetching API data, but it expires in 3600 seconds. If just going to render some remote data to the user immediately and only once, you can skip the following parts about refresh token.

Otherwise, for any offline access you have to use refresh token that only returns at the first time requesting for access tokens. If you miss it, revoking the authorisation from the Google account will reset.

#google_api.rb
class GoogleAPI  
  ...
  def init_refresh_token(authorization_code)
    @client.update!(code: authorization_code)
    # @client.fetch_access_token!['access_token'] gives you the access token
    @client.fetch_access_token!['refresh_token']
  end
  ...
end

#google_controller.rb
class GoogleController < ApplicationController  
  ...
  def google_callback
    if params[:code]
      refresh_token = GoogleAPI.new.init_refresh_token(params[:code])
      #store the refresh token in database for later access from server
    end
  end
  ...
end  
Play!

Before real playing, do not forget reauthorisation to exchange a fresh access token with the stored refresh token (don't store access token!) from your server job (not triggered by users).

#google_api.rb
class GoogleAPI  
  ...
  def reauthorize!(refresh_token)
    @client.update!(refresh_token: refresh_token, grant_type: :refresh_token)
    access_token = @client.fetch_access_token!['access_token']
    @client.update!(access_token: access_token)
  end

  def init_service(refresh_token)
    self.reauthorize!(refresh_token)
    service = Google::Apis::AnalyticsV3::AnalyticsService.new
    service.authorization = @client
    service
  end
  ...
end

#in your server job
service = GoogleAPI.new.init_service(refresh_token) #refresh_token from your database  
account_summaries = service.list_account_summaries  
Summary

Yes, it's as simply as this and none of the steps are complicated above. But nowhere I could find to gather all the them together. Probably because Google does not take Ruby as one of the major programming languages that will consume its API, as the usage for Java is way clearer.

Thanks to the blog that helped me more than any of Google's documentation or guide (if you still believe they really does), but just misses the offline access part.

I have not been to any difficulties in requesting the analytic data part, so leaving the Play! short and simple. Trust me, going through the source code of google-api-client is way way more effective than searching from Google's documentation to call the right endpoint.

Version:  
  ruby 2.3.0
  rails 4.2.5
  google-api-client 0.9