facebookads 0.0.1 → 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +17 -0
- data/README.md +222 -0
- data/lib/facebook_ads/ad_object.rb +177 -0
- data/lib/facebook_ads/ad_objects/ad.rb +215 -0
- data/lib/facebook_ads/ad_objects/ad_account.rb +665 -0
- data/lib/facebook_ads/ad_objects/ad_account_roas.rb +97 -0
- data/lib/facebook_ads/ad_objects/ad_account_targeting_unified.rb +136 -0
- data/lib/facebook_ads/ad_objects/ad_account_user.rb +39 -0
- data/lib/facebook_ads/ad_objects/ad_activity.rb +123 -0
- data/lib/facebook_ads/ad_objects/ad_async_request.rb +66 -0
- data/lib/facebook_ads/ad_objects/ad_async_request_set.rb +68 -0
- data/lib/facebook_ads/ad_objects/ad_async_request_set_notification_result.rb +38 -0
- data/lib/facebook_ads/ad_objects/ad_creative.rb +163 -0
- data/lib/facebook_ads/ad_objects/ad_creative_link_data.rb +62 -0
- data/lib/facebook_ads/ad_objects/ad_creative_link_data_app_link_spec.rb +40 -0
- data/lib/facebook_ads/ad_objects/ad_creative_link_data_call_to_action.rb +75 -0
- data/lib/facebook_ads/ad_objects/ad_creative_link_data_call_to_action_value.rb +46 -0
- data/lib/facebook_ads/ad_objects/ad_creative_link_data_child_attachment.rb +47 -0
- data/lib/facebook_ads/ad_objects/ad_creative_object_story_spec.rb +43 -0
- data/lib/facebook_ads/ad_objects/ad_creative_offer_data.rb +44 -0
- data/lib/facebook_ads/ad_objects/ad_creative_photo_data.rb +42 -0
- data/lib/facebook_ads/ad_objects/ad_creative_place_data.rb +41 -0
- data/lib/facebook_ads/ad_objects/ad_creative_text_data.rb +37 -0
- data/lib/facebook_ads/ad_objects/ad_creative_video_data.rb +48 -0
- data/lib/facebook_ads/ad_objects/ad_image.rb +58 -0
- data/lib/facebook_ads/ad_objects/ad_keyword_stats.rb +55 -0
- data/lib/facebook_ads/ad_objects/ad_label.rb +57 -0
- data/lib/facebook_ads/ad_objects/ad_place_page_set.rb +44 -0
- data/lib/facebook_ads/ad_objects/ad_preview.rb +54 -0
- data/lib/facebook_ads/ad_objects/ad_promoted_object.rb +64 -0
- data/lib/facebook_ads/ad_objects/ad_recommendation.rb +55 -0
- data/lib/facebook_ads/ad_objects/ad_recommendation_data.rb +37 -0
- data/lib/facebook_ads/ad_objects/ad_report_run.rb +70 -0
- data/lib/facebook_ads/ad_objects/ad_set.rb +267 -0
- data/lib/facebook_ads/ad_objects/ad_study.rb +69 -0
- data/lib/facebook_ads/ad_objects/ad_study_cell.rb +39 -0
- data/lib/facebook_ads/ad_objects/ad_study_objective.rb +59 -0
- data/lib/facebook_ads/ad_objects/ad_video.rb +25 -0
- data/lib/facebook_ads/ad_objects/adgroup_placement_specific_review_feedback.rb +43 -0
- data/lib/facebook_ads/ad_objects/adgroup_relevance_score.rb +40 -0
- data/lib/facebook_ads/ad_objects/adgroup_review_feedback.rb +38 -0
- data/lib/facebook_ads/ad_objects/ads_action_stats.rb +53 -0
- data/lib/facebook_ads/ad_objects/ads_data_partner.rb +37 -0
- data/lib/facebook_ads/ad_objects/ads_image_crops.rb +42 -0
- data/lib/facebook_ads/ad_objects/ads_insights.rb +225 -0
- data/lib/facebook_ads/ad_objects/ads_pixel.rb +64 -0
- data/lib/facebook_ads/ad_objects/ads_pixel_stats.rb +39 -0
- data/lib/facebook_ads/ad_objects/ads_pixel_stats_result.rb +50 -0
- data/lib/facebook_ads/ad_objects/agency_client_declaration.rb +48 -0
- data/lib/facebook_ads/ad_objects/android_app_link.rb +40 -0
- data/lib/facebook_ads/ad_objects/app_links.rb +43 -0
- data/lib/facebook_ads/ad_objects/broad_targeting_categories.rb +46 -0
- data/lib/facebook_ads/ad_objects/business.rb +242 -0
- data/lib/facebook_ads/ad_objects/business_ad_account_request.rb +37 -0
- data/lib/facebook_ads/ad_objects/business_page_request.rb +37 -0
- data/lib/facebook_ads/ad_objects/campaign.rb +211 -0
- data/lib/facebook_ads/ad_objects/conversion_action_query.rb +63 -0
- data/lib/facebook_ads/ad_objects/custom_audience.rb +166 -0
- data/lib/facebook_ads/ad_objects/custom_audience_ad_account.rb +36 -0
- data/lib/facebook_ads/ad_objects/custom_audience_data_source.rb +94 -0
- data/lib/facebook_ads/ad_objects/custom_audience_permission.rb +41 -0
- data/lib/facebook_ads/ad_objects/custom_audience_prefill_state.rb +39 -0
- data/lib/facebook_ads/ad_objects/custom_audience_session.rb +44 -0
- data/lib/facebook_ads/ad_objects/custom_audience_status.rb +38 -0
- data/lib/facebook_ads/ad_objects/custom_audiences_tos.rb +38 -0
- data/lib/facebook_ads/ad_objects/custom_conversion.rb +78 -0
- data/lib/facebook_ads/ad_objects/custom_conversion_stats_result.rb +50 -0
- data/lib/facebook_ads/ad_objects/day_part.rb +40 -0
- data/lib/facebook_ads/ad_objects/delivery_check.rb +40 -0
- data/lib/facebook_ads/ad_objects/delivery_check_extra_info.rb +39 -0
- data/lib/facebook_ads/ad_objects/delivery_estimate.rb +41 -0
- data/lib/facebook_ads/ad_objects/domain.rb +37 -0
- data/lib/facebook_ads/ad_objects/event.rb +74 -0
- data/lib/facebook_ads/ad_objects/event_source_group.rb +43 -0
- data/lib/facebook_ads/ad_objects/external_event_source.rb +38 -0
- data/lib/facebook_ads/ad_objects/flexible_targeting.rb +64 -0
- data/lib/facebook_ads/ad_objects/funding_source_details.rb +39 -0
- data/lib/facebook_ads/ad_objects/funding_source_details_coupon.rb +40 -0
- data/lib/facebook_ads/ad_objects/helpers/custom_audience_helpers.rb +170 -0
- data/lib/facebook_ads/ad_objects/hotel.rb +61 -0
- data/lib/facebook_ads/ad_objects/hotel_room.rb +44 -0
- data/lib/facebook_ads/ad_objects/id_name.rb +37 -0
- data/lib/facebook_ads/ad_objects/ios_app_link.rb +39 -0
- data/lib/facebook_ads/ad_objects/lead.rb +47 -0
- data/lib/facebook_ads/ad_objects/lead_gen_qualifier.rb +40 -0
- data/lib/facebook_ads/ad_objects/lead_gen_question.rb +40 -0
- data/lib/facebook_ads/ad_objects/lead_gen_question_option.rb +38 -0
- data/lib/facebook_ads/ad_objects/leadgen_form.rb +70 -0
- data/lib/facebook_ads/ad_objects/legacy_business_ad_account_request.rb +38 -0
- data/lib/facebook_ads/ad_objects/lookalike_spec.rb +43 -0
- data/lib/facebook_ads/ad_objects/minimum_budget.rb +41 -0
- data/lib/facebook_ads/ad_objects/offsite_pixel.rb +57 -0
- data/lib/facebook_ads/ad_objects/outcome_prediction_point.rb +40 -0
- data/lib/facebook_ads/ad_objects/partner_category.rb +51 -0
- data/lib/facebook_ads/ad_objects/product_catalog.rb +257 -0
- data/lib/facebook_ads/ad_objects/product_catalog_hotel_rooms_batch.rb +50 -0
- data/lib/facebook_ads/ad_objects/product_catalog_image_settings.rb +38 -0
- data/lib/facebook_ads/ad_objects/product_catalog_image_settings_operation.rb +37 -0
- data/lib/facebook_ads/ad_objects/product_catalog_pricing_variables_batch.rb +50 -0
- data/lib/facebook_ads/ad_objects/product_feed.rb +88 -0
- data/lib/facebook_ads/ad_objects/product_feed_schedule.rb +61 -0
- data/lib/facebook_ads/ad_objects/product_feed_upload.rb +48 -0
- data/lib/facebook_ads/ad_objects/product_feed_upload_error.rb +49 -0
- data/lib/facebook_ads/ad_objects/product_feed_upload_error_sample.rb +37 -0
- data/lib/facebook_ads/ad_objects/product_group.rb +98 -0
- data/lib/facebook_ads/ad_objects/product_item.rb +147 -0
- data/lib/facebook_ads/ad_objects/product_item_commerce_insights.rb +39 -0
- data/lib/facebook_ads/ad_objects/product_set.rb +49 -0
- data/lib/facebook_ads/ad_objects/product_variant.rb +39 -0
- data/lib/facebook_ads/ad_objects/profile_picture_source.rb +52 -0
- data/lib/facebook_ads/ad_objects/rate_card.rb +39 -0
- data/lib/facebook_ads/ad_objects/reach_estimate.rb +60 -0
- data/lib/facebook_ads/ad_objects/reach_frequency_prediction.rb +89 -0
- data/lib/facebook_ads/ad_objects/reach_frequency_spec.rb +42 -0
- data/lib/facebook_ads/ad_objects/rev_share_policy.rb +38 -0
- data/lib/facebook_ads/ad_objects/roas_cohorts_data.rb +41 -0
- data/lib/facebook_ads/ad_objects/roas_cohorts_per_cohort_interval_unit.rb +38 -0
- data/lib/facebook_ads/ad_objects/targeting.rb +133 -0
- data/lib/facebook_ads/ad_objects/targeting_dynamic_rule.rb +44 -0
- data/lib/facebook_ads/ad_objects/targeting_geo_location.rb +47 -0
- data/lib/facebook_ads/ad_objects/targeting_geo_location_city.rb +43 -0
- data/lib/facebook_ads/ad_objects/targeting_geo_location_custom_location.rb +50 -0
- data/lib/facebook_ads/ad_objects/targeting_geo_location_electoral_district.rb +40 -0
- data/lib/facebook_ads/ad_objects/targeting_geo_location_market.rb +40 -0
- data/lib/facebook_ads/ad_objects/targeting_geo_location_place.rb +45 -0
- data/lib/facebook_ads/ad_objects/targeting_geo_location_political_district.rb +40 -0
- data/lib/facebook_ads/ad_objects/targeting_geo_location_region.rb +39 -0
- data/lib/facebook_ads/ad_objects/targeting_geo_location_zip.rb +41 -0
- data/lib/facebook_ads/ad_objects/targeting_product_audience_spec.rb +39 -0
- data/lib/facebook_ads/ad_objects/targeting_product_audience_sub_spec.rb +38 -0
- data/lib/facebook_ads/ad_objects/targeting_sentence_line.rb +38 -0
- data/lib/facebook_ads/ad_objects/transaction.rb +56 -0
- data/lib/facebook_ads/ad_objects/transaction_currency_amount.rb +39 -0
- data/lib/facebook_ads/ad_objects/user.rb +127 -0
- data/lib/facebook_ads/ad_objects/user_lead_gen_disclaimer_response.rb +38 -0
- data/lib/facebook_ads/ad_objects/user_lead_gen_field_data.rb +38 -0
- data/lib/facebook_ads/ad_objects/video_thumbnail.rb +42 -0
- data/lib/facebook_ads/ad_objects/web_app_link.rb +38 -0
- data/lib/facebook_ads/ad_objects/windows_app_link.rb +40 -0
- data/lib/facebook_ads/ad_objects/windows_phone_app_link.rb +39 -0
- data/lib/facebook_ads/api_request.rb +123 -0
- data/lib/facebook_ads/api_response.rb +47 -0
- data/lib/facebook_ads/batch_api/batch.rb +86 -0
- data/lib/facebook_ads/batch_api/batch_proxy.rb +67 -0
- data/lib/facebook_ads/config.rb +43 -0
- data/lib/facebook_ads/edge.rb +184 -0
- data/lib/facebook_ads/errors.rb +55 -0
- data/lib/facebook_ads/field_types/ad_object.rb +37 -0
- data/lib/facebook_ads/field_types/base.rb +33 -0
- data/lib/facebook_ads/field_types/boolean.rb +25 -0
- data/lib/facebook_ads/field_types/datetime.rb +47 -0
- data/lib/facebook_ads/field_types/double.rb +29 -0
- data/lib/facebook_ads/field_types/enum.rb +31 -0
- data/lib/facebook_ads/field_types/integer.rb +33 -0
- data/lib/facebook_ads/field_types/list.rb +57 -0
- data/lib/facebook_ads/field_types/object.rb +33 -0
- data/lib/facebook_ads/field_types/string_type.rb +34 -0
- data/lib/facebook_ads/field_types/upload_file.rb +121 -0
- data/lib/facebook_ads/field_types.rb +65 -0
- data/lib/facebook_ads/fields.rb +66 -0
- data/lib/facebook_ads/helpers/edge_helpers.rb +57 -0
- data/lib/facebook_ads/helpers/node_helpers.rb +80 -0
- data/lib/facebook_ads/helpers/shortcuts.rb +34 -0
- data/lib/facebook_ads/param_set.rb +74 -0
- data/lib/facebook_ads/ruby2patch.rb +27 -0
- data/lib/facebook_ads/session.rb +99 -0
- data/lib/facebook_ads/utils/utils.rb +29 -0
- data/lib/facebook_ads/version.rb +24 -0
- data/lib/facebook_ads/videos/video_io.rb +25 -0
- data/lib/facebook_ads/videos/video_request.rb +42 -0
- data/lib/facebook_ads.rb +72 -0
- metadata +337 -13
- data/lib/facebookads.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5aa03ab8b6c47b81656efca672e6341fc9d76c4
|
4
|
+
data.tar.gz: be8de8a6fea10fda4584841141eb8aeb5398a439
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|