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.
- 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
|