facebook_ads 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +16 -0
  5. data/Gemfile.lock +129 -0
  6. data/README.markdown +380 -0
  7. data/bin/console +13 -0
  8. data/facebook_ads.gemspec +26 -0
  9. data/lib/facebook_ads.rb +46 -0
  10. data/lib/facebook_ads/ad.rb +34 -0
  11. data/lib/facebook_ads/ad_account.rb +126 -0
  12. data/lib/facebook_ads/ad_campaign.rb +54 -0
  13. data/lib/facebook_ads/ad_creative.rb +66 -0
  14. data/lib/facebook_ads/ad_image.rb +28 -0
  15. data/lib/facebook_ads/ad_insight.rb +24 -0
  16. data/lib/facebook_ads/ad_set.rb +35 -0
  17. data/lib/facebook_ads/ad_targeting.rb +61 -0
  18. data/lib/facebook_ads/base.rb +151 -0
  19. data/spec/ad_account_spec.rb +78 -0
  20. data/spec/ad_campaign_spec.rb +13 -0
  21. data/spec/ad_creative_spec.rb +14 -0
  22. data/spec/ad_image_spec.rb +11 -0
  23. data/spec/ad_insight_spec.rb +11 -0
  24. data/spec/ad_set_spec.rb +13 -0
  25. data/spec/ad_spec.rb +13 -0
  26. data/spec/ad_targeting_spec.rb +4 -0
  27. data/spec/spec_helper.rb +15 -0
  28. data/spec/support/fixtures.sh +17 -0
  29. data/spec/support/fixtures/6057330925170.json +1 -0
  30. data/spec/support/fixtures/6057810634370.json +1 -0
  31. data/spec/support/fixtures/6057810946970.json +1 -0
  32. data/spec/support/fixtures/6057824295570.json +1 -0
  33. data/spec/support/fixtures/act_861827983860489.json +1 -0
  34. data/spec/support/fixtures/act_861827983860489/adcreatives.json +1 -0
  35. data/spec/support/fixtures/act_861827983860489/adimages.json +1 -0
  36. data/spec/support/fixtures/act_861827983860489/ads.json +1 -0
  37. data/spec/support/fixtures/act_861827983860489/adsets.json +1 -0
  38. data/spec/support/fixtures/act_861827983860489/campaigns.json +1 -0
  39. data/spec/support/fixtures/me/adaccounts.json +1 -0
  40. data/spec/support/rack_facebook.rb +22 -0
  41. 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
@@ -0,0 +1,3 @@
1
+ .DS_Store
2
+ test_access_token
3
+ coverage
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2
4
+ branches:
5
+ only:
6
+ - master
7
+ cache: bundler
8
+ script: bundle exec rspec spec
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).