facebook_ads 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.travis.yml +8 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +129 -0
- data/README.markdown +380 -0
- data/bin/console +13 -0
- data/facebook_ads.gemspec +26 -0
- data/lib/facebook_ads.rb +46 -0
- data/lib/facebook_ads/ad.rb +34 -0
- data/lib/facebook_ads/ad_account.rb +126 -0
- data/lib/facebook_ads/ad_campaign.rb +54 -0
- data/lib/facebook_ads/ad_creative.rb +66 -0
- data/lib/facebook_ads/ad_image.rb +28 -0
- data/lib/facebook_ads/ad_insight.rb +24 -0
- data/lib/facebook_ads/ad_set.rb +35 -0
- data/lib/facebook_ads/ad_targeting.rb +61 -0
- data/lib/facebook_ads/base.rb +151 -0
- data/spec/ad_account_spec.rb +78 -0
- data/spec/ad_campaign_spec.rb +13 -0
- data/spec/ad_creative_spec.rb +14 -0
- data/spec/ad_image_spec.rb +11 -0
- data/spec/ad_insight_spec.rb +11 -0
- data/spec/ad_set_spec.rb +13 -0
- data/spec/ad_spec.rb +13 -0
- data/spec/ad_targeting_spec.rb +4 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/fixtures.sh +17 -0
- data/spec/support/fixtures/6057330925170.json +1 -0
- data/spec/support/fixtures/6057810634370.json +1 -0
- data/spec/support/fixtures/6057810946970.json +1 -0
- data/spec/support/fixtures/6057824295570.json +1 -0
- data/spec/support/fixtures/act_861827983860489.json +1 -0
- data/spec/support/fixtures/act_861827983860489/adcreatives.json +1 -0
- data/spec/support/fixtures/act_861827983860489/adimages.json +1 -0
- data/spec/support/fixtures/act_861827983860489/ads.json +1 -0
- data/spec/support/fixtures/act_861827983860489/adsets.json +1 -0
- data/spec/support/fixtures/act_861827983860489/campaigns.json +1 -0
- data/spec/support/fixtures/me/adaccounts.json +1 -0
- data/spec/support/rack_facebook.rb +22 -0
- metadata +127 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 54f327543c28ab824b5defb8dfedaa8559579c8c
|
4
|
+
data.tar.gz: f38f4804345dcd76a557caee36f32dd290b24cf2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 99a0f3b2ef4e464b0a8ed19a632359031a5b25f4aa6e7f7e322741ea7e033bfc93636d7b8be1fa01f69d9bdbaa90dee2335f63166fe66d4c81990ba90fdb4889
|
7
|
+
data.tar.gz: 9dcee742fa347d78707f29fc3318b95eb2df13efe8c7d01b98c10b0be0e0f26902b8a1aa4e89e6f56293a16782ce141f16c32bcac02acb9519dbba10a42a8f74
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
gemspec
|
3
|
+
|
4
|
+
group :development do
|
5
|
+
gem 'bundler', '~> 1.7'
|
6
|
+
gem 'rake', '~> 10.0'
|
7
|
+
gem 'pry', '~> 0.10'
|
8
|
+
gem 'awesome_print', '~> 1.7'
|
9
|
+
end
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem 'rspec', '~> 3.4'
|
13
|
+
gem 'webmock', '~> 2.1'
|
14
|
+
gem 'sinatra', '~> 1.4'
|
15
|
+
gem 'coveralls', require: false
|
16
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
facebook_ads (0.1.5)
|
5
|
+
activesupport (~> 4.2)
|
6
|
+
hashie (~> 3.4)
|
7
|
+
httmultiparty (~> 0.3)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
activesupport (4.2.7.1)
|
13
|
+
i18n (~> 0.7)
|
14
|
+
json (~> 1.7, >= 1.7.7)
|
15
|
+
minitest (~> 5.1)
|
16
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
17
|
+
tzinfo (~> 1.1)
|
18
|
+
addressable (2.4.0)
|
19
|
+
awesome_print (1.7.0)
|
20
|
+
coderay (1.1.1)
|
21
|
+
coveralls (0.8.10)
|
22
|
+
json (~> 1.8)
|
23
|
+
rest-client (>= 1.6.8, < 2)
|
24
|
+
simplecov (~> 0.11.0)
|
25
|
+
term-ansicolor (~> 1.3)
|
26
|
+
thor (~> 0.19.1)
|
27
|
+
tins (~> 1.6.0)
|
28
|
+
crack (0.4.3)
|
29
|
+
safe_yaml (~> 1.0.0)
|
30
|
+
diff-lcs (1.2.5)
|
31
|
+
docile (1.1.5)
|
32
|
+
domain_name (0.5.20160310)
|
33
|
+
unf (>= 0.0.5, < 1.0.0)
|
34
|
+
ffi (1.9.14-java)
|
35
|
+
hashdiff (0.3.0)
|
36
|
+
hashie (3.4.4)
|
37
|
+
httmultiparty (0.3.16)
|
38
|
+
httparty (>= 0.7.3)
|
39
|
+
mimemagic
|
40
|
+
multipart-post
|
41
|
+
http-cookie (1.0.2)
|
42
|
+
domain_name (~> 0.5)
|
43
|
+
httparty (0.14.0)
|
44
|
+
multi_xml (>= 0.5.2)
|
45
|
+
i18n (0.7.0)
|
46
|
+
json (1.8.3)
|
47
|
+
method_source (0.8.2)
|
48
|
+
mime-types (2.99.1)
|
49
|
+
mimemagic (0.3.2)
|
50
|
+
minitest (5.9.0)
|
51
|
+
multi_xml (0.5.5)
|
52
|
+
multipart-post (2.0.0)
|
53
|
+
netrc (0.11.0)
|
54
|
+
pry (0.10.4)
|
55
|
+
coderay (~> 1.1.0)
|
56
|
+
method_source (~> 0.8.1)
|
57
|
+
slop (~> 3.4)
|
58
|
+
pry (0.10.4-java)
|
59
|
+
coderay (~> 1.1.0)
|
60
|
+
method_source (~> 0.8.1)
|
61
|
+
slop (~> 3.4)
|
62
|
+
spoon (~> 0.0)
|
63
|
+
rack (1.6.0)
|
64
|
+
rack-protection (1.5.3)
|
65
|
+
rack
|
66
|
+
rake (10.5.0)
|
67
|
+
rest-client (1.8.0)
|
68
|
+
http-cookie (>= 1.0.2, < 2.0)
|
69
|
+
mime-types (>= 1.16, < 3.0)
|
70
|
+
netrc (~> 0.7)
|
71
|
+
rspec (3.4.0)
|
72
|
+
rspec-core (~> 3.4.0)
|
73
|
+
rspec-expectations (~> 3.4.0)
|
74
|
+
rspec-mocks (~> 3.4.0)
|
75
|
+
rspec-core (3.4.4)
|
76
|
+
rspec-support (~> 3.4.0)
|
77
|
+
rspec-expectations (3.4.0)
|
78
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
79
|
+
rspec-support (~> 3.4.0)
|
80
|
+
rspec-mocks (3.4.1)
|
81
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
82
|
+
rspec-support (~> 3.4.0)
|
83
|
+
rspec-support (3.4.1)
|
84
|
+
safe_yaml (1.0.4)
|
85
|
+
simplecov (0.11.1)
|
86
|
+
docile (~> 1.1.0)
|
87
|
+
json (~> 1.8)
|
88
|
+
simplecov-html (~> 0.10.0)
|
89
|
+
simplecov-html (0.10.0)
|
90
|
+
sinatra (1.4.5)
|
91
|
+
rack (~> 1.4)
|
92
|
+
rack-protection (~> 1.4)
|
93
|
+
tilt (~> 1.3, >= 1.3.4)
|
94
|
+
slop (3.6.0)
|
95
|
+
spoon (0.0.4)
|
96
|
+
ffi
|
97
|
+
term-ansicolor (1.3.2)
|
98
|
+
tins (~> 1.0)
|
99
|
+
thor (0.19.1)
|
100
|
+
thread_safe (0.3.5)
|
101
|
+
tilt (1.4.1)
|
102
|
+
tins (1.6.0)
|
103
|
+
tzinfo (1.2.2)
|
104
|
+
thread_safe (~> 0.1)
|
105
|
+
unf (0.1.4)
|
106
|
+
unf_ext
|
107
|
+
unf_ext (0.0.7.2)
|
108
|
+
webmock (2.1.0)
|
109
|
+
addressable (>= 2.3.6)
|
110
|
+
crack (>= 0.3.2)
|
111
|
+
hashdiff
|
112
|
+
|
113
|
+
PLATFORMS
|
114
|
+
java
|
115
|
+
ruby
|
116
|
+
|
117
|
+
DEPENDENCIES
|
118
|
+
awesome_print (~> 1.7)
|
119
|
+
bundler (~> 1.7)
|
120
|
+
coveralls
|
121
|
+
facebook_ads!
|
122
|
+
pry (~> 0.10)
|
123
|
+
rake (~> 10.0)
|
124
|
+
rspec (~> 3.4)
|
125
|
+
sinatra (~> 1.4)
|
126
|
+
webmock (~> 2.1)
|
127
|
+
|
128
|
+
BUNDLED WITH
|
129
|
+
1.12.5
|
data/README.markdown
ADDED
@@ -0,0 +1,380 @@
|
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/facebook_ads.svg)](https://badge.fury.io/rb/facebook_ads)
|
2
|
+
[![Build Status](https://travis-ci.org/cte/facebook-ads-sdk-ruby.svg?branch=master)](https://travis-ci.org/cte/facebook-ads-sdk-ruby)
|
3
|
+
[![Coverage Status](https://coveralls.io/repos/github/cte/facebook-ads-sdk-ruby/badge.svg)](https://coveralls.io/github/cte/facebook-ads-sdk-ruby)
|
4
|
+
|
5
|
+
## [Facebook Marketing API](https://developers.facebook.com/docs/marketing-apis) SDK for Ruby
|
6
|
+
|
7
|
+
![Facebook Ads](http://i.imgur.com/GrxAj07.png)
|
8
|
+
|
9
|
+
This gem allows you to manage your Facebook Ads using a ruby interface. It allows you to list, create, update and destroy Facebook Ad objects (campaigns, ad sets, ads, etc) and get real-time insights about the performance of Facebook Ads.
|
10
|
+
|
11
|
+
### Install
|
12
|
+
|
13
|
+
```bash
|
14
|
+
gem install facebook_ads
|
15
|
+
```
|
16
|
+
|
17
|
+
Or, add the following to your Gemfile:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
gem 'facebook_ads', '~> 0.1'
|
21
|
+
```
|
22
|
+
|
23
|
+
### Permissions
|
24
|
+
|
25
|
+
You'll need an [Access Token](https://developers.facebook.com/docs/marketing-api/authentication) with `ads_management` permissions in order to use Facebook's Marketing API.
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
FacebookAds.access_token = '[YOUR_ACCESS_TOKEN]'
|
29
|
+
```
|
30
|
+
|
31
|
+
### Console
|
32
|
+
|
33
|
+
This gem provides a console using [Pry](https://github.com/pry/pry) and [AwesomePrint](https://github.com/awesome-print/awesome_print) for you to test & debug.
|
34
|
+
It reads the Access Token from a file called test_access_token.
|
35
|
+
|
36
|
+
```bash
|
37
|
+
echo [YOUR_ACCESS_TOKEN] > test_access_token
|
38
|
+
bin/console
|
39
|
+
```
|
40
|
+
|
41
|
+
### Usage Examples
|
42
|
+
|
43
|
+
A strong understanding of the Facebook Ads [object structure](https://developers.facebook.com/docs/marketing-api/buying-api) will greatly help you use this gem.
|
44
|
+
|
45
|
+
The basic object structure:
|
46
|
+
|
47
|
+
![Facebook Ads Object Structure](http://i.imgur.com/Ak4FQ4H.jpg)
|
48
|
+
|
49
|
+
In total, there are 7 Facebook Ads objects that can be interacted with via this gem: AdAccount, AdCampaign, AdImage, AdCreative, AdSet, Ad and AdInsight.
|
50
|
+
|
51
|
+
The typical flow is as follows:
|
52
|
+
|
53
|
+
1. Create an **AdCampaign** for an **AdAccount**.
|
54
|
+
2. Create **AdImages** for an **AdAccount**.
|
55
|
+
3. Create an **AdCreative** for an **AdAccount** using the **AdImages** from #2.
|
56
|
+
4. Create ad **AdSet** for the **AdCampaign** from #1.
|
57
|
+
5. Create an **Ad** for the **AdSet** from #4 using the **AdCreative** from #3.
|
58
|
+
6. Monitor the performance of the **Ad** from #5 using **AdInsights**.
|
59
|
+
7. Update the daily budget of the **AdSet** from #4 as needed.
|
60
|
+
|
61
|
+
You'll find usage examples for each of these 7 objects below.
|
62
|
+
|
63
|
+
### [Ad Accounts](https://developers.facebook.com/docs/marketing-api/reference/ad-account) (Fetch, Find, Update)
|
64
|
+
|
65
|
+
Fetch all accounts that can be accessed using your access token:
|
66
|
+
```ruby
|
67
|
+
accounts = FacebookAds::AdAccount.all
|
68
|
+
```
|
69
|
+
|
70
|
+
Find an account by ID:
|
71
|
+
```ruby
|
72
|
+
account = FacebookAds::AdAccount.find('act_1132789356764349')
|
73
|
+
```
|
74
|
+
|
75
|
+
Find an account by name:
|
76
|
+
```ruby
|
77
|
+
account = FacebookAds::AdAccount.find_by(name: 'ReFuel4')
|
78
|
+
```
|
79
|
+
|
80
|
+
Update an account (using both .save() and .update()):
|
81
|
+
```ruby
|
82
|
+
account.name = 'ReFuel4 [Updated]'
|
83
|
+
account = account.save # Returns the updated object.
|
84
|
+
account.update(name: 'ReFuel4') # Returns a boolean.
|
85
|
+
```
|
86
|
+
|
87
|
+
The list of fields that can be updated is [here](https://developers.facebook.com/docs/marketing-api/reference/ad-account#Updating).
|
88
|
+
|
89
|
+
### [Ad Campaigns](https://developers.facebook.com/docs/marketing-api/reference/ad-campaign-group) (Fetch, Find, Create, Update, Destroy)
|
90
|
+
|
91
|
+
Fetch all active campaigns:
|
92
|
+
```ruby
|
93
|
+
campaigns = account.ad_campaigns
|
94
|
+
```
|
95
|
+
|
96
|
+
Fetch all paused campaigns (can pass multiple statuses in the array):
|
97
|
+
```ruby
|
98
|
+
campaigns = account.ad_campaigns(effective_status: ['PAUSED'])
|
99
|
+
```
|
100
|
+
See FacebookAds::AdCampaign::STATUSES for a list of all statuses.
|
101
|
+
|
102
|
+
Fetch all campaigns:
|
103
|
+
```ruby
|
104
|
+
campaigns = account.ad_campaigns(effective_status: nil)
|
105
|
+
```
|
106
|
+
|
107
|
+
Create a new campaign for website conversions that is initially paused:
|
108
|
+
```ruby
|
109
|
+
campaign = account.create_ad_campaign(
|
110
|
+
name: 'Test Campaign',
|
111
|
+
objective: 'CONVERSIONS',
|
112
|
+
status: 'PAUSED'
|
113
|
+
)
|
114
|
+
```
|
115
|
+
See FacebookAds::AdCampaign::OBJECTIVES for a list of all objectives.
|
116
|
+
|
117
|
+
Find a campaign by ID:
|
118
|
+
```ruby
|
119
|
+
campaign = FacebookAds::AdCampaign.find(campaign.id)
|
120
|
+
```
|
121
|
+
|
122
|
+
Update a campaign (using both .save() and .update()):
|
123
|
+
```ruby
|
124
|
+
campaign.status = 'ACTIVE'
|
125
|
+
campaign = campaign.save # Returns the updated object.
|
126
|
+
campaign.update(status: 'PAUSED') # Returns a boolean.
|
127
|
+
```
|
128
|
+
The list of fields that can be updated is [here](https://developers.facebook.com/docs/marketing-api/reference/ad-campaign-group#Updating).
|
129
|
+
|
130
|
+
Destroy a campaign:
|
131
|
+
```ruby
|
132
|
+
campaign.destroy
|
133
|
+
```
|
134
|
+
|
135
|
+
### [Ad Images](https://developers.facebook.com/docs/marketing-api/reference/ad-image) (Fetch, Find, Create, Destroy)
|
136
|
+
|
137
|
+
Notes:
|
138
|
+
* Images cannot be updated.
|
139
|
+
* You can upload the same image multiple times and Facebook will de-duplicate them server side.
|
140
|
+
* An image will always generate the same hash on Facebook's end - event across ad accounts.
|
141
|
+
* Image uploading via a URL currently assumes a \*nix system (Mac OS, linux). It likely will fail on Windows. A cross-platform tempfile-based solution is in the works.
|
142
|
+
* You can't destroy an image if its being used by a creative. You have to destroy the creative first.
|
143
|
+
|
144
|
+
Fetch all images owned by an account:
|
145
|
+
```ruby
|
146
|
+
ad_images = account.ad_images
|
147
|
+
```
|
148
|
+
|
149
|
+
Create images using an array of URLs:
|
150
|
+
```ruby
|
151
|
+
ad_images = account.create_ad_images([
|
152
|
+
'https://d38eepresuu519.cloudfront.net/485674b133dc2f1d66d20c9d52c62bec/original.jpg',
|
153
|
+
'https://d38eepresuu519.cloudfront.net/3977d2a47b584820969e2acf4d923e33/original.jpg'
|
154
|
+
])
|
155
|
+
```
|
156
|
+
|
157
|
+
Find images using their hash values:
|
158
|
+
```ruby
|
159
|
+
ad_images = account.ad_images(hashes: ad_images.map(&:hash))
|
160
|
+
```
|
161
|
+
|
162
|
+
Destroy images:
|
163
|
+
```ruby
|
164
|
+
ad_images.map(&:destroy)
|
165
|
+
```
|
166
|
+
|
167
|
+
### [Ad Creatives](https://developers.facebook.com/docs/marketing-api/reference/ad-creative) (Fetch, Find, Create, Update, Destroy)
|
168
|
+
|
169
|
+
Notes:
|
170
|
+
* I'd like to add a configuration object that allows you to specify the Facebook Page, Instagram account, website, iOS app and/or Android app that you will be advertising. This is needed when creating both Ad Creative objects and Ad Set objects.
|
171
|
+
|
172
|
+
Fetch all creatives owned by an account:
|
173
|
+
```ruby
|
174
|
+
ad_creatives = account.ad_creatives
|
175
|
+
```
|
176
|
+
|
177
|
+
Create a carousel creative driving installs for an Android app:
|
178
|
+
```ruby
|
179
|
+
carousel_ad_creative = account.create_ad_creative({
|
180
|
+
name: 'Test Carousel Creative',
|
181
|
+
page_id: '300664329976860', # Add your Facebook Page ID here.
|
182
|
+
link: 'http://play.google.com/store/apps/details?id=com.tophatter', # Add your Play Store ID here.
|
183
|
+
message: 'A message.',
|
184
|
+
assets: [
|
185
|
+
{ hash: ad_images.first.hash, title: 'Image #1 Title' },
|
186
|
+
{ hash: ad_images.second.hash, title: 'Image #2 Title' }
|
187
|
+
],
|
188
|
+
call_to_action_type: 'SHOP_NOW',
|
189
|
+
multi_share_optimized: true,
|
190
|
+
multi_share_end_card: false
|
191
|
+
}, carousel: true)
|
192
|
+
```
|
193
|
+
See FacebookAds::AdCreative::CALL_TO_ACTION_TYPES for a list of all call to action types.
|
194
|
+
|
195
|
+
Create a single image creative advertising an Android app:
|
196
|
+
```ruby
|
197
|
+
image_ad_creative = account.create_ad_creative({
|
198
|
+
name: 'Test Single Image Creative',
|
199
|
+
page_id: '300664329976860', # Add your Facebook Page ID here.
|
200
|
+
message: 'A message.',
|
201
|
+
link: 'http://play.google.com/store/apps/details?id=com.tophatter', # Add your Play Store ID here.
|
202
|
+
link_title: 'A link title.',
|
203
|
+
image_hash: ad_images.first.hash,
|
204
|
+
call_to_action_type: 'SHOP_NOW'
|
205
|
+
}, carousel: false)
|
206
|
+
```
|
207
|
+
The options will be different depending on the thing being advertised (Android app, iOS app or website).
|
208
|
+
|
209
|
+
Find a creative by ID:
|
210
|
+
```ruby
|
211
|
+
ad_creative = FacebookAds::AdCreative.find(ad_creative.id)
|
212
|
+
```
|
213
|
+
|
214
|
+
Update a creative (using both .save() and .update()):
|
215
|
+
```ruby
|
216
|
+
ad_creative.name = 'Test Carousel Creative [Updated]'
|
217
|
+
ad_creative = ad_creative.save # Returns the updated object.
|
218
|
+
ad_creative.update(name: 'Test Carousel Creative') # Returns a boolean.
|
219
|
+
```
|
220
|
+
The list of fields that can be updated is [here](https://developers.facebook.com/docs/marketing-api/reference/ad-creative#Updating).
|
221
|
+
|
222
|
+
Destroy a creative:
|
223
|
+
```ruby
|
224
|
+
ad_creative.destroy
|
225
|
+
```
|
226
|
+
|
227
|
+
### [Ad Sets](https://developers.facebook.com/docs/marketing-api/reference/ad-campaign) (Fetch, Find, Create, Update, Destroy)
|
228
|
+
|
229
|
+
Notes:
|
230
|
+
* It's important to make sure your targeting spec makes sense in the context of the promoted object. For example if the promoted object is an iOS app and the targeting spec specifies Android devices your ads are not likely to perform well since no one will be able to download your iOS app.
|
231
|
+
|
232
|
+
You interact with ad sets via a campaign:
|
233
|
+
```ruby
|
234
|
+
campaign = account.ad_campaigns(effective_status: nil).first
|
235
|
+
```
|
236
|
+
|
237
|
+
Fetch all active ad sets for a campaign:
|
238
|
+
```ruby
|
239
|
+
ad_sets = campaign.ad_sets
|
240
|
+
```
|
241
|
+
|
242
|
+
Fetch all paused ad sets for a campaign (can pass multiple statuses in the array):
|
243
|
+
```ruby
|
244
|
+
ad_sets = campaign.ad_sets(effective_status: ['PAUSED'])
|
245
|
+
```
|
246
|
+
See FacebookAds::AdSet::STATUSES for a list of all statuses.
|
247
|
+
|
248
|
+
Fetch all ad sets for a campaign:
|
249
|
+
```ruby
|
250
|
+
ad_sets = campaign.ad_sets(effective_status: nil)
|
251
|
+
```
|
252
|
+
|
253
|
+
Specify the audience targeted by this ad set:
|
254
|
+
```ruby
|
255
|
+
targeting = FacebookAds::AdTargeting.new
|
256
|
+
targeting.genders = [FacebookAds::AdTargeting::WOMEN]
|
257
|
+
targeting.age_min = 29
|
258
|
+
targeting.age_max = 65
|
259
|
+
targeting.countries = ['US']
|
260
|
+
targeting.user_os = [FacebookAds::AdTargeting::ANDROID_OS]
|
261
|
+
targeting.user_device = FacebookAds::AdTargeting::ANDROID_DEVICES
|
262
|
+
targeting.app_install_state = FacebookAds::AdTargeting::NOT_INSTALLED
|
263
|
+
```
|
264
|
+
A lot can be done with targeting. You can learn more about targeting specs [here](https://developers.facebook.com/docs/marketing-api/targeting-specs).
|
265
|
+
|
266
|
+
Create an ad set to drive installs to an Android app using the targeting above:
|
267
|
+
```ruby
|
268
|
+
ad_set = campaign.create_ad_set(
|
269
|
+
name: 'Test Ad Set',
|
270
|
+
targeting: targeting,
|
271
|
+
promoted_object: { # This can be an Android app, iOS app or pixel ID, plus an optional custom event.
|
272
|
+
application_id: '295802707128640',
|
273
|
+
object_store_url: 'http://play.google.com/store/apps/details?id=com.tophatter',
|
274
|
+
custom_event_type: 'PURCHASE'
|
275
|
+
},
|
276
|
+
optimization_goal: 'OFFSITE_CONVERSIONS', # See FacebookAds::AdSet::OPTIMIZATION_GOALS.
|
277
|
+
daily_budget: 500, # This is in cents, so the daily budget here is $5.
|
278
|
+
billing_event: 'IMPRESSIONS', # See FacebookAds::AdSet::BILLING_EVENTS for a list of all billing events.
|
279
|
+
status: 'PAUSED'
|
280
|
+
)
|
281
|
+
```
|
282
|
+
|
283
|
+
Find an ad set by ID:
|
284
|
+
```ruby
|
285
|
+
ad_set = FacebookAds::AdSet.find(ad_set.id)
|
286
|
+
```
|
287
|
+
|
288
|
+
Update an ad set (using both .save() and .update()):
|
289
|
+
```ruby
|
290
|
+
ad_set.status = 'ACTIVE'
|
291
|
+
ad_set.daily_budget = 400
|
292
|
+
ad_set = ad_set.save # Returns the updated object.
|
293
|
+
ad_set.update(status: 'PAUSED', daily_budget: 500) # Returns a boolean.
|
294
|
+
```
|
295
|
+
The list of fields that can be updated is [here](https://developers.facebook.com/docs/marketing-api/reference/ad-campaign#Updating).
|
296
|
+
|
297
|
+
Destroy an ad set:
|
298
|
+
```ruby
|
299
|
+
ad_set.destroy
|
300
|
+
```
|
301
|
+
|
302
|
+
### [Ads](https://developers.facebook.com/docs/marketing-api/reference/adgroup) (Fetch, Find, Create, Update, Destroy)
|
303
|
+
|
304
|
+
You interact with ads via an ad set:
|
305
|
+
```ruby
|
306
|
+
ad_set = account.ad_sets(effective_status: nil).first
|
307
|
+
```
|
308
|
+
|
309
|
+
Fetch all active ads for an ad set:
|
310
|
+
```ruby
|
311
|
+
ads = ad_set.ads
|
312
|
+
```
|
313
|
+
|
314
|
+
Fetch all paused ads for an ad set (can pass multiple statuses in the array):
|
315
|
+
```ruby
|
316
|
+
ads = ad_set.ads(effective_status: ['PAUSED'])
|
317
|
+
```
|
318
|
+
See FacebookAds::Ad::STATUSES for a list of all statuses.
|
319
|
+
|
320
|
+
Fetch all ads for an ad set:
|
321
|
+
```ruby
|
322
|
+
ads = ad_set.ads(effective_status: nil)
|
323
|
+
```
|
324
|
+
|
325
|
+
Fetch a creative that we'll use to create an ad:
|
326
|
+
```ruby
|
327
|
+
ad_creative = account.ad_creatives.first
|
328
|
+
```
|
329
|
+
|
330
|
+
Create an ad:
|
331
|
+
```ruby
|
332
|
+
ad = ad_set.create_ad(name: 'Test Ad', creative_id: ad_creative.id)
|
333
|
+
```
|
334
|
+
|
335
|
+
Find an ad by ID:
|
336
|
+
```ruby
|
337
|
+
ad = FacebookAds::Ad.find(ad.id)
|
338
|
+
```
|
339
|
+
|
340
|
+
Update an ad (using both .save() and .update()):
|
341
|
+
```ruby
|
342
|
+
ad.name = 'Test Ad [Updated]'
|
343
|
+
ad.status = 'ACTIVE'
|
344
|
+
ad = ad.save # Returns the updated object.
|
345
|
+
ad.update(name: 'Test Ad', status: 'PAUSED') # Returns a boolean.
|
346
|
+
```
|
347
|
+
The list of fields that can be updated is [here](https://developers.facebook.com/docs/marketing-api/reference/adgroup#Updating).
|
348
|
+
|
349
|
+
Destroy an ad:
|
350
|
+
```ruby
|
351
|
+
ad.destroy
|
352
|
+
```
|
353
|
+
|
354
|
+
### [Ad Insights](https://developers.facebook.com/docs/marketing-api/insights/overview) (Fetch)
|
355
|
+
|
356
|
+
Fetch today's insights for an account:
|
357
|
+
```ruby
|
358
|
+
account.ad_insights
|
359
|
+
```
|
360
|
+
|
361
|
+
Fetch yesterday's insights for an account:
|
362
|
+
```ruby
|
363
|
+
account.ad_insights(range: Date.yesterday..Date.yesterday)
|
364
|
+
```
|
365
|
+
|
366
|
+
Fetch today's insights for a campaign:
|
367
|
+
```ruby
|
368
|
+
account.ad_campaigns.last.ad_insights
|
369
|
+
```
|
370
|
+
|
371
|
+
Fetch yesterday's insights for a campaign:
|
372
|
+
```ruby
|
373
|
+
account.ad_campaigns.last.ad_insights(range: Date.yesterday..Date.yesterday)
|
374
|
+
```
|
375
|
+
|
376
|
+
### @TODO:
|
377
|
+
|
378
|
+
* Unit tests (add rspec - need to build out the tests now).
|
379
|
+
* [Batch operations](https://developers.facebook.com/docs/marketing-api/batch-requests).
|
380
|
+
* Upgrade to [2.7](https://developers.facebook.com/docs/marketing-api/versions).
|