adparlor-facebook 0.5.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 +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
|
+
### [](https://gitlab.ak-networks.com/ci/projects/8?ref=master) Master (GitLab CI)
|
|
2
|
+
|
|
3
|
+
###[](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
|