google-analytics 0.1.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.
- data/CHANGELOG +1 -0
- data/LICENSE +0 -0
- data/Manifest +17 -0
- data/README.textile +3 -0
- data/Rakefile +12 -0
- data/google-analytics.gemspec +40 -0
- data/lib/google_analytics.rb +9 -0
- data/lib/google_analytics/account.rb +25 -0
- data/lib/google_analytics/client.rb +98 -0
- data/lib/google_analytics/report.rb +93 -0
- data/lib/google_analytics/user.rb +31 -0
- data/test.rb +11 -0
- data/test/google_analytics/account_test.rb +4 -0
- data/test/google_analytics/client_test.rb +58 -0
- data/test/google_analytics/report_test.rb +4 -0
- data/test/google_analytics/user_test.rb +4 -0
- data/test/test_helper.rb +8 -0
- metadata +116 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
v0.1.0 Nothing here yet
|
data/LICENSE
ADDED
File without changes
|
data/Manifest
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
LICENSE
|
3
|
+
Manifest
|
4
|
+
README.textile
|
5
|
+
Rakefile
|
6
|
+
google-analytics.gemspec
|
7
|
+
lib/google_analytics.rb
|
8
|
+
lib/google_analytics/account.rb
|
9
|
+
lib/google_analytics/client.rb
|
10
|
+
lib/google_analytics/report.rb
|
11
|
+
lib/google_analytics/user.rb
|
12
|
+
test.rb
|
13
|
+
test/google_analytics/account_test.rb
|
14
|
+
test/google_analytics/client_test.rb
|
15
|
+
test/google_analytics/report_test.rb
|
16
|
+
test/google_analytics/user_test.rb
|
17
|
+
test/test_helper.rb
|
data/README.textile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'echoe'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
Echoe.new("google-analytics") do |p|
|
5
|
+
p.author = "Dan Webb"
|
6
|
+
p.email = 'dan@danwebb.net'
|
7
|
+
p.summary = "Wrapper around the Google Analytics API"
|
8
|
+
p.runtime_dependencies = ['nokogiri']
|
9
|
+
p.development_dependencies = ['shoulda', 'fakeweb']
|
10
|
+
p.retain_gemspec = true
|
11
|
+
p.rcov_options = "--exclude 'gems/*'"
|
12
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{google-analytics}
|
5
|
+
s.version = "0.1.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Dan Webb"]
|
9
|
+
s.date = %q{2009-10-12}
|
10
|
+
s.description = %q{Wrapper around the Google Analytics API}
|
11
|
+
s.email = %q{dan@danwebb.net}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.textile", "lib/google_analytics.rb", "lib/google_analytics/account.rb", "lib/google_analytics/client.rb", "lib/google_analytics/report.rb", "lib/google_analytics/user.rb"]
|
13
|
+
s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.textile", "Rakefile", "google-analytics.gemspec", "lib/google_analytics.rb", "lib/google_analytics/account.rb", "lib/google_analytics/client.rb", "lib/google_analytics/report.rb", "lib/google_analytics/user.rb", "test.rb", "test/google_analytics/account_test.rb", "test/google_analytics/client_test.rb", "test/google_analytics/report_test.rb", "test/google_analytics/user_test.rb", "test/test_helper.rb"]
|
14
|
+
s.homepage = %q{}
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Google-analytics", "--main", "README.textile"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = %q{google-analytics}
|
18
|
+
s.rubygems_version = %q{1.3.5}
|
19
|
+
s.summary = %q{Wrapper around the Google Analytics API}
|
20
|
+
s.test_files = ["test/google_analytics/account_test.rb", "test/google_analytics/client_test.rb", "test/google_analytics/report_test.rb", "test/google_analytics/user_test.rb", "test/test_helper.rb"]
|
21
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
24
|
+
s.specification_version = 3
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
27
|
+
s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
|
28
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
29
|
+
s.add_development_dependency(%q<fakeweb>, [">= 0"])
|
30
|
+
else
|
31
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
32
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
33
|
+
s.add_dependency(%q<fakeweb>, [">= 0"])
|
34
|
+
end
|
35
|
+
else
|
36
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
37
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
38
|
+
s.add_dependency(%q<fakeweb>, [">= 0"])
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module GoogleAnalytics
|
2
|
+
autoload :Client, 'google_analytics/client'
|
3
|
+
autoload :User, 'google_analytics/user'
|
4
|
+
autoload :Account, 'google_analytics/account'
|
5
|
+
autoload :Profile, 'google_analytics/profile'
|
6
|
+
autoload :Report, 'google_analytics/report'
|
7
|
+
|
8
|
+
DXP_NAMESPACE = 'http://schemas.google.com/analytics/2009'
|
9
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module GoogleAnalytics
|
2
|
+
|
3
|
+
class Account
|
4
|
+
attr_reader :url, :title, :id, :profile_id, :client
|
5
|
+
|
6
|
+
def self.from_node(client, node)
|
7
|
+
new client,
|
8
|
+
node.xpath('.//xmlns:id').first.content,
|
9
|
+
node.xpath('.//dxp:property[@name="ga:accountName"]', 'dxp' => DXP_NAMESPACE).first.attributes['value'].to_s,
|
10
|
+
node.xpath('.//dxp:property[@name="ga:accountId"]', 'dxp' => DXP_NAMESPACE).first.attributes['value'].to_s,
|
11
|
+
node.xpath('.//dxp:property[@name="ga:profileId"]', 'dxp' => DXP_NAMESPACE).first.attributes['value'].to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(client, url, title, id, profile_id)
|
15
|
+
@client, @url, @title = client, url, title
|
16
|
+
@id, @profile_id = id, profile_id
|
17
|
+
end
|
18
|
+
|
19
|
+
def report(options={})
|
20
|
+
Report.new(self, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
require 'uri'
|
4
|
+
require 'nokogiri'
|
5
|
+
|
6
|
+
module GoogleAnalytics
|
7
|
+
|
8
|
+
AUTH_URL = 'https://www.google.com/accounts/ClientLogin'
|
9
|
+
BASE_URL = 'https://www.google.com/analytics'
|
10
|
+
|
11
|
+
class NotAuthorized < StandardError; end
|
12
|
+
class ResponseError < StandardError; end
|
13
|
+
|
14
|
+
class Client
|
15
|
+
|
16
|
+
def initialize(username, password)
|
17
|
+
@username, @password = username, password
|
18
|
+
end
|
19
|
+
|
20
|
+
def login!
|
21
|
+
data = {
|
22
|
+
:accountType => 'GOOGLE_OR_HOSTED',
|
23
|
+
:service => 'analytics',
|
24
|
+
:Email => @username,
|
25
|
+
:Passwd => @password
|
26
|
+
}
|
27
|
+
|
28
|
+
begin
|
29
|
+
resp = request(URI.parse(AUTH_URL), :post, data)
|
30
|
+
|
31
|
+
if resp =~ /^Auth\=(.+)$/
|
32
|
+
@auth = $1
|
33
|
+
else
|
34
|
+
raise NotAuthorized, 'you cannot access this google account'
|
35
|
+
end
|
36
|
+
rescue GoogleAnalytics::ResponseError
|
37
|
+
raise NotAuthorized, 'you cannot access this google account'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def get(path, args=nil)
|
42
|
+
api_request(path, :get, args)
|
43
|
+
end
|
44
|
+
|
45
|
+
def post(path, args=nil)
|
46
|
+
api_request(path, :post, args)
|
47
|
+
end
|
48
|
+
|
49
|
+
def api_request(path, method, args)
|
50
|
+
login! unless @auth
|
51
|
+
url = URI.parse([BASE_URL, path].join)
|
52
|
+
|
53
|
+
resp = request(url, method, args)
|
54
|
+
|
55
|
+
Nokogiri::XML(resp)
|
56
|
+
end
|
57
|
+
|
58
|
+
def request(url, method=:get, data=nil)
|
59
|
+
case method
|
60
|
+
when :get
|
61
|
+
url.query = encode(data) if data
|
62
|
+
req = Net::HTTP::Get.new(url.request_uri)
|
63
|
+
when :post
|
64
|
+
req = Net::HTTP::Post.new(url.request_uri)
|
65
|
+
req.body = encode(data) if data
|
66
|
+
req.content_type = 'application/x-www-form-urlencoded'
|
67
|
+
end
|
68
|
+
|
69
|
+
req['Authorization'] = "GoogleLogin auth=#{@auth}" if @auth
|
70
|
+
|
71
|
+
puts url.to_s
|
72
|
+
|
73
|
+
http = Net::HTTP.new(url.host, url.port)
|
74
|
+
http.use_ssl = (url.port == 443)
|
75
|
+
|
76
|
+
res = http.start() { |conn| conn.request(req) }
|
77
|
+
|
78
|
+
raise ResponseError, "#{res.code} #{res.message}: #{res.body}" unless res.code == '200'
|
79
|
+
|
80
|
+
res.body
|
81
|
+
end
|
82
|
+
|
83
|
+
protected
|
84
|
+
|
85
|
+
def encode(data)
|
86
|
+
data.map do |k,v|
|
87
|
+
value = v.is_a?(Array) ? v.join(',') : v.to_s
|
88
|
+
("%s=%s" % [uri_encode(k), uri_encode(value)]) unless value.empty?
|
89
|
+
end.compact.join("&")
|
90
|
+
end
|
91
|
+
|
92
|
+
def uri_encode(item)
|
93
|
+
encoded = URI.encode(item.to_s)
|
94
|
+
encoded.gsub(/\=/, '%3D')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module GoogleAnalytics
|
2
|
+
class Report
|
3
|
+
|
4
|
+
def initialize(account, options={})
|
5
|
+
@account = account
|
6
|
+
@options = {
|
7
|
+
:ids => "ga:#{account.profile_id}",
|
8
|
+
:metrics => ga_prefix(options.delete(:metrics)),
|
9
|
+
:dimensions => ga_prefix(options.delete(:dimensions)),
|
10
|
+
:'start-date' => date_format(options.delete(:start) || one_month_ago),
|
11
|
+
:'end-date' => date_format(options.delete(:end) || Time.now)
|
12
|
+
}.merge(options)
|
13
|
+
|
14
|
+
if filters = options.delete(:filters)
|
15
|
+
@options[:filters] = ga_prefix(filters)
|
16
|
+
end
|
17
|
+
|
18
|
+
if sort = options.delete(:sort)
|
19
|
+
@options[:sort] = ga_prefix(sort)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def each
|
24
|
+
page = 1
|
25
|
+
items = rows(page)
|
26
|
+
|
27
|
+
while !items.empty?
|
28
|
+
yield items.pop
|
29
|
+
|
30
|
+
items = rows(page+=1) if items.empty?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def rows(page=1, per_page=10000)
|
35
|
+
parse_rows(get(
|
36
|
+
:"start-index" => start_index(page, per_page),
|
37
|
+
:'max-results' => per_page
|
38
|
+
))
|
39
|
+
end
|
40
|
+
|
41
|
+
def get(options={})
|
42
|
+
@account.client.get('/feeds/data', @options.merge(options))
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
def start_index(page, per_page)
|
48
|
+
((page - 1) * per_page) + 1
|
49
|
+
end
|
50
|
+
|
51
|
+
def parse_rows(data)
|
52
|
+
rows = []
|
53
|
+
data.xpath('.//xmlns:entry').each do |node|
|
54
|
+
row = {}
|
55
|
+
|
56
|
+
node.xpath('./dxp:dimension').each do |dim|
|
57
|
+
row[strip_prefix(dim.attributes['name'])] = dim.attributes['value'].to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
node.xpath('./dxp:metric').each do |dim|
|
61
|
+
row[strip_prefix(dim.attributes['name'])] = dim.attributes['value'].to_s
|
62
|
+
end
|
63
|
+
|
64
|
+
rows << row
|
65
|
+
end
|
66
|
+
return rows
|
67
|
+
end
|
68
|
+
|
69
|
+
def strip_prefix(name)
|
70
|
+
name.to_s.gsub(/^ga\:/, '')
|
71
|
+
end
|
72
|
+
|
73
|
+
def ga_prefix(data)
|
74
|
+
if data.is_a?(Array)
|
75
|
+
data.collect { |d| d.gsub(/(-?)(\w+)/, "\\1ga:\\2") }
|
76
|
+
elsif !data.nil?
|
77
|
+
d.gsub(/(-?)(\w+)/, "\\1ga:\\2")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def date_format(date)
|
82
|
+
if date.nil?
|
83
|
+
nil
|
84
|
+
else
|
85
|
+
date.strftime('%Y-%m-%d')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def one_month_ago
|
90
|
+
Time.now - (28 * 24 * 60 * 60)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module GoogleAnalytics
|
2
|
+
|
3
|
+
class User
|
4
|
+
|
5
|
+
def initialize(username, password)
|
6
|
+
@client = Client.new username, password
|
7
|
+
end
|
8
|
+
|
9
|
+
def accounts
|
10
|
+
return @accounts if @accounts
|
11
|
+
xml = @client.get('/feeds/accounts/default')
|
12
|
+
@accounts = xml.xpath('//xmlns:entry').collect do |account_node|
|
13
|
+
Account.from_node(@client, account_node)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def account(id)
|
18
|
+
accounts.find do |account|
|
19
|
+
account if account.id == id
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid?
|
24
|
+
@client.login!
|
25
|
+
true
|
26
|
+
rescue NotAuthorized
|
27
|
+
false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
data/test.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'google_analytics'
|
3
|
+
|
4
|
+
include GoogleAnalytics
|
5
|
+
|
6
|
+
u = User.new 'dan@danwebb.net', 'poortheory'
|
7
|
+
|
8
|
+
r = u.accounts[1].report :dimensions => ['keyword'],
|
9
|
+
:metrics => ['visits', 'bounces', 'newVisits', 'timeOnSite']
|
10
|
+
|
11
|
+
puts r.rows(1).inspect
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../test_helper')
|
2
|
+
|
3
|
+
class ClientTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context 'given an instance of Client' do
|
6
|
+
setup do
|
7
|
+
@client = GoogleAnalytics::Client.new('user', 'password')
|
8
|
+
end
|
9
|
+
|
10
|
+
should 'turn a hash into a url encoded string when encode called' do
|
11
|
+
res = @client.send :encode, { :thing => 12, :thong => 'something with spaces' }
|
12
|
+
assert_match /thing\=12/, res
|
13
|
+
assert_match /thong\=something\%20with\%20spaces/, res
|
14
|
+
end
|
15
|
+
|
16
|
+
should 'should comma seperate arrays when encode called' do
|
17
|
+
res = @client.send :encode, { :thong => [:blurg, :blargh] }
|
18
|
+
assert_match /thong\=blurg,blargh/, res
|
19
|
+
end
|
20
|
+
|
21
|
+
should 'send request to correct url with username and password' do
|
22
|
+
@client.expects(:request).with(
|
23
|
+
URI.parse(GoogleAnalytics::AUTH_URL),
|
24
|
+
:post,
|
25
|
+
{
|
26
|
+
:Email => 'user', :Passwd => 'password',
|
27
|
+
:accountType => 'GOOGLE_OR_HOSTED', :service => 'analytics'
|
28
|
+
}
|
29
|
+
).returns('Auth=thing')
|
30
|
+
|
31
|
+
@client.login!
|
32
|
+
end
|
33
|
+
|
34
|
+
should 'raise not authorized if failed to log in' do
|
35
|
+
@client.expects(:request).with(
|
36
|
+
URI.parse(GoogleAnalytics::AUTH_URL),
|
37
|
+
:post,
|
38
|
+
{
|
39
|
+
:Email => 'user', :Passwd => 'password',
|
40
|
+
:accountType => 'GOOGLE_OR_HOSTED', :service => 'analytics'
|
41
|
+
}
|
42
|
+
).returns('fail')
|
43
|
+
|
44
|
+
assert_raises GoogleAnalytics::NotAuthorized do
|
45
|
+
@client.login!
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
should 'login if auth is not set before api_request' do
|
50
|
+
@client.instance_variable_set(:@auth, nil)
|
51
|
+
@client.expects(:login!)
|
52
|
+
@client.expects(:request).returns('')
|
53
|
+
|
54
|
+
@client.api_request('/', :get, {})
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: google-analytics
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dan Webb
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-12 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: nokogiri
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: shoulda
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: fakeweb
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
description: Wrapper around the Google Analytics API
|
46
|
+
email: dan@danwebb.net
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- CHANGELOG
|
53
|
+
- LICENSE
|
54
|
+
- README.textile
|
55
|
+
- lib/google_analytics.rb
|
56
|
+
- lib/google_analytics/account.rb
|
57
|
+
- lib/google_analytics/client.rb
|
58
|
+
- lib/google_analytics/report.rb
|
59
|
+
- lib/google_analytics/user.rb
|
60
|
+
files:
|
61
|
+
- CHANGELOG
|
62
|
+
- LICENSE
|
63
|
+
- Manifest
|
64
|
+
- README.textile
|
65
|
+
- Rakefile
|
66
|
+
- google-analytics.gemspec
|
67
|
+
- lib/google_analytics.rb
|
68
|
+
- lib/google_analytics/account.rb
|
69
|
+
- lib/google_analytics/client.rb
|
70
|
+
- lib/google_analytics/report.rb
|
71
|
+
- lib/google_analytics/user.rb
|
72
|
+
- test.rb
|
73
|
+
- test/google_analytics/account_test.rb
|
74
|
+
- test/google_analytics/client_test.rb
|
75
|
+
- test/google_analytics/report_test.rb
|
76
|
+
- test/google_analytics/user_test.rb
|
77
|
+
- test/test_helper.rb
|
78
|
+
has_rdoc: true
|
79
|
+
homepage: ""
|
80
|
+
licenses: []
|
81
|
+
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options:
|
84
|
+
- --line-numbers
|
85
|
+
- --inline-source
|
86
|
+
- --title
|
87
|
+
- Google-analytics
|
88
|
+
- --main
|
89
|
+
- README.textile
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: "0"
|
97
|
+
version:
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: "1.2"
|
103
|
+
version:
|
104
|
+
requirements: []
|
105
|
+
|
106
|
+
rubyforge_project: google-analytics
|
107
|
+
rubygems_version: 1.3.5
|
108
|
+
signing_key:
|
109
|
+
specification_version: 3
|
110
|
+
summary: Wrapper around the Google Analytics API
|
111
|
+
test_files:
|
112
|
+
- test/google_analytics/account_test.rb
|
113
|
+
- test/google_analytics/client_test.rb
|
114
|
+
- test/google_analytics/report_test.rb
|
115
|
+
- test/google_analytics/user_test.rb
|
116
|
+
- test/test_helper.rb
|