facebookads 0.0.1 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +17 -0
  3. data/README.md +222 -0
  4. data/lib/facebook_ads/ad_object.rb +177 -0
  5. data/lib/facebook_ads/ad_objects/ad.rb +215 -0
  6. data/lib/facebook_ads/ad_objects/ad_account.rb +665 -0
  7. data/lib/facebook_ads/ad_objects/ad_account_roas.rb +97 -0
  8. data/lib/facebook_ads/ad_objects/ad_account_targeting_unified.rb +136 -0
  9. data/lib/facebook_ads/ad_objects/ad_account_user.rb +39 -0
  10. data/lib/facebook_ads/ad_objects/ad_activity.rb +123 -0
  11. data/lib/facebook_ads/ad_objects/ad_async_request.rb +66 -0
  12. data/lib/facebook_ads/ad_objects/ad_async_request_set.rb +68 -0
  13. data/lib/facebook_ads/ad_objects/ad_async_request_set_notification_result.rb +38 -0
  14. data/lib/facebook_ads/ad_objects/ad_creative.rb +163 -0
  15. data/lib/facebook_ads/ad_objects/ad_creative_link_data.rb +62 -0
  16. data/lib/facebook_ads/ad_objects/ad_creative_link_data_app_link_spec.rb +40 -0
  17. data/lib/facebook_ads/ad_objects/ad_creative_link_data_call_to_action.rb +75 -0
  18. data/lib/facebook_ads/ad_objects/ad_creative_link_data_call_to_action_value.rb +46 -0
  19. data/lib/facebook_ads/ad_objects/ad_creative_link_data_child_attachment.rb +47 -0
  20. data/lib/facebook_ads/ad_objects/ad_creative_object_story_spec.rb +43 -0
  21. data/lib/facebook_ads/ad_objects/ad_creative_offer_data.rb +44 -0
  22. data/lib/facebook_ads/ad_objects/ad_creative_photo_data.rb +42 -0
  23. data/lib/facebook_ads/ad_objects/ad_creative_place_data.rb +41 -0
  24. data/lib/facebook_ads/ad_objects/ad_creative_text_data.rb +37 -0
  25. data/lib/facebook_ads/ad_objects/ad_creative_video_data.rb +48 -0
  26. data/lib/facebook_ads/ad_objects/ad_image.rb +58 -0
  27. data/lib/facebook_ads/ad_objects/ad_keyword_stats.rb +55 -0
  28. data/lib/facebook_ads/ad_objects/ad_label.rb +57 -0
  29. data/lib/facebook_ads/ad_objects/ad_place_page_set.rb +44 -0
  30. data/lib/facebook_ads/ad_objects/ad_preview.rb +54 -0
  31. data/lib/facebook_ads/ad_objects/ad_promoted_object.rb +64 -0
  32. data/lib/facebook_ads/ad_objects/ad_recommendation.rb +55 -0
  33. data/lib/facebook_ads/ad_objects/ad_recommendation_data.rb +37 -0
  34. data/lib/facebook_ads/ad_objects/ad_report_run.rb +70 -0
  35. data/lib/facebook_ads/ad_objects/ad_set.rb +267 -0
  36. data/lib/facebook_ads/ad_objects/ad_study.rb +69 -0
  37. data/lib/facebook_ads/ad_objects/ad_study_cell.rb +39 -0
  38. data/lib/facebook_ads/ad_objects/ad_study_objective.rb +59 -0
  39. data/lib/facebook_ads/ad_objects/ad_video.rb +25 -0
  40. data/lib/facebook_ads/ad_objects/adgroup_placement_specific_review_feedback.rb +43 -0
  41. data/lib/facebook_ads/ad_objects/adgroup_relevance_score.rb +40 -0
  42. data/lib/facebook_ads/ad_objects/adgroup_review_feedback.rb +38 -0
  43. data/lib/facebook_ads/ad_objects/ads_action_stats.rb +53 -0
  44. data/lib/facebook_ads/ad_objects/ads_data_partner.rb +37 -0
  45. data/lib/facebook_ads/ad_objects/ads_image_crops.rb +42 -0
  46. data/lib/facebook_ads/ad_objects/ads_insights.rb +225 -0
  47. data/lib/facebook_ads/ad_objects/ads_pixel.rb +64 -0
  48. data/lib/facebook_ads/ad_objects/ads_pixel_stats.rb +39 -0
  49. data/lib/facebook_ads/ad_objects/ads_pixel_stats_result.rb +50 -0
  50. data/lib/facebook_ads/ad_objects/agency_client_declaration.rb +48 -0
  51. data/lib/facebook_ads/ad_objects/android_app_link.rb +40 -0
  52. data/lib/facebook_ads/ad_objects/app_links.rb +43 -0
  53. data/lib/facebook_ads/ad_objects/broad_targeting_categories.rb +46 -0
  54. data/lib/facebook_ads/ad_objects/business.rb +242 -0
  55. data/lib/facebook_ads/ad_objects/business_ad_account_request.rb +37 -0
  56. data/lib/facebook_ads/ad_objects/business_page_request.rb +37 -0
  57. data/lib/facebook_ads/ad_objects/campaign.rb +211 -0
  58. data/lib/facebook_ads/ad_objects/conversion_action_query.rb +63 -0
  59. data/lib/facebook_ads/ad_objects/custom_audience.rb +166 -0
  60. data/lib/facebook_ads/ad_objects/custom_audience_ad_account.rb +36 -0
  61. data/lib/facebook_ads/ad_objects/custom_audience_data_source.rb +94 -0
  62. data/lib/facebook_ads/ad_objects/custom_audience_permission.rb +41 -0
  63. data/lib/facebook_ads/ad_objects/custom_audience_prefill_state.rb +39 -0
  64. data/lib/facebook_ads/ad_objects/custom_audience_session.rb +44 -0
  65. data/lib/facebook_ads/ad_objects/custom_audience_status.rb +38 -0
  66. data/lib/facebook_ads/ad_objects/custom_audiences_tos.rb +38 -0
  67. data/lib/facebook_ads/ad_objects/custom_conversion.rb +78 -0
  68. data/lib/facebook_ads/ad_objects/custom_conversion_stats_result.rb +50 -0
  69. data/lib/facebook_ads/ad_objects/day_part.rb +40 -0
  70. data/lib/facebook_ads/ad_objects/delivery_check.rb +40 -0
  71. data/lib/facebook_ads/ad_objects/delivery_check_extra_info.rb +39 -0
  72. data/lib/facebook_ads/ad_objects/delivery_estimate.rb +41 -0
  73. data/lib/facebook_ads/ad_objects/domain.rb +37 -0
  74. data/lib/facebook_ads/ad_objects/event.rb +74 -0
  75. data/lib/facebook_ads/ad_objects/event_source_group.rb +43 -0
  76. data/lib/facebook_ads/ad_objects/external_event_source.rb +38 -0
  77. data/lib/facebook_ads/ad_objects/flexible_targeting.rb +64 -0
  78. data/lib/facebook_ads/ad_objects/funding_source_details.rb +39 -0
  79. data/lib/facebook_ads/ad_objects/funding_source_details_coupon.rb +40 -0
  80. data/lib/facebook_ads/ad_objects/helpers/custom_audience_helpers.rb +170 -0
  81. data/lib/facebook_ads/ad_objects/hotel.rb +61 -0
  82. data/lib/facebook_ads/ad_objects/hotel_room.rb +44 -0
  83. data/lib/facebook_ads/ad_objects/id_name.rb +37 -0
  84. data/lib/facebook_ads/ad_objects/ios_app_link.rb +39 -0
  85. data/lib/facebook_ads/ad_objects/lead.rb +47 -0
  86. data/lib/facebook_ads/ad_objects/lead_gen_qualifier.rb +40 -0
  87. data/lib/facebook_ads/ad_objects/lead_gen_question.rb +40 -0
  88. data/lib/facebook_ads/ad_objects/lead_gen_question_option.rb +38 -0
  89. data/lib/facebook_ads/ad_objects/leadgen_form.rb +70 -0
  90. data/lib/facebook_ads/ad_objects/legacy_business_ad_account_request.rb +38 -0
  91. data/lib/facebook_ads/ad_objects/lookalike_spec.rb +43 -0
  92. data/lib/facebook_ads/ad_objects/minimum_budget.rb +41 -0
  93. data/lib/facebook_ads/ad_objects/offsite_pixel.rb +57 -0
  94. data/lib/facebook_ads/ad_objects/outcome_prediction_point.rb +40 -0
  95. data/lib/facebook_ads/ad_objects/partner_category.rb +51 -0
  96. data/lib/facebook_ads/ad_objects/product_catalog.rb +257 -0
  97. data/lib/facebook_ads/ad_objects/product_catalog_hotel_rooms_batch.rb +50 -0
  98. data/lib/facebook_ads/ad_objects/product_catalog_image_settings.rb +38 -0
  99. data/lib/facebook_ads/ad_objects/product_catalog_image_settings_operation.rb +37 -0
  100. data/lib/facebook_ads/ad_objects/product_catalog_pricing_variables_batch.rb +50 -0
  101. data/lib/facebook_ads/ad_objects/product_feed.rb +88 -0
  102. data/lib/facebook_ads/ad_objects/product_feed_schedule.rb +61 -0
  103. data/lib/facebook_ads/ad_objects/product_feed_upload.rb +48 -0
  104. data/lib/facebook_ads/ad_objects/product_feed_upload_error.rb +49 -0
  105. data/lib/facebook_ads/ad_objects/product_feed_upload_error_sample.rb +37 -0
  106. data/lib/facebook_ads/ad_objects/product_group.rb +98 -0
  107. data/lib/facebook_ads/ad_objects/product_item.rb +147 -0
  108. data/lib/facebook_ads/ad_objects/product_item_commerce_insights.rb +39 -0
  109. data/lib/facebook_ads/ad_objects/product_set.rb +49 -0
  110. data/lib/facebook_ads/ad_objects/product_variant.rb +39 -0
  111. data/lib/facebook_ads/ad_objects/profile_picture_source.rb +52 -0
  112. data/lib/facebook_ads/ad_objects/rate_card.rb +39 -0
  113. data/lib/facebook_ads/ad_objects/reach_estimate.rb +60 -0
  114. data/lib/facebook_ads/ad_objects/reach_frequency_prediction.rb +89 -0
  115. data/lib/facebook_ads/ad_objects/reach_frequency_spec.rb +42 -0
  116. data/lib/facebook_ads/ad_objects/rev_share_policy.rb +38 -0
  117. data/lib/facebook_ads/ad_objects/roas_cohorts_data.rb +41 -0
  118. data/lib/facebook_ads/ad_objects/roas_cohorts_per_cohort_interval_unit.rb +38 -0
  119. data/lib/facebook_ads/ad_objects/targeting.rb +133 -0
  120. data/lib/facebook_ads/ad_objects/targeting_dynamic_rule.rb +44 -0
  121. data/lib/facebook_ads/ad_objects/targeting_geo_location.rb +47 -0
  122. data/lib/facebook_ads/ad_objects/targeting_geo_location_city.rb +43 -0
  123. data/lib/facebook_ads/ad_objects/targeting_geo_location_custom_location.rb +50 -0
  124. data/lib/facebook_ads/ad_objects/targeting_geo_location_electoral_district.rb +40 -0
  125. data/lib/facebook_ads/ad_objects/targeting_geo_location_market.rb +40 -0
  126. data/lib/facebook_ads/ad_objects/targeting_geo_location_place.rb +45 -0
  127. data/lib/facebook_ads/ad_objects/targeting_geo_location_political_district.rb +40 -0
  128. data/lib/facebook_ads/ad_objects/targeting_geo_location_region.rb +39 -0
  129. data/lib/facebook_ads/ad_objects/targeting_geo_location_zip.rb +41 -0
  130. data/lib/facebook_ads/ad_objects/targeting_product_audience_spec.rb +39 -0
  131. data/lib/facebook_ads/ad_objects/targeting_product_audience_sub_spec.rb +38 -0
  132. data/lib/facebook_ads/ad_objects/targeting_sentence_line.rb +38 -0
  133. data/lib/facebook_ads/ad_objects/transaction.rb +56 -0
  134. data/lib/facebook_ads/ad_objects/transaction_currency_amount.rb +39 -0
  135. data/lib/facebook_ads/ad_objects/user.rb +127 -0
  136. data/lib/facebook_ads/ad_objects/user_lead_gen_disclaimer_response.rb +38 -0
  137. data/lib/facebook_ads/ad_objects/user_lead_gen_field_data.rb +38 -0
  138. data/lib/facebook_ads/ad_objects/video_thumbnail.rb +42 -0
  139. data/lib/facebook_ads/ad_objects/web_app_link.rb +38 -0
  140. data/lib/facebook_ads/ad_objects/windows_app_link.rb +40 -0
  141. data/lib/facebook_ads/ad_objects/windows_phone_app_link.rb +39 -0
  142. data/lib/facebook_ads/api_request.rb +123 -0
  143. data/lib/facebook_ads/api_response.rb +47 -0
  144. data/lib/facebook_ads/batch_api/batch.rb +86 -0
  145. data/lib/facebook_ads/batch_api/batch_proxy.rb +67 -0
  146. data/lib/facebook_ads/config.rb +43 -0
  147. data/lib/facebook_ads/edge.rb +184 -0
  148. data/lib/facebook_ads/errors.rb +55 -0
  149. data/lib/facebook_ads/field_types/ad_object.rb +37 -0
  150. data/lib/facebook_ads/field_types/base.rb +33 -0
  151. data/lib/facebook_ads/field_types/boolean.rb +25 -0
  152. data/lib/facebook_ads/field_types/datetime.rb +47 -0
  153. data/lib/facebook_ads/field_types/double.rb +29 -0
  154. data/lib/facebook_ads/field_types/enum.rb +31 -0
  155. data/lib/facebook_ads/field_types/integer.rb +33 -0
  156. data/lib/facebook_ads/field_types/list.rb +57 -0
  157. data/lib/facebook_ads/field_types/object.rb +33 -0
  158. data/lib/facebook_ads/field_types/string_type.rb +34 -0
  159. data/lib/facebook_ads/field_types/upload_file.rb +121 -0
  160. data/lib/facebook_ads/field_types.rb +65 -0
  161. data/lib/facebook_ads/fields.rb +66 -0
  162. data/lib/facebook_ads/helpers/edge_helpers.rb +57 -0
  163. data/lib/facebook_ads/helpers/node_helpers.rb +80 -0
  164. data/lib/facebook_ads/helpers/shortcuts.rb +34 -0
  165. data/lib/facebook_ads/param_set.rb +74 -0
  166. data/lib/facebook_ads/ruby2patch.rb +27 -0
  167. data/lib/facebook_ads/session.rb +99 -0
  168. data/lib/facebook_ads/utils/utils.rb +29 -0
  169. data/lib/facebook_ads/version.rb +24 -0
  170. data/lib/facebook_ads/videos/video_io.rb +25 -0
  171. data/lib/facebook_ads/videos/video_request.rb +42 -0
  172. data/lib/facebook_ads.rb +72 -0
  173. metadata +337 -13
  174. data/lib/facebookads.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a07d30ce302a0f97e845a894449cbdbd6d25cff
4
- data.tar.gz: 47edb0889a1434afc6f44a64859808faf253241e
3
+ metadata.gz: b5aa03ab8b6c47b81656efca672e6341fc9d76c4
4
+ data.tar.gz: be8de8a6fea10fda4584841141eb8aeb5398a439
5
5
  SHA512:
6
- metadata.gz: fe8e6ee424ae6ece43b4a3fd93fa6eb1600e930bdafed74704726eebeea370f8e5175b780a11c2e386f8e4a5867c7c6ecf4fe18eef5170028ac6e22410273320
7
- data.tar.gz: 6f4e4ee85b25bc27c02a33d481b97b9e9455660956a7b8f9a792e516154f9ace81af69489eb49596a8de85fcf12aefa14e1e8ba66349f6666e5f7b4e53eb5580
6
+ metadata.gz: 4b607cad195d7498d0e72f06a3aeafc6b6abdda6eebf11d9d42d0b33db7a00f9f0ad6a6629859e1f920ba59e7061f4bebcc9d4dd1e88ddaef3b84338d6466cfa
7
+ data.tar.gz: 3bfd0ee8fa82d92f00cfed0cf28e3e764aff8d311e446f25ac42ca0c30e0bfdddd3773f472ddbe973ebd0920f186bddd38500a61e8e0d79c58938e30d8ec4bde
data/LICENSE.txt ADDED
@@ -0,0 +1,17 @@
1
+ Copyright (c) 2017-present, Facebook, Inc. All rights reserved.
2
+
3
+ You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
4
+ copy, modify, and distribute this software in source code or binary form for use
5
+ in connection with the web services and APIs provided by Facebook.
6
+
7
+ As with any software that integrates with the Facebook platform, your use of
8
+ this software is subject to the Facebook Platform Policy
9
+ [http://developers.facebook.com/policy/]. This copyright notice shall be
10
+ included in all copies or substantial portions of the software.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
14
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
16
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
17
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,222 @@
1
+ # Facebook Ads API SDK for Ruby
2
+
3
+ ## Pre-requisites
4
+ ### Ruby Version
5
+ We developed this SDK using Ruby 2.0, and supports Ruby 2.0+, however, the SDK is not thread-safe at the moment.
6
+
7
+ ### App
8
+ To get started with the SDK you must have a Facebook app registered on [developers.facebook.com](https://developers.facebook.com).
9
+
10
+ **IMPORTANT**: Enable all migrations in the App's Settings->Migrations page.
11
+
12
+ **IMPORTANT**: To have better security, we recommend you to turn on 'App Secret Proof for Server API calls' in your app's Settings->Advanced page.
13
+
14
+ ## Installation
15
+ The SDK is available as a RubyGem. To use the gem, you can add the following to Gemfile
16
+
17
+ ```ruby
18
+ gem 'facebookads'
19
+ ```
20
+
21
+ or install it using command line
22
+
23
+ ```bash
24
+ gem install facebookads
25
+ ```
26
+
27
+ and then in your code
28
+
29
+ ```ruby
30
+ require 'facebook_ads'
31
+ ```
32
+
33
+
34
+ ## Configuration
35
+ ### Access Token
36
+ There are several ways to configure access token and app secret. If you only use one access token and app secret (example: an internal app managing only your own assets). You can set a global access token and app secret will will be used across all requests
37
+
38
+ ```ruby
39
+ FacebookAds.configure do |config|
40
+ config.access_token = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
41
+ config.app_secret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
42
+ end
43
+ ```
44
+
45
+ Another way is to configure using environment variables, which will be picked up by the SDK as the default
46
+
47
+ ```bash
48
+ FB_ACCESS_TOKEN=asdsadasds
49
+ FB_APP_SECRET=asdasdsa
50
+ ```
51
+
52
+ Or you can create a session object for particular object
53
+
54
+ ```ruby
55
+ # Create a Session object to be reused
56
+ session = FacebookAds::Session.new(access_token: <ACCESS_TOKEN>, app_secret: <APP SECRET>)
57
+ ad_account = FacebookAds::AdAccount.get('act_12334', 'name', session)
58
+
59
+ # Or a using shortcut during object instantiation
60
+ ad_account = FacebookAds::AdAccount.get('act_12334', 'name', {
61
+ access_token: <ACCESS_TOKEN>, app_secret: <APP SECRET>
62
+ })
63
+ ```
64
+
65
+ ## Basic Operations
66
+
67
+ ### Reading a node
68
+ The SDK contains ad object files auto generated from our API metadata, each node type has its own corresponding Ruby class under the `FacebookAds` module. For example, to fetch an AdAccount
69
+
70
+ ```ruby
71
+ ad_account = FacebookAds::AdAccount.get('act_1234567', 'name')
72
+ print "Ad Account Name: #{ad_account.name}"
73
+ ```
74
+
75
+ The `#get` method doesn't trigger the `GET` request immeidately. The API request for `GET` is fired on-demand. In the example above, API request won't fire until `ad_account.name` is executed.
76
+
77
+ ### Updating a node
78
+ To update a node, you can use the `#save` method of ad object classes.
79
+
80
+ ```ruby
81
+ ad_account = FacebookAds::AdAccount.get('act_1234567', 'name')
82
+ ad_account.name = "New Ad Account"
83
+ ad_account.save
84
+
85
+ # Fetch it again
86
+ ad_account.reload!
87
+ ad_account.name
88
+ => "New Ad Account"
89
+ ```
90
+
91
+ ### Deleting a node
92
+ To delete a node, you can use the `#destroy` method.
93
+
94
+ ```ruby
95
+ campaign = FacebookAds::Campaign.get('<CAMPAIGN_ID>')
96
+ campaign.destroy
97
+ ```
98
+
99
+ ### Reference
100
+ You can refer to our [Marketing API reference](https://developers.facebook.com/docs/marketing-api/reference/) or look inside `lib/facebook_ads/ad_objects` directory of the code base to see the complete list of available ad objects.
101
+
102
+ ## Interacting with Edges
103
+
104
+ To interact with an edge, you first need to instantiate the parent node. Since, as mentioned above, `GET` request of a node is triggered on-demand, so you don't need to worry about consuming unnecessary API quota.
105
+
106
+ ### Fetching Edges (GET)
107
+
108
+ Iterating edges is easy, instantiate the parent nodes and then simply iterate with `#each`. The edge is an `Enumerable` so a bunch of handy methods such as `#map`, `#select`, `#find` etc. come for free!
109
+
110
+ ```ruby
111
+ ad_account = FacebookAds::AdAccount.get('act_1234567', 'name')
112
+
113
+ # Printing all campaign names
114
+ ad_account.campaigns(fields: 'name').each do |campaign|
115
+ print campaign.name
116
+ end
117
+
118
+ # Getting all campaign names
119
+ ad_account.campaigns(fields: 'name').map(&:name)
120
+
121
+ ```
122
+
123
+ ### Creating new nodes (POST)
124
+ To `POST` to a edge, you can use the `#create` method on the edge and supply parameter if needed
125
+
126
+ ```ruby
127
+ campaign = ad_account.campaigns.create({
128
+ name: "My First campaign",
129
+ objective: "CONVERSIONS",
130
+ })
131
+ ```
132
+
133
+ ### Removing from edge (DELETE)
134
+ To `DELETE` an edge, you can use the `#destroy` method on the edge and supply parameter if needed
135
+
136
+ ```ruby
137
+ # Deleting an AdImage by its hash
138
+ ad_account.adimages.destroy({hash: 'abcd1234'})
139
+ ```
140
+
141
+ ## Images/Videos
142
+ The SDK supports image/video uploads. Just supply a parameter of `File` type.
143
+
144
+ Image upload example:
145
+
146
+ ```ruby
147
+ # AdImage supports multiple images upload
148
+ ad_account.adimages.create({
149
+ 'logo1.png' => File.open('./assets/logo1.jpg'),
150
+ 'logo2.png' => File.open('./assets/logo2.jpg'),
151
+ })
152
+ => [#<FacebookAds::AdImage {:hash=>"..."}>, #<FacebookAds::AdImage {:hash=>"..."}>]
153
+ ```
154
+
155
+ Video upload example:
156
+
157
+ ```ruby
158
+ ad_account.advideos.create({
159
+ name: 'My first video',
160
+ source: File.open(File.expand_path("../video_ad_example.mp4", __FILE__))
161
+ })
162
+ ```
163
+
164
+ ## Batch API
165
+
166
+ [Batch API](https://developers.facebook.com/docs/marketing-api/asyncrequests) allows you to make API calls in a batch. You can collect a bunch of API requests and fire them all at once to reduce wait time. To create a batch, just wrap operations with a block to `FacebookAds::Batch#with_batch`
167
+
168
+ ```ruby
169
+ ad_account = FacebookAds::AdAccount.get('act_<ACT_ID>')
170
+
171
+ batch = FacebookAds::Batch.with_batch do
172
+ 10.times.map do |n|
173
+ ad_account.campaigns.create({
174
+ name: 'My Test Campaign #' + n,
175
+ objective: 'CONVERSIONS',
176
+ status: 'PAUSED',
177
+ })
178
+ end
179
+ end
180
+
181
+ batch.execute
182
+ ```
183
+
184
+ ### Dependencies within a batch (Experimental)
185
+ Dependencies between requests is supported, the SDK simplifies the use of JSONPath references between batched operations.
186
+
187
+ ```ruby
188
+ ad_account = FacebookAds::AdAccount.get('act_12334')
189
+
190
+ batch = FacebookAds::Batch.with_batch do
191
+ # This won't be sent out immediately!
192
+ campaign = ad_account.campaigns.create({
193
+ name: 'My Test Campaign',
194
+ objective: 'CONVERSIONS',
195
+ status: 'PAUSED',
196
+ })
197
+
198
+ # Even the request above is not being sent yet, reference to campaign.id still works
199
+ ad_accounts.adsets.create({
200
+ name: 'My AdSet',
201
+ campaign_id: campaign.id, # campaign.id here will return {result=create-campaign:$.id}
202
+ ...
203
+ ...
204
+ ...
205
+ })
206
+ end
207
+ ```
208
+
209
+ ## Logging
210
+
211
+ ```ruby
212
+ FacebookAds.configure do |config|
213
+ # Logger for debugger
214
+ config.logger = ::Logger.new(STDOUT).tap { |d| d.level = Logger::DEBUG }
215
+
216
+ # Log Http request & response to logger
217
+ config.log_api_bodies = true
218
+ end
219
+ ```
220
+
221
+ ## Reporting Bugs/Feedback
222
+ Please raise any issue on Github.
@@ -0,0 +1,177 @@
1
+ # Copyright (c) 2017-present, Facebook, Inc. All rights reserved.
2
+ #
3
+ # You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
4
+ # copy, modify, and distribute this software in source code or binary form for use
5
+ # in connection with the web services and APIs provided by Facebook.
6
+ #
7
+ # As with any software that integrates with the Facebook platform, your use of
8
+ # this software is subject to the Facebook Platform Policy
9
+ # [http://developers.facebook.com/policy/]. This copyright notice shall be
10
+ # included in all copies or substantial portions of the software.
11
+ #
12
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
14
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
16
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
17
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18
+
19
+ require 'json'
20
+ require 'facebook_ads/api_request'
21
+ require 'facebook_ads/api_response'
22
+ require 'facebook_ads/helpers/node_helpers'
23
+ require 'facebook_ads/helpers/edge_helpers'
24
+
25
+ module FacebookAds
26
+ class AdObject
27
+ attr_reader :attributes, :fields, :last_api_response
28
+ attr_accessor :deserializer
29
+ attr_accessor :last_saved, :last_destroyed
30
+
31
+ include Fields
32
+ include GraphNodes
33
+ include GraphEdges
34
+
35
+ def initialize(attributes, *args)
36
+ if attributes.empty?
37
+ raise InvalidParameterError, 'Invalid attributes. Must include at least one attribute'
38
+ end
39
+
40
+ update_attributes(attributes)
41
+ # assume object with only id in the attributes as not loaded
42
+
43
+ # is next arg a list of fields?
44
+ fields = (args[0].is_a?(Array) || args[0].is_a?(String)) ? args.shift : []
45
+ fields = fields.split(',') if fields.is_a?(String)
46
+ session = args.shift
47
+
48
+ self.fields = fields + attributes.keys
49
+ self.session = session
50
+ end
51
+
52
+ def self.get(id, *args)
53
+ obj = new({id: id}, *args)
54
+ yield obj if block_given?
55
+ obj
56
+ end
57
+
58
+ def id
59
+ self[:id]
60
+ end
61
+
62
+ def update_attributes(attrs)
63
+ @attributes ||= {}
64
+ @attributes.merge!(
65
+ self.class.deserializer ?
66
+ self.class.deserializer.deserialize(symbolize_keys_shallow(attrs)) :
67
+ symbolize_keys_shallow(attrs)
68
+ )
69
+ self
70
+ end
71
+
72
+ def [](attr_name)
73
+ @attributes[attr_name.to_sym]
74
+ end
75
+
76
+ def to_hash
77
+ @attributes.merge(changes)
78
+ end
79
+
80
+ def as_json(*opts)
81
+ to_hash
82
+ end
83
+
84
+ def to_json(*a)
85
+ as_json.to_json(*a)
86
+ end
87
+
88
+ def inspect
89
+ "#<#{self.class.name} #{to_hash.inspect}>"
90
+ end
91
+
92
+ def fields_as_string
93
+ @fields.to_a.join(',')
94
+ end
95
+
96
+ def fields=(fields)
97
+ @fields = Set.new((fields.is_a?(String) ? fields.split(',') : fields.map(&:to_s)).map(&:to_sym))
98
+ end
99
+
100
+ def loaded?
101
+ (@fields - attributes.keys).empty?
102
+ end
103
+
104
+ def load!
105
+ get(graph_params) do |attrs|
106
+ update_attributes(attrs)
107
+ end
108
+ end
109
+
110
+ def reload!
111
+ # delete all attribute except id
112
+ @attributes = @attributes.keep_if { |k,_| k == :id }
113
+ end
114
+
115
+ # TODO refactor this to somewhere
116
+ def graph_params
117
+ {fields: fields_as_string}
118
+ end
119
+
120
+ [:get, :post, :delete].each do |verb|
121
+ define_method(verb) do |params = {}, &block|
122
+ params, options = extract_options(params)
123
+ APIRequest.new(verb, self.id, session: session, params: params, options: options).execute do |api_response|
124
+ @last_api_response = api_response
125
+ block ? block[api_response.result] : api_response
126
+ end
127
+ end
128
+
129
+ define_method("#{verb}_edge") do |edge_name, params = {}, &block|
130
+ params, options = extract_options(params)
131
+ path = "#{self.id}/#{edge_name}"
132
+ APIRequest.new(verb, path, session: session, params: params, options: options).execute do |api_response|
133
+ @last_api_response = api_response
134
+ block ? block[api_response.result] : api_response
135
+ end
136
+ end
137
+ end
138
+
139
+ def save(params = {})
140
+ post(graph_params.merge(changes).merge(params)) do |attrs|
141
+ update_attributes(attrs)
142
+ @changes = {}
143
+ self.last_saved = Time.now
144
+ end
145
+ end
146
+
147
+ def destroy(params = {})
148
+ delete(params) do |attrs|
149
+ self.last_destroyed = Time.now if attrs['success']
150
+ end
151
+ end
152
+
153
+ def changes
154
+ @changes ||= {}
155
+ end
156
+
157
+ def session
158
+ @session || Session.default_session
159
+ end
160
+
161
+ def session=(session)
162
+ @session = session.is_a?(Hash) ? Session.new(session) : session
163
+ end
164
+
165
+ private
166
+ def symbolize_keys_shallow(hash)
167
+ Hash[hash.map { |k,v| [k.to_sym,v] }]
168
+ end
169
+
170
+ def extract_options(params)
171
+ option_keys = [:batch_opts]
172
+ options = {}
173
+ option_keys.each { |k| options[k] = params.delete(k) if params.has_key?(k) }
174
+ [params, options]
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,215 @@
1
+ # Copyright (c) 2017-present, Facebook, Inc. All rights reserved.
2
+ #
3
+ # You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
4
+ # copy, modify, and distribute this software in source code or binary form for use
5
+ # in connection with the web services and APIs provided by Facebook.
6
+ #
7
+ # As with any software that integrates with the Facebook platform, your use of
8
+ # this software is subject to the Facebook Platform Policy
9
+ # [http://developers.facebook.com/policy/]. This copyright notice shall be
10
+ # included in all copies or substantial portions of the software.
11
+ #
12
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
14
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
16
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
17
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18
+
19
+ # FB:AUTOGEN
20
+
21
+ module FacebookAds
22
+ # This class is auto-genereated.
23
+
24
+ # For any issues or feature requests related to this class, please let us know
25
+ # on github and we'll fix in our codegen framework. We'll not be able to accept
26
+ # pull request for this class.
27
+
28
+ class Ad < AdObject
29
+ BID_TYPE = [
30
+ "CPC",
31
+ "CPM",
32
+ "MULTI_PREMIUM",
33
+ "ABSOLUTE_OCPM",
34
+ "CPA",
35
+ ]
36
+
37
+ CONFIGURED_STATUS = [
38
+ "ACTIVE",
39
+ "PAUSED",
40
+ "DELETED",
41
+ "ARCHIVED",
42
+ ]
43
+
44
+ EFFECTIVE_STATUS = [
45
+ "ACTIVE",
46
+ "PAUSED",
47
+ "DELETED",
48
+ "PENDING_REVIEW",
49
+ "DISAPPROVED",
50
+ "PREAPPROVED",
51
+ "PENDING_BILLING_INFO",
52
+ "CAMPAIGN_PAUSED",
53
+ "ARCHIVED",
54
+ "ADSET_PAUSED",
55
+ ]
56
+
57
+ STATUS = [
58
+ "ACTIVE",
59
+ "PAUSED",
60
+ "DELETED",
61
+ "ARCHIVED",
62
+ ]
63
+
64
+ DATE_PRESET = [
65
+ "today",
66
+ "yesterday",
67
+ "this_month",
68
+ "last_month",
69
+ "this_quarter",
70
+ "lifetime",
71
+ "last_3d",
72
+ "last_7d",
73
+ "last_14d",
74
+ "last_28d",
75
+ "last_30d",
76
+ "last_90d",
77
+ "last_week_mon_sun",
78
+ "last_week_sun_sat",
79
+ "last_quarter",
80
+ "last_year",
81
+ "this_week_mon_today",
82
+ "this_week_sun_today",
83
+ "this_year",
84
+ ]
85
+
86
+ EXECUTION_OPTIONS = [
87
+ "validate_only",
88
+ "synchronous_ad_review",
89
+ "include_recommendations",
90
+ ]
91
+
92
+ OPERATOR = [
93
+ "ALL",
94
+ "ANY",
95
+ ]
96
+
97
+
98
+ field :account_id, 'string'
99
+ field :ad_review_feedback, 'AdgroupReviewFeedback'
100
+ field :adlabels, { list: 'AdLabel' }
101
+ field :adset, 'AdSet'
102
+ field :adset_id, 'string'
103
+ field :bid_amount, 'int'
104
+ field :bid_info, 'map<string, unsigned int>'
105
+ field :bid_type, { enum: -> { BID_TYPE }}
106
+ field :campaign, 'Campaign'
107
+ field :campaign_id, 'string'
108
+ field :configured_status, { enum: -> { CONFIGURED_STATUS }}
109
+ field :conversion_specs, { list: 'ConversionActionQuery' }
110
+ field :created_time, 'datetime'
111
+ field :creative, 'AdCreative'
112
+ field :effective_status, { enum: -> { EFFECTIVE_STATUS }}
113
+ field :id, 'string'
114
+ field :last_updated_by_app_id, 'string'
115
+ field :name, 'string'
116
+ field :recommendations, { list: 'AdRecommendation' }
117
+ field :status, { enum: -> { STATUS }}
118
+ field :tracking_specs, { list: 'ConversionActionQuery' }
119
+ field :updated_time, 'datetime'
120
+ field :adset_spec, 'AdSet'
121
+ field :date_format, 'string'
122
+ field :display_sequence, 'int'
123
+ field :execution_options, { list: { enum: -> { EXECUTION_OPTIONS }} }
124
+ field :redownload, 'bool'
125
+
126
+ has_edge :adcreatives do |edge|
127
+ edge.get 'AdCreative'
128
+ end
129
+
130
+ has_edge :adlabels do |edge|
131
+ edge.delete do |api|
132
+ api.has_param :adlabels, { list: 'object' }
133
+ api.has_param :execution_options, { list: { enum: -> { AdLabel::EXECUTION_OPTIONS }} }
134
+ end
135
+ edge.post 'AdLabel' do |api|
136
+ api.has_param :adlabels, { list: 'object' }
137
+ api.has_param :execution_options, { list: { enum: -> { AdLabel::EXECUTION_OPTIONS }} }
138
+ end
139
+ end
140
+
141
+ has_edge :insights do |edge|
142
+ edge.get 'AdsInsights' do |api|
143
+ api.has_param :action_attribution_windows, { list: { enum: -> { AdsInsights::ACTION_ATTRIBUTION_WINDOWS }} }
144
+ api.has_param :action_breakdowns, { list: { enum: -> { AdsInsights::ACTION_BREAKDOWNS }} }
145
+ api.has_param :action_report_time, { enum: -> { AdsInsights::ACTION_REPORT_TIME }}
146
+ api.has_param :breakdowns, { list: { enum: -> { AdsInsights::BREAKDOWNS }} }
147
+ api.has_param :date_preset, { enum: -> { AdsInsights::DATE_PRESET }}
148
+ api.has_param :default_summary, 'bool'
149
+ api.has_param :export_columns, { list: 'string' }
150
+ api.has_param :export_format, 'string'
151
+ api.has_param :export_name, 'string'
152
+ api.has_param :fields, { list: { enum: -> { AdsInsights::SUMMARY }} }
153
+ api.has_param :filtering, { list: 'object' }
154
+ api.has_param :level, { enum: -> { AdsInsights::LEVEL }}
155
+ api.has_param :product_id_limit, 'int'
156
+ api.has_param :sort, { list: 'string' }
157
+ api.has_param :summary, { list: { enum: -> { AdsInsights::SUMMARY }} }
158
+ api.has_param :summary_action_breakdowns, { list: { enum: -> { AdsInsights::SUMMARY_ACTION_BREAKDOWNS }} }
159
+ api.has_param :time_increment, 'string'
160
+ api.has_param :time_range, 'object'
161
+ api.has_param :time_ranges, { list: 'object' }
162
+ end
163
+ edge.post 'AdReportRun' do |api|
164
+ api.has_param :action_attribution_windows, { list: { enum: -> { AdsInsights::ACTION_ATTRIBUTION_WINDOWS }} }
165
+ api.has_param :action_breakdowns, { list: { enum: -> { AdsInsights::ACTION_BREAKDOWNS }} }
166
+ api.has_param :action_report_time, { enum: -> { AdsInsights::ACTION_REPORT_TIME }}
167
+ api.has_param :breakdowns, { list: { enum: -> { AdsInsights::BREAKDOWNS }} }
168
+ api.has_param :date_preset, { enum: -> { AdsInsights::DATE_PRESET }}
169
+ api.has_param :default_summary, 'bool'
170
+ api.has_param :export_columns, { list: 'string' }
171
+ api.has_param :export_format, 'string'
172
+ api.has_param :export_name, 'string'
173
+ api.has_param :fields, { list: { enum: -> { AdsInsights::SUMMARY }} }
174
+ api.has_param :filtering, { list: 'object' }
175
+ api.has_param :level, { enum: -> { AdsInsights::LEVEL }}
176
+ api.has_param :product_id_limit, 'int'
177
+ api.has_param :sort, { list: 'string' }
178
+ api.has_param :summary, { list: { enum: -> { AdsInsights::SUMMARY }} }
179
+ api.has_param :summary_action_breakdowns, { list: { enum: -> { AdsInsights::SUMMARY_ACTION_BREAKDOWNS }} }
180
+ api.has_param :time_increment, 'string'
181
+ api.has_param :time_range, 'object'
182
+ api.has_param :time_ranges, { list: 'object' }
183
+ end
184
+ end
185
+
186
+ has_edge :keywordstats do |edge|
187
+ edge.get 'AdKeywordStats' do |api|
188
+ api.has_param :date, 'datetime'
189
+ end
190
+ end
191
+
192
+ has_edge :leads do |edge|
193
+ edge.get 'Lead'
194
+ end
195
+
196
+ has_edge :previews do |edge|
197
+ edge.get 'AdPreview' do |api|
198
+ api.has_param :ad_format, { enum: -> { AdPreview::AD_FORMAT }}
199
+ api.has_param :end_date, 'datetime'
200
+ api.has_param :height, 'int'
201
+ api.has_param :locale, 'string'
202
+ api.has_param :place_page_id, 'int'
203
+ api.has_param :post, 'object'
204
+ api.has_param :product_item_ids, { list: 'string' }
205
+ api.has_param :start_date, 'datetime'
206
+ api.has_param :width, 'int'
207
+ end
208
+ end
209
+
210
+ has_edge :targetingsentencelines do |edge|
211
+ edge.get 'TargetingSentenceLine'
212
+ end
213
+
214
+ end
215
+ end