gaapi 0.0.1alpha1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/bin/gaapi +2 -1
- data/lib/gaapi/access_token.rb +38 -0
- data/lib/gaapi/main.rb +94 -75
- data/lib/gaapi/query.rb +36 -161
- data/lib/gaapi/response.rb +78 -0
- data/lib/gaapi/version.rb +5 -0
- data/lib/gaapi.rb +2 -0
- metadata +64 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ffff326579e103303525b129d3befd2c26304126a20bb7c1f3f54b1aa6d0c7bd
|
4
|
+
data.tar.gz: cef8c48c415155959499cb1c8faec0a422c8cb592ef4159fba906afcbeb47297
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: edf53d316f4c32fadddf748770779f6ab56dd26192b2a3683d42c938e63ae79f2310460cbc7aa87bae516d7ae8fe3166093c5933907ab786e7573cca476eef0d
|
7
|
+
data.tar.gz: 5d67cb658c49b4b883cf75c09d0fb08089d1662ff40ed1a11adfa2e50c0a4bc79299f150f0876e1009a22fe9e8c4b5376db87c06dec7be02b7cd004567a74691
|
data/bin/gaapi
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GAAPI
|
4
|
+
# An access token generated from a credential file provided by Google Analystics.
|
5
|
+
# The credential file is suitable for using in applications where humans aren't
|
6
|
+
# involved, such as scheduled jobs. To obtain a credential file, follow the instructions
|
7
|
+
# at https://developers.google.com/identity/protocols/OAuth2ServiceAccount.
|
8
|
+
class AccessToken
|
9
|
+
# Get a new access token. The actual token is lazily-generated, so no call is
|
10
|
+
# made to Google Analytics until #token is called.
|
11
|
+
# @param credential_file [String] File name of a credential file provided by
|
12
|
+
# Google Analytics.
|
13
|
+
def initialize(credential_file = nil)
|
14
|
+
@credential_file = credential_file || File.expand_path("~/.gaapi/ga-api-key")
|
15
|
+
stat = File::Stat.new(@credential_file)
|
16
|
+
raise "#{@credential_file} must be readable and writable only by you." if stat.world_readable? || stat.world_writable?
|
17
|
+
end
|
18
|
+
|
19
|
+
# An access token that can be used in a request to Google Analytics Reporting API v4.
|
20
|
+
# @return [String] An access token.
|
21
|
+
def token
|
22
|
+
(@token ||= fetch_access_token)["access_token"]
|
23
|
+
end
|
24
|
+
alias to_s token
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def fetch_access_token
|
29
|
+
File.open(@credential_file) do |fd|
|
30
|
+
authorization = Google::Auth::ServiceAccountCredentials.make_creds(
|
31
|
+
json_key_io: fd,
|
32
|
+
scope: "https://www.googleapis.com/auth/analytics.readonly"
|
33
|
+
)
|
34
|
+
authorization.fetch_access_token!
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/gaapi/main.rb
CHANGED
@@ -2,104 +2,123 @@
|
|
2
2
|
|
3
3
|
require "optparse"
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
module GAAPI
|
6
|
+
module Main
|
7
|
+
class << self
|
8
|
+
def call
|
9
|
+
begin
|
10
|
+
return 1 if (options = process_options).nil?
|
11
|
+
|
12
|
+
puts "options: #{options.inspect}" if options[:debug]
|
13
|
+
|
14
|
+
# return unless (result = Query.call(options))
|
15
|
+
query = Query.new((options[:query_file] || $stdin).read,
|
16
|
+
options[:view_id],
|
17
|
+
options[:access_token],
|
18
|
+
options[:start_date],
|
19
|
+
options[:end_date])
|
20
|
+
puts "query: #{query.inspect}" if options[:debug]
|
21
|
+
rescue StandardError => e
|
22
|
+
$stderr.puts e.message # rubocop:disable Style/StderrPuts
|
23
|
+
return 1
|
24
|
+
end
|
11
25
|
|
12
|
-
|
26
|
+
return 0 if options[:dry_run]
|
13
27
|
|
14
|
-
|
15
|
-
|
28
|
+
result = query.execute
|
29
|
+
puts "result: #{result.inspect}" if options[:debug]
|
16
30
|
|
17
|
-
|
31
|
+
unless result.success?
|
32
|
+
# Show the output unformatted, because we don't know what we're going
|
33
|
+
# to get back.
|
34
|
+
puts result.body
|
35
|
+
return 1
|
36
|
+
end
|
18
37
|
|
19
|
-
|
38
|
+
case options[:output_format]
|
39
|
+
when :csv
|
40
|
+
puts result.csv
|
41
|
+
else
|
42
|
+
puts result.pp
|
43
|
+
end
|
20
44
|
|
21
|
-
|
22
|
-
puts "Request failed #{result.code}"
|
23
|
-
puts Query.pp(result.body)
|
24
|
-
return
|
45
|
+
0
|
25
46
|
end
|
26
47
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
48
|
+
def process_options
|
49
|
+
options = {}
|
50
|
+
credential_file = File.join(Dir.home, ".gaapi/ga-api-key")
|
51
|
+
parsed_options = OptionParser.new do |opts|
|
52
|
+
opts.banner = "Usage: [options] VIEW_ID"
|
53
|
+
opts.accept(Date)
|
54
|
+
|
55
|
+
opts.on("-a TOKEN",
|
56
|
+
"--access-token TOKEN",
|
57
|
+
"An access token obtained from https://developers.google.com/oauthplayground.") do |access_token|
|
58
|
+
options[:access_token] = access_token
|
59
|
+
end
|
34
60
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
opts.accept(Date)
|
61
|
+
opts.on("--csv",
|
62
|
+
"Output result as a csv file.") do
|
63
|
+
options[:output_format] = :csv
|
64
|
+
end
|
40
65
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
66
|
+
opts.on("-c CREDENTIALS",
|
67
|
+
"--credentials CREDENTIALS",
|
68
|
+
"Location of the credentials file. Default: `#{credential_file}`.") do |credentials|
|
69
|
+
credential_file = credentials
|
70
|
+
end
|
46
71
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
72
|
+
opts.on("-d", "--debug", "Print debugging information.") do
|
73
|
+
options[:debug] = true
|
74
|
+
end
|
51
75
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
76
|
+
opts.on("-e",
|
77
|
+
"--end-date END_DATE",
|
78
|
+
Date,
|
79
|
+
"Report including END_DATE.") do |end_date|
|
80
|
+
options[:end_date] = end_date
|
56
81
|
end
|
57
82
|
|
58
|
-
|
59
|
-
|
60
|
-
|
83
|
+
opts.on("-n", "--dry-run", "Don't actually send the query to Google.") do
|
84
|
+
options[:dry_run] = true
|
85
|
+
end
|
61
86
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
87
|
+
opts.on("-q QUERYFILE",
|
88
|
+
"--query-file QUERYFILE",
|
89
|
+
"File containing the query. Default STDIN.") do |query_file|
|
90
|
+
options[:query_file] = File.open(query_file)
|
91
|
+
end
|
92
|
+
|
93
|
+
opts.on("-s",
|
94
|
+
"--start-date START_DATE",
|
95
|
+
Date,
|
96
|
+
"Report including START_DATE.") do |start_date|
|
97
|
+
options[:start_date] = start_date
|
98
|
+
end
|
67
99
|
end
|
68
|
-
|
69
|
-
|
70
|
-
|
100
|
+
parsed_options.parse!
|
101
|
+
unless ARGV.size == 1
|
102
|
+
$stderr.puts("gaapi: You must provide a view ID.\n" + parsed_options.to_s) # rubocop:disable Style/StderrPuts
|
103
|
+
return nil
|
71
104
|
end
|
105
|
+
options[:view_id] = ARGV[0]
|
72
106
|
|
73
|
-
|
74
|
-
"--query-file QUERYFILE",
|
75
|
-
"File containing the query. Default STDIN.") do |query_file|
|
76
|
-
options[:query_file] = File.open(query_file)
|
77
|
-
end
|
107
|
+
options[:access_token] ||= GAAPI::AccessToken.new(credential_file)
|
78
108
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
109
|
+
if options[:end_date].nil? && !options[:start_date].nil?
|
110
|
+
options[:end_date] = options[:start_date]
|
111
|
+
elsif options[:start_date].nil? && !options[:end_date].nil?
|
112
|
+
options[:start_date] = options[:end_date]
|
113
|
+
elsif options[:start_date].nil? && options[:end_date].nil?
|
114
|
+
options[:end_date] = options[:start_date] = (Date.today - 1).to_s
|
84
115
|
end
|
85
|
-
end
|
86
|
-
opts.parse!
|
87
|
-
opts.abort("You must provide a view ID. \n" + opts.to_s) unless ARGV.size == 1
|
88
|
-
options[:view_id] = ARGV[0]
|
89
|
-
|
90
|
-
if options[:end_date].nil? && !options[:start_date].nil?
|
91
|
-
options[:end_date] = options[:start_date]
|
92
|
-
elsif options[:start_date].nil? && !options[:end_date].nil?
|
93
|
-
options[:start_date] = options[:end_date]
|
94
|
-
elsif options[:start_date].nil? && options[:end_date].nil?
|
95
|
-
options[:end_date] = options[:start_date] = (Date.today - 1).to_s
|
96
|
-
end
|
97
116
|
|
98
|
-
|
117
|
+
options
|
118
|
+
end
|
99
119
|
end
|
100
120
|
end
|
101
121
|
end
|
102
|
-
|
103
122
|
# Some hints:
|
104
123
|
# https://stackoverflow.com/a/41179467/3109926
|
105
124
|
# http://www.daimto.com/google-service-accounts-with-json-file/
|
data/lib/gaapi/query.rb
CHANGED
@@ -3,172 +3,47 @@
|
|
3
3
|
require "csv"
|
4
4
|
require "net/http"
|
5
5
|
|
6
|
-
|
7
|
-
class
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
view_id: options[:view_id],
|
28
|
-
date_ranges: [Google::Apis::AnalyticsreportingV4::DateRange.new(
|
29
|
-
start_date: options[:start_date],
|
30
|
-
end_date: options[:end_date]
|
31
|
-
)],
|
32
|
-
# dimensions: [
|
33
|
-
# Google::Apis::AnalyticsreportingV4::Dimension.new(name: "ga:segment")
|
34
|
-
# # Google::Apis::AnalyticsreportingV4::Dimension.new(name: "ga:adContent"),
|
35
|
-
# # Google::Apis::AnalyticsreportingV4::Dimension.new(name: "ga:campaign"),
|
36
|
-
# # Google::Apis::AnalyticsreportingV4::Dimension.new(name: "ga:keyword"),
|
37
|
-
# # Google::Apis::AnalyticsreportingV4::Dimension.new(name: "ga:medium"),
|
38
|
-
# # Google::Apis::AnalyticsreportingV4::Dimension.new(name: "ga:socialNetwork"),
|
39
|
-
# # Google::Apis::AnalyticsreportingV4::Dimension.new(name: "ga:source")
|
40
|
-
# ],
|
41
|
-
metrics: [
|
42
|
-
# Google::Apis::AnalyticsreportingV4::Metric.new(
|
43
|
-
# expression: "ga:bounces"
|
44
|
-
# ),
|
45
|
-
Google::Apis::AnalyticsreportingV4::Metric.new(
|
46
|
-
expression: "ga:newUsers"
|
47
|
-
),
|
48
|
-
Google::Apis::AnalyticsreportingV4::Metric.new(
|
49
|
-
expression: "ga:pageviewsPerSession"
|
50
|
-
),
|
51
|
-
Google::Apis::AnalyticsreportingV4::Metric.new(
|
52
|
-
expression: "ga:sessions"
|
53
|
-
),
|
54
|
-
Google::Apis::AnalyticsreportingV4::Metric.new(
|
55
|
-
expression: "ga:sessionDuration"
|
56
|
-
),
|
57
|
-
# Google::Apis::AnalyticsreportingV4::Metric.new(
|
58
|
-
# expression: "ga:organicSearches"
|
59
|
-
# ),
|
60
|
-
Google::Apis::AnalyticsreportingV4::Metric.new(
|
61
|
-
expression: "ga:users"
|
62
|
-
)
|
63
|
-
],
|
64
|
-
metric_filter_clauses: [
|
65
|
-
Google::Apis::AnalyticsreportingV4::MetricFilterClause.new(
|
66
|
-
filters: [
|
67
|
-
Google::Apis::AnalyticsreportingV4::MetricFilter.new(
|
68
|
-
metric_name: "ga:pageviews",
|
69
|
-
comparison_value: "0",
|
70
|
-
operator: "GREATER_THAN"
|
71
|
-
)
|
72
|
-
]
|
73
|
-
)
|
74
|
-
],
|
75
|
-
include_empty_rows: true
|
76
|
-
)
|
77
|
-
|
78
|
-
# puts "request.to_json: #{JSON.pretty_generate(JSON.parse(request.to_json))}" if options[:debug]
|
79
|
-
get_reports_requests = Google::Apis::AnalyticsreportingV4::GetReportsRequest.new(report_requests: [request])
|
80
|
-
# puts get_reports_requests.to_json if options[:debug]
|
81
|
-
puts JSON.pretty_generate(JSON.parse(get_reports_requests.to_json)) if options[:debug]
|
82
|
-
return nil if options[:dry_run]
|
83
|
-
|
84
|
-
result = service.batch_get_reports(get_reports_requests)
|
85
|
-
puts "result: #{result.inspect}" if options[:debug]
|
86
|
-
result
|
87
|
-
end
|
88
|
-
|
89
|
-
def csv(result)
|
90
|
-
result = result.to_json if result.is_a?(Google::Apis::AnalyticsreportingV4::GetReportsResponse)
|
91
|
-
result = JSON.parse(result) if result.is_a?(String)
|
92
|
-
CSV.generate do |csv|
|
93
|
-
result["reports"].each do |report|
|
94
|
-
# puts report.column_header.dimensions.inspect
|
95
|
-
# puts report.column_header.metric_header.metric_header_entries.map(&:name).inspect
|
96
|
-
csv << csv_header_row(report)
|
97
|
-
report["data"]["rows"].each do |row|
|
98
|
-
csv << csv_data_row(row["dimensions"], row["metrics"])
|
99
|
-
end
|
100
|
-
csv << csv_data_row("Totals", report["data"]["totals"]) if report["data"]["totals"]
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def csv_data_row(row_headers, metrics)
|
106
|
-
(Array(row_headers) || []) + metrics[0]["values"]
|
107
|
-
end
|
108
|
-
|
109
|
-
def csv_header_row(report)
|
110
|
-
(report["columnHeader"]["dimensions"] || []) + report["columnHeader"]["metricHeader"]["metricHeaderEntries"].map do |entry|
|
111
|
-
entry["name"]
|
6
|
+
module GAAPI
|
7
|
+
class Query
|
8
|
+
# Create a Query object.
|
9
|
+
# @param access_token [String] A valid access token with which to make a request to
|
10
|
+
# the specified View ID.
|
11
|
+
# @param end_date [Date, String] The end date for the report.
|
12
|
+
# @param query_string [String] The query in JSON format.
|
13
|
+
# @param start_date [Date, String] The start date for the report.
|
14
|
+
# @param view_id [String] The view ID of the property for which to submit the
|
15
|
+
# query.
|
16
|
+
def initialize(query_string, view_id, access_token, start_date, end_date)
|
17
|
+
@access_token = access_token
|
18
|
+
query_string = JSON.parse(query_string) unless query_string.is_a?(Hash)
|
19
|
+
@query = {}
|
20
|
+
@query["reportRequests"] = query_string["reportRequests"].map do |report_request|
|
21
|
+
report_request["viewId"] = view_id
|
22
|
+
report_request["dateRanges"] = [
|
23
|
+
"startDate": start_date.to_s,
|
24
|
+
"endDate": end_date.to_s
|
25
|
+
]
|
26
|
+
report_request
|
112
27
|
end
|
28
|
+
# puts "query: #{JSON.pretty_generate(query)}"
|
113
29
|
end
|
114
30
|
|
115
|
-
|
116
|
-
|
31
|
+
# Send the requested query to Google Analytics and return the response.
|
32
|
+
# @return [HTTPResponse] The response from the request.
|
33
|
+
def execute
|
34
|
+
uri = URI.parse("https://analyticsreporting.googleapis.com/v4/reports:batchGet")
|
35
|
+
https = Net::HTTP.new(uri.host, uri.port)
|
36
|
+
https.use_ssl = true
|
37
|
+
# https.set_debug_output($stdout)
|
38
|
+
request = Net::HTTP::Post.new(uri.request_uri,
|
39
|
+
"Content-Type" => "application/json",
|
40
|
+
"Authorization" => "Bearer #{access_token}")
|
41
|
+
request.body = query.to_json
|
42
|
+
Response.new(https.request(request))
|
117
43
|
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def initialize(query_string, options)
|
121
|
-
# puts "query_string: #{query_string}"
|
122
|
-
puts "Initializing query. Options: #{options.inspect}" if options[:debug]
|
123
44
|
|
124
|
-
|
125
|
-
@access_token = options[:access_token]
|
126
|
-
puts "options[:credentials]: #{options[:credentials]}"
|
127
|
-
@access_token ||= access_token_from_credentials(options[:credentials])
|
128
|
-
puts "Final access_token: #{access_token}"
|
129
|
-
@dry_run = options[:dry_run]
|
130
|
-
|
131
|
-
query_string = JSON.parse(query_string) unless query_string.is_a?(Hash)
|
132
|
-
@query = {}
|
133
|
-
@query["reportRequests"] = query_string["reportRequests"].map do |report_request|
|
134
|
-
report_request["viewId"] = options[:view_id]
|
135
|
-
report_request["dateRanges"] = [
|
136
|
-
"startDate": options[:start_date],
|
137
|
-
"endDate": options[:end_date]
|
138
|
-
]
|
139
|
-
report_request
|
140
|
-
end
|
141
|
-
# puts "query: #{JSON.pretty_generate(query)}"
|
142
|
-
end
|
45
|
+
private
|
143
46
|
|
144
|
-
|
145
|
-
uri = URI.parse("https://analyticsreporting.googleapis.com/v4/reports:batchGet")
|
146
|
-
https = Net::HTTP.new(uri.host, uri.port)
|
147
|
-
https.use_ssl = true
|
148
|
-
# https.set_debug_output($stdout)
|
149
|
-
request = Net::HTTP::Post.new(uri.request_uri,
|
150
|
-
"Content-Type" => "application/json",
|
151
|
-
"Authorization" => "Bearer #{access_token}")
|
152
|
-
request.body = query.to_json
|
153
|
-
response = https.request(request)
|
154
|
-
response
|
155
|
-
end
|
156
|
-
|
157
|
-
private
|
158
|
-
|
159
|
-
attr_reader :access_token, :dry_run, :query
|
160
|
-
|
161
|
-
def access_token_from_credentials(credential_file_name)
|
162
|
-
stat = File::Stat.new(credential_file_name)
|
163
|
-
if stat.world_readable? || stat.world_writable?
|
164
|
-
raise "#{credential_file_name} must be readable and writable only by you."
|
165
|
-
end
|
166
|
-
authorization = Google::Auth::ServiceAccountCredentials.make_creds(
|
167
|
-
json_key_io: File.open(credential_file_name),
|
168
|
-
scope: "https://www.googleapis.com/auth/analytics.readonly"
|
169
|
-
)
|
170
|
-
token = authorization.fetch_access_token!
|
171
|
-
puts token
|
172
|
-
token["access_token"]
|
47
|
+
attr_reader :access_token, :query
|
173
48
|
end
|
174
49
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GAAPI
|
4
|
+
# Holds the result of a Google Analytics query, and provides some methods to
|
5
|
+
# present the result in useful ways.
|
6
|
+
class Response
|
7
|
+
attr_reader :response
|
8
|
+
|
9
|
+
# Raw body of the response. Typically only used for diagnostic purposes.
|
10
|
+
def body
|
11
|
+
response.body
|
12
|
+
end
|
13
|
+
|
14
|
+
# Raw code of the response. Typically only used for diagnostic purposes.
|
15
|
+
def code
|
16
|
+
response.code
|
17
|
+
end
|
18
|
+
|
19
|
+
# Convert a response from Google Analytics into a comma-separated values
|
20
|
+
# format file.
|
21
|
+
# @return [String] The result of the query formatted as a comma-separated
|
22
|
+
# values string.
|
23
|
+
def csv
|
24
|
+
result = to_json
|
25
|
+
@csv ||= CSV.generate do |csv|
|
26
|
+
result["reports"].each do |report|
|
27
|
+
# puts report.column_header.dimensions.inspect
|
28
|
+
# puts report.column_header.metric_header.metric_header_entries.map(&:name).inspect
|
29
|
+
csv << csv_header_row(report)
|
30
|
+
report["data"]["rows"].each do |row|
|
31
|
+
csv << csv_data_row(row["dimensions"], row["metrics"])
|
32
|
+
end
|
33
|
+
csv << csv_data_row("Totals", report["data"]["totals"]) if report["data"]["totals"]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(response)
|
39
|
+
@response = response
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return the JSON result in a readable format.
|
43
|
+
# @return [String] The JSON result formatted in a human-readable way.
|
44
|
+
def pp
|
45
|
+
@pp ||= JSON.pretty_generate(to_json)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Return true if the request was successful.
|
49
|
+
# @return [Boolean] True if the request was successful (response code 200).
|
50
|
+
def success?
|
51
|
+
code == "200"
|
52
|
+
end
|
53
|
+
|
54
|
+
# Return the body of the response
|
55
|
+
# @return [String] JSON-formatted response in a String.
|
56
|
+
def to_json
|
57
|
+
@to_json ||= JSON.parse(to_s)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Return the body of the response
|
61
|
+
# @return [String] JSON-formatted response in a String.
|
62
|
+
def to_s
|
63
|
+
response.body
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def csv_data_row(row_headers, metrics)
|
69
|
+
(Array(row_headers) || []) + metrics[0]["values"]
|
70
|
+
end
|
71
|
+
|
72
|
+
def csv_header_row(report)
|
73
|
+
(report["columnHeader"]["dimensions"] || []) + report["columnHeader"]["metricHeader"]["metricHeaderEntries"].map do |entry|
|
74
|
+
entry["name"]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/gaapi.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gaapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Larry Reid
|
@@ -9,8 +9,50 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-
|
12
|
+
date: 2018-09-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: chandler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: minitest
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: webmock
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
14
56
|
- !ruby/object:Gem::Dependency
|
15
57
|
name: google-api-client
|
16
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -25,6 +67,20 @@ dependencies:
|
|
25
67
|
- - "~>"
|
26
68
|
- !ruby/object:Gem::Version
|
27
69
|
version: '0.19'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: googleauth
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
28
84
|
description: |2
|
29
85
|
Submit queries expressed in JSON to Google Analytics. Can be run
|
30
86
|
from unattended scripts, batch jobs, etc.
|
@@ -36,8 +92,11 @@ extra_rdoc_files: []
|
|
36
92
|
files:
|
37
93
|
- bin/gaapi
|
38
94
|
- lib/gaapi.rb
|
95
|
+
- lib/gaapi/access_token.rb
|
39
96
|
- lib/gaapi/main.rb
|
40
97
|
- lib/gaapi/query.rb
|
98
|
+
- lib/gaapi/response.rb
|
99
|
+
- lib/gaapi/version.rb
|
41
100
|
homepage: https://github.com/weenhanceit/gaapi
|
42
101
|
licenses:
|
43
102
|
- MIT
|
@@ -54,12 +113,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
54
113
|
version: '0'
|
55
114
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
115
|
requirements:
|
57
|
-
- - "
|
116
|
+
- - ">="
|
58
117
|
- !ruby/object:Gem::Version
|
59
|
-
version:
|
118
|
+
version: '0'
|
60
119
|
requirements: []
|
61
120
|
rubyforge_project:
|
62
|
-
rubygems_version: 2.
|
121
|
+
rubygems_version: 2.7.6
|
63
122
|
signing_key:
|
64
123
|
specification_version: 4
|
65
124
|
summary: Query Google Analytics from the command line.
|