pocketmath-advertise 0.0.3 → 0.0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4c9ff5e64083c8fbfebd787eeea561cec50bdf79
4
- data.tar.gz: 7f670f3d445182aa9a86728fc212bc0599ef85d9
3
+ metadata.gz: 1fa5aa04e223ff53658c46d7b519315fb79e8546
4
+ data.tar.gz: 0d3b61f58a15c21b323ccba55c2244fa82ab1d0e
5
5
  SHA512:
6
- metadata.gz: 56289da6d8e1acc54fc44a68a5c29e50da6efbcee24aa5ab4b70bb0277684cf4542990b51a6b901d60915602381fe852cffe21735ac5ef3b10d85ec92df3bc5e
7
- data.tar.gz: 277c043dfbee2c67a2989d7ee01f0ba85421deb8ede18226460d2c534d4924ff3bcc9497d906d161f5f37edebce4993095b5fa5cd1c5dee00e1dc8640e17ce9c
6
+ metadata.gz: ceade68a085ea00f3c7bdc1c5bb0b9516a90682135a13cd0ecac309fd74dbb4fe5a30f466a47eee6692a916ca337fc4545da638c3a3c33e2bfa181b8b5275e1b
7
+ data.tar.gz: e93f468332b6b9fb624148b0778a1631c2090007a113853213c456690bab303d64fa0e08029cc679ee1253ed5cc00fd28e43c5fc1c90ed3b8d040c5c46d724ea
@@ -0,0 +1,42 @@
1
+ module PocketMath::Advertiser::V1
2
+
3
+ class InsertionOrderStats
4
+
5
+ # Cost per thousand Impressions
6
+ attr_reader :cpm
7
+
8
+ # Cost per Click
9
+ attr_reader :cpc
10
+
11
+ # Cost per Action (Cost per Conversion)
12
+ attr_reader :cpa
13
+
14
+ # Click-through Rate (Clicks per impression)
15
+ attr_reader :ctr
16
+
17
+ attr_reader :impressions, :clicks, :conversions
18
+
19
+ # Ad spend in currency
20
+ attr_reader :spend
21
+
22
+ private
23
+
24
+ attr_writer :cpm, :cpc, :cpa, :ctr
25
+ attr_writer :impressions, :clicks, :conversions
26
+ attr_writer :spend
27
+
28
+ public
29
+
30
+ # Create a new instance.
31
+ # * Specify attributes in a hash as { :cpm => 1.25, :cpc => 2.33, ... }
32
+ def self.create(opts = {})
33
+ iostats = InsertionOrderStats.new
34
+ opts.each_pair do |k,v|
35
+ raise "#{k.to_s}=#{v} was not a number" if !v.is_a?(Numeric)
36
+ iostats.send(k.to_s + "=", v)
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -1,2 +1,3 @@
1
1
  require 'pocketmath-geocode'
2
2
  require 'pocketmath-advertiser'
3
+ require 'model/insertion_order_stats'
@@ -1,5 +1,4 @@
1
1
  require 'json'
2
- require 'open-uri'
3
2
  require 'net/http'
4
3
  require 'net/https'
5
4
  require 'uri'
@@ -10,152 +9,213 @@ require 'curb'
10
9
  module PocketMath
11
10
  module PocketMath::Advertiser
12
11
  module PocketMath::Advertiser::V1
13
-
14
- API_BASE_URL = "https://api.pocketmath.com"
12
+
13
+ DEFAULT_API_BASE_URL = "https://api.pocketmath.com"
14
+
15
+ def self.open(pocketmath_api_key, pocketmath_api_base_url = DEFAULT_API_BASE_URL)
16
+ return Client.new(pocketmath_api_key, pocketmath_api_base_url)
17
+ end
18
+
19
+ class PocketMath::Advertiser::V1::Client
20
+
21
+ def initialize(pocketmath_api_key, pocketmath_api_base_url)
22
+ @pocketmath_api_key = pocketmath_api_key
23
+ @pocketmath_api_base_url = pocketmath_api_base_url
24
+ end
25
+
26
+ def close
27
+ end
15
28
 
16
- def self.find_gps_list_id_by_name(name)
17
- p "get_gps_list_id"
18
- url = "#{API_BASE_URL}/v1/lists/gps/list.json?token=#{POCKETMATH_API_KEY}&limit=10000"
19
- response = Net::HTTP.get_response(URI.parse(url))
20
- data = response.body
21
- obj = JSON.parse(data)
22
- obj.each do |result|
23
- return result["id"] if result["name"] == name
29
+ def find_gps_list_id_by_name(name)
30
+ p "get_gps_list_id"
31
+ url = "#{@pocketmath_api_base_url}/v1/lists/gps/list.json?token=#{@pocketmath_api_key}&limit=10000"
32
+ response = Net::HTTP.get_response(URI.parse(url))
33
+ data = response.body
34
+ obj = JSON.parse(data)
35
+ obj.each do |result|
36
+ return result["id"] if result["name"] == name
37
+ end
24
38
  end
25
- end
26
39
 
27
- def self.create_gps_list(name)
28
- raise "name was nil" if name.nil?
29
- raise "name was blank" if name.empty?
40
+ def create_gps_list(name)
41
+ raise "name was nil" if name.nil?
42
+ raise "name was blank" if name.empty?
30
43
 
31
- add_list_json = JSON::generate(
32
- {
33
- "token" => "#{POCKETMATH_API_KEY}",
34
- "list" =>
35
- {
36
- "name" => "#{name}"
37
- }
38
- })
44
+ add_list_json = JSON::generate(
45
+ {
46
+ "token" => "#{@pocketmath_api_key}",
47
+ "list" =>
48
+ {
49
+ "name" => "#{name}"
50
+ }
51
+ })
39
52
 
40
- uri = URI.parse(API_BASE_URL)
41
- response = nil
42
- Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
43
- request = Net::HTTP::Post.new("/v1/lists/gps/add_list.json")
44
- request.body = add_list_json
45
- request.content_type = "application/json"
46
- response = http.request(request)
47
- end
48
- if !response.nil?
49
- data = response.body
50
- obj = JSON::parse(data)
51
- list_id = obj["id"]
52
- return list_id
53
- else
54
- return nil
53
+ uri = URI.parse(@pocketmath_api_base_url)
54
+ response = nil
55
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
56
+ request = Net::HTTP::Post.new("/v1/lists/gps/add_list.json")
57
+ request.body = add_list_json
58
+ request.content_type = "application/json"
59
+ response = http.request(request)
60
+ end
61
+ if !response.nil?
62
+ data = response.body
63
+ obj = JSON::parse(data)
64
+ list_id = obj["id"]
65
+ return list_id
66
+ else
67
+ return nil
68
+ end
55
69
  end
56
- end
57
70
 
58
- def self.upload_gps_list(id, coordinates = [])
59
- raise "id was nil" if id.nil?
60
- raise "coordinates was nil" if coordinates.nil?
61
- raise "coordiantes was empty" if coordinates.empty?
71
+ def upload_gps_list(id, coordinates = [])
72
+ raise "id was nil" if id.nil?
73
+ raise "coordinates was nil" if coordinates.nil?
74
+ raise "coordiantes was empty" if coordinates.empty?
62
75
 
63
- c = Curl::Easy.new("#{API_BASE_URL}/v1/lists/gps/upload.json")
64
- c.multipart_form_post = true
76
+ c = Curl::Easy.new("#{@pocketmath_api_base_url}/v1/lists/gps/upload.json")
77
+ c.multipart_form_post = true
65
78
 
66
- coordinates_string = ''
67
- coordinates.each do |coord|
68
- coordinates_string << "#{coord[:latitude]},#{coord[:longitude]}\r\n"
69
- end
79
+ coordinates_string = ''
80
+ coordinates.each do |coord|
81
+ coordinates_string << "#{coord[:latitude]},#{coord[:longitude]}\r\n"
82
+ end
70
83
 
71
- r = Random.new
72
- remote_file_name = "pm-advert-client-gps-list-#{r.rand(2*1000*1000*1000)}-#{r.rand(2*1000*1000*1000)}.txt"
73
- content_field = Curl::PostField.file('file', remote_file_name) do |field|
74
- field.content = coordinates_string
75
- end
84
+ r = Random.new
85
+ remote_file_name = "pm-advert-client-gps-list-#{r.rand(2*1000*1000*1000)}-#{r.rand(2*1000*1000*1000)}.txt"
86
+ content_field = Curl::PostField.file('file', remote_file_name) do |field|
87
+ field.content = coordinates_string
88
+ end
76
89
 
77
- success = nil
90
+ success = nil
78
91
 
79
- success = c.http_post(
80
- content_field,
81
- Curl::PostField.content('token', POCKETMATH_API_KEY),
82
- Curl::PostField.content('mode', 'append'),
83
- Curl::PostField.content('list_id', id.to_s )
84
- )
92
+ success = c.http_post(
93
+ content_field,
94
+ Curl::PostField.content('token', @pocketmath_api_key),
95
+ Curl::PostField.content('mode', 'append'),
96
+ Curl::PostField.content('list_id', id.to_s )
97
+ )
85
98
 
86
- return success
87
- end
88
-
89
- private
90
-
91
- def self.deep_copy(o)
92
- Marshal.load(Marshal.dump(o))
93
- end
94
-
95
- public
96
-
97
- def self.create_insertion_order( opts =
98
- {
99
- "name" => nil,
100
- "start_datetime" => Date.now,
101
- "end_datetime" => Date.now + 7.days,
102
- "creative_type_ids" => [],
103
- "budget" => "1.00",
104
- "iab_catgories" => [],
105
- "bid_per_impression" => "2.00",
106
- "top_level_domain" => "pocketmath.com",
107
- "country" => "223",
108
- "image_url" => "https://s3.amazonaws.com/pocketmath/pocketmath_320x50.jpg",
109
- "landing_page_url" => "www.pocketmath.com",
110
- "size_id" => "11"
111
- })
112
-
113
- o = deep_copy(opts)
114
-
115
- if o["name"].nil?
116
- raise "name was nil"
99
+ return success
117
100
  end
118
101
 
119
- if o["iab_category_codes"].empty?
120
- raise "no iab_category_codes specified"
102
+ def get_insertion_order_stats(id, start_date = nil, end_date = nil)
103
+ url = "#{@pocketmath_api_base_url}/v1/stats/id.json?token=#{@pocketmath_api_key}&id=#{URI.encode(id)}"
104
+ start_date_string = to_date_string(start_date)
105
+ end_date_string = to_date_string(end_date)
106
+ url << "&start_date=#{URI.encode(start_date_string)}" if !start_date_string.nil?
107
+ url << "&end_date=#{URI.encode(end_date_string)}" if !end_date_string.nil?
108
+ uri = URI.parse(url)
109
+
110
+ response = Net::HTTP.get(uri)
111
+ p response
112
+
113
+ if !response.nil?
114
+ data = response
115
+ obj = JSON::parse(data)
116
+ stats = obj["stats"]
117
+ return nil if stats.nil?
118
+ io_totals = stats["io_totals"]
119
+ return nil if io_totals.nil?
120
+ p io_totals
121
+ iostats = InsertionOrderStats.create({
122
+ :impressions => io_totals["imp"].to_i,
123
+ :clicks => io_totals["clk"].to_i,
124
+ :conversions => io_totals["conv"].to_i,
125
+ :spend => io_totals["spend"].gsub(/[^\d\.]/, '').to_f,
126
+ :cpm => io_totals["cpm"].gsub(/[^\d\.]/, '').to_f,
127
+ :cpc => io_totals["cpc"].gsub(/[^\d\.]/, '').to_f,
128
+ :cpa => io_totals["cpa"].gsub(/[^\d\.]/, '').to_f,
129
+ :ctr => io_totals["ctr"].to_f
130
+ })
131
+ return iostats
132
+ else
133
+ return nil
134
+ end
121
135
  end
122
136
 
123
- if o["start_datetime"].is_a?(Date)
124
- o["start_datetime"] = o["start_datetime"].strftime("%d %b %Y")
125
- elsif ! o["start_datetime"].is_a?(String)
126
- raise "unsupported type"
137
+ private
138
+
139
+ def deep_copy(o)
140
+ Marshal.load(Marshal.dump(o))
127
141
  end
128
142
 
129
- if o["end_datetime"].is_a?(Date)
130
- o["end_datetime"] = o["end_datetime"].strftime("%d %b %Y")
131
- elsif ! o["end_datetime"].is_a?(String)
132
- raise "unsupported type"
143
+ def to_date_string(o)
144
+ if o.nil?
145
+ return nil
146
+ elsif o.is_a?(Date)
147
+ return o.strftime("%d %b %Y")
148
+ elsif o.is_a?(String)
149
+ raise "case not handled"
150
+ end
133
151
  end
152
+
153
+ public
154
+
155
+ def create_insertion_order( opts =
156
+ {
157
+ "name" => nil,
158
+ "start_datetime" => Date.now,
159
+ "end_datetime" => Date.now + 7.days,
160
+ "creative_type_ids" => [],
161
+ "budget" => "1.00",
162
+ "iab_catgories" => [],
163
+ "bid_per_impression" => "2.00",
164
+ "top_level_domain" => "pocketmath.com",
165
+ "country" => "223",
166
+ "image_url" => "https://s3.amazonaws.com/pocketmath/pocketmath_320x50.jpg",
167
+ "landing_page_url" => "www.pocketmath.com",
168
+ "size_id" => "11"
169
+ })
134
170
 
135
- obj = { "token" => POCKETMATH_API_KEY, "io" => o }
171
+ o = deep_copy(opts)
136
172
 
137
- create_io_json = JSON.generate(obj)
173
+ if o["name"].nil?
174
+ raise "name was nil"
175
+ end
138
176
 
139
- uri = URI.parse(API_BASE_URL)
140
- response = nil
141
- Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
142
- request = Net::HTTP::Post.new("/v1/io/create.json")
143
- request.body = create_io_json
144
- request.content_type = "application/json"
145
- response = http.request(request)
146
- end
147
- if !response.nil?
148
- data = response.body
149
- p response
150
- p data
151
- obj = JSON::parse(data)
152
- io_id = obj["id"]
153
- return io_id
154
- else
155
- return nil
156
- end
177
+ if o["iab_category_codes"].empty?
178
+ raise "no iab_category_codes specified"
179
+ end
157
180
 
158
- end
181
+ if o["start_datetime"].is_a?(Date)
182
+ o["start_datetime"] = o["start_datetime"].strftime("%d %b %Y")
183
+ elsif ! o["start_datetime"].is_a?(String)
184
+ raise "unsupported type"
185
+ end
186
+
187
+ if o["end_datetime"].is_a?(Date)
188
+ o["end_datetime"] = o["end_datetime"].strftime("%d %b %Y")
189
+ elsif ! o["end_datetime"].is_a?(String)
190
+ raise "unsupported type"
191
+ end
192
+
193
+ obj = { "token" => @pocketmath_api_key, "io" => o }
194
+
195
+ create_io_json = JSON.generate(obj)
196
+
197
+ uri = URI.parse(@pocketmath_api_base_url)
198
+ response = nil
199
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
200
+ request = Net::HTTP::Post.new("/v1/io/create.json")
201
+ request.body = create_io_json
202
+ request.content_type = "application/json"
203
+ response = http.request(request)
204
+ end
205
+ if !response.nil?
206
+ data = response.body
207
+ p response
208
+ p data
209
+ obj = JSON::parse(data)
210
+ io_id = obj["id"]
211
+ return io_id
212
+ else
213
+ return nil
214
+ end
215
+
216
+ end
217
+
218
+ end # end Client
159
219
 
160
220
  end # module PocketMath::Advertiser::V1
161
221
  end # module PocketMath::Advertiser
@@ -1,73 +1,113 @@
1
1
  require 'json'
2
- require 'open-uri'
3
2
  require 'net/http'
4
3
  require 'uri'
5
4
 
6
- GEOCODING_PROVIDER = :open # May also use :google (see Google Map API Terms of Service to determine licensing requirements)
7
-
8
5
  module PocketMath
9
6
  module PocketMath::Geocode
10
7
 
11
- private
8
+ DEFAULT_GEOCODING_PROVIDER = :open # May also use :google (see Google Map API Terms of Service to determine licensing requirements)
12
9
 
13
- def self.get_gps_coordinates_open(location, max_results = 1)
14
- url = "http://open.mapquestapi.com/geocoding/v1/address?key=#{MAPQUEST_API_KEY}&location=#{URI.encode(location)}&maxResults=#{max_results.to_s}&inFormat=kvp&outFormat=json&json=true"
15
- response = Net::HTTP.get_response(URI.parse(url))
16
- data = response.body
17
- obj = JSON.parse(data)
18
- p url
19
- p obj
20
- gps_coordinates = []
21
- obj["results"].each do |result|
22
- result["locations"].each do |location|
23
- lat_lng = location["latLng"]
24
- gps_coordinates << { :latitude => lat_lng["lat"], :longitude => lat_lng["lng"] }
10
+ def self.open( opts = { :mapquest_api_key => nil, :provider => DEFAULT_GEOCODING_PROVIDER } )
11
+ return Geocode::Client.new(opts)
12
+ end
13
+
14
+ class PocketMath::Geocode::Client
15
+
16
+ private
17
+
18
+ def initialize( opts = { :mapquest_api_key => nil, :provider => DEFAULT_GEOCODING_PROVIDER } )
19
+ if !opts[:provider].nil?
20
+ @provider = opts[:provider]
21
+ else
22
+ @provider = DEFAULT_GEOCODING_PROVIDER
23
+ end
24
+
25
+ if !opts[:mapquest_api_key].nil?
26
+ @mapquest_api_key = opts[:mapquest_api_key]
27
+ else
28
+ @mapquest_api_key = nil
29
+ end
30
+
31
+ if @provider == :open && @mapquest_api_key.nil?
32
+ raise "Geocoding provider OPEN requires MapQuest API key. No key was specified. Please specify like this: Geocode.open{ :mapquest_api_key => \"...\" }"
25
33
  end
26
34
  end
27
- return nil if gps_coordinates.empty?
28
- return gps_coordinates
29
- end
30
35
 
31
- private
36
+ private
32
37
 
33
- #
34
- # Use of the Google Map API requires licensing from Google.
35
- #
36
- def self.get_gps_coordinates_google(location, max_results = 1)
37
- url = "http://maps.googleapis.com/maps/api/geocode/json?address=#{URI.encode(location)}&sensor=true"
38
- response = Net::HTTP.get_response(URI.parse(url))
39
- data = response.body
40
- obj = JSON.parse(data)
41
- p url
42
- p obj
43
- gps_coordinates = []
44
- n = 0
45
- obj["results"].each do |result|
46
- break if n >= max_results
47
- geometry = result["geometry"]
48
- raise "geometry was unavailable" if geometry.nil?
49
- location = geometry["location"]
50
- raise "location was unavailable" if location.nil?
51
- lat = location["lat"]
52
- lng = location["lng"]
53
- gps_coordinates << { :latitude => lat, :longitude => lng }
54
- n += 1
38
+ def get_gps_coordinates_open(location, max_results = 1)
39
+ url = "http://open.mapquestapi.com/geocoding/v1/address?key=#{@mapquest_api_key}&location=#{URI.encode(location)}&maxResults=#{max_results.to_s}&inFormat=kvp&outFormat=json&json=true"
40
+ response = Net::HTTP.get_response(URI.parse(url))
41
+ data = response.body
42
+ obj = JSON.parse(data)
43
+ p url
44
+ p obj
45
+ gps_coordinates = []
46
+ obj["results"].each do |result|
47
+ result["locations"].each do |location|
48
+ lat_lng = location["latLng"]
49
+ gps_coordinates << { :latitude => lat_lng["lat"], :longitude => lat_lng["lng"] }
50
+ end
51
+ end
52
+ return nil if gps_coordinates.empty?
53
+ return gps_coordinates
55
54
  end
56
- return nil if gps_coordinates.empty?
57
- return gps_coordinates
58
- end
59
55
 
60
- public
56
+ private
61
57
 
62
- def self.get_gps_coordinates(location, max_results = 1)
63
- if GEOCODING_PROVIDER == :google
64
- return get_gps_coordinates_google(location, max_results)
65
- elsif GEOCODING_PROVIDER == :open
66
- return get_gps_coordinates_open(location, max_results)
67
- else
68
- raise "map provider was not specified"
58
+ #
59
+ # Use of the Google Map API requires licensing from Google.
60
+ #
61
+ def get_gps_coordinates_google(location, max_results = 1)
62
+ url = "http://maps.googleapis.com/maps/api/geocode/json?address=#{URI.encode(location)}&sensor=true"
63
+ response = Net::HTTP.get_response(URI.parse(url))
64
+ data = response.body
65
+ obj = JSON.parse(data)
66
+ p url
67
+ p obj
68
+ gps_coordinates = []
69
+ n = 0
70
+ obj["results"].each do |result|
71
+ break if n >= max_results
72
+ geometry = result["geometry"]
73
+ raise "geometry was unavailable" if geometry.nil?
74
+ location = geometry["location"]
75
+ raise "location was unavailable" if location.nil?
76
+ lat = location["lat"]
77
+ lng = location["lng"]
78
+ gps_coordinates << { :latitude => lat, :longitude => lng }
79
+ n += 1
80
+ end
81
+ return nil if gps_coordinates.empty?
82
+ return gps_coordinates
69
83
  end
70
- end
71
84
 
85
+ public
86
+
87
+ def get_gps_coordinates(locations, max_results = 1)
88
+ _locations = nil
89
+ if (!locations.is_a?(Array))
90
+ _locations = [ locations ]
91
+ else
92
+ _locations = locations
93
+ end
94
+ gps_coordinates = []
95
+ _locations.each do |location|
96
+ if @provider == :google
97
+ gps_coordinates = gps_coordinates + get_gps_coordinates_google(location, max_results)
98
+ elsif @provider == :open
99
+ gps_coordinates = gps_coordinates + get_gps_coordinates_open(location, max_results)
100
+ else
101
+ raise "map provider was not specified"
102
+ end
103
+ end
104
+ gps_coodinates = gps_coordinates.zip
105
+ return gps_coordinates
106
+ end
107
+
108
+ def close
109
+ end
110
+
111
+ end
72
112
  end
73
113
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pocketmath-advertise
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Tucker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-05 00:00:00.000000000 Z
11
+ date: 2014-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curb
@@ -16,20 +16,27 @@ dependencies:
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '0.8'
20
+ - - '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 0.8.5
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - ~>
25
28
  - !ruby/object:Gem::Version
26
- version: '0'
29
+ version: '0.8'
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 0.8.5
27
33
  description: A client to connect to the PocketMath advertising API.
28
34
  email: eric@pocketmath.com
29
35
  executables: []
30
36
  extensions: []
31
37
  extra_rdoc_files: []
32
38
  files:
39
+ - lib/model/insertion_order_stats.rb
33
40
  - lib/pocketmath-advertise.rb
34
41
  - lib/pocketmath-advertiser.rb
35
42
  - lib/pocketmath-geocode.rb