ga-shikomi 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.
- checksums.yaml +15 -0
- data/.gitignore +7 -0
- data/Gemfile +4 -0
- data/README.md +33 -0
- data/Rakefile +8 -0
- data/bin/shikomi +5 -0
- data/ga_shikomi.gemspec +30 -0
- data/lib/ga_shikomi.rb +4 -0
- data/lib/ga_shikomi/api.rb +67 -0
- data/lib/ga_shikomi/command.rb +87 -0
- data/lib/ga_shikomi/config.rb +20 -0
- data/lib/ga_shikomi/renderer.rb +167 -0
- data/lib/ga_shikomi/subcommand/accounts.rb +19 -0
- data/lib/ga_shikomi/subcommand/base.rb +11 -0
- data/lib/ga_shikomi/subcommand/filters.rb +9 -0
- data/lib/ga_shikomi/subcommand/ga.rb +43 -0
- data/lib/ga_shikomi/subcommand/goals.rb +13 -0
- data/lib/ga_shikomi/subcommand/metadata.rb +47 -0
- data/lib/ga_shikomi/subcommand/profiles.rb +9 -0
- data/lib/ga_shikomi/subcommand/segments.rb +9 -0
- data/lib/ga_shikomi/subcommand/webproperties.rb +32 -0
- data/lib/ga_shikomi/version.rb +3 -0
- data/spec/renderer_spec.rb +34 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/support/ga_double.rb +45 -0
- data/spec/support/metadata_double.rb +29 -0
- metadata +186 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NThjZDViNTQ0MDRmNjZiMTBjMThjOWUyYWUyODcyMTZiZDg0YzI3Mw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZDhhM2U1MDgxMzIxZmFhZjM5NWRlNGYyYWQ3YTE1MmMwYjQzMjgyOQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YmUwYzJkMjc4NjdlODdjZjUyNTIwZDMwNThkN2U4NDFmOWYyMTQ1YTQyYmVh
|
10
|
+
MTYzMTBkYzQ2OWE3ZTRjYTczNmQ5YTQ3ZWJmOTg5ODhkZWNlZDA1ZjQwZWQ3
|
11
|
+
YmE1ZWUwZDYzYzY2YThmNjk1YmQ0YTVhMzYwYTRmODgzNDM2NDQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZTQwYjJhOWU3N2RiYjExZDE1NWZmNTk4YjkyZDM0M2EwNDgxMzA0YjdjNmMz
|
14
|
+
M2E1ZmRkMmFlZmYwNGEyODNjYTg4ZmZhMmQzZjc5NGM2MWUzZmVkNGQyZDll
|
15
|
+
NDI5ZDNiOWNjOTE4YmEyY2YyYjRhYmZkODBkOTQ0NDJiMGY2OTY=
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# GAShikomi
|
2
|
+
|
3
|
+
Google Analytics API wrapper for CLI written in Ruby.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Now, You can fetch general ga data.
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'ga-shikomi'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install ga-shikomi
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
type
|
24
|
+
|
25
|
+
shikomi help
|
26
|
+
|
27
|
+
## Contributing
|
28
|
+
|
29
|
+
1. Fork it ( https://github.com/[my-github-username]/ga-cli/fork )
|
30
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
31
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
32
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
33
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/shikomi
ADDED
data/ga_shikomi.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- mode: ruby; coding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ga_shikomi/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ga-shikomi"
|
8
|
+
spec.version = GAShikomi::VERSION
|
9
|
+
spec.authors = ["wtnabe"]
|
10
|
+
spec.email = ["wtnabe@gmail.com"]
|
11
|
+
spec.summary = %q{Google Analytics API wrapper for CLI written in Ruby.}
|
12
|
+
spec.description = %q{Now, You can fetch general ga data.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "BSD"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency "google-api-client"
|
22
|
+
spec.add_runtime_dependency "thor"
|
23
|
+
spec.add_runtime_dependency "hirb"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_development_dependency "minitest", "> 5"
|
28
|
+
spec.add_development_dependency "minitest-power_assert"
|
29
|
+
spec.add_development_dependency "minitest-reporters", "> 1"
|
30
|
+
end
|
data/lib/ga_shikomi.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'google/api_client'
|
2
|
+
require 'google/api_client/client_secrets'
|
3
|
+
require 'google/api_client/auth/installed_app'
|
4
|
+
require 'google/api_client/auth/file_storage'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module GAShikomi
|
8
|
+
class Api
|
9
|
+
class InexpectantResponse < StandardError; end
|
10
|
+
|
11
|
+
#
|
12
|
+
# [param] String store
|
13
|
+
#
|
14
|
+
def initialize(store)
|
15
|
+
@client = nil
|
16
|
+
@analytics = nil
|
17
|
+
@last_request = nil
|
18
|
+
|
19
|
+
init_and_auth_analytics(store)
|
20
|
+
end
|
21
|
+
attr_reader :client, :analytics, :last_request
|
22
|
+
|
23
|
+
#
|
24
|
+
# [param] String store
|
25
|
+
#
|
26
|
+
def init_and_auth_analytics(store)
|
27
|
+
@client = ::Google::APIClient.new(
|
28
|
+
:application_name => :gacli,
|
29
|
+
:application_version => VERSION)
|
30
|
+
|
31
|
+
credential = ::Google::APIClient::FileStorage.new(store)
|
32
|
+
secrets = ::Google::APIClient::ClientSecrets.load(File.dirname(store))
|
33
|
+
|
34
|
+
if credential.authorization.nil?
|
35
|
+
flow = ::Google::APIClient::InstalledAppFlow.new(
|
36
|
+
:client_id => secrets.client_id,
|
37
|
+
:client_secret => secrets.client_secret,
|
38
|
+
:scope => ['https://www.googleapis.com/auth/analytics',
|
39
|
+
'https://www.googleapis.com/auth/analytics.edit'])
|
40
|
+
|
41
|
+
client.authorization = flow.authorize
|
42
|
+
credential.write_credentials(client.authorization)
|
43
|
+
else
|
44
|
+
client.authorization = credential.authorization
|
45
|
+
end
|
46
|
+
|
47
|
+
@analytics = client.discovered_api('analytics', 'v3')
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# [param] Object method
|
52
|
+
# [return] Hash
|
53
|
+
#
|
54
|
+
def execute(method, params = {})
|
55
|
+
@last_request = client.execute(
|
56
|
+
:api_method => method,
|
57
|
+
:parameters => params)
|
58
|
+
|
59
|
+
result = JSON.parse(last_request.response.body)
|
60
|
+
if result['error']
|
61
|
+
raise InexpectantResponse, result['error']
|
62
|
+
else
|
63
|
+
result
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'thor'
|
2
|
+
Dir.glob(File.dirname(__FILE__) + '/subcommand/*.rb').each {|f| require f}
|
3
|
+
|
4
|
+
module GAShikomi
|
5
|
+
class Command < Thor
|
6
|
+
class_option :config_file
|
7
|
+
class_option :credential_store
|
8
|
+
class_option :format, :type => :string
|
9
|
+
class_option :with_csv_header, :type => :boolean
|
10
|
+
|
11
|
+
def initialize(*args)
|
12
|
+
super
|
13
|
+
|
14
|
+
if args.last[:current_command].name != 'help'
|
15
|
+
store = (!options.nil? && options['credential-store']) || File.join(Dir.pwd, '.ga-cli-credential')
|
16
|
+
@api = Api.new(store)
|
17
|
+
@config = Config.new(options['config_file']).config if options['config_file']
|
18
|
+
end
|
19
|
+
end
|
20
|
+
attr_reader :api, :config
|
21
|
+
|
22
|
+
desc 'ga', 'fetch and display ga data with profile'
|
23
|
+
option :profile_id, :type => :string, :required => true
|
24
|
+
option :start_date, :type => :string, :required => true
|
25
|
+
option :end_date, :type => :string, :required => true
|
26
|
+
option :metrics, :type => :string, :default => 'ga:pageviews,ga:users'
|
27
|
+
def ga
|
28
|
+
Renderer.new(Subcommand::Ga.new(api, options).get(config), options).render_ga
|
29
|
+
end
|
30
|
+
|
31
|
+
desc 'accounts', 'display accounts'
|
32
|
+
def accounts
|
33
|
+
Renderer.new(Subcommand::Accounts.new(api).list, options).render_accounts
|
34
|
+
end
|
35
|
+
|
36
|
+
desc 'properties', 'display properties'
|
37
|
+
option :account_id, :type => :string, :required => true
|
38
|
+
def properties
|
39
|
+
Renderer.new(Subcommand::Webproperties.new(api, options).list, options).render_properties
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'property', 'display property'
|
43
|
+
option :account_id, :type => :string, :required => true
|
44
|
+
option :property_id, :type => :string, :required => true
|
45
|
+
def property
|
46
|
+
Renderer.new(Subcommand::Webproperties.new(api, options).get, options).render_properties
|
47
|
+
end
|
48
|
+
|
49
|
+
desc 'profiles', 'display profiles (with property)'
|
50
|
+
option :account_id, :type => :string, :required => true
|
51
|
+
option :property_id, :type => :string, :required => true
|
52
|
+
def profiles
|
53
|
+
Renderer.new(Subcommand::Profiles.new(api, options).list, options).render_profiles
|
54
|
+
end
|
55
|
+
|
56
|
+
desc 'filters', 'display filters (with profile)'
|
57
|
+
option :account_id, :type => :string, :required => true
|
58
|
+
def filters
|
59
|
+
Renderer.new(Subcommand::Filters.new(api, options).list, options).render_filters
|
60
|
+
end
|
61
|
+
|
62
|
+
desc 'goals', 'display goals (with profile)'
|
63
|
+
option :account_id, :type => :string, :required => true
|
64
|
+
option :property_id, :type => :string, :required => true
|
65
|
+
option :profile_id, :type => :string, :required => true
|
66
|
+
def goals
|
67
|
+
Renderer.new(Subcommand::Goals.new(api, options).list, options).render_goals
|
68
|
+
end
|
69
|
+
|
70
|
+
desc 'metrices', 'display metrics'
|
71
|
+
option :include_deprecated, :type => :boolean
|
72
|
+
def metrics
|
73
|
+
Renderer.new(Subcommand::Metadata.new(api, options).metrics, options).render_metadata
|
74
|
+
end
|
75
|
+
|
76
|
+
desc 'dimensions', 'display dimensions'
|
77
|
+
option :include_deprecated, :type => :boolean
|
78
|
+
def dimensions
|
79
|
+
Renderer.new(Subcommand::Metadata.new(api, options).dimensions, options).render_metadata
|
80
|
+
end
|
81
|
+
|
82
|
+
desc 'segments', 'display segments'
|
83
|
+
def segments
|
84
|
+
Renderer.new(Subcommand::Segments.new(api).list, options).render_segments
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module GAShikomi
|
2
|
+
class Config
|
3
|
+
class FileNotFound < StandardError; end
|
4
|
+
|
5
|
+
def initialize(file)
|
6
|
+
@config = {}
|
7
|
+
|
8
|
+
load(file)
|
9
|
+
end
|
10
|
+
attr_reader :config
|
11
|
+
|
12
|
+
def load(file)
|
13
|
+
if File.exist? file
|
14
|
+
@config = YAML.load_file(file)
|
15
|
+
else
|
16
|
+
raise FileNotFound, "config_file #{file}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'hirb'
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
module GAShikomi
|
5
|
+
class Renderer
|
6
|
+
#
|
7
|
+
# [param] Array records
|
8
|
+
# [param] Hash oprions
|
9
|
+
#
|
10
|
+
def initialize(records, options)
|
11
|
+
@records = records
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
attr_reader :records, :options
|
15
|
+
|
16
|
+
def raw
|
17
|
+
pp records
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# [param] Array
|
22
|
+
# [param] Proc preprocess
|
23
|
+
#
|
24
|
+
def render(fields, &preprocess)
|
25
|
+
if options[:format] == 'original'
|
26
|
+
pp records
|
27
|
+
else
|
28
|
+
result = records.map {|e| preprocess.call(e)}
|
29
|
+
|
30
|
+
case options[:format]
|
31
|
+
when 'csv'
|
32
|
+
csv(result, :fields => fields)
|
33
|
+
else
|
34
|
+
table(result, :fields => fields)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def render_ga
|
40
|
+
case records.size
|
41
|
+
when 1
|
42
|
+
render(records.first.keys) {|record| record}
|
43
|
+
else
|
44
|
+
fields = [''] + records['totalsForAllResults'].keys
|
45
|
+
|
46
|
+
@records = records['rows'].map {|row|
|
47
|
+
Hash[*fields.zip(row).flatten]
|
48
|
+
} + [records['totalsForAllResults'].merge('' => 'totalsForAllResults')]
|
49
|
+
|
50
|
+
render(fields) {|record| record}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def render_accounts
|
55
|
+
render(%w(id permissions)) {|record|
|
56
|
+
{
|
57
|
+
'id' => record['id'],
|
58
|
+
'permissions' => record['permissions']['effective'].join(',')
|
59
|
+
}
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
def render_properties
|
64
|
+
render(%w(id name websiteUrl permissions)) {|record|
|
65
|
+
{
|
66
|
+
'id' => record['id'],
|
67
|
+
'name' => record['name'],
|
68
|
+
'websiteUrl' => record['websiteUrl'],
|
69
|
+
'permissions' => record['permissions']['effective'].join(',')
|
70
|
+
}
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
def render_profiles
|
75
|
+
render(%w(id name websiteUrl permissions)) {|record|
|
76
|
+
{
|
77
|
+
'id' => record['id'],
|
78
|
+
'name' => record['name'],
|
79
|
+
'websiteUrl' => record['websiteUrl'],
|
80
|
+
'permissions' => record['permissions']['effective'].join(',')
|
81
|
+
}
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
def render_filters
|
86
|
+
render(%w(id name type details)) {|record|
|
87
|
+
pick_id_name_type_and_details(record)
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
def render_goals
|
92
|
+
render(%w(id name type details)) {|record|
|
93
|
+
pick_id_name_type_and_details(record)
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
def render_metadata
|
98
|
+
render(%w(id description)) {|record| pick_id_and_description(record)}
|
99
|
+
end
|
100
|
+
|
101
|
+
def render_segments
|
102
|
+
fields = %w(id segmentId name type)
|
103
|
+
|
104
|
+
render(fields) {|record|
|
105
|
+
Hash[*fields.map {|f| [f, record[f]]}.flatten]
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
# [param] Hash item
|
111
|
+
# [return] Hash
|
112
|
+
#
|
113
|
+
def pick_id_and_description(item)
|
114
|
+
{
|
115
|
+
'id' => item['id'],
|
116
|
+
'description' => item['attributes']['description']
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
#
|
121
|
+
# [param] Hash item
|
122
|
+
# [return] Hash
|
123
|
+
#
|
124
|
+
def pick_id_name_type_and_details(item)
|
125
|
+
{
|
126
|
+
'id' => item['id'],
|
127
|
+
'name' => item['name'],
|
128
|
+
'type' => item['type'],
|
129
|
+
'details' => item["#{small_camelize(item['type'])}Details"]
|
130
|
+
}
|
131
|
+
end
|
132
|
+
|
133
|
+
#
|
134
|
+
# [param] String str
|
135
|
+
# [return] String str
|
136
|
+
#
|
137
|
+
def small_camelize(str)
|
138
|
+
str.split('_').map {|e| e.capitalize}.tap {|a| a.first.downcase!}.join
|
139
|
+
end
|
140
|
+
|
141
|
+
#
|
142
|
+
# [param] Array result
|
143
|
+
# [param] Hash opts
|
144
|
+
#
|
145
|
+
def table(result, opts = {})
|
146
|
+
require 'hirb'
|
147
|
+
puts Hirb::Helpers::AutoTable.render(result, opts)
|
148
|
+
end
|
149
|
+
|
150
|
+
#
|
151
|
+
# [param] Array result
|
152
|
+
# [param] Hash opts
|
153
|
+
#
|
154
|
+
def csv(result, opts = {})
|
155
|
+
require 'csv'
|
156
|
+
|
157
|
+
fields = opts[:fields] || result.first.keys.sort
|
158
|
+
|
159
|
+
puts CSV.generate {|csv|
|
160
|
+
csv << fields if options[:with_csv_header]
|
161
|
+
result.each {|r|
|
162
|
+
csv << fields.map {|f| r[f]}
|
163
|
+
}
|
164
|
+
}
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative './base'
|
2
|
+
|
3
|
+
module GACli
|
4
|
+
module Subcommand
|
5
|
+
class Accounts < Base
|
6
|
+
#
|
7
|
+
# [{
|
8
|
+
# "id": "",
|
9
|
+
# "permission": []
|
10
|
+
# }]
|
11
|
+
#
|
12
|
+
# [return] Array
|
13
|
+
#
|
14
|
+
def list
|
15
|
+
api.execute(api.analytics.management.accounts.list)['items']
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module GACli
|
2
|
+
module Subcommand
|
3
|
+
class Ga < Base
|
4
|
+
#
|
5
|
+
# require
|
6
|
+
# --profile-id
|
7
|
+
# --begin-date
|
8
|
+
# --end-date
|
9
|
+
# --metrics
|
10
|
+
def get(config)
|
11
|
+
opts = {
|
12
|
+
'ids' => options['profile_id'],
|
13
|
+
'start-date' => options['start_date'],
|
14
|
+
'end-date' => options['end_date'],
|
15
|
+
'metrics' => options['metrics']
|
16
|
+
}
|
17
|
+
%w(ids
|
18
|
+
metrics
|
19
|
+
dimensions
|
20
|
+
filters
|
21
|
+
max-results
|
22
|
+
output
|
23
|
+
samplingLevel
|
24
|
+
segment
|
25
|
+
sort
|
26
|
+
start-index
|
27
|
+
fields).each {|e|
|
28
|
+
opts[e] = config[e] if config[e]
|
29
|
+
} if config
|
30
|
+
|
31
|
+
result = api.execute(api.analytics.data.ga.get, opts)
|
32
|
+
|
33
|
+
case result['rows'].size
|
34
|
+
when 1
|
35
|
+
[result['totalsForAllResults']]
|
36
|
+
else
|
37
|
+
fields = %w(columnHeaders totalsForAllResults rows)
|
38
|
+
fields.map {|e| {e => result[e]}}.reduce(:merge)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module GACli
|
2
|
+
module Subcommand
|
3
|
+
class Goals < Base
|
4
|
+
def list
|
5
|
+
api.execute(
|
6
|
+
api.analytics.management.goals.list,
|
7
|
+
:accountId => options['account_id'],
|
8
|
+
:webPropertyId => options['property_id'],
|
9
|
+
:profileId => options['profile_id'])['items']
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require_relative './base'
|
2
|
+
|
3
|
+
module GACli
|
4
|
+
module Subcommand
|
5
|
+
class Metadata < Base
|
6
|
+
#
|
7
|
+
# [return] Hash
|
8
|
+
#
|
9
|
+
def original
|
10
|
+
api.execute(api.analytics.metadata.columns.list, {:reportType => 'ga'})
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# [return] Array
|
15
|
+
#
|
16
|
+
def items
|
17
|
+
original['items']
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# [return] Array
|
22
|
+
#
|
23
|
+
def metrics
|
24
|
+
items.select {|m| m['attributes']['type'] == 'METRIC' && visible?(m)}
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# [return] Array
|
29
|
+
#
|
30
|
+
def dimensions
|
31
|
+
items.select {|m| m['attributes']['type'] == 'DIMENSION' && visible?(m)}
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# [param] Hash item
|
36
|
+
# [return] Boolean
|
37
|
+
#
|
38
|
+
def visible?(item)
|
39
|
+
if options[:include_deprecated]
|
40
|
+
true
|
41
|
+
else
|
42
|
+
item['attributes']['status'] == 'PUBLIC'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module GACli
|
2
|
+
module Subcommand
|
3
|
+
class Webproperties < Base
|
4
|
+
#
|
5
|
+
# [{
|
6
|
+
# "id": "UA-xxxx-x",
|
7
|
+
# "internalWebPropertyId": xxxx,
|
8
|
+
# "permissions": []
|
9
|
+
# "websiteUrl": "",
|
10
|
+
# }]
|
11
|
+
#
|
12
|
+
# [return] Array
|
13
|
+
#
|
14
|
+
def list
|
15
|
+
api.execute(api.analytics.management.webproperties.list, :accountId => options["account_id"])['items']
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# {
|
20
|
+
# "id": "UA-xxxx-xx",
|
21
|
+
# "websiteUrl": "",
|
22
|
+
# "permissions": []
|
23
|
+
# }
|
24
|
+
#
|
25
|
+
# [return] Array
|
26
|
+
#
|
27
|
+
def get
|
28
|
+
[api.execute(api.analytics.management.webproperties.get, :accountId => options['account_id'], :webPropertyId => options['property_id'])]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
module GAShikomi
|
4
|
+
describe Renderer do
|
5
|
+
include MetadataDouble
|
6
|
+
|
7
|
+
describe '#table' do
|
8
|
+
describe '--verbose' do
|
9
|
+
it {
|
10
|
+
Renderer.new(metadata_double, :format => 'table', :verbose => true).render_metadata
|
11
|
+
}
|
12
|
+
end
|
13
|
+
describe 'picked' do
|
14
|
+
it {
|
15
|
+
Renderer.new(metadata_double, :format => 'table').render_metadata
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#csv' do
|
21
|
+
it {
|
22
|
+
Renderer.new(metadata_double, :format => 'csv').render_metadata
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#render_ga' do
|
28
|
+
include GaDouble
|
29
|
+
it {
|
30
|
+
Renderer.new(multi_rows, {}).render_ga
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
require_relative "../lib/ga_shikomi"
|
2
|
+
Dir.glob(File.dirname(__FILE__) + '/support/*.rb').each {|f| require f}
|
3
|
+
|
4
|
+
require "minitest/spec"
|
5
|
+
require "minitest/autorun"
|
6
|
+
require "minitest-power_assert"
|
7
|
+
require "minitest/reporters"
|
8
|
+
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module GAShikomi
|
2
|
+
module GaDouble
|
3
|
+
def multi_rows
|
4
|
+
{
|
5
|
+
"columnHeaders"=>[
|
6
|
+
{
|
7
|
+
"name" => "ga:deviceCategory",
|
8
|
+
"columnType" => "DIMENSION",
|
9
|
+
"dataType" => "STRING"
|
10
|
+
},
|
11
|
+
{
|
12
|
+
"name" => "ga:pageviews",
|
13
|
+
"columnType" => "METRIC",
|
14
|
+
"dataType" => "INTEGER"},
|
15
|
+
{
|
16
|
+
"name" => "ga:sessions",
|
17
|
+
"columnType" => "METRIC",
|
18
|
+
"dataType" => "INTEGER"
|
19
|
+
},
|
20
|
+
{
|
21
|
+
"name" => "ga:pageviewsPerSession",
|
22
|
+
"columnType" => "METRIC",
|
23
|
+
"dataType" => "FLOAT"
|
24
|
+
},
|
25
|
+
{
|
26
|
+
"name" => "ga:goal1Value",
|
27
|
+
"columnType" => "METRIC",
|
28
|
+
"dataType" => "CURRENCY"
|
29
|
+
}
|
30
|
+
],
|
31
|
+
"totalsForAllResults" => {
|
32
|
+
"ga:pageviews" => "4090",
|
33
|
+
"ga:sessions" => "3649",
|
34
|
+
"ga:pageviewsPerSession" => "1.1208550287750068",
|
35
|
+
"ga:goal1Value" => "0.0"
|
36
|
+
},
|
37
|
+
"rows" => [
|
38
|
+
["desktop", "3846", "3442", "1.1173736199883788", "0.0"],
|
39
|
+
["mobile", "172", "141", "1.2198581560283688", "0.0"],
|
40
|
+
["tablet", "72", "66", "1.0909090909090908", "0.0"]
|
41
|
+
]
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module GAShikomi
|
2
|
+
module MetadataDouble
|
3
|
+
def metadata_double
|
4
|
+
[
|
5
|
+
{
|
6
|
+
'id' => 1,
|
7
|
+
'attributes' => {
|
8
|
+
'description' => 'description1',
|
9
|
+
'foobar' => 'foobar1'
|
10
|
+
}
|
11
|
+
},
|
12
|
+
{
|
13
|
+
'id' => 2,
|
14
|
+
'attributes' => {
|
15
|
+
'description' => 'description2',
|
16
|
+
'foobar' => 'foobar2'
|
17
|
+
}
|
18
|
+
},
|
19
|
+
{
|
20
|
+
'id' => 3,
|
21
|
+
'attributes' => {
|
22
|
+
'description' => 'description3',
|
23
|
+
'foobar' => 'foobar3'
|
24
|
+
}
|
25
|
+
}
|
26
|
+
]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ga-shikomi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- wtnabe
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: google-api-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thor
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: hirb
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.7'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.7'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: minitest
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ! '>'
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '5'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ! '>'
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '5'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: minitest-power_assert
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: minitest-reporters
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ! '>'
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ! '>'
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1'
|
125
|
+
description: Now, You can fetch general ga data.
|
126
|
+
email:
|
127
|
+
- wtnabe@gmail.com
|
128
|
+
executables:
|
129
|
+
- shikomi
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- .gitignore
|
134
|
+
- Gemfile
|
135
|
+
- README.md
|
136
|
+
- Rakefile
|
137
|
+
- bin/shikomi
|
138
|
+
- ga_shikomi.gemspec
|
139
|
+
- lib/ga_shikomi.rb
|
140
|
+
- lib/ga_shikomi/api.rb
|
141
|
+
- lib/ga_shikomi/command.rb
|
142
|
+
- lib/ga_shikomi/config.rb
|
143
|
+
- lib/ga_shikomi/renderer.rb
|
144
|
+
- lib/ga_shikomi/subcommand/accounts.rb
|
145
|
+
- lib/ga_shikomi/subcommand/base.rb
|
146
|
+
- lib/ga_shikomi/subcommand/filters.rb
|
147
|
+
- lib/ga_shikomi/subcommand/ga.rb
|
148
|
+
- lib/ga_shikomi/subcommand/goals.rb
|
149
|
+
- lib/ga_shikomi/subcommand/metadata.rb
|
150
|
+
- lib/ga_shikomi/subcommand/profiles.rb
|
151
|
+
- lib/ga_shikomi/subcommand/segments.rb
|
152
|
+
- lib/ga_shikomi/subcommand/webproperties.rb
|
153
|
+
- lib/ga_shikomi/version.rb
|
154
|
+
- spec/renderer_spec.rb
|
155
|
+
- spec/spec_helper.rb
|
156
|
+
- spec/support/ga_double.rb
|
157
|
+
- spec/support/metadata_double.rb
|
158
|
+
homepage: ''
|
159
|
+
licenses:
|
160
|
+
- BSD
|
161
|
+
metadata: {}
|
162
|
+
post_install_message:
|
163
|
+
rdoc_options: []
|
164
|
+
require_paths:
|
165
|
+
- lib
|
166
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
167
|
+
requirements:
|
168
|
+
- - ! '>='
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: '0'
|
171
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - ! '>='
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0'
|
176
|
+
requirements: []
|
177
|
+
rubyforge_project:
|
178
|
+
rubygems_version: 2.4.6
|
179
|
+
signing_key:
|
180
|
+
specification_version: 4
|
181
|
+
summary: Google Analytics API wrapper for CLI written in Ruby.
|
182
|
+
test_files:
|
183
|
+
- spec/renderer_spec.rb
|
184
|
+
- spec/spec_helper.rb
|
185
|
+
- spec/support/ga_double.rb
|
186
|
+
- spec/support/metadata_double.rb
|