facebook_ads 0.6.6 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.circleci/config.yml +27 -0
- data/.rubocop.yml +11 -10
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +30 -9
- data/Gemfile +2 -2
- data/LICENSE.md +1 -1
- data/README.md +4 -5
- data/bin/facebook_ads_console +1 -1
- data/facebook_ads.gemspec +4 -5
- data/lib/facebook_ads.rb +71 -5
- data/lib/facebook_ads/ad.rb +2 -2
- data/lib/facebook_ads/ad_account.rb +18 -23
- data/lib/facebook_ads/ad_audience.rb +7 -7
- data/lib/facebook_ads/ad_campaign.rb +7 -7
- data/lib/facebook_ads/ad_creative.rb +3 -3
- data/lib/facebook_ads/ad_exception.rb +1 -0
- data/lib/facebook_ads/ad_image.rb +2 -2
- data/lib/facebook_ads/ad_insight.rb +5 -5
- data/lib/facebook_ads/ad_set.rb +5 -2
- data/lib/facebook_ads/ad_targeting.rb +2 -4
- data/lib/facebook_ads/base.rb +9 -16
- data/spec/facebook_ads/ad_account_spec.rb +16 -13
- data/spec/facebook_ads/ad_campaign_spec.rb +0 -3
- data/spec/facebook_ads/facebook_ads_spec.rb +50 -10
- data/spec/fixtures/cassettes/FacebookAds/_stubbornly_get/executes_the_request_for_the_provided_url.yml +63 -0
- data/spec/fixtures/cassettes/FacebookAds_AdAccount/_ad_creatives/lists_creatives.yml +1 -1
- data/spec/fixtures/cassettes/FacebookAds_AdAccount/_ad_sets/lists_ad_sets.yml +1 -1
- data/spec/fixtures/cassettes/FacebookAds_AdAccount/_create_ad_creative/creates_carousel_ad_creative.yml +7 -7
- data/spec/fixtures/cassettes/FacebookAds_AdCampaign/_create_ad_set/creates_valid_ad_set.yml +3 -3
- data/spec/spec_helper.rb +1 -4
- data/spec/support/rest_client.rb +1 -1
- metadata +21 -39
- data/.coveralls.yml +0 -1
- data/.travis.yml +0 -7
- data/spec/facebook_ads/ad_creative_spec.rb +0 -6
- data/spec/facebook_ads/ad_image_spec.rb +0 -6
- data/spec/facebook_ads/ad_insight_spec.rb +0 -6
- data/spec/facebook_ads/ad_product_catalog_spec.rb +0 -29
- data/spec/facebook_ads/ad_product_feed_spec.rb +0 -6
- data/spec/facebook_ads/ad_product_set_spec.rb +0 -6
- data/spec/facebook_ads/ad_product_spec.rb +0 -23
- data/spec/facebook_ads/ad_set_activity_spec.rb +0 -6
- data/spec/facebook_ads/ad_set_spec.rb +0 -49
- data/spec/facebook_ads/ad_spec.rb +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5a7277800ac2a81f155ef378e2f5a0b78a85cf00c284ccb18c521b0288d6d467
|
4
|
+
data.tar.gz: 603886d3c551084d3b317fa18a0f55a9992113a7a29ae78bd8036490d56bd18c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c943be4095453ed6ef0da92ec2c8b1e542c92e0f10d898c958855f593e857c769697a36b0d0a6b168f8fa6ef7c47f616b84418807c0916b5dda447665130751b
|
7
|
+
data.tar.gz: 0ccc1ad73365c2791e1a58329265964d18c6af52fb1ffe85d3d95314971f3802ca716a2d6ca5403b7874882922ca2f2fe55c53104d9199f9e91ef1618489ad1c
|
@@ -0,0 +1,27 @@
|
|
1
|
+
version: 2.1
|
2
|
+
|
3
|
+
orbs:
|
4
|
+
aws-cli: circleci/aws-cli@1.2.1
|
5
|
+
ruby: circleci/ruby@1.1.0
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
test:
|
9
|
+
docker:
|
10
|
+
- image: circleci/ruby:2.7.0-node
|
11
|
+
executor: ruby/default
|
12
|
+
working_directory: ~/repo
|
13
|
+
environment:
|
14
|
+
APP_BUNDLER_VERSION: '2.1.2'
|
15
|
+
steps:
|
16
|
+
- checkout:
|
17
|
+
path: ~/repo
|
18
|
+
- ruby/install-deps:
|
19
|
+
with-cache: false
|
20
|
+
- ruby/rspec-test
|
21
|
+
- ruby/rubocop-check
|
22
|
+
|
23
|
+
workflows:
|
24
|
+
version: 2
|
25
|
+
build:
|
26
|
+
jobs:
|
27
|
+
- test
|
data/.rubocop.yml
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
AllCops:
|
2
|
-
TargetRubyVersion: 2.
|
2
|
+
TargetRubyVersion: 2.5
|
3
|
+
NewCops: enable
|
3
4
|
|
4
5
|
Metrics/AbcSize:
|
5
6
|
Enabled: false
|
@@ -7,9 +8,6 @@ Metrics/CyclomaticComplexity:
|
|
7
8
|
Enabled: false
|
8
9
|
Metrics/PerceivedComplexity:
|
9
10
|
Enabled: false
|
10
|
-
|
11
|
-
Metrics/LineLength:
|
12
|
-
Enabled: false
|
13
11
|
Metrics/ClassLength:
|
14
12
|
Enabled: false
|
15
13
|
Metrics/MethodLength:
|
@@ -19,15 +17,18 @@ Metrics/BlockLength:
|
|
19
17
|
Metrics/ParameterLists:
|
20
18
|
Enabled: false
|
21
19
|
|
22
|
-
|
20
|
+
Layout/ElseAlignment:
|
23
21
|
Enabled: false
|
24
|
-
|
25
|
-
Layout/IndentationWidth:
|
22
|
+
Layout/EndAlignment:
|
26
23
|
Enabled: false
|
27
|
-
Layout/
|
24
|
+
Layout/RescueEnsureAlignment:
|
25
|
+
Enabled: false
|
26
|
+
Layout/EmptyLineAfterGuardClause:
|
27
|
+
Enabled: false
|
28
|
+
Layout/LineLength:
|
29
|
+
Enabled: false
|
30
|
+
Layout/IndentationWidth:
|
28
31
|
Enabled: false
|
29
32
|
|
30
33
|
Style/Documentation:
|
31
34
|
Enabled: false
|
32
|
-
Style/GuardClause:
|
33
|
-
Enabled: false
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
facebook-ruby-ads-sdk
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.7.0
|
data/CHANGELOG.md
CHANGED
@@ -1,27 +1,48 @@
|
|
1
|
+
## 0.7.0 (2020-09-29)
|
2
|
+
- Add stubborn network call helpers.
|
3
|
+
- Update default version to v7.0.
|
4
|
+
- Switch from TravisCI to CircleCI.
|
5
|
+
- Remove coveralls.
|
6
|
+
- Require ruby 2.5+.
|
7
|
+
- Update Rubocop & fix warnings.
|
8
|
+
|
9
|
+
## 0.6.11 (2020-02-28)
|
10
|
+
- Fixed memoization in `FacebookAds::Ad`.
|
11
|
+
|
12
|
+
## 0.6.10 (2019-05-06)
|
13
|
+
- Set default version to 3.2.
|
14
|
+
- Removed `relevance_score` from the list of default fields in `AdInsight`.
|
15
|
+
|
16
|
+
## 0.6.9 (2019-03-25)
|
17
|
+
- Added the following fields to `AdCreative`: `product_set_id` and `url_tags`. (#37, @cte)
|
18
|
+
|
19
|
+
## 0.6.7 (2019-03-07)
|
20
|
+
- Added the following fields to `AdSet`: `attribution_spec`, `start_time` and `end_time`. (#36, @cte)
|
21
|
+
|
1
22
|
## 0.6.6 (2018-11-29)
|
2
|
-
- Added ability to pass date range when fetching `ad_set_activities`.
|
23
|
+
- Added ability to pass date range when fetching `ad_set_activities`. (#34, @amosharrafa)
|
3
24
|
|
4
25
|
## 0.6.5 (2018-11-26)
|
5
|
-
- Expose `ad_set_activities` for `ad_sets`.
|
26
|
+
- Expose `ad_set_activities` for `ad_sets`. (#31, @amosharrafa)
|
6
27
|
|
7
28
|
## 0.6.4 (2018-10-03)
|
8
|
-
- Expose `budget_remaining`, `daily_budget`, `lifetime_budget` for
|
29
|
+
- Expose `budget_remaining`, `daily_budget`, `lifetime_budget` for the `AdCampaign` object. You now have the option to set the budget ad the campaign level instead of the ad set level.
|
9
30
|
|
10
31
|
## 0.6.3 (2018-05-17)
|
11
|
-
- Replaced deprecated `is_autobid` with new `bid_strategy` field
|
32
|
+
- Replaced deprecated `is_autobid` with new `bid_strategy` field.
|
12
33
|
|
13
34
|
## 0.6.2 (2018-05-08)
|
14
|
-
- Set Product Catalog path to `/owned_product_catalogs` for API v2.11 compatibility
|
35
|
+
- Set Product Catalog path to `/owned_product_catalogs` for API v2.11 compatibility.
|
15
36
|
|
16
37
|
## 0.4 (2017-07-25)
|
17
|
-
- Added ability to pass `bid_amount` parameter when creating ad sets
|
18
|
-
- Ad Set `is_autobid` parameter now defaults to `nil` rather than `true
|
38
|
+
- Added ability to pass `bid_amount` parameter when creating ad sets.
|
39
|
+
- Ad Set `is_autobid` parameter now defaults to `nil` rather than `true`.
|
19
40
|
|
20
41
|
## 0.3 (2017-07-24)
|
21
|
-
- Added ability to pass `app_link` parameter with ad creatives
|
42
|
+
- Added ability to pass `app_link` parameter with ad creatives.
|
22
43
|
|
23
44
|
## 0.2 (2017-07-20)
|
24
|
-
- Added ability to configure App Secret to be included with API requests
|
45
|
+
- Added ability to configure App Secret to be included with API requests.
|
25
46
|
|
26
47
|
## 0.1.12 (2017-05-25)
|
27
48
|
- Added complete set of ad campaign objectives. (#9, @cte)
|
data/Gemfile
CHANGED
@@ -7,14 +7,14 @@ group :development, :test do
|
|
7
7
|
gem 'awesome_print'
|
8
8
|
gem 'pry'
|
9
9
|
gem 'rake'
|
10
|
-
gem 'rubocop'
|
10
|
+
gem 'rubocop'
|
11
11
|
end
|
12
12
|
|
13
13
|
group :test do
|
14
14
|
gem 'approvals'
|
15
|
-
gem 'coveralls', require: false
|
16
15
|
gem 'multi_json'
|
17
16
|
gem 'rspec'
|
17
|
+
gem 'rspec_junit_formatter'
|
18
18
|
gem 'vcr'
|
19
19
|
gem 'webmock'
|
20
20
|
end
|
data/LICENSE.md
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
[![Gem Version](https://badge.fury.io/rb/facebook_ads.svg)](https://badge.fury.io/rb/facebook_ads)
|
2
|
-
[![Build Status](https://
|
3
|
-
[![Coverage Status](https://coveralls.io/repos/github/tophatter/facebook-ruby-ads-sdk/badge.svg?branch=master)](https://coveralls.io/github/tophatter/facebook-ruby-ads-sdk?branch=master)
|
2
|
+
[![Build Status](https://circleci.com/gh/tophatter/facebook-ruby-ads-sdk.svg?style=svg&circle-token=3fa538bc2aece310fdc07b82ce77d117758afb02)](https://circleci.com/gh/tophatter/facebook-ruby-ads-sdk)
|
4
3
|
|
5
4
|
# [Facebook Marketing API](https://developers.facebook.com/docs/marketing-apis) SDK for Ruby
|
6
5
|
|
@@ -17,7 +16,7 @@ gem install facebook_ads
|
|
17
16
|
Or, add the following to your Gemfile:
|
18
17
|
|
19
18
|
```ruby
|
20
|
-
gem 'facebook_ads', '~> 0.
|
19
|
+
gem 'facebook_ads', '~> 0.7'
|
21
20
|
```
|
22
21
|
|
23
22
|
## Permissions
|
@@ -36,10 +35,10 @@ FacebookAds.app_secret = '[YOUR_APP_SECRET]'
|
|
36
35
|
|
37
36
|
## API Version
|
38
37
|
|
39
|
-
This gem currently
|
38
|
+
This gem currently defaults v3.2 of the Marketing API. You can change the version as desired with the following:
|
40
39
|
|
41
40
|
```ruby
|
42
|
-
FacebookAds.base_uri = 'https://graph.facebook.com/
|
41
|
+
FacebookAds.base_uri = 'https://graph.facebook.com/[desired-version-here]'
|
43
42
|
```
|
44
43
|
|
45
44
|
## Console
|
data/bin/facebook_ads_console
CHANGED
@@ -19,7 +19,7 @@ rescue Errno::ENOENT
|
|
19
19
|
puts 'Create a test_business_id file and add your Business ID to it.'
|
20
20
|
end
|
21
21
|
|
22
|
-
FacebookAds.logger = Logger.new(
|
22
|
+
FacebookAds.logger = Logger.new($stdout)
|
23
23
|
FacebookAds.logger.level = Logger::Severity::DEBUG
|
24
24
|
|
25
25
|
require 'awesome_print'
|
data/facebook_ads.gemspec
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
# To publish the next version:
|
5
4
|
# gem build facebook_ads.gemspec
|
6
|
-
# gem push facebook_ads-0.
|
5
|
+
# gem push facebook_ads-0.7.0.gem
|
7
6
|
Gem::Specification.new do |s|
|
8
7
|
s.name = 'facebook_ads'
|
9
|
-
s.version = '0.
|
8
|
+
s.version = '0.7.0'
|
10
9
|
s.platform = Gem::Platform::RUBY
|
11
10
|
s.licenses = ['MIT']
|
12
11
|
s.authors = ['Chris Estreich']
|
@@ -17,10 +16,10 @@ Gem::Specification.new do |s|
|
|
17
16
|
|
18
17
|
s.extra_rdoc_files = ['README.md']
|
19
18
|
|
20
|
-
s.required_ruby_version = '
|
19
|
+
s.required_ruby_version = '>= 2.5'
|
21
20
|
|
21
|
+
s.add_dependency 'hashie'
|
22
22
|
s.add_dependency 'rest-client', '>= 1.6'
|
23
|
-
s.add_dependency 'hashie', '~> 3.4'
|
24
23
|
|
25
24
|
s.files = `git ls-files`.split("\n")
|
26
25
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/lib/facebook_ads.rb
CHANGED
@@ -9,10 +9,31 @@ require 'openssl'
|
|
9
9
|
|
10
10
|
# Internal requires.
|
11
11
|
require 'facebook_ads/base'
|
12
|
-
|
12
|
+
require 'facebook_ads/account'
|
13
|
+
require 'facebook_ads/ad_account'
|
14
|
+
require 'facebook_ads/ad_audience'
|
15
|
+
require 'facebook_ads/ad_campaign'
|
16
|
+
require 'facebook_ads/ad_creative'
|
17
|
+
require 'facebook_ads/ad_exception'
|
18
|
+
require 'facebook_ads/ad_image'
|
19
|
+
require 'facebook_ads/ad_insight'
|
20
|
+
require 'facebook_ads/ad_product_catalog'
|
21
|
+
require 'facebook_ads/ad_product_feed'
|
22
|
+
require 'facebook_ads/ad_product'
|
23
|
+
require 'facebook_ads/ad_set_activity'
|
24
|
+
require 'facebook_ads/ad_set'
|
25
|
+
require 'facebook_ads/ad_targeting'
|
26
|
+
require 'facebook_ads/ad_user'
|
27
|
+
require 'facebook_ads/ad'
|
28
|
+
require 'facebook_ads/advertisable_application'
|
13
29
|
|
14
30
|
# The primary namespace for this gem.
|
15
31
|
module FacebookAds
|
32
|
+
REQUEST_HEADERS = { accept: :json, accept_encoding: :identity }.freeze
|
33
|
+
RETRYABLE_ERRORS = [RestClient::ExceptionWithResponse, Errno::ECONNRESET, Errno::ECONNREFUSED].freeze
|
34
|
+
RETRY_LIMIT = 10
|
35
|
+
RECOVERABLE_CODES = [1, 2, 2601].freeze
|
36
|
+
|
16
37
|
def self.logger=(logger)
|
17
38
|
@logger = logger
|
18
39
|
end
|
@@ -31,17 +52,16 @@ module FacebookAds
|
|
31
52
|
end
|
32
53
|
|
33
54
|
def self.base_uri
|
34
|
-
@base_uri
|
35
|
-
@base_uri
|
55
|
+
@base_uri ||= "https://graph.facebook.com/v#{api_version}"
|
36
56
|
end
|
37
57
|
|
38
58
|
def self.api_version=(api_version)
|
39
59
|
@api_version = api_version
|
60
|
+
@base_uri = nil
|
40
61
|
end
|
41
62
|
|
42
63
|
def self.api_version
|
43
|
-
@api_version
|
44
|
-
@api_version
|
64
|
+
@api_version ||= '7.0'
|
45
65
|
end
|
46
66
|
|
47
67
|
def self.access_token=(access_token)
|
@@ -71,4 +91,50 @@ module FacebookAds
|
|
71
91
|
def self.business_id
|
72
92
|
@business_id
|
73
93
|
end
|
94
|
+
|
95
|
+
# Stubborn network calls.
|
96
|
+
|
97
|
+
def self.stubbornly(retry_limit: RETRY_LIMIT, recoverable_codes: RECOVERABLE_CODES, debug: false)
|
98
|
+
raise ArgumentError unless block_given?
|
99
|
+
|
100
|
+
response = nil
|
101
|
+
retry_count = 0
|
102
|
+
|
103
|
+
loop do
|
104
|
+
response = yield
|
105
|
+
break
|
106
|
+
rescue *RETRYABLE_ERRORS => e
|
107
|
+
if e.is_a?(RestClient::ExceptionWithResponse)
|
108
|
+
error = begin
|
109
|
+
JSON.parse(e.response)
|
110
|
+
rescue JSON::ParserError
|
111
|
+
nil
|
112
|
+
end
|
113
|
+
|
114
|
+
code = error&.[]('code')
|
115
|
+
raise e if code && !recoverable_codes.include?(code)
|
116
|
+
end
|
117
|
+
|
118
|
+
raise e if retry_count >= retry_limit
|
119
|
+
|
120
|
+
retry_count += 1
|
121
|
+
wait = (retry_count**2) + 15 + (rand(15) * (retry_count + 1))
|
122
|
+
puts "retry ##{retry_count} will start in #{wait}s" if debug
|
123
|
+
sleep wait
|
124
|
+
end
|
125
|
+
|
126
|
+
response
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.stubbornly_get(url, retry_limit: RETRY_LIMIT, recoverable_codes: RECOVERABLE_CODES, debug: false)
|
130
|
+
stubbornly(retry_limit: retry_limit, recoverable_codes: recoverable_codes, debug: debug) do
|
131
|
+
RestClient.get(url, REQUEST_HEADERS)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.stubbornly_post(url, payload, retry_limit: RETRY_LIMIT, recoverable_codes: RECOVERABLE_CODES, debug: false)
|
136
|
+
stubbornly(retry_limit: retry_limit, recoverable_codes: recoverable_codes, debug: debug) do
|
137
|
+
RestClient.post(url, payload, REQUEST_HEADERS)
|
138
|
+
end
|
139
|
+
end
|
74
140
|
end
|
data/lib/facebook_ads/ad.rb
CHANGED
@@ -10,13 +10,13 @@ module FacebookAds
|
|
10
10
|
# belongs_to ad_account
|
11
11
|
|
12
12
|
def ad_account
|
13
|
-
@
|
13
|
+
@ad_account ||= AdAccount.find(account_id)
|
14
14
|
end
|
15
15
|
|
16
16
|
# belongs_to ad_campaign
|
17
17
|
|
18
18
|
def ad_campaign
|
19
|
-
@
|
19
|
+
@ad_campaign ||= AdCampaign.find(campaign_id)
|
20
20
|
end
|
21
21
|
|
22
22
|
# belongs_to ad_set
|
@@ -30,15 +30,15 @@ module FacebookAds
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def create_ad_campaign(name:, objective:, status: 'ACTIVE')
|
33
|
-
raise
|
34
|
-
raise
|
33
|
+
raise ArgumentError, "Objective must be one of: #{AdCampaign::OBJECTIVES.join(', ')}" unless AdCampaign::OBJECTIVES.include?(objective)
|
34
|
+
raise ArgumentError, "Status must be one of: #{AdCampaign::STATUSES.join(', ')}" unless AdCampaign::STATUSES.include?(status)
|
35
35
|
query = { name: name, objective: objective, status: status }
|
36
36
|
result = AdCampaign.post("/#{id}/campaigns", query: query)
|
37
37
|
AdCampaign.find(result['id'])
|
38
38
|
end
|
39
39
|
|
40
40
|
def create_dynamic_ad_campaign(name:, product_catalog_id:, status: 'ACTIVE')
|
41
|
-
raise
|
41
|
+
raise ArgumentError, "Status must be one of: #{AdCampaign::STATUSES.join(', ')}" unless AdCampaign::STATUSES.include?(status)
|
42
42
|
query = { name: name, objective: 'PRODUCT_CATALOG_SALES', status: status, promoted_object: { product_catalog_id: product_catalog_id } }
|
43
43
|
result = AdCampaign.post("/#{id}/campaigns", query: query)
|
44
44
|
AdCampaign.find(result['id'])
|
@@ -73,7 +73,7 @@ module FacebookAds
|
|
73
73
|
end.to_h
|
74
74
|
|
75
75
|
response = AdImage.post("/#{id}/adimages", query: files)
|
76
|
-
files.
|
76
|
+
files.each_value { |file| File.delete(file.path) }
|
77
77
|
!response['images'].nil? ? ad_images(hashes: response['images'].map { |_key, hash| hash['hash'] }) : []
|
78
78
|
end
|
79
79
|
|
@@ -84,8 +84,9 @@ module FacebookAds
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def create_ad_creative(creative, creative_type: nil, carousel: false)
|
87
|
-
# Support old deprecated carousel param
|
87
|
+
# Support old deprecated carousel param.
|
88
88
|
return create_carousel_ad_creative(creative) if carousel
|
89
|
+
|
89
90
|
case creative_type
|
90
91
|
when 'carousel'
|
91
92
|
create_carousel_ad_creative(creative)
|
@@ -127,14 +128,11 @@ module FacebookAds
|
|
127
128
|
end
|
128
129
|
|
129
130
|
def reach_estimate(targeting:, optimization_goal:, currency: 'USD')
|
130
|
-
raise
|
131
|
+
raise ArgumentError, "Optimization goal must be one of: #{AdSet::OPTIMIZATION_GOALS.join(', ')}" unless AdSet::OPTIMIZATION_GOALS.include?(optimization_goal)
|
131
132
|
|
132
133
|
if targeting.is_a?(AdTargeting)
|
133
|
-
|
134
|
-
|
135
|
-
else
|
136
|
-
raise Exception, 'The provided targeting spec is not valid.'
|
137
|
-
end
|
134
|
+
raise ArgumentError, 'The provided targeting spec is not valid.' unless targeting.validate!
|
135
|
+
targeting = targeting.to_hash
|
138
136
|
end
|
139
137
|
|
140
138
|
query = {
|
@@ -147,14 +145,11 @@ module FacebookAds
|
|
147
145
|
end
|
148
146
|
|
149
147
|
def delivery_estimate(targeting:, optimization_goal:, currency: 'USD')
|
150
|
-
raise
|
148
|
+
raise ArgumentError, "Optimization goal must be one of: #{AdSet::OPTIMIZATION_GOALS.join(', ')}" unless AdSet::OPTIMIZATION_GOALS.include?(optimization_goal)
|
151
149
|
|
152
150
|
if targeting.is_a?(AdTargeting)
|
153
|
-
|
154
|
-
|
155
|
-
else
|
156
|
-
raise Exception, 'The provided targeting spec is not valid.'
|
157
|
-
end
|
151
|
+
raise ArgumentError, 'The provided targeting spec is not valid.' unless targeting.validate!
|
152
|
+
targeting = targeting.to_hash
|
158
153
|
end
|
159
154
|
|
160
155
|
query = {
|
@@ -172,12 +167,12 @@ module FacebookAds
|
|
172
167
|
required = %i[name page_id link message assets call_to_action_type multi_share_optimized multi_share_end_card]
|
173
168
|
|
174
169
|
unless (keys = required - creative.keys).length.zero?
|
175
|
-
raise
|
170
|
+
raise ArgumentError, "Creative is missing the following: #{keys.join(', ')}"
|
176
171
|
end
|
177
172
|
|
178
|
-
raise
|
173
|
+
raise ArgumentError, "Creative call_to_action_type must be one of: #{AdCreative::CALL_TO_ACTION_TYPES.join(', ')}" unless AdCreative::CALL_TO_ACTION_TYPES.include?(creative[:call_to_action_type])
|
179
174
|
|
180
|
-
query = if creative[:product_set_id]
|
175
|
+
query = if creative[:product_set_id]
|
181
176
|
AdCreative.product_set(
|
182
177
|
name: creative[:name],
|
183
178
|
page_id: creative[:page_id],
|
@@ -199,10 +194,10 @@ module FacebookAds
|
|
199
194
|
required = %i[name page_id message link link_title image_hash call_to_action_type]
|
200
195
|
|
201
196
|
unless (keys = required - creative.keys).length.zero?
|
202
|
-
raise
|
197
|
+
raise ArgumentError, "Creative is missing the following: #{keys.join(', ')}"
|
203
198
|
end
|
204
199
|
|
205
|
-
raise
|
200
|
+
raise ArgumentError, "Creative call_to_action_type must be one of: #{AdCreative::CALL_TO_ACTION_TYPES.join(', ')}" unless AdCreative::CALL_TO_ACTION_TYPES.include?(creative[:call_to_action_type])
|
206
201
|
query = AdCreative.photo(creative)
|
207
202
|
result = AdCreative.post("/#{id}/adcreatives", query: query)
|
208
203
|
AdCreative.find(result['id'])
|
@@ -212,7 +207,7 @@ module FacebookAds
|
|
212
207
|
required = %i[name title body object_url link_url image_hash page_id]
|
213
208
|
|
214
209
|
unless (keys = required - creative.keys).length.zero?
|
215
|
-
raise
|
210
|
+
raise ArgumentError, "Creative is missing the following: #{keys.join(', ')}"
|
216
211
|
end
|
217
212
|
|
218
213
|
query = AdCreative.link(creative)
|