google_api 1.0.0.beta
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.
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +453 -0
- data/Rakefile +9 -0
- data/google_api.gemspec +22 -0
- data/lib/google_api.rb +37 -0
- data/lib/google_api/cache.rb +49 -0
- data/lib/google_api/configuration.rb +37 -0
- data/lib/google_api/core_ext/hash.rb +11 -0
- data/lib/google_api/core_ext/string.rb +13 -0
- data/lib/google_api/date.rb +59 -0
- data/lib/google_api/ga.rb +52 -0
- data/lib/google_api/ga/data.rb +335 -0
- data/lib/google_api/ga/data/data_dsl.rb +66 -0
- data/lib/google_api/ga/data/filters_dsl.rb +11 -0
- data/lib/google_api/ga/data/segment_dsl.rb +11 -0
- data/lib/google_api/ga/helper.rb +41 -0
- data/lib/google_api/ga/management/account.rb +37 -0
- data/lib/google_api/ga/management/goal.rb +58 -0
- data/lib/google_api/ga/management/management.rb +36 -0
- data/lib/google_api/ga/management/profile.rb +64 -0
- data/lib/google_api/ga/management/segment.rb +41 -0
- data/lib/google_api/ga/management/webproperty.rb +52 -0
- data/lib/google_api/ga/session.rb +165 -0
- data/lib/google_api/version.rb +3 -0
- data/spec/lib/google_api_spec.rb +63 -0
- data/spec/spec_helper.rb +8 -0
- metadata +125 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
module GoogleApi
|
2
|
+
module Ga
|
3
|
+
class DataDsl
|
4
|
+
|
5
|
+
OPERATORS = ['==', '!=', '>', '<', '>=', '<=', '=~', '!~']
|
6
|
+
OPERATORS_METHOD = {'%' => '=@', '**' => '!@'}
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@result = []
|
10
|
+
end
|
11
|
+
|
12
|
+
# Make operators
|
13
|
+
OPERATORS.each do |operator|
|
14
|
+
eval <<-METHOD
|
15
|
+
def #{operator} (value)
|
16
|
+
@result << @attribute + "#{operator}" + value.to_s
|
17
|
+
self
|
18
|
+
end
|
19
|
+
METHOD
|
20
|
+
end
|
21
|
+
OPERATORS_METHOD.each do |key, value|
|
22
|
+
eval <<-METHOD
|
23
|
+
def #{key} (value)
|
24
|
+
@result << @attribute + "#{value}" + value.to_s
|
25
|
+
self
|
26
|
+
end
|
27
|
+
METHOD
|
28
|
+
end
|
29
|
+
|
30
|
+
def method_missing(name)
|
31
|
+
if name.to_s =~ /\A[a-zA-Z0-9]+\Z/
|
32
|
+
@attribute = "ga:#{name}"
|
33
|
+
self
|
34
|
+
else
|
35
|
+
super
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def &(other)
|
40
|
+
@result << :and
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def |(other)
|
45
|
+
@result << :or
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
def build_parameter
|
50
|
+
i = @result.index{ |x| x.is_a?(Symbol) }
|
51
|
+
|
52
|
+
if !i.nil?
|
53
|
+
result = @result[i-2] + (@result[i] == :and ? ";" : ",") + @result[i-1]
|
54
|
+
@result.delete_at(i)
|
55
|
+
@result.delete_at(i-1)
|
56
|
+
@result[i-2] = result
|
57
|
+
|
58
|
+
build_parameter
|
59
|
+
else
|
60
|
+
@result.join
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module GoogleApi
|
2
|
+
module Ga
|
3
|
+
module Helper
|
4
|
+
|
5
|
+
# Same as get but automaticly add day, month and year to dimension
|
6
|
+
#
|
7
|
+
# Also check cache
|
8
|
+
#
|
9
|
+
def get_by_day(parameters, start_date = prev_month, end_date = now, expire = nil)
|
10
|
+
|
11
|
+
[:dimensions, :sort].each do |param|
|
12
|
+
parameters[param] = [] unless parameters[param]
|
13
|
+
|
14
|
+
if parameters[param].is_a?(String) || parameters[param].is_a?(Symbol)
|
15
|
+
parameters[param] = [parameters[param]]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
parameters[:dimensions] << :day
|
20
|
+
|
21
|
+
if more_years?(start_date, end_date)
|
22
|
+
parameters[:dimensions] << :month
|
23
|
+
parameters[:dimensions] << :year
|
24
|
+
|
25
|
+
parameters[:sort] << :year
|
26
|
+
parameters[:sort] << :month
|
27
|
+
|
28
|
+
elsif more_months?(start_date, end_date)
|
29
|
+
parameters[:dimensions] << :month
|
30
|
+
|
31
|
+
parameters[:sort] << :month
|
32
|
+
end
|
33
|
+
|
34
|
+
parameters[:sort] << :day
|
35
|
+
|
36
|
+
get(parameters, start_date, end_date, expire)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module GoogleApi
|
2
|
+
module Ga
|
3
|
+
class Account < Management
|
4
|
+
|
5
|
+
def initialize(account)
|
6
|
+
set(account)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.all(account_id = '~all')
|
10
|
+
get({ accountId: account_id }).map { |account| Account.new(account) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.find(account_id)
|
14
|
+
all(account_id).first
|
15
|
+
end
|
16
|
+
|
17
|
+
def refresh
|
18
|
+
@webproperties = nil
|
19
|
+
|
20
|
+
set( Account.get({ accountId: @id }).first )
|
21
|
+
|
22
|
+
return true
|
23
|
+
end
|
24
|
+
|
25
|
+
def webproperties
|
26
|
+
@webproperties ||= Webproperty.all(@id)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def self.get(parameters = nil)
|
32
|
+
super(@@session.api.management.accounts.list, parameters)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module GoogleApi
|
2
|
+
module Ga
|
3
|
+
class Goal < Management
|
4
|
+
|
5
|
+
attr_reader :accountId
|
6
|
+
attr_reader :webPropertyId
|
7
|
+
attr_reader :profileId
|
8
|
+
attr_reader :value
|
9
|
+
attr_reader :active
|
10
|
+
attr_reader :type
|
11
|
+
attr_reader :goal
|
12
|
+
|
13
|
+
def initialize(goal)
|
14
|
+
set(goal)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.all(account_id = '~all', webproperty_id = '~all', profile_id = '~all', goal_id = '~all')
|
18
|
+
get({ accountId: account_id, webPropertyId: webproperty_id, profileId: profile_id, goalId: goal_id }).map { |goal| Goal.new(goal) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.find(goal_id)
|
22
|
+
all('~all', '~all', '~all', goal_id).first
|
23
|
+
end
|
24
|
+
|
25
|
+
def refresh
|
26
|
+
@profile = nil
|
27
|
+
|
28
|
+
set( Goal.get({ accountId: @accountId, webPropertyId: @id, profileId: @profileId, goalId: @id }).first )
|
29
|
+
|
30
|
+
return true
|
31
|
+
end
|
32
|
+
|
33
|
+
def profile
|
34
|
+
@profile ||= Profile.find(@profileId)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def self.get(parameters = nil)
|
40
|
+
super(@@session.api.management.goals.list, parameters)
|
41
|
+
end
|
42
|
+
|
43
|
+
def set(goal)
|
44
|
+
@accountId = goal['accountId']
|
45
|
+
@webPropertyId = goal['webPropertyId']
|
46
|
+
@profileId = goal['profileId']
|
47
|
+
@value = goal['value']
|
48
|
+
@active = goal['active']
|
49
|
+
@type = goal['type']
|
50
|
+
|
51
|
+
@goal = goal[camelize(@type) + 'Details']
|
52
|
+
|
53
|
+
super(goal)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module GoogleApi
|
2
|
+
module Ga
|
3
|
+
class Management
|
4
|
+
|
5
|
+
@@session = Session
|
6
|
+
|
7
|
+
attr_reader :id
|
8
|
+
attr_reader :name
|
9
|
+
attr_reader :created
|
10
|
+
attr_reader :updated
|
11
|
+
|
12
|
+
def camelize(string)
|
13
|
+
string = string.downcase.split('_').map!(&:capitalize).join
|
14
|
+
string[0] = string[0].downcase
|
15
|
+
string
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def self.get(api_method, parameters = nil)
|
21
|
+
JSON.parse(
|
22
|
+
@@session.client.execute(api_method: api_method,
|
23
|
+
parameters: parameters).body
|
24
|
+
)["items"]
|
25
|
+
end
|
26
|
+
|
27
|
+
def set(values)
|
28
|
+
@id = values['id']
|
29
|
+
@name = values['name']
|
30
|
+
@created = values['created']
|
31
|
+
@updated = values['updated']
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module GoogleApi
|
2
|
+
module Ga
|
3
|
+
class Profile < Management
|
4
|
+
|
5
|
+
attr_reader :accountId
|
6
|
+
attr_reader :webPropertyId
|
7
|
+
attr_reader :currency
|
8
|
+
attr_reader :timezone
|
9
|
+
|
10
|
+
def initialize(profile)
|
11
|
+
set(profile)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.all(account_id = '~all', webproperty_id = '~all', profile_id = '~all')
|
15
|
+
get({ accountId: account_id, webPropertyId: webproperty_id, profileId: '~all' }).map { |profile| Profile.new(profile) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.find(profile_id)
|
19
|
+
all('~all', '~all', profile_id).first
|
20
|
+
end
|
21
|
+
|
22
|
+
def refresh
|
23
|
+
@webproperty = nil
|
24
|
+
@goals = nil
|
25
|
+
|
26
|
+
set( Profile.get({ accountId: @accountId, webPropertyId: @webPropertyId, profileId: @id }).first )
|
27
|
+
|
28
|
+
return true
|
29
|
+
end
|
30
|
+
|
31
|
+
def webproperty
|
32
|
+
@webproperty ||= Webproperty.find(@webpropertyId)
|
33
|
+
end
|
34
|
+
|
35
|
+
def goals
|
36
|
+
@goals ||= Goal.all(@accountId, @webPropertyId, @id)
|
37
|
+
end
|
38
|
+
|
39
|
+
# def get(parameters, start_date = prev_month, end_date = now, expire = nil)
|
40
|
+
# Data.get(@id, parameters, start_date, end_date, expire)
|
41
|
+
# end
|
42
|
+
|
43
|
+
# def get!(parameters, start_date = prev_month, end_date = now)
|
44
|
+
# Data.get!(@id, parameters, start_date, end_date)
|
45
|
+
# end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def self.get(parameters = nil)
|
50
|
+
super(@@session.api.management.profiles.list, parameters)
|
51
|
+
end
|
52
|
+
|
53
|
+
def set(profile)
|
54
|
+
@accountId = profile['accountId']
|
55
|
+
@webPropertyId = profile['webPropertyId']
|
56
|
+
@currency = profile['currency']
|
57
|
+
@timezone = profile['timezone']
|
58
|
+
|
59
|
+
super(profile)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module GoogleApi
|
2
|
+
module Ga
|
3
|
+
class Segment < Management
|
4
|
+
|
5
|
+
attr_accessor :segmentId
|
6
|
+
attr_accessor :definition
|
7
|
+
|
8
|
+
def initialize(segment)
|
9
|
+
set(segment)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.all(segment_id = '~all')
|
13
|
+
get({ segmentId: segment_id }).map { |segment| Segment.new(segment) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.find(segment_id)
|
17
|
+
all(segment_id).first
|
18
|
+
end
|
19
|
+
|
20
|
+
def refresh
|
21
|
+
set( Segment.get({ segmentId: @id }).first )
|
22
|
+
|
23
|
+
return true
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def self.get(parameters = nil)
|
29
|
+
super(@@session.api.management.segments.list, parameters)
|
30
|
+
end
|
31
|
+
|
32
|
+
def set(segment)
|
33
|
+
@segmentId = segment['segmentId']
|
34
|
+
@definition = segment['definition']
|
35
|
+
|
36
|
+
super(segment)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module GoogleApi
|
2
|
+
module Ga
|
3
|
+
class Webproperty < Management
|
4
|
+
|
5
|
+
attr_reader :accountId
|
6
|
+
attr_reader :websiteUrl
|
7
|
+
|
8
|
+
def initialize(webproperty)
|
9
|
+
set(webproperty)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.all(account_id = '~all', webproperty_id = '~all')
|
13
|
+
get({ accountId: account_id, webPropertyId: webproperty_id }).map { |webproperty| Webproperty.new(webproperty) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.find(webproperty_id)
|
17
|
+
all('~all', webproperty_id).first
|
18
|
+
end
|
19
|
+
|
20
|
+
def refresh
|
21
|
+
@account = nil
|
22
|
+
@profiles = nil
|
23
|
+
|
24
|
+
set( Webproperty.get({ accountId: @accountId, webPropertyId: @id }).first )
|
25
|
+
|
26
|
+
return true
|
27
|
+
end
|
28
|
+
|
29
|
+
def account
|
30
|
+
@account ||= Account.find(@accountId)
|
31
|
+
end
|
32
|
+
|
33
|
+
def profiles
|
34
|
+
@profiles ||= Profile.all(@accountId, @id)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def self.get(parameters = nil)
|
40
|
+
super(@@session.api.management.webproperties.list, parameters)
|
41
|
+
end
|
42
|
+
|
43
|
+
def set(webproperty)
|
44
|
+
@accountId = webproperty['accountId']
|
45
|
+
@websiteUrl = webproperty['websiteUrl']
|
46
|
+
|
47
|
+
super(webproperty)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require "google_api/core_ext/string"
|
2
|
+
|
3
|
+
module GoogleApi
|
4
|
+
module Ga
|
5
|
+
|
6
|
+
class Session
|
7
|
+
|
8
|
+
SCOPE = "https://www.googleapis.com/auth/analytics.readonly"
|
9
|
+
NAME_API = "analytics"
|
10
|
+
VERSION_API = "v3"
|
11
|
+
|
12
|
+
@@api = nil
|
13
|
+
@@client = nil
|
14
|
+
|
15
|
+
# Config --------------------------------------------------------------------------------
|
16
|
+
|
17
|
+
def self._config
|
18
|
+
GoogleApi.config
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.client_id
|
22
|
+
_config.ga.client_id ? _config.ga.client_id : _config.client_id
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.client_secret
|
26
|
+
_config.ga.client_secret ? _config.ga.client_secret : _config.client_secret
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.redirect_uri
|
30
|
+
_config.ga.redirect_uri ? _config.ga.redirect_uri : _config.redirect_uri
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.client_cert_file
|
34
|
+
_config.ga.client_cert_file ? _config.ga.client_cert_file : _config.client_cert_file
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.client_developer_email
|
38
|
+
_config.ga.client_developer_email ? _config.ga.client_developer_email : _config.client_developer_email
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.key_secret
|
42
|
+
_config.ga.key_secret ? _config.ga.key_secret : _config.key_secret
|
43
|
+
end
|
44
|
+
|
45
|
+
# ---------------------------------------------------------------------------------------
|
46
|
+
|
47
|
+
def self.login_by_cert
|
48
|
+
@@client = Google::APIClient.new
|
49
|
+
|
50
|
+
key = Google::APIClient::PKCS12.load_key(client_cert_file, key_secret)
|
51
|
+
asserter = Google::APIClient::JWTAsserter.new(client_developer_email, SCOPE, key)
|
52
|
+
|
53
|
+
begin
|
54
|
+
@@client.authorization = asserter.authorize()
|
55
|
+
@@api = @@client.discovered_api(NAME_API, VERSION_API)
|
56
|
+
rescue
|
57
|
+
return false
|
58
|
+
end
|
59
|
+
|
60
|
+
return true
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.login_by_cert!
|
64
|
+
i = 0
|
65
|
+
while !login_by_cert
|
66
|
+
print "\r[#{Time.now.strftime("%H:%M:%S")}] ##{i += 1} ... \r".bold
|
67
|
+
sleep(1)
|
68
|
+
end
|
69
|
+
|
70
|
+
return true
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.login(code = nil)
|
74
|
+
@@client = Google::APIClient.new
|
75
|
+
@@client.authorization.client_id = client_id
|
76
|
+
@@client.authorization.client_secret = client_secret
|
77
|
+
@@client.authorization.scope = SCOPE
|
78
|
+
@@client.authorization.redirect_uri = redirect_uri
|
79
|
+
|
80
|
+
@@api = @@client.discovered_api(NAME_API, VERSION_API)
|
81
|
+
|
82
|
+
if code
|
83
|
+
@@client.authorization.code = code
|
84
|
+
|
85
|
+
begin
|
86
|
+
@@client.authorization.fetch_access_token!
|
87
|
+
rescue
|
88
|
+
return false
|
89
|
+
end
|
90
|
+
|
91
|
+
return true
|
92
|
+
else
|
93
|
+
@@client.authorization.authorization_uri.to_s
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.login_by_line(server = 'http://localhost/oauth2callback', port = 0)
|
98
|
+
require "launchy" # open browser
|
99
|
+
require "socket" # make tcp server
|
100
|
+
require "uri" # parse uri
|
101
|
+
|
102
|
+
uri = URI(server)
|
103
|
+
|
104
|
+
# Start webserver.
|
105
|
+
webserver = TCPServer.new(uri.host, port)
|
106
|
+
|
107
|
+
# By default port is 0. It means that TCPServer will get first free port.
|
108
|
+
# Port is required for redirect_uri.
|
109
|
+
uri.port = webserver.addr[1]
|
110
|
+
|
111
|
+
# Add redirect_uri for google oauth 2 callback.
|
112
|
+
GoogleApi.config.ga.redirect_uri = uri.to_s
|
113
|
+
|
114
|
+
# Open browser.
|
115
|
+
Launchy.open(login)
|
116
|
+
|
117
|
+
# Wait for new session.
|
118
|
+
session = webserver.accept
|
119
|
+
|
120
|
+
# Parse header for query.
|
121
|
+
request = session.gets.gsub(/GET\ \//, '').gsub(/\ HTTP.*/, '')
|
122
|
+
request = Hash[URI.decode_www_form(URI(request).query)]
|
123
|
+
|
124
|
+
code = request['code']
|
125
|
+
|
126
|
+
# Close session and webserver.
|
127
|
+
session.close
|
128
|
+
|
129
|
+
if login(code)
|
130
|
+
session.write("You have been successfully logged. Now you can close the browser.")
|
131
|
+
|
132
|
+
return true
|
133
|
+
end
|
134
|
+
|
135
|
+
session.write("You have not been logged. Please try again.")
|
136
|
+
|
137
|
+
return false
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.check_session!
|
141
|
+
if @@api.nil? || @@client.nil?
|
142
|
+
raise GoogleApi::SessionError, "You are not log in."
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.api
|
147
|
+
check_session!
|
148
|
+
|
149
|
+
@@api
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.client
|
153
|
+
check_session!
|
154
|
+
|
155
|
+
if @@client.authorization.refresh_token && @@client.authorization.expired?
|
156
|
+
@@client.authorization.fetch_access_token!
|
157
|
+
end
|
158
|
+
|
159
|
+
@@client
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
end
|