facebook_ads 0.1.8 → 0.1.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/facebook_ads.gemspec +2 -2
- data/lib/facebook_ads/ad_account.rb +8 -7
- data/lib/facebook_ads/ad_audience.rb +3 -1
- data/lib/facebook_ads/ad_campaign.rb +2 -2
- data/lib/facebook_ads/ad_exception.rb +5 -0
- data/lib/facebook_ads/ad_product_catalog.rb +8 -6
- data/lib/facebook_ads/ad_set.rb +32 -3
- data/lib/facebook_ads/base.rb +28 -16
- data/test/ad_set_test.rb +37 -0
- data/test/vcr_cassettes/AdSetTest-test_create.yml +189 -0
- data/test/vcr_cassettes/AdSetTest-test_destroy.yml +124 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6da1d5a4ec51406066404c86c95a51e413617c8
|
4
|
+
data.tar.gz: 8520c0ea1111ea0dd115e819643ac1e10cf6922f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce833767545b4d0e32008e02aab0e3c5e94091a5adc3c08fea5e96b74e2e73528699f503208c31fc267194672ad1d6ef24856445bd5c337c7b261cdbbc897fe0
|
7
|
+
data.tar.gz: d773c3fd49a912fde691380c36af876e704a2a445cd924d76d933ad2ccaafbf8a2cda2cc36959329a2fcc1b171cd9e8b65273639d06686129104f76032b6d8e5
|
data/Gemfile.lock
CHANGED
data/facebook_ads.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# To release a new version:
|
2
2
|
# gem build facebook_ads.gemspec
|
3
|
-
# gem push facebook_ads-0.1.
|
3
|
+
# gem push facebook_ads-0.1.9.gem
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = 'facebook_ads'
|
6
|
-
s.version = '0.1.
|
6
|
+
s.version = '0.1.9'
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
8
|
s.licenses = ['MIT']
|
9
9
|
s.authors = ['Chris Estreich']
|
@@ -27,8 +27,9 @@ module FacebookAds
|
|
27
27
|
def create_ad_campaign(name:, objective:, status: 'ACTIVE')
|
28
28
|
raise Exception, "Objective must be one of: #{AdCampaign::OBJECTIVES.to_sentence}" unless AdCampaign::OBJECTIVES.include?(objective)
|
29
29
|
raise Exception, "Status must be one of: #{AdCampaign::STATUSES.to_sentence}" unless AdCampaign::STATUSES.include?(status)
|
30
|
-
|
31
|
-
AdCampaign.
|
30
|
+
query = { name: name, objective: objective, status: status }
|
31
|
+
result = AdCampaign.post("/#{id}/campaigns", query: query)
|
32
|
+
AdCampaign.find(result['id'])
|
32
33
|
end
|
33
34
|
|
34
35
|
# has_many ad_images
|
@@ -47,7 +48,7 @@ module FacebookAds
|
|
47
48
|
[name, File.open(path)]
|
48
49
|
end.to_h
|
49
50
|
|
50
|
-
response = AdImage.post("/#{id}/adimages", query: files
|
51
|
+
response = AdImage.post("/#{id}/adimages", query: files)
|
51
52
|
files.values.each { |file| File.delete(file.path) }
|
52
53
|
!response['images'].nil? ? ad_images(hashes: response['images'].map { |_key, hash| hash['hash'] }) : []
|
53
54
|
end
|
@@ -105,8 +106,8 @@ module FacebookAds
|
|
105
106
|
|
106
107
|
raise Exception, "Creative call_to_action_type must be one of: #{AdCreative::CALL_TO_ACTION_TYPES.to_sentence}" unless AdCreative::CALL_TO_ACTION_TYPES.include?(creative[:call_to_action_type])
|
107
108
|
query = AdCreative.carousel(creative)
|
108
|
-
|
109
|
-
AdCreative.find(
|
109
|
+
result = AdCreative.post("/#{id}/adcreatives", query: query)
|
110
|
+
AdCreative.find(result['id'])
|
110
111
|
end
|
111
112
|
|
112
113
|
def create_image_ad_creative(creative)
|
@@ -118,8 +119,8 @@ module FacebookAds
|
|
118
119
|
|
119
120
|
raise Exception, "Creative call_to_action_type must be one of: #{AdCreative::CALL_TO_ACTION_TYPES.to_sentence}" unless AdCreative::CALL_TO_ACTION_TYPES.include?(creative[:call_to_action_type])
|
120
121
|
query = AdCreative.photo(creative)
|
121
|
-
|
122
|
-
AdCreative.find(
|
122
|
+
result = AdCreative.post("/#{id}/adcreatives", query: query)
|
123
|
+
AdCreative.find(result['id'])
|
123
124
|
end
|
124
125
|
|
125
126
|
def download(url)
|
@@ -16,7 +16,9 @@ module FacebookAds
|
|
16
16
|
share_with_object_id: account_id,
|
17
17
|
share_with_object_type: 'Account'
|
18
18
|
}
|
19
|
-
AdAccount.post("/#{id}/share_with_objects", query: query
|
19
|
+
result = AdAccount.post("/#{id}/share_with_objects", query: query)
|
20
|
+
# result['success']
|
21
|
+
result # No idea what this response looks like.
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|
@@ -40,8 +40,8 @@ module FacebookAds
|
|
40
40
|
status: status,
|
41
41
|
is_autobid: is_autobid
|
42
42
|
}
|
43
|
-
|
44
|
-
AdSet.find(
|
43
|
+
result = AdSet.post("/act_#{account_id}/adsets", query: query)
|
44
|
+
AdSet.find(result['id'])
|
45
45
|
end
|
46
46
|
|
47
47
|
# has_many ad_insights
|
@@ -17,8 +17,9 @@ module FacebookAds
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def create(name:)
|
20
|
-
|
21
|
-
|
20
|
+
query = { name: name }
|
21
|
+
result = post("/#{FacebookAds.business_id}/product_catalogs", query: query)
|
22
|
+
find(result['id'])
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
@@ -30,8 +31,9 @@ module FacebookAds
|
|
30
31
|
|
31
32
|
# catalog.create_ad_product_feed(name: 'Test', schedule: { url: 'https://tophatter.com/admin/ad_automation/ad_product_feeds/1.csv', interval: 'HOURLY' })
|
32
33
|
def create_ad_product_feed(name:, schedule:)
|
33
|
-
|
34
|
-
|
34
|
+
query = { name: name, schedule: schedule }
|
35
|
+
result = AdProductCatalog.post("/#{id}/product_feeds", query: query)
|
36
|
+
AdProductFeed.find(result['id'])
|
35
37
|
end
|
36
38
|
|
37
39
|
# has_many product_groups
|
@@ -53,8 +55,8 @@ module FacebookAds
|
|
53
55
|
end
|
54
56
|
|
55
57
|
def create_ad_product(data)
|
56
|
-
|
57
|
-
AdProduct.find(
|
58
|
+
result = AdProductCatalog.post("/#{id}/products", query: data)
|
59
|
+
AdProduct.find(result['id'])
|
58
60
|
end
|
59
61
|
end
|
60
62
|
end
|
data/lib/facebook_ads/ad_set.rb
CHANGED
@@ -2,7 +2,35 @@ module FacebookAds
|
|
2
2
|
# An ad set belongs to a campaign and has many ads.
|
3
3
|
# https://developers.facebook.com/docs/marketing-api/reference/ad-campaign
|
4
4
|
class AdSet < Base
|
5
|
-
|
5
|
+
# Full set of fields:
|
6
|
+
# FIELDS = %w(
|
7
|
+
# id account_id adlabels adset_schedule attribution_window_days
|
8
|
+
# bid_amount bid_info billing_event budget_remaining
|
9
|
+
# campaign campaign_id configured_status created_time
|
10
|
+
# creative_sequence daily_budget effective_status end_time
|
11
|
+
# frequency_cap frequency_cap_reset_period
|
12
|
+
# frequency_control_specs instagram_actor_id
|
13
|
+
# is_autobid is_average_price_pacing lifetime_budget
|
14
|
+
# lifetime_frequency_cap lifetime_imps name optimization_goal
|
15
|
+
# pacing_type promoted_object recommendations
|
16
|
+
# recurring_budget_semantics rf_prediction_id rtb_flag
|
17
|
+
# start_time status targeting time_based_ad_rotation_id_blocks
|
18
|
+
# time_based_ad_rotation_intervals updated_time
|
19
|
+
# use_new_app_click
|
20
|
+
# ).freeze
|
21
|
+
|
22
|
+
# Fields we might actually care about:
|
23
|
+
FIELDS = %w(
|
24
|
+
id account_id campaign_id
|
25
|
+
name
|
26
|
+
status configured_status effective_status
|
27
|
+
bid_amount billing_event optimization_goal pacing_type
|
28
|
+
daily_budget budget_remaining lifetime_budget
|
29
|
+
promoted_object
|
30
|
+
targeting
|
31
|
+
created_time updated_time
|
32
|
+
).freeze
|
33
|
+
|
6
34
|
STATUSES = %w(ACTIVE PAUSED DELETED PENDING_REVIEW DISAPPROVED PREAPPROVED PENDING_BILLING_INFO CAMPAIGN_PAUSED ARCHIVED ADSET_PAUSED).freeze
|
7
35
|
BILLING_EVENTS = %w(APP_INSTALLS IMPRESSIONS).freeze
|
8
36
|
OPTIMIZATION_GOALS = %w(APP_INSTALLS OFFSITE_CONVERSIONS).freeze
|
@@ -26,8 +54,9 @@ module FacebookAds
|
|
26
54
|
end
|
27
55
|
|
28
56
|
def create_ad(name:, creative_id:)
|
29
|
-
|
30
|
-
Ad.
|
57
|
+
query = { name: name, adset_id: id, creative: { creative_id: creative_id }.to_json }
|
58
|
+
result = Ad.post("/act_#{account_id}/ads", query: query)
|
59
|
+
Ad.find(result['id'])
|
31
60
|
end
|
32
61
|
end
|
33
62
|
end
|
data/lib/facebook_ads/base.rb
CHANGED
@@ -7,7 +7,7 @@ module FacebookAds
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def get(path, query: {}, objectify:)
|
10
|
-
query = pack(query, objectify) # Adds access token, fields, etc.
|
10
|
+
query = pack(query, objectify: objectify) # Adds access token, fields, etc.
|
11
11
|
uri = "#{FacebookAds.base_uri}#{path}?" + build_nested_query(query)
|
12
12
|
FacebookAds.logger.debug "GET #{uri}"
|
13
13
|
response = begin
|
@@ -18,8 +18,8 @@ module FacebookAds
|
|
18
18
|
unpack(response, objectify: objectify)
|
19
19
|
end
|
20
20
|
|
21
|
-
def post(path, query: {}
|
22
|
-
query = pack(query, objectify)
|
21
|
+
def post(path, query: {})
|
22
|
+
query = pack(query, objectify: false)
|
23
23
|
uri = "#{FacebookAds.base_uri}#{path}"
|
24
24
|
FacebookAds.logger.debug "POST #{uri} #{query}"
|
25
25
|
response = begin
|
@@ -27,11 +27,11 @@ module FacebookAds
|
|
27
27
|
rescue RestClient::Exception => e
|
28
28
|
exception(:post, path, e)
|
29
29
|
end
|
30
|
-
unpack(response, objectify:
|
30
|
+
unpack(response, objectify: false)
|
31
31
|
end
|
32
32
|
|
33
33
|
def delete(path, query: {})
|
34
|
-
query = pack(query, false)
|
34
|
+
query = pack(query, objectify: false)
|
35
35
|
uri = "#{FacebookAds.base_uri}#{path}?" + build_nested_query(query)
|
36
36
|
FacebookAds.logger.debug "DELETE #{uri}"
|
37
37
|
response = begin
|
@@ -81,7 +81,7 @@ module FacebookAds
|
|
81
81
|
object
|
82
82
|
end
|
83
83
|
|
84
|
-
def pack(hash, objectify)
|
84
|
+
def pack(hash, objectify:)
|
85
85
|
hash = hash.merge(access_token: FacebookAds.access_token)
|
86
86
|
hash = hash.merge(fields: self::FIELDS.join(',')) if objectify
|
87
87
|
hash.delete_if { |_k, v| v.nil? }
|
@@ -129,21 +129,33 @@ module FacebookAds
|
|
129
129
|
end
|
130
130
|
end
|
131
131
|
|
132
|
-
def exception(verb, path,
|
133
|
-
|
132
|
+
def exception(verb, path, exception)
|
133
|
+
FacebookAds.logger.error exception.response
|
134
|
+
response = exception.response
|
135
|
+
|
136
|
+
message = if response.is_a?(String)
|
134
137
|
begin
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
+
if (error = JSON.parse(response)['error']).nil?
|
139
|
+
response
|
140
|
+
else
|
141
|
+
if error['error_subcode'].nil? ||
|
142
|
+
error['error_user_title'].nil? ||
|
143
|
+
error['error_user_msg'].nil?
|
144
|
+
"#{error['type']} / #{error['code']}: #{error['message']}"
|
145
|
+
else
|
146
|
+
exception = AdException.new(code: error['error_subcode'], title: error['error_user_title'], message: error['error_user_msg'])
|
147
|
+
"#{error['error_subcode']} / #{error['error_user_title']}: #{error['error_user_msg']}"
|
148
|
+
end
|
149
|
+
end
|
138
150
|
rescue JSON::ParserError
|
139
|
-
|
151
|
+
response
|
140
152
|
end
|
141
153
|
else
|
142
|
-
|
154
|
+
response.inspect
|
143
155
|
end
|
144
156
|
|
145
|
-
FacebookAds.logger.error "#{verb.upcase} #{path}
|
146
|
-
raise
|
157
|
+
FacebookAds.logger.error "#{verb.upcase} #{path} #{message}"
|
158
|
+
raise exception
|
147
159
|
end
|
148
160
|
end
|
149
161
|
|
@@ -157,7 +169,7 @@ module FacebookAds
|
|
157
169
|
|
158
170
|
def update(data)
|
159
171
|
return false if data.nil?
|
160
|
-
response = self.class.post("/#{id}", query: data
|
172
|
+
response = self.class.post("/#{id}", query: data)
|
161
173
|
response['success']
|
162
174
|
end
|
163
175
|
|
data/test/ad_set_test.rb
CHANGED
@@ -2,10 +2,47 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
# rake test TEST=test/ad_set_test.rb
|
4
4
|
class AdSetTest < BaseTest
|
5
|
+
def test_create
|
6
|
+
vcr do
|
7
|
+
ad_campaign = FacebookAds::AdCampaign.find('6069436026057')
|
8
|
+
ad_set = ad_campaign.create_ad_set(
|
9
|
+
name: 'Test',
|
10
|
+
promoted_object: {
|
11
|
+
pixel_id: '1472889202927380',
|
12
|
+
custom_event_type: 'PURCHASE'
|
13
|
+
},
|
14
|
+
targeting: {
|
15
|
+
age_max: 65,
|
16
|
+
age_min: 18,
|
17
|
+
app_install_state: 'not_installed',
|
18
|
+
excluded_custom_audiences: [{ "name"=>"All-Users-2016-07-28", "id"=>"6068994792257" }],
|
19
|
+
genders: [2],
|
20
|
+
geo_locations: { countries: %w(US), location_types: %w(home recent) },
|
21
|
+
locales: [24, 6],
|
22
|
+
publisher_platforms: %w(facebook instagram audience_network),
|
23
|
+
device_platforms: %w(desktop),
|
24
|
+
facebook_positions: %w(feed right_hand_column)
|
25
|
+
},
|
26
|
+
daily_budget: 1000,
|
27
|
+
optimization_goal: 'OFFSITE_CONVERSIONS'
|
28
|
+
)
|
29
|
+
assert_equal '6081945233457', ad_set.id
|
30
|
+
assert_equal '1000', ad_set.daily_budget
|
31
|
+
assert_equal 'OFFSITE_CONVERSIONS', ad_set.optimization_goal
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
5
35
|
def test_update
|
6
36
|
vcr do
|
7
37
|
ad_set = FacebookAds::AdSet.find('6078462927057')
|
8
38
|
assert ad_set.update(daily_budget: 149900)
|
9
39
|
end
|
10
40
|
end
|
41
|
+
|
42
|
+
def test_destroy
|
43
|
+
vcr do
|
44
|
+
ad_set = FacebookAds::AdSet.find('6081945233457')
|
45
|
+
assert ad_set.destroy
|
46
|
+
end
|
47
|
+
end
|
11
48
|
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://graph.facebook.com/v2.8/6069436026057?access_token=TEST_ACCESS_TOKEN&fields=id,account_id,buying_type,can_use_spend_cap,configured_status,created_time,effective_status,name,objective,start_time,stop_time,updated_time,spend_cap
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- "*/*"
|
12
|
+
Accept-Encoding:
|
13
|
+
- gzip, deflate
|
14
|
+
User-Agent:
|
15
|
+
- rest-client/2.0.0 (darwin16.3.0 x86_64) ruby/2.2.6p396
|
16
|
+
Host:
|
17
|
+
- graph.facebook.com
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Access-Control-Allow-Origin:
|
24
|
+
- "*"
|
25
|
+
Etag:
|
26
|
+
- '"3093fb2c3c70fd686df36b0d287b0e7bfb65cb68"'
|
27
|
+
Pragma:
|
28
|
+
- no-cache
|
29
|
+
Cache-Control:
|
30
|
+
- private, no-cache, no-store, must-revalidate
|
31
|
+
Facebook-Api-Version:
|
32
|
+
- v2.8
|
33
|
+
Expires:
|
34
|
+
- Sat, 01 Jan 2000 00:00:00 GMT
|
35
|
+
Content-Type:
|
36
|
+
- application/json; charset=UTF-8
|
37
|
+
X-Fb-Trace-Id:
|
38
|
+
- DUi9h6Na23I
|
39
|
+
X-Fb-Rev:
|
40
|
+
- '2769824'
|
41
|
+
Vary:
|
42
|
+
- Accept-Encoding
|
43
|
+
Content-Encoding:
|
44
|
+
- gzip
|
45
|
+
X-Fb-Debug:
|
46
|
+
- PNBIKRQfFP8ih7Pci3/yzuOwZsjTBbk/ZgYMC/sy8EgEdnMFm95vMqyVgGtzmwkw5pszlRXz1qS1vkgDPDvtHw==
|
47
|
+
Date:
|
48
|
+
- Tue, 10 Jan 2017 07:38:21 GMT
|
49
|
+
Connection:
|
50
|
+
- keep-alive
|
51
|
+
Content-Length:
|
52
|
+
- '242'
|
53
|
+
body:
|
54
|
+
encoding: ASCII-8BIT
|
55
|
+
string: !binary |-
|
56
|
+
H4sIAAAAAAAAA22OwWrDMAyGX2X4vICUpk7iW8l66KUdS7odjZMoxYM6IbYL
|
57
|
+
Zezdp2Sww+hN6Pv+X/oSthdKSJBltpGQStjm4lmYrhujC3qFCFssNwVigUVa
|
58
|
+
wMLbeLfuosN9IhZ256o5nI6874zT0ZP2E7led2YSKsyRGIxusJc4U699MCF6
|
59
|
+
jr3uzvX+ZUnNZAKTYK9LXQooEygSSBtAhZnKygRyADZpGKgL9kYPWpxZ0x/U
|
60
|
+
ehvoqRrdjWZvR+cZju3nb5CN6nR837/V/HHNhIvm8Ph0KhX+nY5T/+/JPAFk
|
61
|
+
uUE2Ua0zm98/F4f8j1MBAAA=
|
62
|
+
http_version:
|
63
|
+
recorded_at: Tue, 10 Jan 2017 07:38:21 GMT
|
64
|
+
- request:
|
65
|
+
method: post
|
66
|
+
uri: https://graph.facebook.com/v2.8/act_1051938118182807/adsets
|
67
|
+
body:
|
68
|
+
encoding: UTF-8
|
69
|
+
string: campaign_id=6069436026057&name=Test&targeting=%7B%22age_max%22%3A65%2C%22age_min%22%3A18%2C%22app_install_state%22%3A%22not_installed%22%2C%22excluded_custom_audiences%22%3A%5B%7B%22name%22%3A%22All-Users-2016-07-28%22%2C%22id%22%3A%226068994792257%22%7D%5D%2C%22genders%22%3A%5B2%5D%2C%22geo_locations%22%3A%7B%22countries%22%3A%5B%22US%22%5D%2C%22location_types%22%3A%5B%22home%22%2C%22recent%22%5D%7D%2C%22locales%22%3A%5B24%2C6%5D%2C%22publisher_platforms%22%3A%5B%22facebook%22%2C%22instagram%22%2C%22audience_network%22%5D%2C%22device_platforms%22%3A%5B%22desktop%22%5D%2C%22facebook_positions%22%3A%5B%22feed%22%2C%22right_hand_column%22%5D%7D&promoted_object=%7B%22pixel_id%22%3A%221472889202927380%22%2C%22custom_event_type%22%3A%22PURCHASE%22%7D&optimization_goal=OFFSITE_CONVERSIONS&daily_budget=1000&billing_event=IMPRESSIONS&status=ACTIVE&is_autobid=true&access_token=TEST_ACCESS_TOKEN
|
70
|
+
headers:
|
71
|
+
Accept:
|
72
|
+
- "*/*"
|
73
|
+
Accept-Encoding:
|
74
|
+
- gzip, deflate
|
75
|
+
User-Agent:
|
76
|
+
- rest-client/2.0.0 (darwin16.3.0 x86_64) ruby/2.2.6p396
|
77
|
+
Content-Length:
|
78
|
+
- '1061'
|
79
|
+
Content-Type:
|
80
|
+
- application/x-www-form-urlencoded
|
81
|
+
Host:
|
82
|
+
- graph.facebook.com
|
83
|
+
response:
|
84
|
+
status:
|
85
|
+
code: 200
|
86
|
+
message: OK
|
87
|
+
headers:
|
88
|
+
P3p:
|
89
|
+
- 'CP="Facebook does not have a P3P policy. Learn why here: http://fb.me/p3p"'
|
90
|
+
Access-Control-Allow-Origin:
|
91
|
+
- "*"
|
92
|
+
Pragma:
|
93
|
+
- no-cache
|
94
|
+
Cache-Control:
|
95
|
+
- private, no-cache, no-store, must-revalidate
|
96
|
+
Facebook-Api-Version:
|
97
|
+
- v2.8
|
98
|
+
Expires:
|
99
|
+
- Sat, 01 Jan 2000 00:00:00 GMT
|
100
|
+
Content-Type:
|
101
|
+
- application/json; charset=UTF-8
|
102
|
+
X-Fb-Trace-Id:
|
103
|
+
- AwRM00wrgYX
|
104
|
+
X-Fb-Rev:
|
105
|
+
- '2769824'
|
106
|
+
Set-Cookie:
|
107
|
+
- sW=1484033901%3AAaBh0wN0r79WkD0T; path=/; domain=.graph.facebook.com; secure
|
108
|
+
X-Fb-Debug:
|
109
|
+
- qPat9POKPd9oGXI3rw0jKoygmTYkHzHEW3Lz10stQiKAoK3uXN0J7bB2FrbNcgnoHZLfHnN0m7oXnSpa0LDK2Q==
|
110
|
+
Date:
|
111
|
+
- Tue, 10 Jan 2017 07:38:22 GMT
|
112
|
+
Connection:
|
113
|
+
- keep-alive
|
114
|
+
Content-Length:
|
115
|
+
- '22'
|
116
|
+
body:
|
117
|
+
encoding: UTF-8
|
118
|
+
string: '{"id":"6081945233457"}'
|
119
|
+
http_version:
|
120
|
+
recorded_at: Tue, 10 Jan 2017 07:38:22 GMT
|
121
|
+
- request:
|
122
|
+
method: get
|
123
|
+
uri: https://graph.facebook.com/v2.8/6081945233457?access_token=TEST_ACCESS_TOKEN&fields=id,account_id,campaign_id,name,status,configured_status,effective_status,bid_amount,billing_event,optimization_goal,pacing_type,daily_budget,budget_remaining,lifetime_budget,promoted_object,targeting,created_time,updated_time
|
124
|
+
body:
|
125
|
+
encoding: US-ASCII
|
126
|
+
string: ''
|
127
|
+
headers:
|
128
|
+
Accept:
|
129
|
+
- "*/*"
|
130
|
+
Accept-Encoding:
|
131
|
+
- gzip, deflate
|
132
|
+
User-Agent:
|
133
|
+
- rest-client/2.0.0 (darwin16.3.0 x86_64) ruby/2.2.6p396
|
134
|
+
Host:
|
135
|
+
- graph.facebook.com
|
136
|
+
response:
|
137
|
+
status:
|
138
|
+
code: 200
|
139
|
+
message: OK
|
140
|
+
headers:
|
141
|
+
Access-Control-Allow-Origin:
|
142
|
+
- "*"
|
143
|
+
Etag:
|
144
|
+
- '"0983c34785b31e38d0cf8f37ed607f5a8291d0cd"'
|
145
|
+
Pragma:
|
146
|
+
- no-cache
|
147
|
+
Cache-Control:
|
148
|
+
- private, no-cache, no-store, must-revalidate
|
149
|
+
Facebook-Api-Version:
|
150
|
+
- v2.8
|
151
|
+
Expires:
|
152
|
+
- Sat, 01 Jan 2000 00:00:00 GMT
|
153
|
+
Content-Type:
|
154
|
+
- application/json; charset=UTF-8
|
155
|
+
X-Fb-Trace-Id:
|
156
|
+
- AM3sukRLuz3
|
157
|
+
X-Fb-Rev:
|
158
|
+
- '2769824'
|
159
|
+
Vary:
|
160
|
+
- Accept-Encoding
|
161
|
+
Content-Encoding:
|
162
|
+
- gzip
|
163
|
+
X-Fb-Debug:
|
164
|
+
- wluPtKeCIEfsitUpt6Q66u1Q4wvfvEno0Nm4AvxgyjpQ7yBYG4oBOq83X8Bgjun4quG/9QYEgHrHu7fVPqHR7A==
|
165
|
+
Date:
|
166
|
+
- Tue, 10 Jan 2017 07:38:22 GMT
|
167
|
+
Connection:
|
168
|
+
- keep-alive
|
169
|
+
Content-Length:
|
170
|
+
- '578'
|
171
|
+
body:
|
172
|
+
encoding: ASCII-8BIT
|
173
|
+
string: !binary |-
|
174
|
+
H4sIAAAAAAAAA41SwW7iMBD9F59BShwICTfE0l0OpaiBXqrKMs4QvDi25Thd
|
175
|
+
uoh/37EBtau97M0z82bem+c5E1mTKcmTIi1HY5plo/GEDAgXwvTas1hMk3Fa
|
176
|
+
ZkWaFmlBiyTUBW8tl41mt+68HGV5QvMkdmveAqY30HmMOs9932E8m2+WL4vQ
|
177
|
+
bfReNr2Dmv1bhP0ehJfv8Fmbzx7Xs+X3FVvPttXiG4J2UimpGwbvoD0ilo/r
|
178
|
+
50VVLZ9WFVaN9bKVv7mXRrPGcIWIp4eHarlZsPnT6mXxfEdaLsIY/2FR8GuQ
|
179
|
+
qmvuavI2IDWX6oPt+roBH01IkkAcY+ag5VJja6iMMa/kHpAUPhsC2jrTGo9r
|
180
|
+
mt1PXIpMz8TKE6ibr6MJLYqSJrSkk6wIDaLvvGmva91UkfX2ef5jVi3IZUA8
|
181
|
+
dzg98p4Jb4C1/ESm+XhwDaQm07TAwFomNW6jVHQxjNHG33NQB59PQvU1artx
|
182
|
+
8r6WoAWg4a/n+1XkRVmOJiWlX/91ptRw24HrhjRJ82FKh0lKLmhZA7rGNA6g
|
183
|
+
MTJMGRF/oQt640k5GRnItgom3+tx15g/GOQYEAci/Ozb5YpRsUhHg/ztiwns
|
184
|
+
60ejMDhZrrswDpcM9vc7JbsDOGYV93vj2kix5wJ2xhwREQ1pHG/Dzd8MYBr8
|
185
|
+
L+OOQd8dyqzp5G0RHADRQSebg2cHPBkmjOpbHc8G3iXO+Iuwhu7ojY3bCAc8
|
186
|
+
XEQ4FpSMDk7QvmFSbmg2zYopxXcRT6239X8hL38ARmr8p8QDAAA=
|
187
|
+
http_version:
|
188
|
+
recorded_at: Tue, 10 Jan 2017 07:38:22 GMT
|
189
|
+
recorded_with: VCR 3.0.3
|
@@ -0,0 +1,124 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://graph.facebook.com/v2.8/6081945233457?access_token=TEST_ACCESS_TOKEN&fields=id,account_id,campaign_id,name,status,configured_status,effective_status,bid_amount,billing_event,optimization_goal,pacing_type,daily_budget,budget_remaining,lifetime_budget,promoted_object,targeting,created_time,updated_time
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- "*/*"
|
12
|
+
Accept-Encoding:
|
13
|
+
- gzip, deflate
|
14
|
+
User-Agent:
|
15
|
+
- rest-client/2.0.0 (darwin16.3.0 x86_64) ruby/2.2.6p396
|
16
|
+
Host:
|
17
|
+
- graph.facebook.com
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Access-Control-Allow-Origin:
|
24
|
+
- "*"
|
25
|
+
Etag:
|
26
|
+
- '"0983c34785b31e38d0cf8f37ed607f5a8291d0cd"'
|
27
|
+
Pragma:
|
28
|
+
- no-cache
|
29
|
+
Cache-Control:
|
30
|
+
- private, no-cache, no-store, must-revalidate
|
31
|
+
Facebook-Api-Version:
|
32
|
+
- v2.8
|
33
|
+
Expires:
|
34
|
+
- Sat, 01 Jan 2000 00:00:00 GMT
|
35
|
+
Content-Type:
|
36
|
+
- application/json; charset=UTF-8
|
37
|
+
X-Fb-Trace-Id:
|
38
|
+
- DBFCj3ipgSr
|
39
|
+
X-Fb-Rev:
|
40
|
+
- '2769824'
|
41
|
+
Vary:
|
42
|
+
- Accept-Encoding
|
43
|
+
Content-Encoding:
|
44
|
+
- gzip
|
45
|
+
X-Fb-Debug:
|
46
|
+
- AZ7nHqabtntJxydYIChMjiwtsfqoRPKiLQ8/IBmYKniFQ+E+cG66ht6U2DLsiAYEaBZVcKxdxTTjZogNXlGGEQ==
|
47
|
+
Date:
|
48
|
+
- Tue, 10 Jan 2017 07:39:49 GMT
|
49
|
+
Connection:
|
50
|
+
- keep-alive
|
51
|
+
Content-Length:
|
52
|
+
- '578'
|
53
|
+
body:
|
54
|
+
encoding: ASCII-8BIT
|
55
|
+
string: !binary |-
|
56
|
+
H4sIAAAAAAAAA41SwW7iMBD9F59BShwICTfE0l0OpaiBXqrKMs4QvDi25Thd
|
57
|
+
uoh/37EBtau97M0z82bem+c5E1mTKcmTIi1HY5plo/GEDAgXwvTas1hMk3Fa
|
58
|
+
ZkWaFmlBiyTUBW8tl41mt+68HGV5QvMkdmveAqY30HmMOs9932E8m2+WL4vQ
|
59
|
+
bfReNr2Dmv1bhP0ehJfv8Fmbzx7Xs+X3FVvPttXiG4J2UimpGwbvoD0ilo/r
|
60
|
+
50VVLZ9WFVaN9bKVv7mXRrPGcIWIp4eHarlZsPnT6mXxfEdaLsIY/2FR8GuQ
|
61
|
+
qmvuavI2IDWX6oPt+roBH01IkkAcY+ag5VJja6iMMa/kHpAUPhsC2jrTGo9r
|
62
|
+
mt1PXIpMz8TKE6ibr6MJLYqSJrSkk6wIDaLvvGmva91UkfX2ef5jVi3IZUA8
|
63
|
+
dzg98p4Jb4C1/ESm+XhwDaQm07TAwFomNW6jVHQxjNHG33NQB59PQvU1artx
|
64
|
+
8r6WoAWg4a/n+1XkRVmOJiWlX/91ptRw24HrhjRJ82FKh0lKLmhZA7rGNA6g
|
65
|
+
MTJMGRF/oQt640k5GRnItgom3+tx15g/GOQYEAci/Ozb5YpRsUhHg/ztiwns
|
66
|
+
60ejMDhZrrswDpcM9vc7JbsDOGYV93vj2kix5wJ2xhwREQ1pHG/Dzd8MYBr8
|
67
|
+
L+OOQd8dyqzp5G0RHADRQSebg2cHPBkmjOpbHc8G3iXO+Iuwhu7ojY3bCAc8
|
68
|
+
XEQ4FpSMDk7QvmFSbmg2zYopxXcRT6239X8hL38ARmr8p8QDAAA=
|
69
|
+
http_version:
|
70
|
+
recorded_at: Tue, 10 Jan 2017 07:39:49 GMT
|
71
|
+
- request:
|
72
|
+
method: delete
|
73
|
+
uri: https://graph.facebook.com/v2.8/6081945233457?access_token=TEST_ACCESS_TOKEN
|
74
|
+
body:
|
75
|
+
encoding: US-ASCII
|
76
|
+
string: ''
|
77
|
+
headers:
|
78
|
+
Accept:
|
79
|
+
- "*/*"
|
80
|
+
Accept-Encoding:
|
81
|
+
- gzip, deflate
|
82
|
+
User-Agent:
|
83
|
+
- rest-client/2.0.0 (darwin16.3.0 x86_64) ruby/2.2.6p396
|
84
|
+
Host:
|
85
|
+
- graph.facebook.com
|
86
|
+
response:
|
87
|
+
status:
|
88
|
+
code: 200
|
89
|
+
message: OK
|
90
|
+
headers:
|
91
|
+
P3p:
|
92
|
+
- 'CP="Facebook does not have a P3P policy. Learn why here: http://fb.me/p3p"'
|
93
|
+
Access-Control-Allow-Origin:
|
94
|
+
- "*"
|
95
|
+
Pragma:
|
96
|
+
- no-cache
|
97
|
+
Cache-Control:
|
98
|
+
- private, no-cache, no-store, must-revalidate
|
99
|
+
Facebook-Api-Version:
|
100
|
+
- v2.8
|
101
|
+
Expires:
|
102
|
+
- Sat, 01 Jan 2000 00:00:00 GMT
|
103
|
+
Content-Type:
|
104
|
+
- application/json; charset=UTF-8
|
105
|
+
X-Fb-Trace-Id:
|
106
|
+
- AKVHkQrgYjj
|
107
|
+
X-Fb-Rev:
|
108
|
+
- '2769824'
|
109
|
+
Set-Cookie:
|
110
|
+
- sW=1484033990%3AAaAd4deeT2KlMMk2; path=/; domain=.graph.facebook.com; secure
|
111
|
+
X-Fb-Debug:
|
112
|
+
- 4NAqA+2lkZSqcoAQnNc09Kgsxu7YkAPWvcdh8WQiVpcotRf7ov5BnzAWr5qnXYVGxmKcQemTl0V9LTaREiSWiQ==
|
113
|
+
Date:
|
114
|
+
- Tue, 10 Jan 2017 07:39:50 GMT
|
115
|
+
Connection:
|
116
|
+
- keep-alive
|
117
|
+
Content-Length:
|
118
|
+
- '16'
|
119
|
+
body:
|
120
|
+
encoding: UTF-8
|
121
|
+
string: '{"success":true}'
|
122
|
+
http_version:
|
123
|
+
recorded_at: Tue, 10 Jan 2017 07:39:50 GMT
|
124
|
+
recorded_with: VCR 3.0.3
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: facebook_ads
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Estreich
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- lib/facebook_ads/ad_audience.rb
|
63
63
|
- lib/facebook_ads/ad_campaign.rb
|
64
64
|
- lib/facebook_ads/ad_creative.rb
|
65
|
+
- lib/facebook_ads/ad_exception.rb
|
65
66
|
- lib/facebook_ads/ad_image.rb
|
66
67
|
- lib/facebook_ads/ad_insight.rb
|
67
68
|
- lib/facebook_ads/ad_product.rb
|
@@ -95,6 +96,8 @@ files:
|
|
95
96
|
- test/vcr_cassettes/AdProductCatalogTest-test_all.yml
|
96
97
|
- test/vcr_cassettes/AdProductCatalogTest-test_create.yml
|
97
98
|
- test/vcr_cassettes/AdProductTest-test_list.yml
|
99
|
+
- test/vcr_cassettes/AdSetTest-test_create.yml
|
100
|
+
- test/vcr_cassettes/AdSetTest-test_destroy.yml
|
98
101
|
- test/vcr_cassettes/AdSetTest-test_update.yml
|
99
102
|
homepage: https://github.com/cte/facebook-ruby-ads-sdk
|
100
103
|
licenses:
|