zuck 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +0 -4
- data/VERSION +1 -1
- data/lib/zuck/facebook/ad_keyword.rb +45 -0
- data/lib/zuck/facebook/targeting_spec.rb +3 -29
- data/lib/zuck/helpers.rb +11 -0
- data/lib/zuck.rb +1 -0
- data/spec/fixtures/ad_keyword_search_disney.yml +53 -0
- data/spec/fixtures/ad_keyword_search_nonexistant.yml +48 -0
- data/spec/fixtures/ad_keyword_search_steve_carell.yml +49 -0
- data/spec/lib/zuck/facebook/ad_keyword_spec.rb +23 -0
- data/spec/lib/zuck/facebook/targeting_spec_spec.rb +16 -35
- data/zuck.gemspec +8 -2
- metadata +9 -3
data/README.markdown
CHANGED
@@ -10,10 +10,6 @@ for a nice diagram that explains how things work.
|
|
10
10
|
|
11
11
|
![](https://dl.dropbox.com/u/1953503/kw29_koelner_gelierzucker_31_oder_diamant_feinster_zucker_462982.jpeg)
|
12
12
|
|
13
|
-
We just hacked this up and are not using it in production yet,
|
14
|
-
so handle with care. On the other hand, simplecov reports 100%
|
15
|
-
coverage. But as it is a gem in a very early stage, a warning was
|
16
|
-
due.
|
17
13
|
|
18
14
|
Usage
|
19
15
|
=====
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Zuck
|
2
|
+
module AdKeyword
|
3
|
+
extend Zuck::Helpers
|
4
|
+
extend self
|
5
|
+
|
6
|
+
# Given a keyword, make a guess on what the closest keyword
|
7
|
+
# on the facebook ads api is. It tends to use a # prefixed
|
8
|
+
# keyword if available, and also a more popular one over a less
|
9
|
+
# popular one
|
10
|
+
def best_guess(graph, keyword)
|
11
|
+
search(graph, keyword).sort do |a,b|
|
12
|
+
if a[:audience].to_i > 0 || b[:audience].to_i > 0
|
13
|
+
a[:audience].to_i <=> b[:audience].to_i
|
14
|
+
else
|
15
|
+
b[:keyword].length <=> a[:keyword].length
|
16
|
+
end
|
17
|
+
end.last
|
18
|
+
end
|
19
|
+
|
20
|
+
# Checks the ad api to see if the given keywords are valid
|
21
|
+
# @return [Hash] The keys are the (lowercased) keywords and the values their validity
|
22
|
+
def validate(graph, keywords)
|
23
|
+
keywords = normalize_array(keywords).map{|k| k.gsub(',', '%2C')}
|
24
|
+
search = graph.search(nil, type: 'adkeywordvalid', keyword_list: keywords.join(","))
|
25
|
+
results = {}
|
26
|
+
search.each do |r|
|
27
|
+
results[r['name']] = r['valid']
|
28
|
+
end
|
29
|
+
results
|
30
|
+
end
|
31
|
+
|
32
|
+
# Ad keyword search
|
33
|
+
def search(graph, keyword)
|
34
|
+
results = graph.search(keyword, type: :adkeyword).map do |r|
|
35
|
+
audience = r['description'].scan(/[0-9]+/).join('').to_i rescue nil
|
36
|
+
{
|
37
|
+
keyword: r['name'],
|
38
|
+
id: r['id'],
|
39
|
+
audience: audience
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -49,6 +49,8 @@ module Zuck
|
|
49
49
|
# => 12345
|
50
50
|
#
|
51
51
|
class TargetingSpec
|
52
|
+
include Zuck::Helpers
|
53
|
+
|
52
54
|
attr_reader :spec, :graph
|
53
55
|
|
54
56
|
# @param graph [Koala::Facebook::API] The koala graph object to use
|
@@ -103,23 +105,11 @@ module Zuck
|
|
103
105
|
def validate_keyword(keyword)
|
104
106
|
if @validated_keywords[keyword] == nil
|
105
107
|
keywords = normalize_array([@spec[:keywords]] + [keyword])
|
106
|
-
@validated_keywords =
|
108
|
+
@validated_keywords = Zuck::AdKeyword.validate(@graph, keywords)
|
107
109
|
end
|
108
110
|
@validated_keywords[keyword] == true
|
109
111
|
end
|
110
112
|
|
111
|
-
# Checks the ad api to see if the given keywords are valid
|
112
|
-
# @return [Hash] The keys are the (lowercased) keywords and the values their validity
|
113
|
-
def self.validate_keywords(graph, keywords)
|
114
|
-
keywords = normalize_array(keywords).map{|k| k.gsub(',', '%2C')}
|
115
|
-
search = graph.search(nil, type: 'adkeywordvalid', keyword_list: keywords.join(","))
|
116
|
-
results = {}
|
117
|
-
search.each do |r|
|
118
|
-
results[r['name']] = r['valid']
|
119
|
-
end
|
120
|
-
results
|
121
|
-
end
|
122
|
-
|
123
113
|
# Fetches a bunch of reach estimates from facebook at once.
|
124
114
|
# @param graph Koala graph instance
|
125
115
|
# @param specs [Array<Hash>] An array of specs as you would pass to {#initialize}
|
@@ -162,22 +152,6 @@ module Zuck
|
|
162
152
|
|
163
153
|
private
|
164
154
|
|
165
|
-
def self.normalize_array(arr)
|
166
|
-
[arr].flatten.compact.map(&:to_s).uniq.sort
|
167
|
-
end
|
168
|
-
|
169
|
-
def self.normalize_countries(countries)
|
170
|
-
normalize_array(countries).map(&:upcase)
|
171
|
-
end
|
172
|
-
|
173
|
-
def normalize_array(arr)
|
174
|
-
self.class.normalize_array(arr)
|
175
|
-
end
|
176
|
-
|
177
|
-
def normalize_countries(countries)
|
178
|
-
self.class.normalize_countries(countries)
|
179
|
-
end
|
180
|
-
|
181
155
|
def validate_spec
|
182
156
|
@spec[:countries] = normalize_countries(@spec[:countries])
|
183
157
|
@spec[:keywords] = normalize_array(@spec[:keywords])
|
data/lib/zuck/helpers.rb
ADDED
data/lib/zuck.rb
CHANGED
@@ -0,0 +1,53 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://graph.facebook.com/search?access_token=CAAEvJ5vzhl8BAE7m0kztNbbASKHymRlXoBZCdZCtMsebNEgaR0yOmZCBfeTIXT8MnuV3ZCH5lBDQOcC4S9geswWZBuF707gJ42lV9DHgGILsRaiG2upipiHggl7UZAeDVgBSSsap9s9uv1ghZCxNsmH&q=disney&type=adkeyword
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Faraday v0.8.7
|
12
|
+
Accept-Encoding:
|
13
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
14
|
+
Accept:
|
15
|
+
- ! '*/*'
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 200
|
19
|
+
message: OK
|
20
|
+
headers:
|
21
|
+
Access-Control-Allow-Origin:
|
22
|
+
- ! '*'
|
23
|
+
Cache-Control:
|
24
|
+
- private, no-cache, no-store, must-revalidate
|
25
|
+
Content-Type:
|
26
|
+
- application/json; charset=UTF-8
|
27
|
+
Etag:
|
28
|
+
- ! '"167c644dd8fab56d0277dc91306a5636a7994715"'
|
29
|
+
Expires:
|
30
|
+
- Sat, 01 Jan 2000 00:00:00 GMT
|
31
|
+
Pragma:
|
32
|
+
- no-cache
|
33
|
+
X-Fb-Rev:
|
34
|
+
- '880776'
|
35
|
+
X-Fb-Debug:
|
36
|
+
- Fc7xjOmnC+MtzLHCEOi9yDh3oWYLK/7+pqNc61S25kg=
|
37
|
+
Date:
|
38
|
+
- Fri, 19 Jul 2013 09:46:15 GMT
|
39
|
+
Connection:
|
40
|
+
- keep-alive
|
41
|
+
Content-Length:
|
42
|
+
- '589'
|
43
|
+
body:
|
44
|
+
encoding: US-ASCII
|
45
|
+
string: ! '{"data":[{"name":"Disney Channel","id":6003711659516},{"name":"Disneyland","id":6003361056187},{"name":"Disney","id":6003663755307},{"name":"#The
|
46
|
+
Walt Disney Company","description":"Audience: 72,500,000","id":6003270522085},{"name":"#Disneyland","description":"Audience:
|
47
|
+
24,100,000","id":6003274193708},{"name":"#Disney Channel","description":"Audience:
|
48
|
+
17,800,000","id":6003327130854},{"name":"#The Walt Disney Company#Walt Disney
|
49
|
+
Pictures","description":"Audience: 14,600,000","id":6004710425192},{"name":"#Walt
|
50
|
+
Disney Pictures","description":"Audience: 14,600,000","id":6003050377616}]}'
|
51
|
+
http_version:
|
52
|
+
recorded_at: Fri, 19 Jul 2013 09:46:19 GMT
|
53
|
+
recorded_with: VCR 2.3.0
|
@@ -0,0 +1,48 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://graph.facebook.com/search?access_token=CAAEvJ5vzhl8BAE7m0kztNbbASKHymRlXoBZCdZCtMsebNEgaR0yOmZCBfeTIXT8MnuV3ZCH5lBDQOcC4S9geswWZBuF707gJ42lV9DHgGILsRaiG2upipiHggl7UZAeDVgBSSsap9s9uv1ghZCxNsmH&q=ick%20spickeby&type=adkeyword
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Faraday v0.8.7
|
12
|
+
Accept-Encoding:
|
13
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
14
|
+
Accept:
|
15
|
+
- ! '*/*'
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 200
|
19
|
+
message: OK
|
20
|
+
headers:
|
21
|
+
Access-Control-Allow-Origin:
|
22
|
+
- ! '*'
|
23
|
+
Cache-Control:
|
24
|
+
- private, no-cache, no-store, must-revalidate
|
25
|
+
Content-Type:
|
26
|
+
- application/json; charset=UTF-8
|
27
|
+
Etag:
|
28
|
+
- ! '"1050253aec7b29caff644806927dabfa81406eee"'
|
29
|
+
Expires:
|
30
|
+
- Sat, 01 Jan 2000 00:00:00 GMT
|
31
|
+
Pragma:
|
32
|
+
- no-cache
|
33
|
+
X-Fb-Rev:
|
34
|
+
- '880776'
|
35
|
+
X-Fb-Debug:
|
36
|
+
- 9OW6+vCkQZB0G4ete2rLeuHXg2keTeb0soekntO0k0c=
|
37
|
+
Date:
|
38
|
+
- Fri, 19 Jul 2013 10:16:13 GMT
|
39
|
+
Connection:
|
40
|
+
- keep-alive
|
41
|
+
Content-Length:
|
42
|
+
- '11'
|
43
|
+
body:
|
44
|
+
encoding: US-ASCII
|
45
|
+
string: ! '{"data":[]}'
|
46
|
+
http_version:
|
47
|
+
recorded_at: Fri, 19 Jul 2013 10:16:17 GMT
|
48
|
+
recorded_with: VCR 2.3.0
|
@@ -0,0 +1,49 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://graph.facebook.com/search?access_token=CAAEvJ5vzhl8BAE7m0kztNbbASKHymRlXoBZCdZCtMsebNEgaR0yOmZCBfeTIXT8MnuV3ZCH5lBDQOcC4S9geswWZBuF707gJ42lV9DHgGILsRaiG2upipiHggl7UZAeDVgBSSsap9s9uv1ghZCxNsmH&q=steve%20carell&type=adkeyword
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Faraday v0.8.7
|
12
|
+
Accept-Encoding:
|
13
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
14
|
+
Accept:
|
15
|
+
- ! '*/*'
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 200
|
19
|
+
message: OK
|
20
|
+
headers:
|
21
|
+
Access-Control-Allow-Origin:
|
22
|
+
- ! '*'
|
23
|
+
Cache-Control:
|
24
|
+
- private, no-cache, no-store, must-revalidate
|
25
|
+
Content-Type:
|
26
|
+
- application/json; charset=UTF-8
|
27
|
+
Etag:
|
28
|
+
- ! '"60ec5ec86640fb83726a422cc072f56d0f507bc4"'
|
29
|
+
Expires:
|
30
|
+
- Sat, 01 Jan 2000 00:00:00 GMT
|
31
|
+
Pragma:
|
32
|
+
- no-cache
|
33
|
+
X-Fb-Rev:
|
34
|
+
- '880776'
|
35
|
+
X-Fb-Debug:
|
36
|
+
- kQjivQ0nnGBYWqGHMoygWVVEMyXLEezpddYiJnNYitM=
|
37
|
+
Date:
|
38
|
+
- Fri, 19 Jul 2013 10:09:06 GMT
|
39
|
+
Connection:
|
40
|
+
- keep-alive
|
41
|
+
Content-Length:
|
42
|
+
- '248'
|
43
|
+
body:
|
44
|
+
encoding: US-ASCII
|
45
|
+
string: ! '{"data":[{"name":"Anything With Steve Carell","id":6003332902745},{"name":"Keep
|
46
|
+
Steve Carell On Office","id":6003656406820},{"name":"Steve Carell","id":6004016779789}]}'
|
47
|
+
http_version:
|
48
|
+
recorded_at: Fri, 19 Jul 2013 10:09:10 GMT
|
49
|
+
recorded_with: VCR 2.3.0
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zuck::AdKeyword do
|
4
|
+
let(:graph){ Koala::Facebook::API.new('CAAEvJ5vzhl8BAE7m0kztNbbASKHymRlXoBZCdZCtMsebNEgaR0yOmZCBfeTIXT8MnuV3ZCH5lBDQOcC4S9geswWZBuF707gJ42lV9DHgGILsRaiG2upipiHggl7UZAeDVgBSSsap9s9uv1ghZCxNsmH')}
|
5
|
+
|
6
|
+
it "finds the best keyword with a #" do
|
7
|
+
VCR.use_cassette('ad_keyword_search_disney') do
|
8
|
+
Zuck::AdKeyword.best_guess(graph, 'disney')[:keyword].should == '#The Walt Disney Company'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it "finds the best keyword when no keyword with # is available" do
|
13
|
+
VCR.use_cassette('ad_keyword_search_steve_carell') do
|
14
|
+
Zuck::AdKeyword.best_guess(graph, 'steve carell')[:keyword].should == 'Steve Carell'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "returns nil when nothing could be found" do
|
19
|
+
VCR.use_cassette('ad_keyword_search_nonexistant') do
|
20
|
+
Zuck::AdKeyword.best_guess(graph, 'ick spickeby').should be_nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -3,41 +3,6 @@ require 'spec_helper'
|
|
3
3
|
describe Zuck::TargetingSpec do
|
4
4
|
let(:ad_account){ "2ijdsfoij" }
|
5
5
|
let(:graph){ mock('koala') }
|
6
|
-
let(:reach_response){
|
7
|
-
{ # These can probably go since we have
|
8
|
-
"users" => 23688420, # vcr cassetes with http requests and
|
9
|
-
"bid_estimations" => [ # responses in place
|
10
|
-
{
|
11
|
-
"location" => 3,
|
12
|
-
"cpc_min" => 37,
|
13
|
-
"cpc_median" => 44,
|
14
|
-
"cpc_max" => 57,
|
15
|
-
"cpm_min" => 6,
|
16
|
-
"cpm_median" => 12,
|
17
|
-
"cpm_max" => 33
|
18
|
-
}
|
19
|
-
],
|
20
|
-
"imp_estimates" => [
|
21
|
-
],
|
22
|
-
"data" => {
|
23
|
-
"users" => 23688420,
|
24
|
-
"bid_estimations" => [
|
25
|
-
{
|
26
|
-
"location" => 3,
|
27
|
-
"cpc_min" => 37,
|
28
|
-
"cpc_median" => 44,
|
29
|
-
"cpc_max" => 57,
|
30
|
-
"cpm_min" => 6,
|
31
|
-
"cpm_median" => 12,
|
32
|
-
"cpm_max" => 33
|
33
|
-
}
|
34
|
-
],
|
35
|
-
"imp_estimates" => [
|
36
|
-
]
|
37
|
-
}
|
38
|
-
}
|
39
|
-
}
|
40
|
-
|
41
6
|
|
42
7
|
describe "validating keywords" do
|
43
8
|
|
@@ -166,7 +131,13 @@ describe Zuck::TargetingSpec do
|
|
166
131
|
describe "Batch processing" do
|
167
132
|
let(:graph){ Koala::Facebook::API.new('AAAEvJ5vzhl8BAPLr6fQgNy2wdUHDJ7ZAoX9PTZCFnebwuTBZBEqO7lNTVZA3XNsTHPTATpTmVFs6o6Jp1pZAL8ZA54BRBXWYtztVug8bm2BAZDZD') }
|
168
133
|
let(:ad_account){ 'act_10150585630710217' }
|
134
|
+
let(:spec_mock){ mock(fetch_reach: {some: :data}) }
|
169
135
|
|
136
|
+
it "fetches each reach" do
|
137
|
+
requests = [{some: :thing}] * 51
|
138
|
+
Zuck::TargetingSpec.should_receive(:new).exactly(51).and_return spec_mock
|
139
|
+
Zuck::TargetingSpec.batch_reaches(graph, ad_account, requests)
|
140
|
+
end
|
170
141
|
it "doesn't split up small bunches" do
|
171
142
|
requests = [{some: :thing}] * 50
|
172
143
|
graph.should_receive(:batch).once.and_return([])
|
@@ -178,5 +149,15 @@ describe Zuck::TargetingSpec do
|
|
178
149
|
graph.should_receive(:batch).twice.and_return([])
|
179
150
|
Zuck::TargetingSpec.batch_reaches(graph, ad_account, requests)
|
180
151
|
end
|
152
|
+
|
153
|
+
it "reformats results including errors" do
|
154
|
+
responses = [{facebook: :response}, Koala::KoalaError.new]
|
155
|
+
requests = [{some: :thing}] * 51
|
156
|
+
graph.should_receive(:batch).twice.and_return(responses)
|
157
|
+
reaches = Zuck::TargetingSpec.batch_reaches(graph, ad_account, requests)
|
158
|
+
|
159
|
+
reaches[0][:success].should == true
|
160
|
+
reaches[1][:success].should == false
|
161
|
+
end
|
181
162
|
end
|
182
163
|
end
|
data/zuck.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "zuck"
|
8
|
-
s.version = "0.0
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jannis Hermanns"]
|
12
|
-
s.date = "2013-07-
|
12
|
+
s.date = "2013-07-19"
|
13
13
|
s.description = "This gem allows to easily access facebook's ads api in ruby. See https://developers.facebook.com/docs/reference/ads-api/"
|
14
14
|
s.email = "jannis@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -34,6 +34,7 @@ Gem::Specification.new do |s|
|
|
34
34
|
"lib/zuck/facebook/ad_campaign.rb",
|
35
35
|
"lib/zuck/facebook/ad_creative.rb",
|
36
36
|
"lib/zuck/facebook/ad_group.rb",
|
37
|
+
"lib/zuck/facebook/ad_keyword.rb",
|
37
38
|
"lib/zuck/facebook/targeting_spec.rb",
|
38
39
|
"lib/zuck/fb_object.rb",
|
39
40
|
"lib/zuck/fb_object/dsl.rb",
|
@@ -43,9 +44,13 @@ Gem::Specification.new do |s|
|
|
43
44
|
"lib/zuck/fb_object/read.rb",
|
44
45
|
"lib/zuck/fb_object/read_only.rb",
|
45
46
|
"lib/zuck/fb_object/write.rb",
|
47
|
+
"lib/zuck/helpers.rb",
|
46
48
|
"lib/zuck/koala/koala_methods.rb",
|
47
49
|
"spec/fixtures/a_single_account.yml",
|
48
50
|
"spec/fixtures/a_single_campaign.yml",
|
51
|
+
"spec/fixtures/ad_keyword_search_disney.yml",
|
52
|
+
"spec/fixtures/ad_keyword_search_nonexistant.yml",
|
53
|
+
"spec/fixtures/ad_keyword_search_steve_carell.yml",
|
49
54
|
"spec/fixtures/create_ad_campaign.yml",
|
50
55
|
"spec/fixtures/create_ad_group.yml",
|
51
56
|
"spec/fixtures/delete_ad_group.yml",
|
@@ -60,6 +65,7 @@ Gem::Specification.new do |s|
|
|
60
65
|
"spec/fixtures/reach_for_valid_keywords_male_young.yml",
|
61
66
|
"spec/lib/zuck/facebook/ad_account_spec.rb",
|
62
67
|
"spec/lib/zuck/facebook/ad_campaign_spec.rb",
|
68
|
+
"spec/lib/zuck/facebook/ad_keyword_spec.rb",
|
63
69
|
"spec/lib/zuck/facebook/targeting_spec_spec.rb",
|
64
70
|
"spec/lib/zuck/fb_object/helpers_spec.rb",
|
65
71
|
"spec/lib/zuck/koala/koala_methods_spec.rb",
|
metadata
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
name: zuck
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0
|
5
|
+
version: 0.1.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jannis Hermanns
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rvm
|
@@ -324,6 +324,7 @@ files:
|
|
324
324
|
- lib/zuck/facebook/ad_campaign.rb
|
325
325
|
- lib/zuck/facebook/ad_creative.rb
|
326
326
|
- lib/zuck/facebook/ad_group.rb
|
327
|
+
- lib/zuck/facebook/ad_keyword.rb
|
327
328
|
- lib/zuck/facebook/targeting_spec.rb
|
328
329
|
- lib/zuck/fb_object.rb
|
329
330
|
- lib/zuck/fb_object/dsl.rb
|
@@ -333,9 +334,13 @@ files:
|
|
333
334
|
- lib/zuck/fb_object/read.rb
|
334
335
|
- lib/zuck/fb_object/read_only.rb
|
335
336
|
- lib/zuck/fb_object/write.rb
|
337
|
+
- lib/zuck/helpers.rb
|
336
338
|
- lib/zuck/koala/koala_methods.rb
|
337
339
|
- spec/fixtures/a_single_account.yml
|
338
340
|
- spec/fixtures/a_single_campaign.yml
|
341
|
+
- spec/fixtures/ad_keyword_search_disney.yml
|
342
|
+
- spec/fixtures/ad_keyword_search_nonexistant.yml
|
343
|
+
- spec/fixtures/ad_keyword_search_steve_carell.yml
|
339
344
|
- spec/fixtures/create_ad_campaign.yml
|
340
345
|
- spec/fixtures/create_ad_group.yml
|
341
346
|
- spec/fixtures/delete_ad_group.yml
|
@@ -350,6 +355,7 @@ files:
|
|
350
355
|
- spec/fixtures/reach_for_valid_keywords_male_young.yml
|
351
356
|
- spec/lib/zuck/facebook/ad_account_spec.rb
|
352
357
|
- spec/lib/zuck/facebook/ad_campaign_spec.rb
|
358
|
+
- spec/lib/zuck/facebook/ad_keyword_spec.rb
|
353
359
|
- spec/lib/zuck/facebook/targeting_spec_spec.rb
|
354
360
|
- spec/lib/zuck/fb_object/helpers_spec.rb
|
355
361
|
- spec/lib/zuck/koala/koala_methods_spec.rb
|
@@ -371,7 +377,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
371
377
|
- !ruby/object:Gem::Version
|
372
378
|
segments:
|
373
379
|
- 0
|
374
|
-
hash:
|
380
|
+
hash: 1542161049211835241
|
375
381
|
version: '0'
|
376
382
|
none: false
|
377
383
|
required_rubygems_version: !ruby/object:Gem::Requirement
|