readmedia-garb 0.9.1.1

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.
Files changed (64) hide show
  1. data/README.md +198 -0
  2. data/Rakefile +57 -0
  3. data/lib/garb/account.rb +22 -0
  4. data/lib/garb/account_feed_request.rb +25 -0
  5. data/lib/garb/authentication_request.rb +53 -0
  6. data/lib/garb/data_request.rb +42 -0
  7. data/lib/garb/destination.rb +18 -0
  8. data/lib/garb/filter_parameters.rb +42 -0
  9. data/lib/garb/goal.rb +20 -0
  10. data/lib/garb/management/account.rb +39 -0
  11. data/lib/garb/management/feed.rb +26 -0
  12. data/lib/garb/management/goal.rb +44 -0
  13. data/lib/garb/management/profile.rb +44 -0
  14. data/lib/garb/management/segment.rb +27 -0
  15. data/lib/garb/management/web_property.rb +38 -0
  16. data/lib/garb/model.rb +91 -0
  17. data/lib/garb/profile.rb +33 -0
  18. data/lib/garb/profile_reports.rb +16 -0
  19. data/lib/garb/report.rb +28 -0
  20. data/lib/garb/report_parameter.rb +25 -0
  21. data/lib/garb/report_response.rb +56 -0
  22. data/lib/garb/reports/bounces.rb +5 -0
  23. data/lib/garb/reports/exits.rb +5 -0
  24. data/lib/garb/reports/pageviews.rb +5 -0
  25. data/lib/garb/reports/unique_pageviews.rb +5 -0
  26. data/lib/garb/reports/visits.rb +5 -0
  27. data/lib/garb/reports.rb +5 -0
  28. data/lib/garb/resource.rb +115 -0
  29. data/lib/garb/result_set.rb +21 -0
  30. data/lib/garb/session.rb +25 -0
  31. data/lib/garb/step.rb +13 -0
  32. data/lib/garb/version.rb +14 -0
  33. data/lib/garb.rb +69 -0
  34. data/lib/support.rb +40 -0
  35. data/test/fixtures/cacert.pem +67 -0
  36. data/test/fixtures/profile_feed.xml +72 -0
  37. data/test/fixtures/report_feed.xml +48 -0
  38. data/test/test_helper.rb +45 -0
  39. data/test/unit/garb/account_feed_request_test.rb +42 -0
  40. data/test/unit/garb/account_test.rb +53 -0
  41. data/test/unit/garb/authentication_request_test.rb +121 -0
  42. data/test/unit/garb/data_request_test.rb +107 -0
  43. data/test/unit/garb/destination_test.rb +28 -0
  44. data/test/unit/garb/filter_parameters_test.rb +68 -0
  45. data/test/unit/garb/goal_test.rb +24 -0
  46. data/test/unit/garb/management/account_test.rb +70 -0
  47. data/test/unit/garb/management/feed_test.rb +44 -0
  48. data/test/unit/garb/management/goal_test.rb +81 -0
  49. data/test/unit/garb/management/profile_test.rb +81 -0
  50. data/test/unit/garb/management/segment_test.rb +47 -0
  51. data/test/unit/garb/management/web_property_test.rb +64 -0
  52. data/test/unit/garb/model_test.rb +141 -0
  53. data/test/unit/garb/oauth_session_test.rb +11 -0
  54. data/test/unit/garb/profile_reports_test.rb +29 -0
  55. data/test/unit/garb/profile_test.rb +77 -0
  56. data/test/unit/garb/report_parameter_test.rb +43 -0
  57. data/test/unit/garb/report_response_test.rb +47 -0
  58. data/test/unit/garb/report_test.rb +99 -0
  59. data/test/unit/garb/resource_test.rb +50 -0
  60. data/test/unit/garb/session_test.rb +84 -0
  61. data/test/unit/garb/step_test.rb +15 -0
  62. data/test/unit/garb_test.rb +26 -0
  63. data/test/unit/symbol_operator_test.rb +37 -0
  64. metadata +189 -0
data/README.md ADDED
@@ -0,0 +1,198 @@
1
+ Garb
2
+ ====
3
+
4
+ Originally forked from: http://github.com/vigetlabs/garb
5
+
6
+ Important Changes
7
+ =================
8
+
9
+ Philip Brocoum (readMedia): Google deprecated their API version 2.3 on
10
+ Thursday, August 23, 2012. Version 2.4 of the API is mostly
11
+ backward-compatible except there are new URL endpoints, which have been
12
+ updated in this release of 0.9.1.1.
13
+
14
+ With The release of version 0.9.0 I have officially deprecated Garb::Report, Garb::Resource,
15
+ Garb::Profile, and Garb::Account. Garb::Report and Garb::Resource should be replaced by Garb::Model.
16
+ Garb::Profile and Garb::Account are supplanted by their Garb::Management::* counterparts.
17
+
18
+ I'll be working hard to update the documentation over the next day or so to highlight all of the
19
+ old features in the new classes, as well as any new features brought by the new classes. If you
20
+ are looking for something in particular, please open an issue and I will try to prioritize these
21
+ requests.
22
+
23
+ Please read CHANGELOG
24
+
25
+ Description
26
+ -----------
27
+
28
+ Provides a Ruby API to the Google Analytics API.
29
+
30
+ http://code.google.com/apis/analytics/docs/gdata/gdataDeveloperGuide.html
31
+
32
+ Basic Usage
33
+ ===========
34
+
35
+ Single User Login
36
+ -----------------
37
+
38
+ > Garb::Session.login(username, password)
39
+
40
+ OAuth Access Token
41
+ ------------------
42
+
43
+ > Garb::Session.access_token = access_token # assign from oauth gem
44
+
45
+ Accounts, WebProperties, Profiles, and Goals
46
+ --------
47
+
48
+ > Garb::Management::Account.all
49
+ > Garb::Management::WebProperty.all
50
+ > Garb::Management::Profile.all
51
+ > Garb::Management::Goal.all
52
+
53
+ Profiles for a UA- Number (a WebProperty)
54
+ --------
55
+
56
+ > profile = Garb::Management::Profile.all.detect {|p| p.web_property_id == 'UA-XXXXXXX-X'}
57
+
58
+ Define a Report Class
59
+ ---------------------
60
+
61
+ class Exits
62
+ extend Garb::Model
63
+
64
+ metrics :exits, :pageviews
65
+ dimensions :page_path
66
+ end
67
+
68
+ Get the Results
69
+ ---------------
70
+
71
+ > Exits.results(profile, :filters => {:page_path.eql => '/'})
72
+
73
+ OR shorthand
74
+
75
+ > profile.exits(:filters => {:page_path.eql => '/'})
76
+
77
+ Be forewarned, these numbers are for the last **30** days and may be slightly different from the numbers displayed in Google Analytics' dashboard for **1 month**.
78
+
79
+ Other Parameters
80
+ ----------------
81
+
82
+ * start_date: The date of the period you would like this report to start
83
+ * end_date: The date to end, inclusive
84
+ * limit: The maximum number of results to be returned
85
+ * offset: The starting index
86
+
87
+ Metrics & Dimensions
88
+ --------------------
89
+
90
+ **Metrics and Dimensions are very complex because of the ways in which they can and cannot be combined.**
91
+
92
+ I suggest reading the google documentation to familiarize yourself with this.
93
+
94
+ http://code.google.com/apis/analytics/docs/gdata/gdataReferenceDimensionsMetrics.html#bounceRate
95
+
96
+ When you've returned, you can pass the appropriate combinations to Garb, as symbols.
97
+
98
+ Filtering
99
+ ---------
100
+
101
+ Google Analytics supports a significant number of filtering options.
102
+
103
+ http://code.google.com/apis/analytics/docs/gdata/gdataReference.html#filtering
104
+
105
+ Here is what we can do currently:
106
+ (the operator is a method on a symbol for the appropriate metric or dimension)
107
+
108
+ Operators on metrics:
109
+
110
+ eql => '==',
111
+ not_eql => '!=',
112
+ gt => '>',
113
+ gte => '>=',
114
+ lt => '<',
115
+ lte => '<='
116
+
117
+ Operators on dimensions:
118
+
119
+ matches => '==',
120
+ does_not_match => '!=',
121
+ contains => '=~',
122
+ does_not_contain => '!~',
123
+ substring => '=@',
124
+ not_substring => '!@'
125
+
126
+ Given the previous Exits example report in shorthand, we can add an option for filter:
127
+
128
+ profile.exits(:filters => {:page_path.eql => '/extend/effectively-using-git-with-subversion/')
129
+
130
+ SSL
131
+ ---
132
+
133
+ Version 0.2.3 includes support for real ssl encryption for SINGLE USER authentication. First do:
134
+
135
+ Garb::Session.login(username, password, :secure => true)
136
+
137
+ Next, be sure to download http://curl.haxx.se/ca/cacert.pem into your application somewhere.
138
+ Then, define a constant CA_CERT_FILE and point to that file.
139
+
140
+ For whatever reason, simply creating a new certificate store and setting the defaults would
141
+ not validate the google ssl certificate as authentic.
142
+
143
+ TODOS
144
+ -----
145
+
146
+ * rebuild AND/OR filtering in Garb::Model
147
+
148
+ Requirements
149
+ ------------
150
+
151
+ * crack >= 0.1.6
152
+ * active_support >= 2.2.0
153
+
154
+ Requirements for Testing
155
+ ------------------------
156
+
157
+ * shoulda
158
+ * jferris-mocha
159
+
160
+ Install
161
+ -------
162
+
163
+ gem install garb
164
+
165
+ Contributors
166
+ ------------
167
+
168
+ Many Thanks, for all their help, goes to:
169
+
170
+ * Patrick Reagan
171
+ * Justin Marney
172
+ * Nick Plante
173
+
174
+ License
175
+ -------
176
+
177
+ (The MIT License)
178
+
179
+ Copyright (c) 2010 Viget Labs
180
+
181
+ Permission is hereby granted, free of charge, to any person obtaining
182
+ a copy of this software and associated documentation files (the
183
+ 'Software'), to deal in the Software without restriction, including
184
+ without limitation the rights to use, copy, modify, merge, publish,
185
+ distribute, sublicense, and/or sell copies of the Software, and to
186
+ permit persons to whom the Software is furnished to do so, subject to
187
+ the following conditions:
188
+
189
+ The above copyright notice and this permission notice shall be
190
+ included in all copies or substantial portions of the Software.
191
+
192
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
193
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
194
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
195
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
196
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
197
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
198
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,57 @@
1
+ require 'rake/gempackagetask'
2
+ require 'rake/testtask'
3
+
4
+ $:.unshift File.expand_path('../lib', __FILE__)
5
+ require 'garb'
6
+
7
+ task :default => :test
8
+
9
+ spec = Gem::Specification.new do |s|
10
+ s.name = 'readmedia-garb'
11
+ s.version = Garb::Version.to_s
12
+ s.has_rdoc = false
13
+ s.rubyforge_project = 'readmedia'
14
+ s.summary = "Google Analytics API (v2.4) Ruby Wrapper"
15
+ s.authors = ['Tony Pitale, Philip Brocoum (readMedia)']
16
+ s.email = 'Developer@readMedia.com'
17
+ s.homepage = 'http://github.com/readmedia/garb'
18
+ s.files = %w(README.md Rakefile) + Dir.glob("lib/**/*")
19
+ s.test_files = Dir.glob("test/**/*")
20
+
21
+ s.add_dependency("crack", [">= 0.1.6"])
22
+ s.add_dependency("activesupport", [">= 2.2.0"])
23
+ end
24
+
25
+ Rake::GemPackageTask.new(spec) do |pkg|
26
+ pkg.gem_spec = spec
27
+ end
28
+
29
+ Rake::TestTask.new do |t|
30
+ t.libs << 'test'
31
+ t.test_files = FileList["test/**/*_test.rb"]
32
+ t.verbose = true
33
+ end
34
+
35
+ desc 'Generate the gemspec to serve this Gem from Github'
36
+ task :github do
37
+ file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
38
+ File.open(file, 'w') {|f| f << spec.to_ruby }
39
+ puts "Created gemspec: #{file}"
40
+ end
41
+
42
+ begin
43
+ require 'rcov/rcovtask'
44
+
45
+ desc "Generate RCov coverage report"
46
+ Rcov::RcovTask.new(:rcov) do |t|
47
+ t.libs << "test"
48
+ t.test_files = FileList['test/**/*_test.rb']
49
+ t.rcov_opts << "-x \"test/*,gems/*,/Library/Ruby/*,config/*\" -x lib/garb.rb -x lib/garb/version.rb --rails"
50
+ end
51
+ rescue LoadError
52
+ nil
53
+ end
54
+
55
+ task :default => 'test'
56
+
57
+ # EOF
@@ -0,0 +1,22 @@
1
+ module Garb
2
+ class Account
3
+ attr_reader :id, :name, :profiles
4
+
5
+ def initialize(profiles)
6
+ @id = profiles.first.account_id
7
+ @name = profiles.first.account_name
8
+ @profiles = profiles
9
+ end
10
+
11
+ def self.all(session = Session)
12
+ ActiveSupport::Deprecation.warn("The use of Garb::Account has been deprecated in favor of 'Garb::Management::Account'")
13
+ profiles = {}
14
+
15
+ Profile.all(session).each do |profile|
16
+ (profiles[profile.account_id] ||= []) << profile
17
+ end
18
+
19
+ profiles.map {|k,v| v}.map {|profiles| new(profiles)}
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ module Garb
2
+ class AccountFeedRequest
3
+ URL = "https://www.google.com/analytics/feeds/accounts/default"
4
+
5
+ def initialize(session = Session)
6
+ @request = DataRequest.new(session, URL)
7
+ end
8
+
9
+ def response
10
+ @response ||= @request.send_request
11
+ end
12
+
13
+ def parsed_response
14
+ @parsed_response ||= Crack::XML.parse(response.body)
15
+ end
16
+
17
+ def entries
18
+ parsed_response ? Array(parsed_response['feed']['entry']).flatten.compact : []
19
+ end
20
+
21
+ def segments
22
+ parsed_response ? Array(parsed_response['feed']['dxp:segment']).flatten.compact : []
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,53 @@
1
+ module Garb
2
+ class AuthenticationRequest
3
+ class AuthError < StandardError;end
4
+
5
+ URL = 'https://www.google.com/accounts/ClientLogin'
6
+
7
+ def initialize(email, password, opts={})
8
+ @email = email
9
+ @password = password
10
+ @account_type = opts.fetch(:account_type, 'HOSTED_OR_GOOGLE')
11
+ end
12
+
13
+ def parameters
14
+ {
15
+ 'Email' => @email,
16
+ 'Passwd' => @password,
17
+ 'accountType' => @account_type,
18
+ 'service' => 'analytics',
19
+ 'source' => 'vigetLabs-garb-001'
20
+ }
21
+ end
22
+
23
+ def uri
24
+ URI.parse(URL)
25
+ end
26
+
27
+ def send_request(ssl_mode)
28
+ http = Net::HTTP.new(uri.host, uri.port)
29
+ http.use_ssl = true
30
+ http.verify_mode = ssl_mode
31
+
32
+ if ssl_mode == OpenSSL::SSL::VERIFY_PEER
33
+ http.ca_file = CA_CERT_FILE
34
+ end
35
+
36
+ http.request(build_request) do |response|
37
+ raise AuthError unless response.is_a?(Net::HTTPOK)
38
+ end
39
+ end
40
+
41
+ def build_request
42
+ post = Net::HTTP::Post.new(uri.path)
43
+ post.set_form_data(parameters)
44
+ post
45
+ end
46
+
47
+ def auth_token(opts={})
48
+ ssl_mode = opts[:secure] ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
49
+ send_request(ssl_mode).body.match(/^Auth=(.*)$/)[1]
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,42 @@
1
+ module Garb
2
+ class DataRequest
3
+ class ClientError < StandardError; end
4
+
5
+ def initialize(session, base_url, parameters={})
6
+ @session = session
7
+ @base_url = base_url
8
+ @parameters = parameters
9
+ end
10
+
11
+ def query_string
12
+ parameter_list = @parameters.map {|k,v| "#{k}=#{v}" }
13
+ parameter_list.empty? ? '' : "?#{parameter_list.join('&')}"
14
+ end
15
+
16
+ def uri
17
+ URI.parse(@base_url)
18
+ end
19
+
20
+ def send_request
21
+ response = if @session.single_user?
22
+ single_user_request
23
+ elsif @session.oauth_user?
24
+ oauth_user_request
25
+ end
26
+
27
+ raise ClientError, response.body.inspect unless response.kind_of?(Net::HTTPSuccess)
28
+ response
29
+ end
30
+
31
+ def single_user_request
32
+ http = Net::HTTP.new(uri.host, uri.port)
33
+ http.use_ssl = true
34
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
35
+ http.get("#{uri.path}#{query_string}", {'Authorization' => "GoogleLogin auth=#{@session.auth_token}", 'GData-Version' => '2'})
36
+ end
37
+
38
+ def oauth_user_request
39
+ @session.access_token.get("#{uri}#{query_string}", {'GData-Version' => '2'})
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,18 @@
1
+ module Garb
2
+ class Destination
3
+ attr_reader :match_type, :expression, :steps, :case_sensitive
4
+
5
+ alias :case_sensitive? :case_sensitive
6
+
7
+ def initialize(attributes)
8
+ return unless attributes.is_a?(Hash)
9
+
10
+ @match_type = attributes['matchType']
11
+ @expression = attributes['expression']
12
+ @case_sensitive = (attributes['caseSensitive'] == 'true')
13
+
14
+ step_attributes = attributes[Garb.to_ga('step')]
15
+ @steps = Array(step_attributes.is_a?(Hash) ? [step_attributes] : step_attributes).map {|s| Step.new(s)}
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,42 @@
1
+ module Garb
2
+ class FilterParameters
3
+ def self.define_operators(*methods)
4
+ methods.each do |method|
5
+ class_eval <<-CODE
6
+ def #{method}(field, value)
7
+ @filter_hash.merge!({SymbolOperator.new(field, :#{method}) => value})
8
+ end
9
+ CODE
10
+ end
11
+ end
12
+
13
+ define_operators :eql, :not_eql, :gt, :gte, :lt, :lte, :matches,
14
+ :does_not_match, :contains, :does_not_contain, :substring, :not_substring
15
+
16
+ attr_accessor :parameters
17
+
18
+ def initialize
19
+ self.parameters = []
20
+ end
21
+
22
+ def filters(&block)
23
+ @filter_hash = {}
24
+
25
+ instance_eval &block
26
+
27
+ self.parameters << @filter_hash
28
+ end
29
+
30
+ def to_params
31
+ value = self.parameters.map do |param|
32
+ param.map do |k,v|
33
+ next unless k.is_a?(SymbolOperator)
34
+ escaped_v = v.to_s.gsub(/([,;\\])/) {|c| '\\'+c}
35
+ "#{URI.encode(k.to_google_analytics, /[=<>]/)}#{CGI::escape(escaped_v)}"
36
+ end.join('%3B') # Hash AND (no duplicate keys), escape char for ';' fixes oauth
37
+ end.join(',') # Array OR
38
+
39
+ value.empty? ? {} : {'filters' => value}
40
+ end
41
+ end
42
+ end
data/lib/garb/goal.rb ADDED
@@ -0,0 +1,20 @@
1
+ module Garb
2
+ class Goal
3
+ attr_reader :name, :number, :value, :destination
4
+
5
+ def initialize(attributes={})
6
+ return unless attributes.is_a?(Hash)
7
+
8
+ @name = attributes['name']
9
+ @number = attributes['number'].to_i
10
+ @value = attributes['value'].to_f
11
+ @active = (attributes['active'] == 'true')
12
+
13
+ @destination = Destination.new(attributes[Garb.to_ga('destination')])
14
+ end
15
+
16
+ def active?
17
+ @active
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,39 @@
1
+ module Garb
2
+ module Management
3
+ class Account
4
+ attr_accessor :session, :path
5
+ attr_accessor :id, :title, :name
6
+
7
+ def self.all(session = Session)
8
+ feed = Feed.new(session, '/accounts')
9
+ feed.entries.map {|entry| new_from_entry(entry, session)}
10
+ end
11
+
12
+ def self.new_from_entry(entry, session)
13
+ account = new
14
+ account.session = session
15
+ account.path = Garb.parse_link(entry, "self").gsub(Feed::BASE_URL, '')
16
+ account.title = entry['title'].gsub('Google Analytics Account ', '') # can we get this in properties=?
17
+ account.properties = Garb.parse_properties(entry)
18
+ account
19
+ end
20
+
21
+ def properties=(properties)
22
+ self.id = properties["account_id"]
23
+ self.name = properties["account_name"]
24
+ end
25
+
26
+ def web_properties
27
+ @web_properties ||= WebProperty.for_account(self)
28
+ end
29
+
30
+ def profiles
31
+ @profiles ||= Profile.for_account(self)
32
+ end
33
+
34
+ def goals
35
+ @goals ||= Goal.for_account(self)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,26 @@
1
+ module Garb
2
+ module Management
3
+ class Feed
4
+ BASE_URL = "https://www.google.com/analytics/feeds/datasources/ga"
5
+
6
+ attr_reader :request
7
+
8
+ def initialize(session, path)
9
+ @request = DataRequest.new(session, BASE_URL+path)
10
+ end
11
+
12
+ def parsed_response
13
+ @parsed_response ||= Crack::XML.parse(response.body)
14
+ end
15
+
16
+ def entries
17
+ # possible to have nil entries, yuck
18
+ parsed_response ? [parsed_response['feed']['entry']].flatten.compact : []
19
+ end
20
+
21
+ def response
22
+ @response ||= request.send_request
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,44 @@
1
+ module Garb
2
+ module Management
3
+ class Goal
4
+
5
+ attr_accessor :session, :path
6
+ attr_accessor :name, :number, :value, :destination, :active
7
+
8
+ alias :active? :active
9
+
10
+ def self.all(session = Session, path = '/accounts/~all/webproperties/~all/profiles/~all/goals')
11
+ feed = Feed.new(session, path)
12
+ feed.entries.map {|entry| new_from_entry(entry, session)}
13
+ end
14
+
15
+ def self.for_account(account)
16
+ all(account.session, account.path + '/webproperties/~all/profiles/~all/goals')
17
+ end
18
+
19
+ def self.for_web_property(web_property)
20
+ all(web_property.session, web_property.path + '/profiles/~all/goals')
21
+ end
22
+
23
+ def self.for_profile(profile)
24
+ all(profile.session, profile.path + '/goals')
25
+ end
26
+
27
+ def self.new_from_entry(entry, session)
28
+ goal = new
29
+ goal.session = session
30
+ goal.path = Garb.parse_link(entry, "self").gsub(Feed::BASE_URL, '')
31
+ goal.properties = entry[Garb.to_ga('goal')]
32
+ goal
33
+ end
34
+
35
+ def properties=(properties)
36
+ self.name = properties["name"]
37
+ self.number = properties["number"].to_i
38
+ self.value = properties["value"].to_f
39
+ self.active = (properties["active"] == "true")
40
+ self.destination = Destination.new(properties[Garb.to_ga('destination')])
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,44 @@
1
+ module Garb
2
+ module Management
3
+ class Profile
4
+
5
+ include ProfileReports
6
+
7
+ attr_accessor :session, :path
8
+ attr_accessor :id, :table_id, :title, :account_id, :web_property_id
9
+
10
+ def self.all(session = Session, path = '/accounts/~all/webproperties/~all/profiles')
11
+ feed = Feed.new(session, path)
12
+ feed.entries.map {|entry| new_from_entry(entry, session)}
13
+ end
14
+
15
+ def self.for_account(account)
16
+ all(account.session, account.path+'/webproperties/~all/profiles')
17
+ end
18
+
19
+ def self.for_web_property(web_property)
20
+ all(web_property.session, web_property.path+'/profiles')
21
+ end
22
+
23
+ def self.new_from_entry(entry, session)
24
+ profile = new
25
+ profile.session = session
26
+ profile.path = Garb.parse_link(entry, "self").gsub(Feed::BASE_URL, '')
27
+ profile.properties = Garb.parse_properties(entry)
28
+ profile
29
+ end
30
+
31
+ def properties=(properties)
32
+ self.id = properties['profile_id']
33
+ self.table_id = properties['dxp:table_id']
34
+ self.title = properties['profile_name']
35
+ self.account_id = properties['account_id']
36
+ self.web_property_id = properties['web_property_id']
37
+ end
38
+
39
+ def goals
40
+ Goal.for_profile(self)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,27 @@
1
+ module Garb
2
+ module Management
3
+ class Segment
4
+ attr_accessor :session, :path
5
+ attr_accessor :id, :name, :definition
6
+
7
+ def self.all(session = Session)
8
+ feed = Feed.new(session, '/segments')
9
+ feed.entries.map {|entry| new_from_entry(entry, session)}
10
+ end
11
+
12
+ def self.new_from_entry(entry, session)
13
+ segment = new
14
+ segment.session = session
15
+ segment.path = Garb.parse_link(entry, "self").gsub(Feed::BASE_URL, '')
16
+ segment.properties = entry['dxp:segment']
17
+ segment
18
+ end
19
+
20
+ def properties=(properties)
21
+ self.id = properties['id']
22
+ self.name = properties['name']
23
+ self.definition = properties['dxp:definition']
24
+ end
25
+ end
26
+ end
27
+ end