adapi 0.0.9 → 0.1.0
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.
- data/README.markdown +35 -27
- data/adapi.gemspec +8 -8
- data/examples/add_ad_group.rb +13 -7
- data/examples/add_bare_ad_group.rb +12 -6
- data/examples/add_bare_campaign.rb +13 -6
- data/examples/add_campaign.rb +22 -10
- data/examples/add_campaign_criteria.rb +22 -8
- data/examples/add_invalid_ad_group.rb +9 -5
- data/examples/add_invalid_keywords.rb +3 -0
- data/examples/add_invalid_text_ad.rb +12 -6
- data/examples/add_keywords.rb +20 -9
- data/examples/add_text_ads.rb +45 -0
- data/examples/rollback_campaign.rb +37 -14
- data/examples/update_campaign.rb +1 -5
- data/examples/update_complete_campaign.rb +3 -4
- data/lib/adapi.rb +5 -4
- data/lib/adapi/ad.rb +14 -39
- data/lib/adapi/ad/text_ad.rb +38 -23
- data/lib/adapi/ad_group.rb +35 -30
- data/lib/adapi/ad_group_criterion.rb +7 -4
- data/lib/adapi/ad_param.rb +8 -16
- data/lib/adapi/api.rb +88 -8
- data/lib/adapi/campaign.rb +87 -76
- data/lib/adapi/campaign_criterion.rb +6 -4
- data/lib/adapi/campaign_target.rb +6 -4
- data/lib/adapi/config.rb +2 -2
- data/lib/adapi/keyword.rb +11 -58
- data/lib/adapi/version.rb +7 -1
- data/test/integration/create_ad_group_test.rb +48 -0
- data/test/integration/create_campaign_test.rb +1 -4
- data/test/test_helper.rb +49 -0
- metadata +43 -41
data/README.markdown
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
# Adapi
|
1
|
+
# Adapi [](https://codeclimate.com/github/lstejskal/adapi)
|
2
2
|
|
3
|
-
## Description
|
3
|
+
## Description
|
4
4
|
|
5
5
|
Adapi (ADwords API) is a Ruby library for easy and painless work with Google
|
6
6
|
Adwords API. Its users shouldn't bother with SOAP and tangle of XML- and
|
@@ -21,11 +21,13 @@ come from there, but adapi takes it several steps further:
|
|
21
21
|
Adapi is *still in development* and not nearly done yet! Version 1.0.0 should
|
22
22
|
have all planned functionality.
|
23
23
|
|
24
|
-
|
24
|
+
Adapi supports the latest version of AdWords API: *v201206*.
|
25
|
+
|
26
|
+
## Installation
|
25
27
|
|
26
28
|
`gem install adapi`
|
27
29
|
|
28
|
-
### from git repository
|
30
|
+
### from git repository
|
29
31
|
|
30
32
|
```
|
31
33
|
git clone git@github.com:lstejskal/adapi.git
|
@@ -34,17 +36,17 @@ bundle install
|
|
34
36
|
rake install
|
35
37
|
```
|
36
38
|
|
37
|
-
## Configuration
|
39
|
+
## Configuration
|
38
40
|
|
39
41
|
This section explains how to connect to specific AdWords account and client.
|
40
42
|
There are several options to choose from:
|
41
43
|
|
42
|
-
#### Configuration by adwords_api.yml
|
44
|
+
#### Configuration by adwords_api.yml
|
43
45
|
|
44
46
|
If you already have `google-adwords-api` gem configured and use just one account,
|
45
47
|
the same configuration will also work for adapi: `~/adwords_api.yml`
|
46
48
|
|
47
|
-
#### Single account set directly in code
|
49
|
+
#### Single account set directly in code
|
48
50
|
|
49
51
|
```ruby
|
50
52
|
Adapi::Config.load_settings(:in_hash => {
|
@@ -66,7 +68,7 @@ Adapi::Config.load_settings(:in_hash => {
|
|
66
68
|
Adapi::Config.set(:sandbox)
|
67
69
|
```
|
68
70
|
|
69
|
-
#### Multiple accounts set directly in code
|
71
|
+
#### Multiple accounts set directly in code
|
70
72
|
|
71
73
|
You can set many AdWords accounts to connect to and switch between while running
|
72
74
|
the application. You can even update single values of the settings on-the-fly.
|
@@ -110,7 +112,7 @@ Adapi::Config.set(:coca_cola, :client_customer_id => '777-666-5555')
|
|
110
112
|
# do some stuff here...
|
111
113
|
```
|
112
114
|
|
113
|
-
#### Configuration by `adapi.yml`
|
115
|
+
#### Configuration by `adapi.yml`
|
114
116
|
|
115
117
|
Stored in `~/adapi.yml`. Supports multiple accounts, which are identifed by
|
116
118
|
aliases. Example:
|
@@ -149,7 +151,7 @@ Adapi::Config.set(:sandbox)
|
|
149
151
|
`:default` account available, you have to manually set account alias to
|
150
152
|
`Adapi::Config`.
|
151
153
|
|
152
|
-
### Authentication workflow
|
154
|
+
### Authentication workflow
|
153
155
|
|
154
156
|
* try to load configuration from `~/adapi.yml`
|
155
157
|
* if `~/adapi.yml`doesn't exist, try to load configuration from
|
@@ -157,16 +159,22 @@ Adapi::Config.set(:sandbox)
|
|
157
159
|
* if there are no configuration files available, set configuration directly to
|
158
160
|
`Adapi::Config` (overrides previous settings)
|
159
161
|
|
160
|
-
## API Version Support
|
162
|
+
## API Version Support
|
163
|
+
|
164
|
+
Adapi supports the latest version of AdWords API: *v201206*.
|
161
165
|
|
162
|
-
|
163
|
-
|
166
|
+
For support of earlier versions of AdWords API, downgrade to earlier
|
167
|
+
versions of adapi: 0.0.9 for *v201109_1*, 0.07 for *v201109*.
|
168
|
+
(You shoudn't need it though, because older versions of AdWords API are
|
169
|
+
eventually shut down.) Latest revision for specific AdWords API version
|
170
|
+
is also marked by a tag.
|
164
171
|
|
165
|
-
|
166
|
-
|
167
|
-
|
172
|
+
Adapi tries to not to bother users with AdWords API low-level specifics as much
|
173
|
+
as possible, if you're upgrading to newer version of AdWords API, please be cautious,
|
174
|
+
check the [release notes](https://developers.google.com/adwords/api/docs/reference/)
|
175
|
+
and update your code accordingly. Adapi won't accept obsolete attributes etc.
|
168
176
|
|
169
|
-
## Unsupported AdWords services
|
177
|
+
## Unsupported AdWords services
|
170
178
|
|
171
179
|
Following AdWords services are not supported by adapi at the moment. However,
|
172
180
|
they will be implemented (this also serves as TODO list):
|
@@ -188,18 +196,18 @@ they will be implemented (this also serves as TODO list):
|
|
188
196
|
* MutateJobService
|
189
197
|
* BulkMutateJobService
|
190
198
|
|
191
|
-
## Examples
|
199
|
+
## Examples
|
192
200
|
|
193
201
|
Examples are available in [examples directory](./master/examples/). For now, they
|
194
202
|
are mostly just uninspired rewrites of examples from `google-adwords-api` gem,
|
195
203
|
but that's going to change when proper UI to AdWords models will be implemented.
|
196
204
|
|
197
|
-
### Getting started
|
205
|
+
### Getting started
|
198
206
|
|
199
207
|
Here are some examples to get you started with adapi. (All this is also
|
200
208
|
available in [examples directory](./master/examples/).)
|
201
209
|
|
202
|
-
#### Create complete campaign
|
210
|
+
#### Create complete campaign
|
203
211
|
|
204
212
|
Creates a campaign with ad_groups and ad_texts from hash - by single method call.
|
205
213
|
|
@@ -246,7 +254,7 @@ campaign = Adapi::Campaign.create(
|
|
246
254
|
)
|
247
255
|
```
|
248
256
|
|
249
|
-
#### Create campaign step by step
|
257
|
+
#### Create campaign step by step
|
250
258
|
|
251
259
|
Creates a campaign with ad_groups and ad_texts step by step.
|
252
260
|
|
@@ -295,7 +303,7 @@ new_campaign = Adapi::Campaign.find_complete(campaign.id)
|
|
295
303
|
puts new_campaign.to_hash.inspect
|
296
304
|
```
|
297
305
|
|
298
|
-
#### Create campaign criteria
|
306
|
+
#### Create campaign criteria
|
299
307
|
|
300
308
|
Campaign criteria (formerly targets) have been rewritten from the scratch for
|
301
309
|
*v201109*. The goal is to provide a simple DSL for criteria so user doesn't have
|
@@ -303,7 +311,7 @@ to deal with somewhat convoluted AdWords API syntax made for machines, not
|
|
303
311
|
humans. So far, this has been done only for *language* and *location* criterion.
|
304
312
|
You can use any other criteria, you just have to enter them in AdWords format.
|
305
313
|
|
306
|
-
##### Language
|
314
|
+
##### Language
|
307
315
|
|
308
316
|
```ruby
|
309
317
|
Adapi::CampaignCriterion.create(
|
@@ -317,7 +325,7 @@ Adapi::CampaignCriterion.create(
|
|
317
325
|
`:language` parameter accepts string or symbols for single language target or
|
318
326
|
array of strings/symbols for several language targets.
|
319
327
|
|
320
|
-
##### Location
|
328
|
+
##### Location
|
321
329
|
|
322
330
|
```ruby
|
323
331
|
Adapi::CampaignCriterion.create(
|
@@ -384,7 +392,7 @@ Adapi::CampaignCriterion.create(
|
|
384
392
|
)
|
385
393
|
```
|
386
394
|
|
387
|
-
##### Criterion in AdWords format
|
395
|
+
##### Criterion in AdWords format
|
388
396
|
|
389
397
|
Convenient shortcuts for other criteria besides *language* and *location* are
|
390
398
|
not yet implemented. However, you can use any other criteria, you just have to
|
@@ -399,7 +407,7 @@ Adapi::CampaignCriterion.create(
|
|
399
407
|
)
|
400
408
|
```
|
401
409
|
|
402
|
-
## Logging
|
410
|
+
## Logging
|
403
411
|
|
404
412
|
By default, communication with AdWords API is not logged. In order to log
|
405
413
|
messages of certain log level or above, set `library/log_level` in configuration
|
@@ -421,7 +429,7 @@ Example of logger configuration:
|
|
421
429
|
:log_pretty_format: true
|
422
430
|
```
|
423
431
|
|
424
|
-
## Author
|
432
|
+
## Author
|
425
433
|
|
426
434
|
2011-2012 Lukas Stejskal, Ataxo Interactive, a.s.
|
427
435
|
|
data/adapi.gemspec
CHANGED
@@ -27,20 +27,20 @@ Gem::Specification.new do |s|
|
|
27
27
|
# versions of both gems are freezed, because both gems change a lot and
|
28
28
|
# automatic updates through '~>' can (and already did) break something
|
29
29
|
#
|
30
|
-
s.add_dependency "google-ads-common", "0.
|
31
|
-
s.add_dependency "google-adwords-api", "0.
|
30
|
+
s.add_dependency "google-ads-common", "0.8.0"
|
31
|
+
s.add_dependency "google-adwords-api", "0.7.0"
|
32
32
|
|
33
33
|
s.add_dependency "activemodel", "~> 3.0"
|
34
34
|
s.add_dependency "activesupport", "~> 3.0"
|
35
35
|
s.add_dependency "rake", "~> 0.9.2"
|
36
|
-
s.add_dependency "curb", "~> 0.8.
|
36
|
+
s.add_dependency "curb", "~> 0.8.1"
|
37
37
|
|
38
|
-
s.add_development_dependency "yard", "~> 0.
|
38
|
+
s.add_development_dependency "yard", "~> 0.8"
|
39
39
|
s.add_development_dependency "rcov", "~> 0.9"
|
40
40
|
s.add_development_dependency "turn", "~> 0.9.6"
|
41
|
-
s.add_development_dependency "shoulda"
|
42
|
-
s.add_development_dependency "fakeweb"
|
43
|
-
s.add_development_dependency "factory_girl", "~> 3.3
|
44
|
-
s.add_development_dependency "minitest"
|
41
|
+
s.add_development_dependency "shoulda", "~> 3.1"
|
42
|
+
s.add_development_dependency "fakeweb", "~> 1.3"
|
43
|
+
s.add_development_dependency "factory_girl", "~> 3.3"
|
44
|
+
s.add_development_dependency "minitest", "~> 3.3"
|
45
45
|
|
46
46
|
end
|
data/examples/add_ad_group.rb
CHANGED
@@ -2,12 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'adapi'
|
4
4
|
|
5
|
-
# create campaign
|
6
5
|
require_relative 'add_bare_campaign'
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
ad_group_data = {
|
7
|
+
$ad_group_data = {
|
11
8
|
:name => "AdGroup #%d" % (Time.new.to_f * 1000).to_i,
|
12
9
|
:status => 'ENABLED',
|
13
10
|
:campaign_id => $campaign[:id],
|
@@ -25,7 +22,16 @@ ad_group_data = {
|
|
25
22
|
]
|
26
23
|
}
|
27
24
|
|
28
|
-
$ad_group = Adapi::AdGroup.create(ad_group_data)
|
25
|
+
$ad_group = Adapi::AdGroup.create($ad_group_data)
|
26
|
+
|
27
|
+
unless $ad_group.errors.empty?
|
28
|
+
|
29
|
+
puts "ERROR WHEN CREATING AD GROUP:"
|
30
|
+
pp $ad_group.errors.full_messages
|
31
|
+
|
32
|
+
else
|
33
|
+
|
34
|
+
puts "\nCREATED AD GROUP #{$ad_group[:id]} FOR CAMPAIGN #{$ad_group[:campaign_id]}\n"
|
35
|
+
pp $ad_group.attributes
|
29
36
|
|
30
|
-
|
31
|
-
p $ad_group.attributes
|
37
|
+
end
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require 'adapi'
|
4
4
|
|
5
|
-
# create campaign
|
6
5
|
require_relative 'add_bare_campaign'
|
7
6
|
|
8
7
|
# create ad group with basic data only
|
@@ -14,13 +13,20 @@ $ad_group_data = {
|
|
14
13
|
:status => 'ENABLED',
|
15
14
|
:bids => {
|
16
15
|
:xsi_type => 'BudgetOptimizerAdGroupBids',
|
17
|
-
|
18
|
-
:proxy_keyword_max_cpc => 15,
|
19
|
-
:proxy_site_max_cpc => 30
|
16
|
+
:proxy_keyword_max_cpc => 15
|
20
17
|
}
|
21
18
|
}
|
22
19
|
|
23
20
|
$ad_group = Adapi::AdGroup.create($ad_group_data)
|
24
21
|
|
25
|
-
|
26
|
-
|
22
|
+
unless $ad_group.errors.empty?
|
23
|
+
|
24
|
+
puts "ERROR WHEN CREATING AD GROUP:"
|
25
|
+
pp $ad_group.errors.full_messages
|
26
|
+
|
27
|
+
else
|
28
|
+
|
29
|
+
puts "\nCREATED AD GROUP #{$ad_group[:id]} FOR CAMPAIGN #{$ad_group[:campaign_id]}\n"
|
30
|
+
pp $ad_group.attributes
|
31
|
+
|
32
|
+
end
|
@@ -16,13 +16,20 @@ $campaign_data = {
|
|
16
16
|
:network_setting => {
|
17
17
|
:target_google_search => true,
|
18
18
|
:target_search_network => true,
|
19
|
-
:target_content_network => false
|
20
|
-
:target_content_contextual => false,
|
21
|
-
:target_partner_search_network => false
|
19
|
+
:target_content_network => false
|
22
20
|
}
|
23
21
|
}
|
24
|
-
|
22
|
+
|
25
23
|
$campaign = Adapi::Campaign.create($campaign_data)
|
26
24
|
|
27
|
-
|
28
|
-
|
25
|
+
unless $campaign.errors.empty?
|
26
|
+
|
27
|
+
puts "ERROR WHEN CREATING CAMPAIGN:"
|
28
|
+
pp $campaign.errors.full_messages
|
29
|
+
|
30
|
+
else
|
31
|
+
|
32
|
+
puts "\nCREATED CAMPAIGN #{$campaign[:id]}\n"
|
33
|
+
pp $campaign.attributes
|
34
|
+
|
35
|
+
end
|
data/examples/add_campaign.rb
CHANGED
@@ -15,8 +15,7 @@ campaign_data = {
|
|
15
15
|
:network_setting => {
|
16
16
|
:target_google_search => true,
|
17
17
|
:target_search_network => true,
|
18
|
-
:target_content_network => false
|
19
|
-
:target_content_contextual => false
|
18
|
+
:target_content_network => false
|
20
19
|
},
|
21
20
|
|
22
21
|
# PS: :targets key is obsolete, this should be named :criteria, but it still works
|
@@ -46,15 +45,28 @@ campaign_data = {
|
|
46
45
|
]
|
47
46
|
|
48
47
|
}
|
49
|
-
|
50
|
-
$campaign = Adapi::Campaign.create(campaign_data)
|
51
48
|
|
52
|
-
$campaign = Adapi::Campaign.
|
49
|
+
$campaign = Adapi::Campaign.new(campaign_data)
|
53
50
|
|
54
|
-
|
55
|
-
pp $campaign.attributes
|
51
|
+
$campaign.create
|
56
52
|
|
57
|
-
|
53
|
+
unless $campaign.errors.empty?
|
58
54
|
|
59
|
-
|
60
|
-
pp $
|
55
|
+
puts "ERROR WHEN CREATING CAMPAIGN:"
|
56
|
+
pp $campaign.errors.full_messages
|
57
|
+
|
58
|
+
else
|
59
|
+
|
60
|
+
puts "\nCREATED CAMPAIGN #{$campaign[:id]}\n"
|
61
|
+
|
62
|
+
$campaign = Adapi::Campaign.find($campaign[:id])
|
63
|
+
|
64
|
+
puts "\nCAMPAIGN DATA:"
|
65
|
+
pp $campaign.attributes
|
66
|
+
|
67
|
+
$campaign_criteria = Adapi::CampaignCriterion.find( :campaign_id => $campaign[:id] )
|
68
|
+
|
69
|
+
puts "\nCRITERIA:"
|
70
|
+
pp $campaign_criteria
|
71
|
+
|
72
|
+
end
|
@@ -2,12 +2,11 @@
|
|
2
2
|
|
3
3
|
require 'adapi'
|
4
4
|
|
5
|
-
# create campaign
|
6
5
|
require_relative 'add_bare_campaign'
|
7
6
|
|
8
|
-
$
|
9
|
-
:campaign_id => $campaign
|
10
|
-
:
|
7
|
+
$campaign_criteria_data = {
|
8
|
+
:campaign_id => $campaign[:id],
|
9
|
+
:criteria => {
|
11
10
|
:language => %w{ en cs },
|
12
11
|
|
13
12
|
:location => {
|
@@ -19,9 +18,24 @@ $campaign_criterion = Adapi::CampaignCriterion.new(
|
|
19
18
|
# add custom platform criteria
|
20
19
|
:platform => [ { :id => 30001} ]
|
21
20
|
}
|
22
|
-
|
21
|
+
}
|
23
22
|
|
24
|
-
$
|
23
|
+
$campaign_criteria = Adapi::CampaignCriterion.new($campaign_criteria_data)
|
25
24
|
|
26
|
-
$
|
27
|
-
|
25
|
+
$campaign_criteria.create
|
26
|
+
|
27
|
+
unless $campaign_criteria.errors.empty?
|
28
|
+
|
29
|
+
puts "ERROR WHEN CREATING CAMPAIGN CRITERIA FOR CAMPAIGN #{$campaign[:id]}:"
|
30
|
+
pp $campaign_criteria.errors.full_messages
|
31
|
+
|
32
|
+
else
|
33
|
+
|
34
|
+
puts "\nCREATED CAMPAIGN CRITERIA FOR CAMPAIGN #{$campaign[:id]}\n"
|
35
|
+
|
36
|
+
$campaign_criteria = Adapi::CampaignCriterion.find( :campaign_id => $campaign[:id] )
|
37
|
+
|
38
|
+
puts "\nCRITERIA:"
|
39
|
+
pp $campaign_criteria
|
40
|
+
|
41
|
+
end
|
@@ -27,10 +27,14 @@ ad_group_data = {
|
|
27
27
|
|
28
28
|
$ad_group = Adapi::AdGroup.create(ad_group_data)
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
unless $ad_group.errors.empty?
|
31
|
+
|
32
|
+
puts "ERROR WHEN CREATING AD GROUP:"
|
33
|
+
pp $ad_group.errors.full_messages
|
34
|
+
|
33
35
|
else
|
34
|
-
|
35
|
-
puts $ad_group
|
36
|
+
|
37
|
+
puts "AD GROUP #{$ad_group[:id]} CREATED"
|
38
|
+
pp $ad_group.attributes
|
39
|
+
|
36
40
|
end
|
@@ -4,6 +4,9 @@ require 'adapi'
|
|
4
4
|
|
5
5
|
# Errors will appear only in production, not in sandbox
|
6
6
|
#
|
7
|
+
# Adapi performs exemption requests on receiving policy violation errors.
|
8
|
+
# If keyword errors are exemptable, they will eventually pass.
|
9
|
+
#
|
7
10
|
#Adapi::Config.load_settings
|
8
11
|
#Adapi::Config.set(:production_settings)
|
9
12
|
#
|
@@ -3,6 +3,9 @@ require 'adapi'
|
|
3
3
|
|
4
4
|
# PolicyViolations will appear only in production, not in sandbox
|
5
5
|
#
|
6
|
+
# Adapi performs exemption requests on receiving policy violation errors.
|
7
|
+
# If text_ad errors are exemptable, they will eventually pass.
|
8
|
+
#
|
6
9
|
#Adapi::Config.load_settings
|
7
10
|
#Adapi::Config.set(:production_settings)
|
8
11
|
#
|
@@ -10,21 +13,24 @@ require 'adapi'
|
|
10
13
|
|
11
14
|
require_relative 'add_bare_ad_group'
|
12
15
|
|
16
|
+
# PS: exemptable PolicyViolationError is triggered by "ho":
|
17
|
+
# legimitateword in Czech, but suspicious word in English
|
18
|
+
#
|
13
19
|
$ad = Adapi::Ad::TextAd.create(
|
14
20
|
:ad_group_id => $ad_group[:id],
|
15
|
-
:headline => "
|
16
|
-
:description1 => '
|
17
|
-
:description2 => 'Check out my
|
21
|
+
:headline => "Neo Blog - poznej ho",
|
22
|
+
:description1 => 'Poznej ho kdekoliv',
|
23
|
+
:description2 => 'Check out my ho blog',
|
18
24
|
:url => 'http://www.demcodez.com',
|
19
25
|
:display_url => 'http://www.demcodez.com',
|
20
26
|
:status => 'PAUSED'
|
21
27
|
)
|
22
28
|
|
23
29
|
if $ad.errors.empty?
|
24
|
-
puts "
|
30
|
+
puts "INVALID TEXT AD CREATED"
|
25
31
|
$fresh_ad = Adapi::Ad::TextAd.find(:first, :id => $ad.id, :ad_group_id => $ad_group[:id])
|
26
32
|
pp $fresh_ad.attributes
|
27
33
|
else
|
28
|
-
puts "
|
29
|
-
|
34
|
+
puts "ERRORS:"
|
35
|
+
pp $ad.errors.messages
|
30
36
|
end
|