adparlor-facebook 0.5.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.gitlab-ci.yml +5 -0
- data/.rspec +2 -0
- data/.rubocop.yml +28 -0
- data/.ruby-version +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +136 -0
- data/Guardfile +13 -0
- data/LICENSE.txt +21 -0
- data/README.md +164 -0
- data/Rakefile +3 -0
- data/adparlor-facebook.gemspec +38 -0
- data/bin/console +18 -0
- data/bin/gitlab_runner_specs.sh +22 -0
- data/bin/setup +7 -0
- data/lib/adparlor/facebook/api.rb +106 -0
- data/lib/adparlor/facebook/config.rb +24 -0
- data/lib/adparlor/facebook/error.rb +13 -0
- data/lib/adparlor/facebook/graph_api/activity.rb +11 -0
- data/lib/adparlor/facebook/graph_api/ad.rb +43 -0
- data/lib/adparlor/facebook/graph_api/ad_account.rb +168 -0
- data/lib/adparlor/facebook/graph_api/ad_creative.rb +22 -0
- data/lib/adparlor/facebook/graph_api/ad_image.rb +87 -0
- data/lib/adparlor/facebook/graph_api/ad_label.rb +12 -0
- data/lib/adparlor/facebook/graph_api/ad_preview.rb +15 -0
- data/lib/adparlor/facebook/graph_api/ad_set.rb +39 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_search.rb +64 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_education_major.rb +11 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_education_school.rb +11 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_geolocation.rb +19 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_geolocation_meta.rb +16 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_geolocations/ad_city.rb +13 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_geolocations/ad_country.rb +13 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_geolocations/ad_geo_market.rb +13 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_geolocations/ad_region.rb +13 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_geolocations/ad_zip_code.rb +13 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_interest.rb +11 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_interest_suggestion.rb +12 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_interest_validation.rb +18 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_locale.rb +11 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_radius_suggestion.rb +11 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_targeting_category.rb +18 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_work_employer.rb +11 -0
- data/lib/adparlor/facebook/graph_api/ad_targeting_types/ad_work_position.rb +11 -0
- data/lib/adparlor/facebook/graph_api/ad_video.rb +124 -0
- data/lib/adparlor/facebook/graph_api/ads_pixel.rb +22 -0
- data/lib/adparlor/facebook/graph_api/ads_pixel_stat.rb +25 -0
- data/lib/adparlor/facebook/graph_api/advertisable_application.rb +11 -0
- data/lib/adparlor/facebook/graph_api/app_event_type.rb +11 -0
- data/lib/adparlor/facebook/graph_api/application.rb +15 -0
- data/lib/adparlor/facebook/graph_api/batch_object.rb +147 -0
- data/lib/adparlor/facebook/graph_api/broad_targeting_category.rb +11 -0
- data/lib/adparlor/facebook/graph_api/business.rb +18 -0
- data/lib/adparlor/facebook/graph_api/campaign.rb +43 -0
- data/lib/adparlor/facebook/graph_api/collection_proxy.rb +36 -0
- data/lib/adparlor/facebook/graph_api/connection_object.rb +11 -0
- data/lib/adparlor/facebook/graph_api/custom_audience.rb +31 -0
- data/lib/adparlor/facebook/graph_api/custom_audience_tos.rb +11 -0
- data/lib/adparlor/facebook/graph_api/custom_audience_user.rb +85 -0
- data/lib/adparlor/facebook/graph_api/custom_conversion.rb +22 -0
- data/lib/adparlor/facebook/graph_api/delivery_estimate.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/activity.rb +12 -0
- data/lib/adparlor/facebook/graph_api/fields/ad.rb +60 -0
- data/lib/adparlor/facebook/graph_api/fields/ad_account.rb +21 -0
- data/lib/adparlor/facebook/graph_api/fields/ad_creative.rb +23 -0
- data/lib/adparlor/facebook/graph_api/fields/ad_image.rb +14 -0
- data/lib/adparlor/facebook/graph_api/fields/ad_label.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/ad_preview.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/ad_set.rb +100 -0
- data/lib/adparlor/facebook/graph_api/fields/ad_video.rb +22 -0
- data/lib/adparlor/facebook/graph_api/fields/ads_pixel.rb +12 -0
- data/lib/adparlor/facebook/graph_api/fields/ads_pixel_stat.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/advertisable_application.rb +17 -0
- data/lib/adparlor/facebook/graph_api/fields/app_event_type.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/application.rb +31 -0
- data/lib/adparlor/facebook/graph_api/fields/broad_targeting_category.rb +12 -0
- data/lib/adparlor/facebook/graph_api/fields/business.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/campaign.rb +17 -0
- data/lib/adparlor/facebook/graph_api/fields/connection_object.rb +16 -0
- data/lib/adparlor/facebook/graph_api/fields/custom_audience.rb +22 -0
- data/lib/adparlor/facebook/graph_api/fields/custom_audience_tos.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/custom_audience_user.rb +14 -0
- data/lib/adparlor/facebook/graph_api/fields/custom_conversion.rb +14 -0
- data/lib/adparlor/facebook/graph_api/fields/delivery_estimate.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/field_decorator.rb +51 -0
- data/lib/adparlor/facebook/graph_api/fields/insight.rb +16 -0
- data/lib/adparlor/facebook/graph_api/fields/instagram_account.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/leadgen_form.rb +23 -0
- data/lib/adparlor/facebook/graph_api/fields/page.rb +121 -0
- data/lib/adparlor/facebook/graph_api/fields/page_and_place.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/partner_category.rb +12 -0
- data/lib/adparlor/facebook/graph_api/fields/picture.rb +17 -0
- data/lib/adparlor/facebook/graph_api/fields/post.rb +17 -0
- data/lib/adparlor/facebook/graph_api/fields/product_audience.rb +12 -0
- data/lib/adparlor/facebook/graph_api/fields/product_catalog.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/product_feed.rb +12 -0
- data/lib/adparlor/facebook/graph_api/fields/product_group.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/product_item.rb +18 -0
- data/lib/adparlor/facebook/graph_api/fields/product_set.rb +13 -0
- data/lib/adparlor/facebook/graph_api/fields/reach_estimate.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/reach_frequency_prediction.rb +24 -0
- data/lib/adparlor/facebook/graph_api/fields/targeting_sentence_line.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/targeting_suggestion.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/targeting_validation.rb +11 -0
- data/lib/adparlor/facebook/graph_api/fields/user_lead_gen_info.rb +18 -0
- data/lib/adparlor/facebook/graph_api/fields/video_thumbnail.rb +11 -0
- data/lib/adparlor/facebook/graph_api/graph_object.rb +140 -0
- data/lib/adparlor/facebook/graph_api/insight.rb +18 -0
- data/lib/adparlor/facebook/graph_api/instagram_account.rb +12 -0
- data/lib/adparlor/facebook/graph_api/leadgen_form.rb +10 -0
- data/lib/adparlor/facebook/graph_api/page.rb +27 -0
- data/lib/adparlor/facebook/graph_api/page_and_place.rb +11 -0
- data/lib/adparlor/facebook/graph_api/partner_category.rb +11 -0
- data/lib/adparlor/facebook/graph_api/picture.rb +15 -0
- data/lib/adparlor/facebook/graph_api/post.rb +17 -0
- data/lib/adparlor/facebook/graph_api/product_audience.rb +17 -0
- data/lib/adparlor/facebook/graph_api/product_catalog.rb +27 -0
- data/lib/adparlor/facebook/graph_api/product_feed.rb +11 -0
- data/lib/adparlor/facebook/graph_api/product_group.rb +11 -0
- data/lib/adparlor/facebook/graph_api/product_item.rb +11 -0
- data/lib/adparlor/facebook/graph_api/product_set.rb +26 -0
- data/lib/adparlor/facebook/graph_api/reach_estimate.rb +17 -0
- data/lib/adparlor/facebook/graph_api/reach_frequency_prediction.rb +18 -0
- data/lib/adparlor/facebook/graph_api/targeting_sentence_line.rb +11 -0
- data/lib/adparlor/facebook/graph_api/targeting_suggestion.rb +16 -0
- data/lib/adparlor/facebook/graph_api/targeting_validation.rb +16 -0
- data/lib/adparlor/facebook/graph_api/traits/methods.rb +64 -0
- data/lib/adparlor/facebook/graph_api/user_lead_gen_info.rb +11 -0
- data/lib/adparlor/facebook/graph_api/video_thumbnail.rb +11 -0
- data/lib/adparlor/facebook/graph_api.rb +9 -0
- data/lib/adparlor/facebook/version.rb +5 -0
- data/lib/adparlor/facebook.rb +9 -0
- data/solano.yml +15 -0
- metadata +391 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 25c8f2e2b346a62b86c650d8b2fdc1b692339416
|
4
|
+
data.tar.gz: f63e094b0eccd481167a8b6fe789271f058f9265
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 815c4f75c9d5ee83f0b728dfaeab0d0ca5d64eae605695db5b3bdfafe975db5fac2b0f2550e378b8d5583b6b5e4d52853ab325df8288dd24ff521bfbe7703559
|
7
|
+
data.tar.gz: f98aeb0de7ab5d0c6ff3bd5abe01822fd639ddf476d52935d914378c41df5b729ccdd803889a31bc6ec72e1f9854898dfb56ec63fe7b3e95b6819dd40d386497
|
data/.gitignore
ADDED
data/.gitlab-ci.yml
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- '*.gemspec'
|
4
|
+
- 'spec/vcr/**/*'
|
5
|
+
|
6
|
+
Documentation:
|
7
|
+
Enabled: false
|
8
|
+
|
9
|
+
Metrics/AbcSize:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
Metrics/ClassLength:
|
13
|
+
Max: 125
|
14
|
+
|
15
|
+
Metrics/LineLength:
|
16
|
+
Enabled: false
|
17
|
+
|
18
|
+
Metrics/MethodLength:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
Style/NumericLiterals:
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
Style/RegexpLiteral:
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
Style/SignalException:
|
28
|
+
Enabled: false
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.3.2
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
adparlor-facebook (0.5.9)
|
5
|
+
faraday
|
6
|
+
faraday_middleware
|
7
|
+
httpclient
|
8
|
+
mime-types
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
addressable (2.6.0)
|
14
|
+
public_suffix (>= 2.0.2, < 4.0)
|
15
|
+
ast (2.4.0)
|
16
|
+
byebug (11.0.1)
|
17
|
+
coderay (1.1.2)
|
18
|
+
crack (0.4.3)
|
19
|
+
safe_yaml (~> 1.0.0)
|
20
|
+
diff-lcs (1.3)
|
21
|
+
docile (1.3.1)
|
22
|
+
faraday (0.15.4)
|
23
|
+
multipart-post (>= 1.2, < 3)
|
24
|
+
faraday_middleware (0.13.1)
|
25
|
+
faraday (>= 0.7.4, < 1.0)
|
26
|
+
ffi (1.10.0)
|
27
|
+
formatador (0.2.5)
|
28
|
+
guard (2.15.0)
|
29
|
+
formatador (>= 0.2.4)
|
30
|
+
listen (>= 2.7, < 4.0)
|
31
|
+
lumberjack (>= 1.0.12, < 2.0)
|
32
|
+
nenv (~> 0.1)
|
33
|
+
notiffany (~> 0.0)
|
34
|
+
pry (>= 0.9.12)
|
35
|
+
shellany (~> 0.0)
|
36
|
+
thor (>= 0.18.1)
|
37
|
+
guard-bundler (2.2.1)
|
38
|
+
bundler (>= 1.3.0, < 3)
|
39
|
+
guard (~> 2.2)
|
40
|
+
guard-compat (~> 1.1)
|
41
|
+
guard-compat (1.2.1)
|
42
|
+
guard-rspec (4.7.3)
|
43
|
+
guard (~> 2.1)
|
44
|
+
guard-compat (~> 1.1)
|
45
|
+
rspec (>= 2.99.0, < 4.0)
|
46
|
+
guard-rubocop (1.3.0)
|
47
|
+
guard (~> 2.0)
|
48
|
+
rubocop (~> 0.20)
|
49
|
+
hashdiff (0.3.9)
|
50
|
+
httpclient (2.8.3)
|
51
|
+
jaro_winkler (1.5.2)
|
52
|
+
json (2.2.0)
|
53
|
+
listen (3.1.5)
|
54
|
+
rb-fsevent (~> 0.9, >= 0.9.4)
|
55
|
+
rb-inotify (~> 0.9, >= 0.9.7)
|
56
|
+
ruby_dep (~> 1.2)
|
57
|
+
lumberjack (1.0.13)
|
58
|
+
method_source (0.9.2)
|
59
|
+
mime-types (3.2.2)
|
60
|
+
mime-types-data (~> 3.2015)
|
61
|
+
mime-types-data (3.2019.0331)
|
62
|
+
multipart-post (2.1.1)
|
63
|
+
nenv (0.3.0)
|
64
|
+
notiffany (0.1.1)
|
65
|
+
nenv (~> 0.1)
|
66
|
+
shellany (~> 0.0)
|
67
|
+
parallel (1.17.0)
|
68
|
+
parser (2.6.3.0)
|
69
|
+
ast (~> 2.4.0)
|
70
|
+
pry (0.12.2)
|
71
|
+
coderay (~> 1.1.0)
|
72
|
+
method_source (~> 0.9.0)
|
73
|
+
public_suffix (3.0.3)
|
74
|
+
rainbow (3.0.0)
|
75
|
+
rake (10.5.0)
|
76
|
+
rb-fsevent (0.10.3)
|
77
|
+
rb-inotify (0.10.0)
|
78
|
+
ffi (~> 1.0)
|
79
|
+
rspec (3.8.0)
|
80
|
+
rspec-core (~> 3.8.0)
|
81
|
+
rspec-expectations (~> 3.8.0)
|
82
|
+
rspec-mocks (~> 3.8.0)
|
83
|
+
rspec-core (3.8.0)
|
84
|
+
rspec-support (~> 3.8.0)
|
85
|
+
rspec-expectations (3.8.3)
|
86
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
87
|
+
rspec-support (~> 3.8.0)
|
88
|
+
rspec-mocks (3.8.0)
|
89
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
90
|
+
rspec-support (~> 3.8.0)
|
91
|
+
rspec-rerun (1.1.0)
|
92
|
+
rspec (~> 3.0)
|
93
|
+
rspec-support (3.8.0)
|
94
|
+
rubocop (0.69.0)
|
95
|
+
jaro_winkler (~> 1.5.1)
|
96
|
+
parallel (~> 1.10)
|
97
|
+
parser (>= 2.6)
|
98
|
+
rainbow (>= 2.2.2, < 4.0)
|
99
|
+
ruby-progressbar (~> 1.7)
|
100
|
+
unicode-display_width (>= 1.4.0, < 1.7)
|
101
|
+
ruby-progressbar (1.10.0)
|
102
|
+
ruby_dep (1.5.0)
|
103
|
+
safe_yaml (1.0.5)
|
104
|
+
shellany (0.0.1)
|
105
|
+
simplecov (0.16.1)
|
106
|
+
docile (~> 1.1)
|
107
|
+
json (>= 1.8, < 3)
|
108
|
+
simplecov-html (~> 0.10.0)
|
109
|
+
simplecov-html (0.10.2)
|
110
|
+
thor (0.20.3)
|
111
|
+
unicode-display_width (1.6.0)
|
112
|
+
vcr (4.0.0)
|
113
|
+
webmock (3.5.1)
|
114
|
+
addressable (>= 2.3.6)
|
115
|
+
crack (>= 0.3.2)
|
116
|
+
hashdiff
|
117
|
+
|
118
|
+
PLATFORMS
|
119
|
+
ruby
|
120
|
+
|
121
|
+
DEPENDENCIES
|
122
|
+
adparlor-facebook!
|
123
|
+
bundler (~> 1.10)
|
124
|
+
byebug
|
125
|
+
guard
|
126
|
+
guard-bundler
|
127
|
+
guard-rspec
|
128
|
+
guard-rubocop
|
129
|
+
rake (~> 10.0)
|
130
|
+
rspec-rerun
|
131
|
+
simplecov
|
132
|
+
vcr
|
133
|
+
webmock
|
134
|
+
|
135
|
+
BUNDLED WITH
|
136
|
+
1.16.2
|
data/Guardfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :rubocop, all_on_start: false do
|
5
|
+
watch(%r{.+\.rb$})
|
6
|
+
watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
|
7
|
+
end
|
8
|
+
|
9
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
10
|
+
watch(%r{^spec/.+_spec\.rb$})
|
11
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
12
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
13
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Kel Stopper
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
### [![build status](https://gitlab.ak-networks.com/ci/projects/8/status.png?ref=master)](https://gitlab.ak-networks.com/ci/projects/8?ref=master) Master (GitLab CI)
|
2
|
+
|
3
|
+
###[![](https://ci.solanolabs.com:443/AdParlor//badges/branches/master?badge_token=b5e0dec703fe9ae000ae346dceb0b7ddd53c91db)](https://ci.solanolabs.com:443/AdParlor/facebook_ruby_ads_sdk/suites/509306) Master (Solano CI)
|
4
|
+
|
5
|
+
# Adparlor::Facebook
|
6
|
+
|
7
|
+
The adparlor-facebook gem is a ruby library for interacting with the Facebook ads API. Supporting both REST and batch requests.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'adparlor-facebook', git: 'https://gitlab.ak-networks.com/adparlor/facebook_ruby_ads_sdk.git'
|
15
|
+
```
|
16
|
+
|
17
|
+
or locally for development
|
18
|
+
|
19
|
+
```bash
|
20
|
+
bundle config local.adparlor-facebook ~/Projects/facebook_ruby_ads_sdk
|
21
|
+
```
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
gem 'adparlor-facebook', branch: 'master'
|
25
|
+
```
|
26
|
+
|
27
|
+
And then execute:
|
28
|
+
|
29
|
+
$ bundle
|
30
|
+
|
31
|
+
<!-- Or install it yourself as:) -->
|
32
|
+
|
33
|
+
<!-- $ gem install adparlor-facebook) -->
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
### Graph API
|
38
|
+
|
39
|
+
Once an access token is obtained [https://developers.facebook.com/docs/facebook-login/access-tokens](https://developers.facebook.com/docs/facebook-login/access-tokens) you can begin
|
40
|
+
making requests to the GraphApi.
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
#Get an ad account by the id
|
44
|
+
account = Adparlor::Facebook::GraphApi::AdAccount.get(account_id, access_token: 'access_token')
|
45
|
+
account.name #-> 'the account name'
|
46
|
+
account.account_status #-> 'the account status'
|
47
|
+
|
48
|
+
#Get an ad creative by the id
|
49
|
+
creative = Adparlor::Facebook::GraphApi::AdCreative.get(creative_id, access_token: 'access_token')
|
50
|
+
creative.id #-> '11111111111111111'
|
51
|
+
|
52
|
+
#The Get method also takes the fields option like the graph api by default only returning the minimal fields
|
53
|
+
creative = Adparlor::Facebook::GraphApi::AdCreative.get(creative_id, access_token: 'access_token', fields: %w(body image_hash image_url ...))
|
54
|
+
#OR
|
55
|
+
creative = Adparlor::Facebook::GraphApi::AdCreative.get(creative_id, access_token: 'access_token', fields: Adparlor::Facebook::GraphApi::AdCreative.fields(:all))
|
56
|
+
creative.id #-> '11111111111111111'
|
57
|
+
creative.name #-> 'the creatives name'
|
58
|
+
creative.thumbnail_url #-> 'https://facebook.com/image...'
|
59
|
+
|
60
|
+
#You can also get objects by their edges as referred to in the Facebook documentation
|
61
|
+
#which returns a memoized array of object types.
|
62
|
+
account = Adparlor::Facebook::GraphApi::AdAccount.get(account_id, access_token: 'access_token')
|
63
|
+
account.adcreatives.all #-> [Adparlor::Facebook::GraphApi::AdCreative<...>, Adparlor::Facebook::GraphApi::AdCreative<...>, Adparlor::Facebook::GraphApi::AdCreative<...>, ...]
|
64
|
+
account.adimages.all #-> [Adparlor::Facebook::GraphApi::AdImage<...>, Adparlor::Facebook::GraphApi::AdImage<...>, Adparlor::Facebook::GraphApi::AdImage<...>, ...]
|
65
|
+
account.campaigns.all #-> [Adparlor::Facebook::GraphApi::Campaign<...>, Adparlor::Facebook::GraphApi::Campaign<...>, Adparlor::Facebook::GraphApi::Campaign<...>, ...]
|
66
|
+
|
67
|
+
#The all method also takes the fields option like the graph api by default only returning the minimal fields
|
68
|
+
account.adcreatives.all.first #-> Adparlor::Facebook::GraphApi::AdCreative<@id => '1111111111111111'>
|
69
|
+
account.adcreatives.all(Adparlor::Facebook::GraphApi::AdCreative.fields(:all))).first #-> Adparlor::Facebook::GraphApi::AdCreative<@id='1111111111111111', @body='...', @image_hash='...'>
|
70
|
+
|
71
|
+
#The edges also implement create and delete options
|
72
|
+
account.adimages.delete(hash: '6aec0dd976393abfad84e8f2511960a8') #-> response.body = {"success" => true}
|
73
|
+
|
74
|
+
account.adimages.create(source: 'http://www.example.com/url/to/image.png')
|
75
|
+
#OR
|
76
|
+
account.adimages.create(source: '/path/to/image.png') #-> response.body = :images => { :url => 'https://facebook.com/image/localtion.png', :hash => 'd0f7567af280e1f6760457ff4df782d8' }
|
77
|
+
```
|
78
|
+
|
79
|
+
### Batch requests
|
80
|
+
|
81
|
+
If making large numbers of requests at the same time or requests that depend on each other the batch object can be used.
|
82
|
+
```ruby
|
83
|
+
#The batch api requires an access token in the case some of the requests use different tokens
|
84
|
+
#or one is not supplied for fallback purposes.
|
85
|
+
account = Adparlor::Facebook::GraphApi::AdAccount.get(account_id, access_token: 'access_token')
|
86
|
+
response = account.batch do |batch|
|
87
|
+
batch.get account.id, AdImage, fields: [:id, :name, :hash] # uses the parent objects token
|
88
|
+
batch.get account.id, Campaign, access_token: account.access_token # uses the parent objects token but it is supplied
|
89
|
+
batch.get account2.id, AdImage, access_token: account2.access_token, fields: [:id, :name, :height]
|
90
|
+
end
|
91
|
+
response #-> [[AdImage, AdImage, ...],[Campaign, Campaign, ...],[AdImage, AdImage, ...]]
|
92
|
+
|
93
|
+
#The object can also be created without an account if the requests are all different accounts or non account level objects
|
94
|
+
#This will use the access token of the first object to be the top level access token
|
95
|
+
response = Adparlor::Facebook::GraphObject.new.batch do |batch|
|
96
|
+
batch.get nil, AdCreative, id: '6666666666666', access_token: 'access_token'
|
97
|
+
batch.get nil, AdCreative, id: '7777777777777', access_token: 'access_token'
|
98
|
+
end
|
99
|
+
|
100
|
+
#Posting follows the same style request, files should be accompanied by the source key.
|
101
|
+
response = account.batch do |batch|
|
102
|
+
batch.post account.id, AdImage, source: 'http://www.example.com/url/for/image.png' # uses the parent objects token
|
103
|
+
batch.post account2.id, AdImage, source: 'http://www.example.com/url/for/othe-image.png', access_token: account2.access_token # uses its own token
|
104
|
+
end
|
105
|
+
response #-> [AdImage, AdImage]
|
106
|
+
|
107
|
+
#Deleting follows the same style request
|
108
|
+
response = account.batch do |batch|
|
109
|
+
batch.delete account.id, AdImage, hash: 'bee06e2e03f9b5a32419855e2c7a4225'
|
110
|
+
batch.delete account.id, AdImage, hash: 'd8ebd0caddecb512ec3b782ae9498e13'
|
111
|
+
end
|
112
|
+
|
113
|
+
#You can mix up requests
|
114
|
+
response = account.batch do |batch|
|
115
|
+
batch.post account.id, AdImage, source: 'http://www.example.com/url/for/image.png'
|
116
|
+
batch.post account2.id, AdImage, source: 'http://www.example.com/url/for/othe-image.png', access_token: account2.access_token
|
117
|
+
batch.get account.id, AdImage, fields: [:id, :name, :hash]
|
118
|
+
batch.get account.id, Campaign
|
119
|
+
end
|
120
|
+
response #-> [AdImage, AdImage, [AdImage, AdImage, ...],[Campaign, Campaign, ...]]
|
121
|
+
|
122
|
+
#You can post requests that are dependent on other requests
|
123
|
+
#In this case the post that another post is dependent on will supply a name to the options parameter
|
124
|
+
#which is then referred to in dependents posts appropriate column.
|
125
|
+
#in this case the campaign post gets the name 'create_campaign' the following request refers to it
|
126
|
+
#using the JSONPath expression format required by the batch api '{result=create_campaign:$.id}'
|
127
|
+
# for more information visit: https://developers.facebook.com/docs/marketing-api/batch-requests/v2.5
|
128
|
+
response = account.batch do |batch|
|
129
|
+
batch.post account.id, Campaign,
|
130
|
+
{ name: 'A Test Campaign', objective: 'LOCAL_AWARENESS', status: 'PAUSED' },
|
131
|
+
name: 'create_campaign'
|
132
|
+
batch.post account.id, AdSet,
|
133
|
+
name: 'A Test AdSet', daily_budget: 135, start_time: '00:05:00',
|
134
|
+
campaign_id: '{result=create_campaign:$.id}', bid_amount: 150,
|
135
|
+
billing_event: 'IMPRESSIONS', optimization_goal: 'REACH',
|
136
|
+
targeting: {
|
137
|
+
geo_locations: { cities: [{ key: '2418956', radius: 12, distance_unit: 'mile' }] },
|
138
|
+
page_types: %w(desktopfeed mobilefeed)
|
139
|
+
}, status: 'PAUSED',
|
140
|
+
promoted_object: { page_id: your_page_id }
|
141
|
+
end
|
142
|
+
response #-> [null, AdSet]
|
143
|
+
```
|
144
|
+
|
145
|
+
## Development
|
146
|
+
|
147
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
148
|
+
|
149
|
+
<!-- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). -->
|
150
|
+
|
151
|
+
<!-- ## Contributing -->
|
152
|
+
|
153
|
+
<!-- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/adparlor-facebook. -->
|
154
|
+
|
155
|
+
## License
|
156
|
+
|
157
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
158
|
+
|
159
|
+
## TODO
|
160
|
+
|
161
|
+
* Create requests should probably return an instance of the object instead of the Faraday body
|
162
|
+
* ?Delete requests should return true if deleted or error message?
|
163
|
+
* Continue to add endpoints
|
164
|
+
* More configurable tests for testing live instead of the vcr cassettes.
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'adparlor/facebook/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'adparlor-facebook'
|
8
|
+
spec.version = Adparlor::Facebook::VERSION
|
9
|
+
spec.authors = ['Kel Stopper', 'Lukas Beaton']
|
10
|
+
spec.email = ['kstopper@adparlor.com', 'lbeaton@adparlor.com']
|
11
|
+
|
12
|
+
spec.summary = 'A ruby implementation of the facebook sdk'
|
13
|
+
spec.description = 'The adparlor-facebook gem is a ruby library for interacting with the Facebook ads API. Supporting both REST and batch requests.'
|
14
|
+
spec.homepage = 'http://adparlor.com'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = 'exe'
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.10'
|
23
|
+
spec.add_development_dependency 'guard'
|
24
|
+
spec.add_development_dependency 'guard-bundler'
|
25
|
+
spec.add_development_dependency 'guard-rspec'
|
26
|
+
spec.add_development_dependency 'guard-rubocop'
|
27
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
28
|
+
spec.add_development_dependency 'rspec-rerun'
|
29
|
+
spec.add_development_dependency 'simplecov'
|
30
|
+
spec.add_development_dependency 'vcr'
|
31
|
+
spec.add_development_dependency 'webmock'
|
32
|
+
spec.add_development_dependency 'byebug'
|
33
|
+
|
34
|
+
spec.add_dependency 'faraday'
|
35
|
+
spec.add_dependency 'faraday_middleware'
|
36
|
+
spec.add_dependency 'httpclient'
|
37
|
+
spec.add_dependency 'mime-types'
|
38
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'adparlor/facebook'
|
5
|
+
|
6
|
+
Adparlor::Facebook.configure do |config|
|
7
|
+
config.api_version = 'v2.5'
|
8
|
+
end
|
9
|
+
|
10
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
11
|
+
# with your gem easier. You can also use a different console, if you like.
|
12
|
+
|
13
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
14
|
+
# require "pry"
|
15
|
+
# Pry.start
|
16
|
+
|
17
|
+
require 'irb'
|
18
|
+
IRB.start
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
printf "\n\nRUNNER SCRIPT: Running as `whoami`"
|
4
|
+
printf "\n\nRUNNER SCRIPT: Running in directory `pwd`"
|
5
|
+
|
6
|
+
printf "\n\nRUNNER SCRIPT: Environment Variables..."
|
7
|
+
printf "\n\n`printenv`"
|
8
|
+
|
9
|
+
printf "\n\nRUNNER SCRIPT: Installing Gems...\n"
|
10
|
+
source ~/.bash_profile
|
11
|
+
rbenv local 2.0.0-p353
|
12
|
+
bin/setup
|
13
|
+
errcode=$?
|
14
|
+
|
15
|
+
if [ "$errcode" != 0 ]
|
16
|
+
then
|
17
|
+
printf "\n\nRUNNER SCRIPT: Gem installation failed!"
|
18
|
+
exit $errcode
|
19
|
+
fi
|
20
|
+
|
21
|
+
printf "\n\nRUNNER SCRIPT: Running specs...\n"
|
22
|
+
VCR_RECORD=all bundle exec rake rspec-rerun:spec
|
data/bin/setup
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_middleware'
|
3
|
+
|
4
|
+
module Adparlor
|
5
|
+
module Facebook
|
6
|
+
module MultipleRequestParamsEncoder
|
7
|
+
def self.encode(query_hash)
|
8
|
+
ids_path(query_hash.delete(:ids), query_hash.delete(:fields), query_hash.delete(:access_token))
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.ids_path(ids, fields, access_token)
|
12
|
+
"ids=[#{ids.join(',')}]&fields=#{fields}&access_token=#{access_token}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module Api
|
17
|
+
def base_uri
|
18
|
+
Adparlor::Facebook.configuration.base_uri
|
19
|
+
end
|
20
|
+
|
21
|
+
def proxy_api_key
|
22
|
+
Adparlor::Facebook.configuration.proxy_api_key
|
23
|
+
end
|
24
|
+
|
25
|
+
def conn
|
26
|
+
Faraday.default_adapter = :httpclient
|
27
|
+
@conn ||= Faraday.new do |faraday|
|
28
|
+
faraday.request :multipart
|
29
|
+
faraday.request :retry, max: 3, exceptions: [Exception]
|
30
|
+
faraday.request :url_encoded
|
31
|
+
faraday.response :json
|
32
|
+
faraday.adapter Faraday.default_adapter
|
33
|
+
faraday.headers['x-api-key'] = proxy_api_key unless proxy_api_key.nil?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def conn_multi
|
38
|
+
@conn_multi ||= Faraday.new(
|
39
|
+
full_url('', {}), request: { params_encoder: Adparlor::Facebook::MultipleRequestParamsEncoder }
|
40
|
+
) do |faraday|
|
41
|
+
faraday.request :retry, max: 3, exceptions: [Exception]
|
42
|
+
faraday.response :json
|
43
|
+
faraday.adapter Faraday.default_adapter
|
44
|
+
faraday.headers['x-api-key'] = proxy_api_key unless proxy_api_key.nil?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def get(path, options = {})
|
49
|
+
options[:fields] = self.class.fields(*options[:fields]) if options[:fields] && options[:fields].is_a?(Array)
|
50
|
+
raise FbError.new('required parameter access_token missing', 500) unless options[:access_token] || path.include?('access_token')
|
51
|
+
if path.to_s.empty? && options.key?(:ids)
|
52
|
+
conn_multi.get '', options
|
53
|
+
else
|
54
|
+
conn.get full_url(path, options), options
|
55
|
+
end
|
56
|
+
rescue Faraday::ParsingError
|
57
|
+
# FB has returned some data that we can't parse into JSON
|
58
|
+
raise FbError.new("Unable to make request.", 500)
|
59
|
+
end
|
60
|
+
|
61
|
+
def post(path, options = {}, method = 'CREATE')
|
62
|
+
self.class.validate_post_fields(*instance_variables.map { |k| k.to_s.delete('@') }, method) if self.class.respond_to?(:validate_post_fields)
|
63
|
+
raise FbError.new('required parameter access_token missing', 500) unless options[:access_token] || path.include?('access_token')
|
64
|
+
body = instance_variables.each_with_object({}) { |var, hash| hash[var.to_s.sub(/@/, '').to_sym] = instance_variable_get(var) }
|
65
|
+
content_type_header = options.delete(:content_type_header)
|
66
|
+
content_type_header ||= body[:source].respond_to?(:content_type) || !@files.nil? ? 'multipart/form-data' : 'application/json'
|
67
|
+
body.delete(:files)
|
68
|
+
body[:bytes] = Base64.encode64(open(body.delete(:source).io, &:read)) if body.key?(:source)
|
69
|
+
conn.post full_url(path, options) do |request|
|
70
|
+
request.headers['Content-Type'] = content_type_header
|
71
|
+
request.params = options
|
72
|
+
request.body = content_type_header == 'multipart/form-data' ? (@files || {}).merge(body) : body.to_json
|
73
|
+
end
|
74
|
+
rescue Faraday::ParsingError
|
75
|
+
# FB has returned some data that we can't parse into JSON
|
76
|
+
raise FbError.new("Unable to make request.", 500)
|
77
|
+
end
|
78
|
+
|
79
|
+
def delete(path, options = {})
|
80
|
+
raise FbError.new('required parameter access_token missing', 500) unless options[:access_token] || path.include?('access_token')
|
81
|
+
conn.delete full_url(path, options) do |request|
|
82
|
+
request.headers['Content-Type'] = 'application/json'
|
83
|
+
request.params = options
|
84
|
+
request.body = instance_variables.each_with_object({}) { |var, hash| hash[var.to_s.sub(/@/, '').to_sym] = instance_variable_get(var) }.to_json
|
85
|
+
end
|
86
|
+
rescue Faraday::ParsingError
|
87
|
+
# FB has returned some data that we can't parse into JSON
|
88
|
+
raise FbError.new("Unable to make request.", 500)
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def api_version(options)
|
94
|
+
"/#{options.delete(:api_version) || Adparlor::Facebook.configuration.api_version}/"
|
95
|
+
end
|
96
|
+
|
97
|
+
def full_url(path, options)
|
98
|
+
if URI.parse(path).scheme
|
99
|
+
path
|
100
|
+
else
|
101
|
+
URI.join(base_uri, api_version(options), path.gsub(%r{\A/}, ''))
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Adparlor
|
2
|
+
module Facebook
|
3
|
+
class << self
|
4
|
+
attr_accessor :configuration
|
5
|
+
|
6
|
+
def configure
|
7
|
+
self.configuration ||= Configuration.new
|
8
|
+
yield configuration
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Configuration
|
13
|
+
attr_accessor :api_version
|
14
|
+
attr_accessor :base_uri
|
15
|
+
attr_accessor :proxy_api_key
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@api_version = 'v2.5'
|
19
|
+
@base_uri = 'https://graph.facebook.com'
|
20
|
+
@proxy_api_key = nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Adparlor
|
2
|
+
module Facebook
|
3
|
+
class Error < StandardError
|
4
|
+
attr_reader :error_code
|
5
|
+
|
6
|
+
def initialize(message, error_code = nil, error_attributes = {})
|
7
|
+
@error_code = error_code
|
8
|
+
error_attributes.each { |key, value| instance_variable_set("@#{key}".to_sym, value) }
|
9
|
+
super message
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|