analytics-rb 0.0.10
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/.coveralls.yml +3 -0
- data/.gitignore +23 -0
- data/Gemfile +6 -0
- data/LICENSE +20 -0
- data/README.md +71 -0
- data/Rakefile +11 -0
- data/analytics-rb.gemspec +26 -0
- data/fixtures/vcr_cassettes/assets_up-fluence.yml +99 -0
- data/fixtures/vcr_cassettes/assets_up-fluence/management/accounts.yml +52 -0
- data/lib/analytics-rb.rb +1 -0
- data/lib/analytics.rb +37 -0
- data/lib/analytics/account.rb +28 -0
- data/lib/analytics/client.rb +35 -0
- data/lib/analytics/configurable.rb +22 -0
- data/lib/analytics/core_ext/string.rb +5 -0
- data/lib/analytics/error.rb +12 -0
- data/lib/analytics/error/no_access_token_provided.rb +6 -0
- data/lib/analytics/error/permission_insufficient.rb +7 -0
- data/lib/analytics/oauth.rb +27 -0
- data/lib/analytics/oauth2.rb +27 -0
- data/lib/analytics/profile.rb +23 -0
- data/lib/analytics/renderer/hashed.rb +25 -0
- data/lib/analytics/renderer/plain.rb +9 -0
- data/lib/analytics/report.rb +59 -0
- data/lib/analytics/request.rb +19 -0
- data/lib/analytics/version.rb +3 -0
- data/lib/analytics/web_property.rb +26 -0
- data/spec/analytics/account_spec.rb +17 -0
- data/spec/analytics/client_spec.rb +25 -0
- data/spec/analytics/core_ext/string_spec.rb +13 -0
- data/spec/analytics/profile_spec.rb +19 -0
- data/spec/analytics/renderer/hashed_spec.rb +19 -0
- data/spec/analytics/report_spec.rb +21 -0
- data/spec/analytics/request_spec.rb +33 -0
- data/spec/analytics/web_propery_spec.rb +18 -0
- data/spec/analytics_spec.rb +44 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/support/management_profiles.rb +1 -0
- data/spec/support/management_web_properties.rb +1 -0
- data/spec/support/manangement_accounts.rb +2 -0
- data/spec/support/permission_error.rb +1 -0
- metadata +228 -0
data/.coveralls.yml
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
<<<<<<< HEAD
|
6
|
+
.yardoc
|
7
|
+
Gemfile.lock
|
8
|
+
InstalledFiles
|
9
|
+
_yardoc
|
10
|
+
coverage
|
11
|
+
doc/
|
12
|
+
lib/bundler/man
|
13
|
+
pkg
|
14
|
+
rdoc
|
15
|
+
spec/reports
|
16
|
+
test/tmp
|
17
|
+
test/version_tmp
|
18
|
+
tmp
|
19
|
+
|
20
|
+
# YARD artifacts
|
21
|
+
.yardoc
|
22
|
+
_yardoc
|
23
|
+
doc/
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Alexis Montagne
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# Analytics
|
2
|
+
|
3
|
+
[](https://travis-ci.org/AlexisMontagne/analytics)
|
4
|
+
[](https://codeclimate.com/repos/528d2778c7f3a335fa013259/feed)
|
5
|
+
[](http://githalytics.com/AlexisMontagne/analytics)
|
6
|
+
|
7
|
+
A Ruby interface to the Google Analytics API.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'analytics-rb'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install analytics-rb
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
### Authentification
|
26
|
+
|
27
|
+
To make calls to the Google Analytics API, you have to authenticate via an API key (which you can get from the Google [APIs Console](https://code.google.com/apis/console#access). To set your API key and get started, use:
|
28
|
+
|
29
|
+
Analytics.consumer_key = 'your key'
|
30
|
+
Analytics.consumer_secret = 'your secret'
|
31
|
+
|
32
|
+
Then you have to provide an access token ( OAuth or OAuth2 ) to manage or visualize statistics.
|
33
|
+
|
34
|
+
client = Analytics::Client.new(Analytics::OAuth.access_token('my token', 'my secret')) # With OAuth 1.x
|
35
|
+
client = Analytics::Client.new(Analytics::OAuth.access_token('my token')) # With OAuth 2.x
|
36
|
+
|
37
|
+
### Management
|
38
|
+
|
39
|
+
** You can access to the accounts, web properties and profile from a `Analytics::Client`
|
40
|
+
|
41
|
+
client.accounts # returns an array of Analytics::Account
|
42
|
+
client.web_properties # returns an array of Analytics::WebProperty
|
43
|
+
client.profiles # returns an array of Analytics::Profile
|
44
|
+
|
45
|
+
### Reporting
|
46
|
+
|
47
|
+
From a `Analyics::Profile` you can access to the report object
|
48
|
+
|
49
|
+
profile.report
|
50
|
+
# or
|
51
|
+
Analyics::Report.new('profile_id', access_token) # access_token is a OAuth::AccessToken or OAuth2::AccessToken
|
52
|
+
|
53
|
+
You can grab datas with a simple DSL
|
54
|
+
|
55
|
+
report.visits(0, Time.now) # it should grab all visits from Jan 1st 1970 to now
|
56
|
+
# you can provide all metrics from google analytics ( visitors, new_visits, percent_new_visits, ... )
|
57
|
+
|
58
|
+
# you can provide a metric and a dimension
|
59
|
+
report.visits_by_month(0, Time.now)
|
60
|
+
|
61
|
+
# you can provide multiple metrics and dimensions as well
|
62
|
+
report.visists_and_visitors_by_month_and_city(0, Time.now)
|
63
|
+
|
64
|
+
|
65
|
+
## Contributing
|
66
|
+
|
67
|
+
1. Fork it
|
68
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
69
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
70
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
71
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/analytics/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Alexis Montagne"]
|
6
|
+
gem.email = ["alexis.montagne@gmail.com"]
|
7
|
+
gem.description = %q{A Ruby interface to the Google Analytics API}
|
8
|
+
gem.summary = %q{Basic implementation of an ruby interface to the Analytics API}
|
9
|
+
gem.homepage = "http://www.github.com/AlexisMontagne/analytics"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "analytics-rb"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Analytics::VERSION
|
17
|
+
|
18
|
+
gem.add_runtime_dependency("multi_json")
|
19
|
+
gem.add_runtime_dependency("oauth2")
|
20
|
+
gem.add_runtime_dependency("oauth")
|
21
|
+
gem.add_development_dependency("rspec")
|
22
|
+
gem.add_development_dependency("rake")
|
23
|
+
gem.add_development_dependency("mocha")
|
24
|
+
gem.add_development_dependency("vcr")
|
25
|
+
gem.add_development_dependency("fakeweb")
|
26
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://assets.up-fluence.com/test.json
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Faraday v0.8.8
|
12
|
+
Authorization:
|
13
|
+
- Bearer 123
|
14
|
+
Accept-Encoding:
|
15
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
16
|
+
Accept:
|
17
|
+
- ! '*/*'
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 301
|
21
|
+
message: Moved Permanently
|
22
|
+
headers:
|
23
|
+
Server:
|
24
|
+
- nginx/1.4.1
|
25
|
+
Date:
|
26
|
+
- Tue, 03 Dec 2013 02:42:02 GMT
|
27
|
+
Transfer-Encoding:
|
28
|
+
- chunked
|
29
|
+
Connection:
|
30
|
+
- keep-alive
|
31
|
+
Cache-Control:
|
32
|
+
- no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0
|
33
|
+
Location:
|
34
|
+
- http://images.up-fluence.com/test.json
|
35
|
+
body:
|
36
|
+
encoding: US-ASCII
|
37
|
+
string: ! '<html><head><title>301 Moved Permanently</title><script type=''text/javascript''> var
|
38
|
+
_gaq = _gaq || []; _gaq.push([''_setAccount'', ''UA-41488471-3'']); _gaq.push([''_trackPageview'']); (function()
|
39
|
+
{ var ga = document.createElement(''script''); ga.type
|
40
|
+
= ''text/javascript''; ga.async = true; ga.src = (''https:''
|
41
|
+
== document.location.protocol ? ''https://ssl'' : ''http://www'') + ''.google-analytics.com/ga.js''; var
|
42
|
+
s = document.getElementsByTagName(''script'')[0]; s.parentNode.insertBefore(ga,
|
43
|
+
s); })(); </script> </head>
|
44
|
+
|
45
|
+
<body bgcolor="white">
|
46
|
+
|
47
|
+
<center><h1>301 Moved Permanently</h1></center>
|
48
|
+
|
49
|
+
<hr><center>nginx</center>
|
50
|
+
|
51
|
+
</body>
|
52
|
+
|
53
|
+
</html>'
|
54
|
+
http_version:
|
55
|
+
recorded_at: Tue, 03 Dec 2013 02:42:02 GMT
|
56
|
+
- request:
|
57
|
+
method: get
|
58
|
+
uri: http://images.up-fluence.com/test.json
|
59
|
+
body:
|
60
|
+
encoding: US-ASCII
|
61
|
+
string: ''
|
62
|
+
headers:
|
63
|
+
User-Agent:
|
64
|
+
- Faraday v0.8.8
|
65
|
+
Authorization:
|
66
|
+
- Bearer 123
|
67
|
+
Accept-Encoding:
|
68
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
69
|
+
Accept:
|
70
|
+
- ! '*/*'
|
71
|
+
response:
|
72
|
+
status:
|
73
|
+
code: 200
|
74
|
+
message: OK
|
75
|
+
headers:
|
76
|
+
Server:
|
77
|
+
- nginx/1.4.1
|
78
|
+
Date:
|
79
|
+
- Tue, 03 Dec 2013 02:42:03 GMT
|
80
|
+
Content-Type:
|
81
|
+
- application/json
|
82
|
+
Content-Length:
|
83
|
+
- '17'
|
84
|
+
Last-Modified:
|
85
|
+
- Sun, 28 Jul 2013 12:06:12 GMT
|
86
|
+
Connection:
|
87
|
+
- keep-alive
|
88
|
+
Etag:
|
89
|
+
- ! '"51f50934-11"'
|
90
|
+
Accept-Ranges:
|
91
|
+
- bytes
|
92
|
+
body:
|
93
|
+
encoding: US-ASCII
|
94
|
+
string: ! '{"foo" => "bar"}
|
95
|
+
|
96
|
+
'
|
97
|
+
http_version:
|
98
|
+
recorded_at: Tue, 03 Dec 2013 02:42:02 GMT
|
99
|
+
recorded_with: VCR 2.4.0
|
@@ -0,0 +1,52 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://www.googleapis.com/analytics/v3/management/accounts
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Faraday v0.8.8
|
12
|
+
Authorization:
|
13
|
+
- Bearer 123
|
14
|
+
Accept-Encoding:
|
15
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
16
|
+
Accept:
|
17
|
+
- ! '*/*'
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 401
|
21
|
+
message: Unauthorized
|
22
|
+
headers:
|
23
|
+
Www-Authenticate:
|
24
|
+
- Bearer realm="https://www.google.com/accounts/AuthSubRequest", error=invalid_token
|
25
|
+
Content-Type:
|
26
|
+
- application/json; charset=UTF-8
|
27
|
+
Date:
|
28
|
+
- Tue, 03 Dec 2013 02:42:03 GMT
|
29
|
+
Expires:
|
30
|
+
- Tue, 03 Dec 2013 02:42:03 GMT
|
31
|
+
Cache-Control:
|
32
|
+
- private, max-age=0
|
33
|
+
X-Content-Type-Options:
|
34
|
+
- nosniff
|
35
|
+
X-Frame-Options:
|
36
|
+
- SAMEORIGIN
|
37
|
+
X-Xss-Protection:
|
38
|
+
- 1; mode=block
|
39
|
+
Server:
|
40
|
+
- GSE
|
41
|
+
Alternate-Protocol:
|
42
|
+
- 443:quic
|
43
|
+
Transfer-Encoding:
|
44
|
+
- chunked
|
45
|
+
body:
|
46
|
+
encoding: US-ASCII
|
47
|
+
string: ! '{"error":{"errors":[{"domain":"global","reason":"authError","message":"Invalid
|
48
|
+
Credentials","locationType":"header","location":"Authorization"}],"code":401,"message":"Invalid
|
49
|
+
Credentials"}}'
|
50
|
+
http_version:
|
51
|
+
recorded_at: Tue, 03 Dec 2013 02:42:03 GMT
|
52
|
+
recorded_with: VCR 2.4.0
|
data/lib/analytics-rb.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'analytics'
|
data/lib/analytics.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require "analytics/version"
|
2
|
+
require "analytics/configurable"
|
3
|
+
require "analytics/oauth2"
|
4
|
+
require "analytics/oauth"
|
5
|
+
require "analytics/client"
|
6
|
+
require "analytics/account"
|
7
|
+
require "analytics/web_property"
|
8
|
+
require "analytics/profile"
|
9
|
+
require "analytics/report"
|
10
|
+
require "analytics/request"
|
11
|
+
require "analytics/error"
|
12
|
+
require "analytics/error/permission_insufficient"
|
13
|
+
require "analytics/error/no_access_token_provided"
|
14
|
+
require "analytics/core_ext/string"
|
15
|
+
require "analytics/renderer/plain"
|
16
|
+
require "analytics/renderer/hashed"
|
17
|
+
|
18
|
+
module Analytics
|
19
|
+
BASE_URL = 'https://www.googleapis.com/analytics/v3'
|
20
|
+
|
21
|
+
class << self
|
22
|
+
include Analytics::Configurable
|
23
|
+
|
24
|
+
def client
|
25
|
+
@client ||= Analytics::Client.new(options.fetch(:default_access_token))
|
26
|
+
end
|
27
|
+
|
28
|
+
def from_token(oauth_token)
|
29
|
+
@client = Analytics::Client.new(oauth_token)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def method_missing(name, *args, &block)
|
34
|
+
client.respond_to?(name) ? client.send(name, args, block) : super
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Analytics
|
2
|
+
class Account
|
3
|
+
attr_reader :name, :id
|
4
|
+
|
5
|
+
def initialize(opts, access_token)
|
6
|
+
@name = opts.fetch("name")
|
7
|
+
@id = opts.fetch("id")
|
8
|
+
@access_token = access_token
|
9
|
+
end
|
10
|
+
|
11
|
+
def web_properties
|
12
|
+
@web_properties ||= request_web_properties
|
13
|
+
end
|
14
|
+
|
15
|
+
def flush!
|
16
|
+
@web_properties = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def request_web_properties
|
21
|
+
Analytics::Request.new(Analytics::BASE_URL, "management/accounts/#{@id}/webproperties", @access_token).response["items"].map do |item|
|
22
|
+
Analytics::WebProperty.new(item, @access_token) rescue nil
|
23
|
+
end.compact
|
24
|
+
rescue
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Analytics
|
2
|
+
class Client
|
3
|
+
attr_reader :access_token
|
4
|
+
|
5
|
+
def initialize(access_token)
|
6
|
+
@access_token = access_token
|
7
|
+
raise Analytics::Error::NoAccessTokenProvided if @access_token.nil?
|
8
|
+
end
|
9
|
+
|
10
|
+
def accounts
|
11
|
+
@accounts ||= request_accounts
|
12
|
+
end
|
13
|
+
|
14
|
+
def web_properties
|
15
|
+
accounts.map(&:web_properties).flatten
|
16
|
+
end
|
17
|
+
|
18
|
+
def profiles
|
19
|
+
web_properties.map(&:profiles).flatten
|
20
|
+
end
|
21
|
+
|
22
|
+
def flush!
|
23
|
+
@accounts = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def request_accounts
|
28
|
+
Analytics::Request.new(Analytics::BASE_URL, 'management/accounts', @access_token).response["items"].map do |item|
|
29
|
+
Analytics::Account.new(item, @access_token) rescue nil
|
30
|
+
end.compact
|
31
|
+
rescue
|
32
|
+
[]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Analytics
|
4
|
+
module Configurable
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
attr_accessor :consumer_key, :consumer_secret, :default_access_token
|
8
|
+
|
9
|
+
def configure
|
10
|
+
yield self
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def options
|
15
|
+
{
|
16
|
+
:consumer_key => consumer_key,
|
17
|
+
:consumer_secret => consumer_secret,
|
18
|
+
:default_access_token => default_access_token
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Analytics
|
2
|
+
class Error < StandardError
|
3
|
+
def initialize(exception=$!, response_headers={})
|
4
|
+
@wrapped_exception = exception
|
5
|
+
exception.respond_to?(:backtrace) ? super(exception.message) : super(exception.to_s)
|
6
|
+
end
|
7
|
+
|
8
|
+
def backtrace
|
9
|
+
@wrapped_exception.respond_to?(:backtrace) ? @wrapped_exception.backtrace : super
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "oauth"
|
3
|
+
|
4
|
+
module Analytics
|
5
|
+
class OAuth
|
6
|
+
class << self
|
7
|
+
def oauth_consumer
|
8
|
+
@consumer ||= ::OAuth::Consumer.new(
|
9
|
+
Analytics.consumer_key,
|
10
|
+
Analytics.consumer_secret, {
|
11
|
+
:site => 'https://www.google.com',
|
12
|
+
:request_token_path => '/accounts/OAuthGetRequestToken',
|
13
|
+
:access_token_path => '/accounts/OAuthGetAccessToken',
|
14
|
+
:authorize_path => '/accounts/OAuthAuthorizeToken'
|
15
|
+
})
|
16
|
+
end
|
17
|
+
|
18
|
+
def access_token(token, secret = nil, opts = {})
|
19
|
+
if token.is_a? ::OAuth::AccessToken
|
20
|
+
token
|
21
|
+
else
|
22
|
+
::OAuth::AccessToken.new(oauth_consumer, token, secret)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'oauth2'
|
3
|
+
module Analytics
|
4
|
+
class OAuth2
|
5
|
+
class << self
|
6
|
+
def oauth_client
|
7
|
+
@oauth_client ||= ::OAuth2::Client.new(
|
8
|
+
Analytics.consumer_key,
|
9
|
+
Analytics.consumer_secret,
|
10
|
+
:site => 'https://accounts.google.com',
|
11
|
+
:authorize_url => '/o/oauth2/auth',
|
12
|
+
:token_url => '/o/oauth2/token'
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def access_token(token, opts = {})
|
17
|
+
if token.nil?
|
18
|
+
raise Analytics::Error::NoAccessTokenProvided
|
19
|
+
elsif token.is_a? ::OAuth2::AccessToken
|
20
|
+
token
|
21
|
+
else
|
22
|
+
::OAuth2::AccessToken.new(oauth_client, token, opts)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Analytics
|
2
|
+
class Profile
|
3
|
+
attr_reader :web_property_id, :name, :id, :url, :account_id
|
4
|
+
|
5
|
+
def initialize(opts, access_token)
|
6
|
+
@access_token = access_token
|
7
|
+
@name = opts.fetch("name")
|
8
|
+
@id = opts.fetch("id")
|
9
|
+
@url = opts.fetch("websiteUrl")
|
10
|
+
@web_property_id = opts.fetch("webPropertyId")
|
11
|
+
@account_id = opts.fetch("accountId")
|
12
|
+
end
|
13
|
+
|
14
|
+
def report
|
15
|
+
@report ||= Analytics::Report.new(@id, @access_token)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def method_missing(method_name, *args, &block)
|
20
|
+
report.send(method_name, args, block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Analytics
|
2
|
+
module Renderer
|
3
|
+
class Hashed
|
4
|
+
def self.render(data, metrics, dimensions)
|
5
|
+
if (dimensions + metrics).length > 1
|
6
|
+
data.map do |res|
|
7
|
+
apply!(data, metrics, dimensions)
|
8
|
+
end
|
9
|
+
else
|
10
|
+
data.first
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.apply!(data, metrics, dimensions)
|
15
|
+
elt, itr = {}, 0
|
16
|
+
(dimensions + metrics).each do |d|
|
17
|
+
elt[d] = data[itr]
|
18
|
+
itr += 1
|
19
|
+
end
|
20
|
+
elt
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Analytics
|
2
|
+
class Report
|
3
|
+
METRICS = [
|
4
|
+
:visitors, :new_visits, :percent_new_visits,
|
5
|
+
:visits, :bounces, :pageviews
|
6
|
+
]
|
7
|
+
|
8
|
+
DIMENSIONS = [
|
9
|
+
:continent, :city, :country, :date, :year,
|
10
|
+
:month, :week, :day, :hour
|
11
|
+
]
|
12
|
+
|
13
|
+
|
14
|
+
attr_reader :id, :access_token
|
15
|
+
|
16
|
+
def initialize(id, access_token, renderer = Analytics::Renderer::Plain)
|
17
|
+
@id = id
|
18
|
+
@access_token = access_token
|
19
|
+
@renderer = renderer
|
20
|
+
end
|
21
|
+
|
22
|
+
def get(start_date, end_date, metrics, dimensions = [])
|
23
|
+
response = Analytics::Request.new(Analytics::BASE_URL, get_url(start_date, end_date, metrics, dimensions), @access_token).response
|
24
|
+
return nil unless response["rows"]
|
25
|
+
response["rows"].map do |row|
|
26
|
+
@renderer.render(row, metrics, dimensions)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def get_url(start_date, end_date, metrics, dimensions)
|
32
|
+
str = "data/ga?ids=ga:#{@id}&start-date=#{start_date.strftime("%F")}&end-date=#{end_date.strftime("%F")}&metrics=#{to_ga(metrics)}"
|
33
|
+
str += "&dimensions=#{to_ga(dimensions)}" unless dimensions.empty?
|
34
|
+
str
|
35
|
+
end
|
36
|
+
|
37
|
+
def split_by(method, det = 'and')
|
38
|
+
method.to_s.split("_#{det}_").map(&:to_sym)
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_ga(array)
|
42
|
+
array.map { |x| 'ga:' + x.to_s.to_camelcase(:lower) }.join(",")
|
43
|
+
end
|
44
|
+
|
45
|
+
def method_missing(m, *args, &block)
|
46
|
+
args.flatten!
|
47
|
+
if METRICS.include? m.to_sym
|
48
|
+
get(args[0],args[1], [m.to_sym])
|
49
|
+
elsif m.to_s.split('_by_').length.eql? 2
|
50
|
+
lhs, rhs = split_by(m, 'by')
|
51
|
+
get(args[0],args[1], split_by(lhs), split_by(rhs))
|
52
|
+
elsif split_by(m).length.eql? 2
|
53
|
+
get(args[0],args[1], split_by(m), [])
|
54
|
+
else
|
55
|
+
super
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "multi_json"
|
2
|
+
|
3
|
+
module Analytics
|
4
|
+
class Request < Struct.new(:base_url, :relative_path, :access_token)
|
5
|
+
def full_path
|
6
|
+
"#{base_url.to_s}/#{relative_path.to_s}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def request
|
10
|
+
access_token.get(full_path).body
|
11
|
+
rescue ::OAuth2::Error
|
12
|
+
raise Analytics::Error::PermissionInsufficient
|
13
|
+
end
|
14
|
+
|
15
|
+
def response
|
16
|
+
@response ||= MultiJson.load(request)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Analytics
|
2
|
+
class WebProperty
|
3
|
+
attr_reader :id, :name, :account_id, :url
|
4
|
+
|
5
|
+
def initialize(opts, access_token)
|
6
|
+
@access_token = access_token
|
7
|
+
@id = opts.fetch("id")
|
8
|
+
@name = opts.fetch("name", "Not found")
|
9
|
+
@account_id = opts.fetch("accountId")
|
10
|
+
@url = opts.fetch("websiteUrl", "Not found")
|
11
|
+
end
|
12
|
+
|
13
|
+
def profiles
|
14
|
+
@profiles ||= request_profiles
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def request_profiles
|
19
|
+
Analytics::Request.new(Analytics::BASE_URL, "management/accounts/#{@account_id}/webproperties/#{@id}/profiles", @access_token).response["items"].map do |item|
|
20
|
+
Analytics::Profile.new(item, @access_token) rescue nil
|
21
|
+
end.compact
|
22
|
+
rescue
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Analytics::Account do
|
4
|
+
context ".web_properties" do
|
5
|
+
it "should return a list of web properties" do
|
6
|
+
client = Analytics::Account.new({
|
7
|
+
"id" => 'foo',
|
8
|
+
"name" => 'bar',
|
9
|
+
"username" => 'baz'},
|
10
|
+
nil)
|
11
|
+
Analytics::Request.any_instance.stubs(:request).returns(MANAGEMENT_WEB_PROPERTIES)
|
12
|
+
client.web_properties.count.should == 2
|
13
|
+
client.web_properties.first.class.should == Analytics::WebProperty
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Analytics::Client do
|
4
|
+
context "#initialize" do
|
5
|
+
it "raise error without token provided" do
|
6
|
+
expect { Analytics::Client.new(nil) }.to raise_error
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
context ".flush!" do
|
11
|
+
it "should set nil to datas" do
|
12
|
+
client = Analytics::Client.new('data')
|
13
|
+
client.stubs(:request_accounts).returns([1, 2])
|
14
|
+
ex = client.accounts
|
15
|
+
client.flush!
|
16
|
+
client.accounts.should == ex
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context ".accounts" do
|
21
|
+
client = Analytics::Client.new('data')
|
22
|
+
Analytics::Request.any_instance.stubs(:request).returns(MANAGEMENT_ACCOUNTS)
|
23
|
+
client.accounts.count.should == 1
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe String do
|
4
|
+
context ".camelize" do
|
5
|
+
it "should transform _l to L" do
|
6
|
+
"foo_bar".to_camelcase.should == "FooBar"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should do the same on lower case" do
|
10
|
+
"foo_bar".to_camelcase(:lower).should == "fooBar"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Analytics::Profile do
|
4
|
+
context ".report" do
|
5
|
+
it "should forward methods to the report linked" do
|
6
|
+
client = Analytics::Profile.new({
|
7
|
+
"id" => 'foo',
|
8
|
+
"name" => 'bar',
|
9
|
+
"accountId" => 'baz',
|
10
|
+
"websiteUrl" => 'http://www.gmail.com',
|
11
|
+
"webPropertyId" => 'b'},
|
12
|
+
'1')
|
13
|
+
client.report.stubs(:foo).returns(:bar)
|
14
|
+
client.foo.should == :bar
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Analytics::Renderer::Hashed do
|
4
|
+
context ".apply!" do
|
5
|
+
it "should push data in the correct column" do
|
6
|
+
res = Analytics::Renderer::Hashed.apply!([1, 2, 3, 4], [:m1, :m2], [:m3, :m4])
|
7
|
+
res[:m1].should == 3
|
8
|
+
res[:m2].should == 4
|
9
|
+
res[:m3].should == 1
|
10
|
+
res[:m4].should == 2
|
11
|
+
end
|
12
|
+
end
|
13
|
+
context ".render" do
|
14
|
+
it "should return the data with it has only a metrics registred" do
|
15
|
+
res = Analytics::Renderer::Hashed.render([1],[:m1],[])
|
16
|
+
res.should == 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Analytics::Report do
|
4
|
+
context '.get' do
|
5
|
+
before :each do
|
6
|
+
@report = Analytics::Report.new('1', '2')
|
7
|
+
@report.stubs(:get).returns(:bar)
|
8
|
+
end
|
9
|
+
it "should forwarsd to get with a metrics name" do
|
10
|
+
r = @report.visits(Date.today - 5, Date.today).should == :bar
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should forwards with multiples metrics" do
|
14
|
+
r = @report.visits_and_visitors(Date.today - 5, Date.today).should == :bar
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should forwards to get with metrics and dimensions" do
|
18
|
+
r = @report.visits_by_country(Date.today - 5, Date.today).should == :bar
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Analytics::Request do
|
4
|
+
let(:incorrect_token) { ::OAuth2::AccessToken.new(::OAuth2::Client.new('1','1'),'123') }
|
5
|
+
let(:sample_request) { Analytics::Request.new('http://assets.up-fluence.com', 'test.json', incorrect_token) }
|
6
|
+
|
7
|
+
context ".full_path" do
|
8
|
+
it "should render the normal fullpath" do
|
9
|
+
sample_request.full_path.should == 'http://assets.up-fluence.com/test.json'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context ".request" do
|
14
|
+
it "should return a string with datas" do
|
15
|
+
VCR.use_cassette('assets.up-fluence') do
|
16
|
+
sample_request.request.should include('{"foo" => "bar"}')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should throw an error if the oauth token is wrong" do
|
21
|
+
VCR.use_cassette('assets.up-fluence/management/accounts') do
|
22
|
+
expect { Analytics::Request.new(Analytics::BASE_URL, 'management/accounts', incorrect_token).request }.to raise_error(Analytics::Error::PermissionInsufficient)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context ".response" do
|
28
|
+
it "should parse JSON" do
|
29
|
+
sample_request.stubs(:request).returns(MANAGEMENT_ACCOUNTS)
|
30
|
+
sample_request.response.fetch("kind").should == "analytics#accounts"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Analytics::WebProperty do
|
4
|
+
context ".profiles" do
|
5
|
+
it "should return a list of profile" do
|
6
|
+
client = Analytics::WebProperty.new({
|
7
|
+
"id" => 'foo',
|
8
|
+
"name" => 'bar',
|
9
|
+
"accountId" => 'baz',
|
10
|
+
"websiteUrl" => 'http://www.gmail.com'},
|
11
|
+
nil)
|
12
|
+
Analytics::Request.any_instance.stubs(:request).returns(MANAGEMENT_PROFILES)
|
13
|
+
client.profiles.count.should == 1
|
14
|
+
client.profiles.first.class.should == Analytics::Profile
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Analytics do
|
4
|
+
before(:each) do
|
5
|
+
Analytics.configure do |an|
|
6
|
+
an.consumer_key = 'foo'
|
7
|
+
an.consumer_secret = 'bar'
|
8
|
+
an.default_access_token = OAuth2::AccessToken.new('','')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context "#Configurable" do
|
13
|
+
context ".configure" do
|
14
|
+
it "should persist credentials" do
|
15
|
+
Analytics.consumer_secret.should == 'bar'
|
16
|
+
Analytics.consumer_key.should == 'foo'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context ".options" do
|
21
|
+
it "should return a hash composed by both keys" do
|
22
|
+
Analytics.options.class.should == Hash
|
23
|
+
Analytics.options.fetch(:consumer_key).should == 'foo'
|
24
|
+
Analytics.options.fetch(:consumer_secret).should == 'bar'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context ".client" do
|
30
|
+
it "should be a Analytics::Client" do
|
31
|
+
Analytics.client.class.should == Analytics::Client
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should stay the same" do
|
35
|
+
Analytics.client.should == Analytics.client
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "forward methods to the client" do
|
40
|
+
Analytics.client.stubs(:foo).returns(:bar)
|
41
|
+
|
42
|
+
Analytics.client.foo.should == :bar
|
43
|
+
end
|
44
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'analytics-rb'
|
2
|
+
require 'coveralls'
|
3
|
+
Coveralls.wear!
|
4
|
+
|
5
|
+
require 'vcr'
|
6
|
+
|
7
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
8
|
+
|
9
|
+
VCR.configure do |c|
|
10
|
+
c.cassette_library_dir = 'fixtures/vcr_cassettes'
|
11
|
+
c.hook_into :fakeweb
|
12
|
+
end
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.mock_with :mocha
|
16
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
MANAGEMENT_PROFILES = '{"kind":"analytics#profiles","username":"alexis.montagne@gmail.com","totalResults":1,"startIndex":1,"itemsPerPage":1000,"items":[{"id":"PRO_ID","kind":"analytics#profile","selfLink":"https://www.googleapis.com/analytics/v3/management/accounts/ACC_ID/webproperties/WEB_ID/profiles/PRO_ID","accountId":"ACC_ID","webPropertyId":"WEB_ID","internalWebPropertyId":"PRO_ID","name":"PRO_NAE","currency":"USD","timezone":"Europe/Paris","websiteUrl":"https://www.foo.baz","type":"WEB","created":"2013-06-05T11:19:31.774Z","updated":"2013-07-09T15:35:30.823Z","eCommerceTracking":false,"parentLink":{"type":"analytics#webproperty","href":"https://www.googleapis.com/analytics/v3/management/accounts/ACC_ID/webproperties/WEB_ID"},"childLink":{"type":"analytics#goals","href":"https://www.googleapis.com/analytics/v3/management/accounts/ACC_ID/webproperties/WEB_ID/profiles/PRO_ID/goals"}}]}'
|
@@ -0,0 +1 @@
|
|
1
|
+
MANAGEMENT_WEB_PROPERTIES = '{"kind":"analytics#webproperties","username":"USERNAME","totalResults":3,"startIndex":1,"itemsPerPage":1000,"items":[{"id":"WEB_ID","kind":"analytics#webproperty","selfLink":"https://www.googleapis.com/analytics/v3/management/accounts/ACC_ID/webproperties/WEB_ID","accountId":"ACC_ID","internalWebPropertyId":"WEB_ID","name":"name","websiteUrl":"url","level":"STANDARD","profileCount":1,"industryVertical":"ONLINE_COMMUNITIES","created":"2013-06-05T11:19:31.774Z","updated":"2013-06-05T21:43:13.463Z","parentLink":{"type":"analytics#account","href":"https://www.googleapis.com/analytics/v3/management/accounts/ID"},"childLink":{"type":"analytics#profiles","href":"https://www.googleapis.com/analytics/v3/management/accounts/ACC_ID/webproperties/WEB_ID/profiles"}},{"id":"WEB_ID","kind":"analytics#webproperty","selfLink":"https://www.googleapis.com/analytics/v3/management/accounts/ACC_ID/webproperties/WEB_ID","accountId":"ACC_ID","internalWebPropertyId":"WEB_ID","name":"NAME","websiteUrl":"URL","level":"STANDARD","profileCount":1,"industryVertical":"ONLINE_COMMUNITIES","created":"2013-06-05T11:23:45.793Z","updated":"2013-06-06T08:10:55.753Z","parentLink":{"type":"analytics#account","href":"https://www.googleapis.com/analytics/v3/management/accounts/ACC_ID"},"childLink":{"type":"analytics#profiles","href":"https://www.googleapis.com/analytics/v3/management/accounts/ACC_ID/webproperties/WEB_ID/profiles"}}]}'
|
@@ -0,0 +1,2 @@
|
|
1
|
+
MANAGEMENT_ACCOUNTS = '{"kind":"analytics#accounts","username":"email_address","totalResults":1,"startIndex":1,"itemsPerPage":1000,"items":[{"id":"account_id","kind":"analytics#account","selfLink":"https://www.googleapis.com/analytics/v3/management/accounts/account_id","name":"Account name","created":"2013-06-05T11:19:31.774Z","updated":"2013-07-09T15:35:30.823Z","childLink":{"type":"analytics#webproperties","href":"https://www.googleapis.com/analytics/v3/management/accounts/xxxx/webproperties"}}]}'
|
2
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
PERMISSION_ERROR = '{"error":{"errors":[{"domain":"global","reason":"insufficientPermissions","message":"Insufficient Permission"}],"code":403,"message":"Insufficient Permission"}}'
|
metadata
ADDED
@@ -0,0 +1,228 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: analytics-rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.10
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alexis Montagne
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-12-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: multi_json
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: oauth2
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: oauth
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rake
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: mocha
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: vcr
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: fakeweb
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
description: A Ruby interface to the Google Analytics API
|
143
|
+
email:
|
144
|
+
- alexis.montagne@gmail.com
|
145
|
+
executables: []
|
146
|
+
extensions: []
|
147
|
+
extra_rdoc_files: []
|
148
|
+
files:
|
149
|
+
- .coveralls.yml
|
150
|
+
- .gitignore
|
151
|
+
- Gemfile
|
152
|
+
- LICENSE
|
153
|
+
- README.md
|
154
|
+
- Rakefile
|
155
|
+
- analytics-rb.gemspec
|
156
|
+
- fixtures/vcr_cassettes/assets_up-fluence.yml
|
157
|
+
- fixtures/vcr_cassettes/assets_up-fluence/management/accounts.yml
|
158
|
+
- lib/analytics-rb.rb
|
159
|
+
- lib/analytics.rb
|
160
|
+
- lib/analytics/account.rb
|
161
|
+
- lib/analytics/client.rb
|
162
|
+
- lib/analytics/configurable.rb
|
163
|
+
- lib/analytics/core_ext/string.rb
|
164
|
+
- lib/analytics/error.rb
|
165
|
+
- lib/analytics/error/no_access_token_provided.rb
|
166
|
+
- lib/analytics/error/permission_insufficient.rb
|
167
|
+
- lib/analytics/oauth.rb
|
168
|
+
- lib/analytics/oauth2.rb
|
169
|
+
- lib/analytics/profile.rb
|
170
|
+
- lib/analytics/renderer/hashed.rb
|
171
|
+
- lib/analytics/renderer/plain.rb
|
172
|
+
- lib/analytics/report.rb
|
173
|
+
- lib/analytics/request.rb
|
174
|
+
- lib/analytics/version.rb
|
175
|
+
- lib/analytics/web_property.rb
|
176
|
+
- spec/analytics/account_spec.rb
|
177
|
+
- spec/analytics/client_spec.rb
|
178
|
+
- spec/analytics/core_ext/string_spec.rb
|
179
|
+
- spec/analytics/profile_spec.rb
|
180
|
+
- spec/analytics/renderer/hashed_spec.rb
|
181
|
+
- spec/analytics/report_spec.rb
|
182
|
+
- spec/analytics/request_spec.rb
|
183
|
+
- spec/analytics/web_propery_spec.rb
|
184
|
+
- spec/analytics_spec.rb
|
185
|
+
- spec/spec_helper.rb
|
186
|
+
- spec/support/management_profiles.rb
|
187
|
+
- spec/support/management_web_properties.rb
|
188
|
+
- spec/support/manangement_accounts.rb
|
189
|
+
- spec/support/permission_error.rb
|
190
|
+
homepage: http://www.github.com/AlexisMontagne/analytics
|
191
|
+
licenses: []
|
192
|
+
post_install_message:
|
193
|
+
rdoc_options: []
|
194
|
+
require_paths:
|
195
|
+
- lib
|
196
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
197
|
+
none: false
|
198
|
+
requirements:
|
199
|
+
- - ! '>='
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
203
|
+
none: false
|
204
|
+
requirements:
|
205
|
+
- - ! '>='
|
206
|
+
- !ruby/object:Gem::Version
|
207
|
+
version: '0'
|
208
|
+
requirements: []
|
209
|
+
rubyforge_project:
|
210
|
+
rubygems_version: 1.8.23
|
211
|
+
signing_key:
|
212
|
+
specification_version: 3
|
213
|
+
summary: Basic implementation of an ruby interface to the Analytics API
|
214
|
+
test_files:
|
215
|
+
- spec/analytics/account_spec.rb
|
216
|
+
- spec/analytics/client_spec.rb
|
217
|
+
- spec/analytics/core_ext/string_spec.rb
|
218
|
+
- spec/analytics/profile_spec.rb
|
219
|
+
- spec/analytics/renderer/hashed_spec.rb
|
220
|
+
- spec/analytics/report_spec.rb
|
221
|
+
- spec/analytics/request_spec.rb
|
222
|
+
- spec/analytics/web_propery_spec.rb
|
223
|
+
- spec/analytics_spec.rb
|
224
|
+
- spec/spec_helper.rb
|
225
|
+
- spec/support/management_profiles.rb
|
226
|
+
- spec/support/management_web_properties.rb
|
227
|
+
- spec/support/manangement_accounts.rb
|
228
|
+
- spec/support/permission_error.rb
|