adapi 0.0.3 → 0.0.4
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/.gitignore +3 -0
- data/README.markdown +176 -0
- data/Rakefile +32 -0
- data/adapi.gemspec +7 -4
- data/examples/add_ad_group.rb +1 -0
- data/examples/add_bare_ad_group.rb +2 -6
- data/examples/add_bare_campaign.rb +1 -0
- data/examples/add_campaign.rb +1 -0
- data/examples/add_campaign_targets.rb +1 -0
- data/examples/add_invalid_ad_group.rb +1 -0
- data/examples/add_keywords.rb +13 -1
- data/examples/custom_settings.yml +2 -2
- data/examples/customize_configuration.rb +2 -0
- data/examples/delete_keyword.rb +27 -0
- data/examples/find_all_campaigns.rb +13 -0
- data/examples/find_campaign.rb +39 -0
- data/examples/find_campaign_ad_groups.rb +25 -0
- data/examples/log_to_specific_account.rb +1 -0
- data/examples/rollback_campaign.rb +1 -0
- data/lib/adapi.rb +8 -5
- data/lib/adapi/ad.rb +2 -0
- data/lib/adapi/ad/text_ad.rb +15 -0
- data/lib/adapi/ad_group.rb +45 -6
- data/lib/adapi/ad_group_criterion.rb +14 -0
- data/lib/adapi/api.rb +6 -0
- data/lib/adapi/campaign.rb +48 -5
- data/lib/adapi/campaign_target.rb +67 -8
- data/lib/adapi/config.rb +1 -0
- data/lib/adapi/keyword.rb +78 -11
- data/lib/adapi/version.rb +9 -1
- data/lib/httpi_request_monkeypatch.rb +1 -0
- data/test/factories/ad_group_factory.rb +4 -13
- data/test/factories/ad_text_factory.rb +1 -0
- data/test/test_helper.rb +3 -0
- data/test/unit/ad/ad_text_test.rb +2 -0
- data/test/unit/ad_group_test.rb +11 -2
- data/test/unit/ad_test.rb +2 -0
- data/test/unit/campaign_target_test.rb +15 -0
- metadata +67 -32
- data/README.rdoc +0 -162
- data/lib/collection.rb +0 -429
data/.gitignore
CHANGED
data/README.markdown
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
# Adapi #
|
2
|
+
|
3
|
+
## Description ##
|
4
|
+
|
5
|
+
Adapi (ADwords API) is a Ruby library for easy and painless work with Google
|
6
|
+
Adwords API. Its users shouldn't bother with SOAP and tangle of XML- and
|
7
|
+
API-specific objects, inputs and outputs are plain Ruby arrays and hashes.
|
8
|
+
|
9
|
+
Adapi is built on `google-adwords-api` gem. Arrays and hashes instead of objects
|
10
|
+
come from there, but adapi takes it several steps further:
|
11
|
+
|
12
|
+
* AdWords services are represented by ActiveModel-compatible models with
|
13
|
+
relations. Among other things it's possible to create whole campaign in
|
14
|
+
single method call: `Adapi::Campaign.create(campaign_data)`.
|
15
|
+
|
16
|
+
* Various convenience methods are added to the models, for example:
|
17
|
+
`campaign.pause!` (pauses campaign).
|
18
|
+
|
19
|
+
* Adapi enables you to easily work with multiple AdWords accounts at the same time.
|
20
|
+
|
21
|
+
Adapi is *still in development* and not nearly done yet! Version 1.0.0 should
|
22
|
+
have all planned functionality.
|
23
|
+
|
24
|
+
## Installation ##
|
25
|
+
|
26
|
+
```
|
27
|
+
gem install adapi
|
28
|
+
```
|
29
|
+
|
30
|
+
### from git repository ###
|
31
|
+
|
32
|
+
```
|
33
|
+
git clone git@github.com:lstejskal/adapi.git
|
34
|
+
cd adapi
|
35
|
+
bundle install
|
36
|
+
rake install
|
37
|
+
```
|
38
|
+
|
39
|
+
## Configuration ##
|
40
|
+
|
41
|
+
This section explains how to connect to specific AdWords account and client.
|
42
|
+
|
43
|
+
You can set many AdWords accounts to connect to and switch between while running
|
44
|
+
the application. You can even update single values of the settings on-the-fly.
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
# load the settings
|
48
|
+
Adapi::Config.load_settings(:in_hash => {
|
49
|
+
:coca_cola => {
|
50
|
+
:authentication => {
|
51
|
+
:method => 'ClientLogin',
|
52
|
+
:email => 'coca_cola_email@gmail.com',
|
53
|
+
:password => 'coca_cola_password',
|
54
|
+
:developer_token => 'coca_cola_developer_token',
|
55
|
+
:user_agent => 'Coca-Cola Adwords API Test'
|
56
|
+
},
|
57
|
+
:service => {
|
58
|
+
:environment => 'SANDBOX'
|
59
|
+
}
|
60
|
+
},
|
61
|
+
:pepsi => {
|
62
|
+
:authentication => {
|
63
|
+
:method => 'ClientLogin',
|
64
|
+
:email => 'pepsi_email@gmail.com',
|
65
|
+
:password => 'pepsi_password',
|
66
|
+
:developer_token => 'pepsi_developer_token',
|
67
|
+
:user_agent => 'Pepsi Adwords API Test'
|
68
|
+
},
|
69
|
+
:service => {
|
70
|
+
:environment => 'SANDBOX'
|
71
|
+
}
|
72
|
+
}
|
73
|
+
})
|
74
|
+
|
75
|
+
# set to pepsi and specific client
|
76
|
+
Adapi::Config.set(:pepsi, :client_customer_id => '555-666-7777')
|
77
|
+
|
78
|
+
# do some stuff here...
|
79
|
+
|
80
|
+
# set to coca-cola and another client
|
81
|
+
Adapi::Config.set(:coca_cola, :client_customer_id => '777-666-5555')
|
82
|
+
|
83
|
+
# do some stuff here...
|
84
|
+
```
|
85
|
+
|
86
|
+
### Authentication workflow ###
|
87
|
+
|
88
|
+
* load configuration from `~/adapi.yml`
|
89
|
+
* load configuration from `~/adwords_api.yml` (default configuration for AdWords gems
|
90
|
+
from Google)
|
91
|
+
* set configuration directly to `Adapi::Config` (overrides previous settings)
|
92
|
+
|
93
|
+
### Configuration by `adapi.yml` ###
|
94
|
+
|
95
|
+
Stored in `~/adapi.yml`. Supports multiple accounts, which are identifed by
|
96
|
+
aliases. Example:
|
97
|
+
|
98
|
+
```
|
99
|
+
:default:
|
100
|
+
:authentication:
|
101
|
+
:method: ClientLogin
|
102
|
+
:email: default_email@gmail.com
|
103
|
+
:password: default_password
|
104
|
+
:developer_token: default_token
|
105
|
+
:client_customer_id: 777-666-5555
|
106
|
+
:user_agent: My Adwords API Client
|
107
|
+
:service:
|
108
|
+
:environment: PRODUCTION
|
109
|
+
|
110
|
+
:sandbox:
|
111
|
+
:authentication:
|
112
|
+
:method: ClientLogin
|
113
|
+
:email: sandbox_email@gmail.com
|
114
|
+
:password: sandbox_password
|
115
|
+
:developer_token: sandbox_token
|
116
|
+
:client_customer_id: 555-666-7777
|
117
|
+
:user_agent: Adwords API Test
|
118
|
+
:service:
|
119
|
+
:environment: SANDBOX
|
120
|
+
```
|
121
|
+
|
122
|
+
You tell adapi which account to use by setting an alias:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
Adapi::Config.set(:sandbox)
|
126
|
+
```
|
127
|
+
|
128
|
+
`:default` account is, as name implies, used by default. You must either set an
|
129
|
+
alias to `Adapi::Config` or have account with `:default` alias available.
|
130
|
+
|
131
|
+
### Configuration by adwords_api.yml ###
|
132
|
+
|
133
|
+
If you already have `google-adwords-api` gem configured and use just one account,
|
134
|
+
the same configuration will also work for adapi: `~/adwords_api.yml`
|
135
|
+
|
136
|
+
### Configuration directly in code ###
|
137
|
+
|
138
|
+
Before logging into the Adwords API, you can set global settings through
|
139
|
+
`Adapi::Config`:
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
# load the settings
|
143
|
+
Adapi::Config.load_settings(:in_hash => {
|
144
|
+
:sandbox => {
|
145
|
+
:authentication => {
|
146
|
+
:method => "ClientLogin"
|
147
|
+
:email => "sandbox_email@gmail.com",
|
148
|
+
:password => "sandbox_password",
|
149
|
+
:developer_token => "sandbox_token",
|
150
|
+
:client_customer_id => "555-666-7777",
|
151
|
+
:user_agent => "Adwords API Test"
|
152
|
+
},
|
153
|
+
:service => {
|
154
|
+
:environment => "SANDBOX"
|
155
|
+
}
|
156
|
+
}
|
157
|
+
})
|
158
|
+
|
159
|
+
Adapi::Config.set(:sandbox)
|
160
|
+
```
|
161
|
+
|
162
|
+
## API Version Support ##
|
163
|
+
|
164
|
+
* adapi supports only the latest version of Google AdWords API: *v201109*
|
165
|
+
* older versions will not be supported (well, maybe *v201101*)
|
166
|
+
* *v201109* and newer versions will still be supported when new versions are released
|
167
|
+
|
168
|
+
## Examples ##
|
169
|
+
|
170
|
+
Example are available in [examples directory](./master/examples/). For now, they
|
171
|
+
are mostly just uninspired rewrites of examples from `google-adwords-api` gem,
|
172
|
+
but that's going to change when proper UI to AdWords models will be implemented.
|
173
|
+
|
174
|
+
## Author ##
|
175
|
+
|
176
|
+
Lukas Stejskal
|
data/Rakefile
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
require 'rake'
|
3
3
|
|
4
|
+
### Tests ###
|
5
|
+
|
4
6
|
task :default => :test
|
5
7
|
|
6
8
|
require 'rake/testtask'
|
@@ -10,3 +12,33 @@ Rake::TestTask.new(:test) do |test|
|
|
10
12
|
test.verbose = true
|
11
13
|
end
|
12
14
|
|
15
|
+
require 'rcov/rcovtask'
|
16
|
+
Rcov::RcovTask.new do |t|
|
17
|
+
t.libs << "test"
|
18
|
+
t.pattern = 'test/*/*_test.rb'
|
19
|
+
t.rcov_opts << '--exclude /gems/'
|
20
|
+
end
|
21
|
+
|
22
|
+
### Documentation ###
|
23
|
+
|
24
|
+
require 'yard'
|
25
|
+
require 'yard/rake/yardoc_task'
|
26
|
+
|
27
|
+
desc "Generate documentation"
|
28
|
+
task :doc => 'doc:generate'
|
29
|
+
|
30
|
+
namespace :doc do
|
31
|
+
GEM_ROOT = File.dirname(__FILE__)
|
32
|
+
RDOC_ROOT = File.join(GEM_ROOT, 'doc')
|
33
|
+
|
34
|
+
YARD::Rake::YardocTask.new(:generate) do |rdoc|
|
35
|
+
rdoc.files = Dir.glob(File.join(GEM_ROOT, 'lib', '**', '*.rb')) +
|
36
|
+
[ File.join(GEM_ROOT, 'README.md') ]
|
37
|
+
rdoc.options = ['--output-dir', RDOC_ROOT, '--readme', 'README.md']
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "Remove generated documentation"
|
41
|
+
task :clobber do
|
42
|
+
FileUtils.rm_rf(RDOC_ROOT) if File.exists?(RDOC_ROOT)
|
43
|
+
end
|
44
|
+
end
|
data/adapi.gemspec
CHANGED
@@ -20,13 +20,16 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
s.add_dependency "google-ads-common", "~> 0.5.0"
|
22
22
|
s.add_dependency "google-adwords-api", "~> 0.4.0"
|
23
|
-
s.add_dependency "activemodel", "~> 3.1
|
24
|
-
s.add_dependency "activesupport", "~> 3.1
|
23
|
+
s.add_dependency "activemodel", "~> 3.1"
|
24
|
+
s.add_dependency "activesupport", "~> 3.1"
|
25
25
|
s.add_dependency "rake", "~> 0.9.2"
|
26
|
-
s.add_dependency "curb", "~> 0.7
|
26
|
+
s.add_dependency "curb", "~> 0.7"
|
27
27
|
|
28
|
-
s.add_development_dependency "
|
28
|
+
s.add_development_dependency "yard", "~> 0.7"
|
29
|
+
s.add_development_dependency "rcov", "~> 0.9"
|
30
|
+
s.add_development_dependency "turn", "0.8.2" # PS: 0.8.3 is broken
|
29
31
|
s.add_development_dependency "shoulda"
|
30
32
|
s.add_development_dependency "fakeweb"
|
31
33
|
s.add_development_dependency "factory_girl"
|
34
|
+
s.add_development_dependency "minitest"
|
32
35
|
end
|
data/examples/add_ad_group.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
|
2
3
|
require 'adapi'
|
3
4
|
|
@@ -15,12 +16,7 @@ $ad_group_data = {
|
|
15
16
|
:bids => {
|
16
17
|
# this should be set automatically, it's dependent on Campaign.bids
|
17
18
|
:xsi_type => 'BudgetOptimizerAdGroupBids',
|
18
|
-
|
19
|
-
:proxy_keyword_max_cpc => {
|
20
|
-
:amount => {
|
21
|
-
:micro_amount => 10000000
|
22
|
-
}
|
23
|
-
}
|
19
|
+
:proxy_keyword_max_cpc => 10
|
24
20
|
}
|
25
21
|
}
|
26
22
|
|
data/examples/add_campaign.rb
CHANGED
data/examples/add_keywords.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
|
2
3
|
require 'adapi'
|
3
4
|
|
@@ -11,4 +12,15 @@ $keywords = Adapi::Keyword.new(
|
|
11
12
|
|
12
13
|
$r = $keywords.create
|
13
14
|
|
14
|
-
|
15
|
+
# get array of keywords from Keyword instance
|
16
|
+
$google_keywords = Adapi::Keyword.find(:all, :ad_group_id => $ad_group[:id]).keywords
|
17
|
+
|
18
|
+
$params_keywords = Adapi::Keyword.parameterized($google_keywords)
|
19
|
+
|
20
|
+
$short_keywords = Adapi::Keyword.shortened($google_keywords)
|
21
|
+
|
22
|
+
p "PARAMS:"
|
23
|
+
pp $params_keywords
|
24
|
+
|
25
|
+
p "\nSHORT:"
|
26
|
+
pp $short_keywords
|
@@ -5,7 +5,7 @@
|
|
5
5
|
:email: default_email@gmail.com
|
6
6
|
:password: default_password
|
7
7
|
:developer_token: default_token
|
8
|
-
:
|
8
|
+
:client_customer_id: 555-666-7777
|
9
9
|
:user_agent: My Adwords API Client
|
10
10
|
:service:
|
11
11
|
:environment: PRODUCTION
|
@@ -16,7 +16,7 @@
|
|
16
16
|
:email: sandbox_email@gmail.com
|
17
17
|
:password: sandbox_password
|
18
18
|
:developer_token: sandbox_token
|
19
|
-
:
|
19
|
+
:client_customer_id: 555-666-7777
|
20
20
|
:user_agent: Adwords API Test
|
21
21
|
:service:
|
22
22
|
:environment: SANDBOX
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'adapi'
|
4
|
+
|
5
|
+
# create ad group
|
6
|
+
require File.join(File.dirname(__FILE__), 'add_bare_ad_group')
|
7
|
+
|
8
|
+
$keywords = Adapi::Keyword.new(
|
9
|
+
:ad_group_id => $ad_group[:id],
|
10
|
+
:keywords => [ 'dem codez', '-hacker' ]
|
11
|
+
)
|
12
|
+
|
13
|
+
$r = $keywords.create
|
14
|
+
|
15
|
+
# get array of keywords for ad_group
|
16
|
+
$google_keywords = Adapi::Keyword.find(:all, :ad_group_id => $ad_group[:id]).keywords
|
17
|
+
|
18
|
+
p "BEFORE DELETE: #{$google_keywords.size} keywords"
|
19
|
+
|
20
|
+
if Adapi::Keyword.new(:ad_group_id => $ad_group[:id]).delete($google_keywords.first[:text][:criterion][:id])
|
21
|
+
p "SUCCESS: first keyword deleted."
|
22
|
+
else
|
23
|
+
p "ERROR: keyword could not be deleted."
|
24
|
+
end
|
25
|
+
|
26
|
+
$google_keywords = Adapi::Keyword.find(:all, :ad_group_id => $ad_group[:id]).keywords
|
27
|
+
p "AFTER DELETE: #{$google_keywords.size} keywords"
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'adapi'
|
4
|
+
|
5
|
+
# find all campaigns for customer
|
6
|
+
|
7
|
+
$campaigns = Adapi::Campaign.find :all
|
8
|
+
|
9
|
+
p "Found %s campaigns." % $campaigns.size
|
10
|
+
|
11
|
+
$campaigns.each do |campaign|
|
12
|
+
p "ID: %s, NAME %s" % [ campaign[:id], campaign[:name] ]
|
13
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'adapi'
|
4
|
+
|
5
|
+
# create campaign
|
6
|
+
require File.join(File.dirname(__FILE__), 'add_campaign')
|
7
|
+
|
8
|
+
$campaign = Adapi::Campaign.find_complete($campaign.id).to_hash
|
9
|
+
|
10
|
+
puts "Campaign id: %s" % $campaign[:id]
|
11
|
+
puts "Name: %s" % $campaign[:name]
|
12
|
+
puts "Status: %s" % $campaign[:status]
|
13
|
+
|
14
|
+
puts "\nBudget delivery method: %s" % $campaign[:budget][:delivery_method]
|
15
|
+
puts "Budget period: %s" % $campaign[:budget][:period]
|
16
|
+
# TODO budget.amount
|
17
|
+
|
18
|
+
puts "\nBidding strategy type: %s" % $campaign[:bidding_strategy][:xsi_type]
|
19
|
+
# TODO bidding_strategy.bid_ceiling
|
20
|
+
|
21
|
+
puts "\nTargets:"
|
22
|
+
$campaign[:targets].each do |target|
|
23
|
+
p target[:xsi_type]
|
24
|
+
p target
|
25
|
+
end
|
26
|
+
|
27
|
+
puts "\nAd groups (#{$campaign[:ad_groups].size} in total):"
|
28
|
+
$campaign[:ad_groups].each do |ad_group|
|
29
|
+
puts "ID: %s, NAME %s, STATUS %s" % [ ad_group[:id], ad_group[:name], ad_group[:status] ]
|
30
|
+
puts "KEYWORDS: %s" % ad_group[:keywords].join(", ")
|
31
|
+
puts "ADS:"
|
32
|
+
ad_group[:ads].each do |ad|
|
33
|
+
puts "\nheadline: %s" % ad[:headline]
|
34
|
+
puts "description1: %s" % ad[:description1]
|
35
|
+
puts "description2: %s" % ad[:description2]
|
36
|
+
puts "url: %s" % ad[:url]
|
37
|
+
puts "display_url: %s" % ad[:display_url]
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'adapi'
|
4
|
+
|
5
|
+
# create campaign
|
6
|
+
require File.join(File.dirname(__FILE__), 'add_bare_ad_group')
|
7
|
+
|
8
|
+
# find all ad_groups for campaign
|
9
|
+
|
10
|
+
$ad_groups = Adapi::AdGroup.find :all, :campaign_id => $campaign.to_param
|
11
|
+
|
12
|
+
p "Found %s ad groups." % $ad_groups.size
|
13
|
+
|
14
|
+
$ad_groups.each do |ad_group|
|
15
|
+
puts "ID: %s, NAME %s, STATUS %s" % [ ad_group[:id], ad_group[:name], ad_group[:status] ]
|
16
|
+
puts "KEYWORDS: %s" % ad_group[:keywords].join(", ")
|
17
|
+
puts "ADS:"
|
18
|
+
ad_group[:ads].each do |ad|
|
19
|
+
puts "\nheadline: %s" % ad[:headline]
|
20
|
+
puts "description1: %s" % ad[:description1]
|
21
|
+
puts "description2: %s" % ad[:description2]
|
22
|
+
puts "url: %s" % ad[:url]
|
23
|
+
puts "display_url: %s" % ad[:display_url]
|
24
|
+
end
|
25
|
+
end
|