Skip to content

Instantly share code, notes, and snippets.

@wschenk
Created December 4, 2014 22:48
Show Gist options
  • Select an option

  • Save wschenk/d7f8650d619d8f68730a to your computer and use it in GitHub Desktop.

Select an option

Save wschenk/d7f8650d619d8f68730a to your computer and use it in GitHub Desktop.

Revisions

  1. wschenk renamed this gist Dec 4, 2014. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. wschenk created this gist Dec 4, 2014.
    238 changes: 238 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,238 @@
    #!/usr/bin/env ruby -KU
    #
    # This code has been adapted from
    # https://github.com/google/google-api-ruby-client-samples/tree/master/drive
    #

    require 'thor'
    require 'hirb'
    require 'google/api_client'
    require 'google/api_client/client_secrets'
    require 'google/api_client/auth/file_storage'
    require 'google/api_client/auth/installed_app'
    require 'logger'
    require 'csv'

    API_VERSION = 'v3'
    CACHED_API_FILE = "analytics-#{API_VERSION}.cache"
    CREDENTIAL_STORE_FILE = "analytics-oauth2.json"
    CLIENT_SECRETS_FILE = "client_secrets.json"

    class AnalyticsClient
    def initialize( file_caches = nil )
    client
    end

    def client
    return @client if @client

    @client = Google::APIClient.new(:application_name => 'Analyics-CLI',
    :application_version => '1.0.0')

    # FileStorage stores auth credentials in a file, so they survive multiple runs
    # of the application. This avoids prompting the user for authorization every
    # time the access token expires, by remembering the refresh token.
    # Note: FileStorage is not suitable for multi-user applications.
    file_storage = Google::APIClient::FileStorage.new(CREDENTIAL_STORE_FILE)
    if file_storage.authorization.nil?
    client_secrets = Google::APIClient::ClientSecrets.load(CLIENT_SECRETS_FILE)
    # The InstalledAppFlow is a helper class to handle the OAuth 2.0 installed
    # application flow, which ties in with FileStorage to store credentials
    # between runs.
    flow = Google::APIClient::InstalledAppFlow.new(
    :client_id => client_secrets.client_id,
    :client_secret => client_secrets.client_secret,
    :scope => ['https://www.googleapis.com/auth/analytics']
    )
    @client.authorization = flow.authorize(file_storage)
    else
    @client.authorization = file_storage.authorization
    end

    @client
    end

    def api
    return @api if @api

    # Load cached discovered API, if it exists. This prevents retrieving the
    # discovery document on every run, saving a round-trip to API servers.
    if File.exists? CACHED_API_FILE
    File.open(CACHED_API_FILE) do |file|
    @api = Marshal.load(file)
    end
    else
    @api = client.discovered_api('analytics', API_VERSION)
    File.open(CACHED_API_FILE, 'w') do |file|
    Marshal.dump(@api, file)
    end
    end

    @api
    end

    def profiles
    client.execute(
    api_method: api.management.profiles.list,
    parameters: { accountId: "~all", webPropertyId: "~all" } )
    end

    def print_profiles
    profiles.data.items.each do |profile|
    printf "%-15d %-15s %s\n", profile.id, profile.webPropertyId, profile.websiteUrl
    end
    end

    def query_template( profile_id, start_date = nil, end_date = nil )
    today = Time.now.strftime( "%Y-%m-%d" )
    {
    "ids" => "ga:#{profile_id}",
    "start-date" => start_date || today,
    "end-date" => end_date || today,
    "sort" => "-ga:pageviews",
    "dimensions" => "ga:pageTitle",
    "metrics" => "ga:pageviews,ga:newUsers,ga:users"
    }
    end

    def hotcontent( profile_id, start_date = nil, end_date = nil )
    query = query_template( profile_id, start_date, end_date )
    client.execute(
    api_method: api.data.ga.get,
    parameters: query
    )
    end

    def referers( profile_id, start_date = nil, end_date = nil )
    query = query_template( profile_id, start_date, end_date )
    query["dimensions"] = "ga:source,ga:referralPath,ga:medium"
    client.execute(
    api_method: api.data.ga.get,
    parameters: query
    )
    end

    def content_referers( profile_id, start_date = nil, end_date = nil )
    query = query_template( profile_id, start_date, end_date )
    query["dimensions"] = "ga:landingPagePath,ga:source,ga:referralPath,ga:medium"
    query["sort"] = "ga:landingPagePath,-ga:pageviews"

    client.execute(
    api_method: api.data.ga.get,
    parameters: query
    )
    end

    def timeline( profile_id )
    one_month_ago = Time.now - 30 * 24 * 60 * 60

    start_date = one_month_ago

    today = Time.now

    seen = {}
    title = {}
    while start_date.to_date <= today.to_date
    puts
    puts start_date.to_date

    contents = hotcontent( profile_id, start_date.strftime( "%Y-%m-%d" ), start_date.strftime( "%Y-%m-%d" ) )
    contents.data.rows.each do |content|
    unless title[content[0]]
    puts " Posted: #{content[0]}"
    end

    title[content[0]] = true
    end
    puts

    result = referers( profile_id, start_date.strftime( "%Y-%m-%d" ), start_date.strftime( "%Y-%m-%d" ) )
    result.data.rows.each do |data|
    url = data[0]
    url = "http://#{data[0]}#{data[1]}" if data[2] == 'referral'
    printf " %-10s %5s %s\n", data[2], data[3],url if !seen[url] && data[3].to_i > 2
    seen[url] = true if data[2] == 'referral'
    end
    start_date = start_date + 24 * 60 * 60
    end
    end

    def print_query_result( r )
    headers = r.data.columnHeaders.collect { |x| x.name }
    puts Hirb::Helpers::AutoTable.render(r.data.rows, headers: headers )
    end

    def print_csv_result(r)
    csv_string = CSV.generate do |csv|
    csv << r.data.columnHeaders.collect { |x| x.name }
    r.data.rows.each do |row|
    csv << row
    end
    end

    puts csv_string
    csv_string
    end
    end

    class HammerOfTheGods < Thor
    desc "profiles", "List Account Profiles"
    def profiles
    client.print_profiles
    end

    desc "hotcontent PROFILE_ID", "Show hot content for profile id"
    options [:today, :yesterday, :recently, :month, :table, :csv]
    def hotcontent( profile_id )
    result = client.hotcontent( profile_id, start_date, end_date )
    print_result result
    end

    desc "referers PROFILE_ID", "Show hot content for profile id"
    options [:today, :yesterday, :recently, :month, :table, :csv]
    def referers( profile_id )
    result = client.referers( profile_id, start_date, end_date )
    print_result( result )
    end

    desc "content_referers PROFILE_ID", "Show hot content for profile id"
    options [:today, :yesterday, :recently, :month, :table, :csv]
    def content_referers( profile_id )
    result = client.content_referers( profile_id, start_date, end_date )
    print_result( result )
    end

    desc "timeline PROFILE_ID", "Show a timeline of referers"
    def timeline( profile_id )
    client.timeline( profile_id )
    end

    private
    def client
    @client ||= AnalyticsClient.new
    end

    def start_date
    return (Time.now - (24*60*60)).strftime( "%Y-%m-%d" ) if options[:yesterday]
    return (Time.now - (7*24*60*60)).strftime( "%Y-%m-%d" ) if options[:recently]
    return (Time.now - (30*24*60*60)).strftime( "%Y-%m-%d" ) if options[:month]
    nil
    end

    def end_date
    return (Time.now - (24*60*60)).strftime( "%Y-%m-%d" ) if options[:yesterday]
    nil
    end

    def print_result( result )
    if options[:csv]
    client.print_csv_result( result )
    else
    client.print_query_result( result )
    end
    end
    end

    if __FILE__ == $0
    HammerOfTheGods.start(ARGV)
    end