Skip to content

Instantly share code, notes, and snippets.

@joost
Last active November 27, 2023 15:43
Show Gist options
  • Star 57 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save joost/5344705 to your computer and use it in GitHub Desktop.
Save joost/5344705 to your computer and use it in GitHub Desktop.
Google Analytics API (server-to-server) using Ruby

There are many (old) clients available:

The Google Analytics API is at v3 (at time of writing).

This example uses Google's Ruby API client to access Analytics. Use https://github.com/google/google-api-ruby-client (Google supported).

For server-to-server Analytics API:

Now get access to the Analytics API in your Ruby/Rails app:

  require 'google/api_client'
  require 'date'

  client = Google::APIClient.new(:application_name => 'something you like', :application_version => '1')
  key_file = File.join('SOME PATH', 'KEY_FILE')
  key = Google::APIClient::PKCS12.load_key(key_file, 'notasecret')
  service_account = Google::APIClient::JWTAsserter.new(
      SERVICE_ACCOUNT_EMAIL,
      ['https://www.googleapis.com/auth/analytics.readonly', 'https://www.googleapis.com/auth/prediction'],
      key)
  client.authorization = service_account.authorize

  analytics = client.discovered_api('analytics', 'v3')

  result = client.execute(:api_method => analytics.management.accounts.list)
  result.data.items.first.id

  parameters = {
        'ids'         => "ga:SOME_ID",
        'start-date'  => (Date.today - 30).strftime("%Y-%m-%d"),
        'end-date'    => Time.now.strftime("%Y-%m-%d"),
        'metrics'     => "ga:avgTimeOnPage",
        'filters'     => "ga:pagePath=~/"
      }
  result = client.execute(:api_method => analytics.data.ga.get, :parameters => parameters)
@platphorm
Copy link

This worked great for me. I added the api email to the Profile (Admin -> Profile Permissions -> User Management) too.

BTW, this gist will throw an error if ActiveSupport is not included. You can get around that by adding -

require 'date' 

in the beginning of the code and then replacing

30.days.ago.

with

(Date.today - 30).

@carloslopes
Copy link

@ParthBarot-BoTreeConsulting and @platphorm look my fork, it has some updates that fix the problems you were having https://gist.github.com/carloslopes/6306255

@tpitale
Copy link

tpitale commented Jan 15, 2014

Legato is not abandoned. Where would you get that from? tpitale/legato@0def82f

Even Garb is being supported by another maintainer for legacy fixes.

@joost
Copy link
Author

joost commented Jan 16, 2014

@tastycakeman regarding key file. I just store it in the project /config dir.
@platphorm I updated the gist with your changes.
@tpitale I updated the gist (removed strong statements :) .. those weren ment as note to self).

@tpitale
Copy link

tpitale commented Jan 16, 2014

Thanks @joost. I appreciate the update!

@peter-leonov
Copy link

peter-leonov commented Jul 7, 2014

Works for me.

Made all the steps for setting up key and access.
Then used this script from How to pull Google analytics stats in Ruby:

# you need to set this according to your situation/needs
SERVICE_ACCOUNT_EMAIL_ADDRESS = '...' # looks like 12345@developer.gserviceaccount.com
PATH_TO_KEY_FILE              = '...' # the path to the downloaded .p12 key file
PROFILE                       = '...' # your GA profile id, looks like 'ga:12345'


require 'google/api_client'

# set up a client instance
client  = Google::APIClient.new

client.authorization = Signet::OAuth2::Client.new(
  :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
  :audience             => 'https://accounts.google.com/o/oauth2/token',
  :scope                => 'https://www.googleapis.com/auth/analytics.readonly',
  :issuer               => SERVICE_ACCOUNT_EMAIL_ADDRESS,
  :signing_key          => Google::APIClient::PKCS12.load_key(PATH_TO_KEY_FILE, 'notasecret')
).tap { |auth| auth.fetch_access_token! }

api_method = client.discovered_api('analytics','v3').data.ga.get


# make queries
result = client.execute(:api_method => api_method, :parameters => {
  'ids'        => PROFILE,
  'start-date' => Date.new(1970,1,1).to_s,
  'end-date'   => Date.today.to_s,
  'dimensions' => 'ga:pagePath',
  'metrics'    => 'ga:pageviews',
  'filters'    => 'ga:pagePath==/url/to/user'
})

puts result.data.rows.inspect

@stantoncharlton
Copy link

I am struggling to download key file, but where can i find that?

@danblundell
Copy link

When creating your Client ID in the Google API console, select 'service account' and once it's generate you'll get an option to generate a p12 keyfile.

@albertoalcaraz
Copy link

Everything seems to be ok but it throws me this error:

.../gems/ruby-2.1.0/gems/google-api-client-0.7.1/lib/google/api_client.rb:595:in `execute!': unknown keyword: interval (ArgumentError)

when trying to do this:

analytics = client.discovered_api('analytics', 'v3')

Any clue?

@martinstreicher
Copy link

It looks like the keyword interval is now intervals in the retriable gem. Perhaps we need to downgrade to an older retriable gem.

@rdelasalasvmi
Copy link

Where does the Profile ID come from?

@maier-stefan
Copy link

Got a problem too. buy running the script https://developers.google.com/drive/web/quickstart/quickstart-ruby after adding the needed "application_name" and "application_version" the following error shows up:
/ruby-2.1.1/lib/ruby/gems/2.1.0/gems/google-api-client-0.7.1/lib/google/api_client.rb:595:in `execute!': unknown keyword: interval (ArgumentError)

@albertoalcaraz
Copy link

@Stefflan00 the same is happening to me. Do you figure out how to solve it?

@adrianotadao
Copy link

@Stefflan00 @albertoalcaraz any solution? I have the same =l

@amarcher
Copy link

amarcher commented Nov 4, 2014

ditto

@mafraba
Copy link

mafraba commented Nov 19, 2014

@Stefflan00 Just in case it still helps: maybe you can manually require retriable '~> 1.4' in your Gemfile, so that google-api-client sticks to a version previous to 2.0, since the problem seems to be the one noted by @martinstreicher.

@renugasaraswathy
Copy link

Getting this error in production environment "{ "error" : "invalid_grant" }". Same code works in my development environment with the same Profile ID. Please help...

@renugasaraswathy
Copy link

invalid_grant issue is fixed. Reason for the issue is that timestamp of our server was not in sync with Network time.

@abatko
Copy link

abatko commented Dec 18, 2014

As of this writing the Google Developers Console is different. Also, I am writing in a few more details:

  • Go to https://code.google.com/apis/console/
  • Create a "project" if you haven't already done so
  • Turn "ON" Analytics API
  • Under APIs & auth, click Credentials
  • Click Create new Client ID > Service account > Create Client ID
  • Download the public/private key pair file [KEY_FILE]
  • Go to your Analytics account > Admin > User Management > Add permissions for > [SERVICE_ACCOUNT_EMAIL] (something-long@developer.gserviceaccount.com)

@gabevandesande
Copy link

Which parts exactly of the given code am I supposed to replace with personal information? For example
('SOME PATH', 'KEY_FILE') I realize I must replace, as well as 'something_you_like' for the application name. What are all the segments that I must replace?
Thanks

@elCorsaiR
Copy link

Should mention that this code for ver. 0.8.x

@arjunmenon
Copy link

You know the latest version of this gem throws up the error on
key = Google::APIClient::PKCS12.load_key(key_file, 'notasecret')
Uninitialized constant Google::APIClient(name error)

What is the new method for loading the P12/JSON file?

@jvrsgsty
Copy link

@arjunmenon Did you eventually find out how to load your keys on the new version? I'm unable to make it work with version 0.9.24 of the gem

@jvrsgsty
Copy link

Just found it. Turns out it was deprecated .
So now you need the googleauth gem, which is installed along with the API client. Basically you just need to require the class for the API you want to query. Brief example:

require 'google/apis/analyticsreporting_v4'
analytics = Google::Apis::AnalyticsreportingV4::AnalyticsReportingService.new
credentials = Google::Auth::ServiceAccountCredentials.make_creds(json_key_io: IO.new(IO.sysopen('credentials.json')))
credentials.scope = 'https://www.googleapis.com/auth/analytics.readonly'
analytics.authorization = credentials.fetch_access_token!({})["access_token"]

request = {report_requests:[
        {metric:[{expession: "ga:users"}],
         dimensions:[{name:"ga:pagePath"}],
         date_ranges:[{start_date: "2016-12-28", end_date: "2017-01-26"}],
         view_id:"ga:88064121",
         filters_expression: "ga:pagePath=@solicitudes"
}]}

results = analytics.batch_get_reports Google::Apis::AnalyticsreportingV4::GetReportsRequest.new(request)

@justinperkins
Copy link

@jvrsgsty your code sample pulled me out of a deep hole of google API ruby auth hell, filled with non-functional code snippets and terrible documentation, thank you sir

@louisebolden
Copy link

@jvrsgsty same here (what @justinperkins said) - thank you 👍

@raarellano
Copy link

Thank you @jvrsgsty, really helpful!

@agnel-waghela
Copy link

How to do this after User Authorization? I mean I have the token details ( access_token, refersh_token, etc). How to get the analytics accounts details for such user?

@aldrienht
Copy link

@jvrsgsty @justinperkins what are the data inside in credentials.json?

@santucorephp
Copy link

Just found it. Turns out it was deprecated . So now you need the googleauth gem, which is installed along with the API client. Basically you just need to require the class for the API you want to query. Brief example:

> require 'google/apis/analyticsreporting_v4'
> analytics = Google::Apis::AnalyticsreportingV4::AnalyticsReportingService.new
> credentials = Google::Auth::ServiceAccountCredentials.make_creds(json_key_io: IO.new(IO.sysopen('credentials.json')))
> credentials.scope = 'https://www.googleapis.com/auth/analytics.readonly'
> analytics.authorization = credentials.fetch_access_token!({})["access_token"]
> 
> request = {report_requests:[
>         {metric:[{expession: "ga:users"}],
>          dimensions:[{name:"ga:pagePath"}],
>          date_ranges:[{start_date: "2016-12-28", end_date: "2017-01-26"}],
>          view_id:"ga:88064121",
>          filters_expression: "ga:pagePath=@solicitudes"
> }]}
> 
> results = analytics.batch_get_reports Google::Apis::AnalyticsreportingV4::GetReportsRequest.new(request)
> ```

I have tried this but same error will appear "User does not have sufficient permissions for this profile".

namespace :analyze do
  desc 'Google Analytics has been started'
  task query_for_google_analytics_data_api_v4: :environment do
    require 'google/apis/analyticsreporting_v4'
    set_start_date = "2022-08-08"
    set_end_date = "2022-09-09"
    analytics = Google::Apis::AnalyticsreportingV4::AnalyticsReportingService.new
    credentials = Google::Auth::ServiceAccountCredentials.make_creds(
      json_key_io: File.open('sales-322705-f48f750568d2.json'),
      scope: 'https://www.googleapis.com/auth/analytics.readonly'
    )
    analytics.authorization = credentials.fetch_access_token!({})["access_token"]
    p analytics.authorization
    date_range = Google::Apis::AnalyticsreportingV4::DateRange.new(start_date: set_start_date, end_date: set_end_date)

    metric = Google::Apis::AnalyticsreportingV4::Metric.new(expression: 'ga:sessions', alias: 'sessions')
    dimension = Google::Apis::AnalyticsreportingV4::Dimension.new(name: 'ga:browser')

    request = Google::Apis::AnalyticsreportingV4::GetReportsRequest.new(
      report_requests: [Google::Apis::AnalyticsreportingV4::ReportRequest.new(
        view_id: '331568465',
        metrics: [metric],
        dimensions: [dimension],
        date_ranges: [date_range]
      )]
    )

    response = analytics.batch_get_reports(request)
    response.reports
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment