facebookads 0.0.1 → 0.2.9

Sign up to get free protection for your applications and to get access to all the features.
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