adapi 0.0.4 → 0.0.5

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.
Files changed (49) hide show
  1. data/.gitignore +3 -0
  2. data/GUIDELINES.markdown +61 -0
  3. data/README.markdown +79 -45
  4. data/Rakefile +31 -3
  5. data/adapi.gemspec +10 -3
  6. data/examples/add_ad_group.rb +1 -1
  7. data/examples/add_bare_ad_group.rb +1 -4
  8. data/examples/add_campaign.rb +1 -0
  9. data/examples/add_campaign_criteria.rb +27 -0
  10. data/examples/add_invalid_ad_group.rb +3 -1
  11. data/examples/add_invalid_text_ad.rb +1 -1
  12. data/examples/add_keywords.rb +1 -1
  13. data/examples/add_negative_campaign_criteria.rb +23 -0
  14. data/examples/add_text_ad.rb +1 -1
  15. data/examples/customize_configuration.rb +1 -2
  16. data/examples/delete_keyword.rb +1 -1
  17. data/examples/find_campaign.rb +5 -5
  18. data/examples/find_campaign_ad_groups.rb +1 -1
  19. data/examples/find_campaign_criteria.rb +103 -0
  20. data/examples/find_locations.rb +21 -0
  21. data/examples/rollback_campaign.rb +7 -6
  22. data/examples/update_campaign.rb +1 -1
  23. data/examples/update_campaign_status.rb +1 -1
  24. data/lib/adapi.rb +11 -9
  25. data/lib/adapi/ad/text_ad.rb +2 -1
  26. data/lib/adapi/ad_group.rb +13 -9
  27. data/lib/adapi/ad_param.rb +89 -0
  28. data/lib/adapi/api.rb +8 -0
  29. data/lib/adapi/campaign.rb +27 -18
  30. data/lib/adapi/campaign_criterion.rb +278 -0
  31. data/lib/adapi/campaign_target.rb +5 -123
  32. data/lib/adapi/config.rb +36 -31
  33. data/lib/adapi/constant_data.rb +13 -0
  34. data/lib/adapi/constant_data/language.rb +45 -0
  35. data/lib/adapi/keyword.rb +15 -5
  36. data/lib/adapi/location.rb +91 -0
  37. data/lib/adapi/version.rb +8 -1
  38. data/lib/httpi_request_monkeypatch.rb +4 -0
  39. data/test/config/adapi.yml.template +21 -0
  40. data/test/config/adwords_api.yml.template +10 -0
  41. data/test/integration/create_campaign_test.rb +54 -0
  42. data/test/test_helper.rb +2 -3
  43. data/test/unit/ad_group_test.rb +3 -4
  44. data/test/unit/ad_test.rb +1 -1
  45. data/test/unit/campaign_criterion_test.rb +23 -0
  46. data/test/unit/config_test.rb +52 -0
  47. metadata +48 -35
  48. data/examples/add_campaign_targets.rb +0 -26
  49. data/test/unit/campaign_target_test.rb +0 -51
data/.gitignore CHANGED
@@ -5,3 +5,6 @@ pkg/*
5
5
  doc/*
6
6
  coverage/*
7
7
  .yardoc/*
8
+ adapi.yml
9
+ .rvmrc
10
+ .idea/
@@ -0,0 +1,61 @@
1
+
2
+ ## Commit Guidelines ##
3
+
4
+ Thank you for your pull requests! Please make sure that commits comply with
5
+ following guidelines, so that commit messages will self-explanatory and revision
6
+ history easy to browse and searchable:
7
+
8
+ * commit messages should begin with either *verb* in the simple simple past
9
+ tense (try to use only the following verbs: *Added*, *Changed* or
10
+ *Removed*) or *special prefix* in square brackets:
11
+
12
+ * [FIX] - commit fixes a bug. Message should contain description of the bug.
13
+ Example: https://github.com/lstejskal/adapi/commit/71f881a85a16a174b2faf86c0ec72d5a490db438
14
+
15
+ * [HOTFIX] - commit fixes a bug, but the bugfix is brittle and should be
16
+ improved. Usually this marks a temporary hack which solves an urgent problem.
17
+ Example: https://github.com/lstejskal/adapi/commit/a28e7d1d8d1a26de7e3a380d7fc8153752250388
18
+
19
+ * [REFACTOR] - refactoring without any (or very little) changes in functionality.
20
+ Example: https://github.com/lstejskal/adapi/commit/4eef493857ec0dcb581e88f87c51668c81a97d5d
21
+
22
+ * [BUNDLER] something to do with gems
23
+ Example: https://github.com/lstejskal/adapi/commit/a2838281b725ed6d826495683c822fd81807c674
24
+
25
+ * You can also make create your own custom prefix, but please do it only sparingly.
26
+
27
+ * commit messages should be as short as possible and to the point. Ideally we
28
+ should be able to figure out what the commit is about just by reading the
29
+ commit message, without a glance into the code.
30
+ Example: "[FIX] nil.method error in Keyword#find method"
31
+
32
+ * commits should not be too long, only deal with one thing or a couple of related things
33
+
34
+ * avoid afterthought commits and last-minute fixes so popular in SVN. You're in the git now: ammend and rebase.
35
+
36
+ Example of unnecessary "afterthought" commits:
37
+ 10:00 12345 Added BubbleGum class
38
+ 10:05 12345 [FIX] removed extra comma in BubbleGum class
39
+ 10:15 12345 [REFACTOR] BubbleGum#chew method
40
+
41
+ Last two fixes should be additionaly included to the first commit by `git ammend` command.
42
+
43
+ ## Branch Structure ##
44
+
45
+ * *stable branch* - `master`, obviously. And also branch with the same name
46
+ as current version of gem. For example: if gem is version 0.0.4, stable branch
47
+ in either `master` and `0-0-4`. `master` branch might also contain latest
48
+ bugfixes from development branch.
49
+
50
+ * *development branch* - branch with higher number than current gem version;
51
+ there should be always only one such branch. For example, if gem is version
52
+ 0.0.4, development branch is `0-0-5`. If you living on the edge is your
53
+ thing, use development branch. It's not stable, but it won't be intentionally
54
+ broken either. It contains latest updates and bugfixes. Bigger features have
55
+ their own branches.
56
+
57
+ * *feature branch* - named after feature that's being implemented in it. For
58
+ example: `v201109`, where the latest version of AdWords API is implemented.
59
+ Lots of action is happening there, expect things to be broken, use at your own
60
+ risk and make sure you know what you're doing (like, by reading the source
61
+ code first).
data/README.markdown CHANGED
@@ -23,9 +23,7 @@ have all planned functionality.
23
23
 
24
24
  ## Installation ##
25
25
 
26
- ```
27
- gem install adapi
28
- ```
26
+ `gem install adapi`
29
27
 
30
28
  ### from git repository ###
31
29
 
@@ -39,12 +37,41 @@ rake install
39
37
  ## Configuration ##
40
38
 
41
39
  This section explains how to connect to specific AdWords account and client.
40
+ There are several options to choose from:
41
+
42
+ #### Configuration by adwords_api.yml ####
43
+
44
+ If you already have `google-adwords-api` gem configured and use just one account,
45
+ the same configuration will also work for adapi: `~/adwords_api.yml`
46
+
47
+ #### Single account set directly in code ####
48
+
49
+ ```ruby
50
+ Adapi::Config.load_settings(:in_hash => {
51
+ :sandbox => {
52
+ :authentication => {
53
+ :method => "ClientLogin"
54
+ :email => "sandbox_email@gmail.com",
55
+ :password => "sandbox_password",
56
+ :developer_token => "sandbox_token",
57
+ :client_customer_id => "555-666-7777",
58
+ :user_agent => "Adwords API Test"
59
+ },
60
+ :service => {
61
+ :environment => "SANDBOX"
62
+ }
63
+ }
64
+ })
65
+
66
+ Adapi::Config.set(:sandbox)
67
+ ```
68
+
69
+ #### Multiple accounts set directly in code ####
42
70
 
43
71
  You can set many AdWords accounts to connect to and switch between while running
44
72
  the application. You can even update single values of the settings on-the-fly.
45
73
 
46
74
  ```ruby
47
- # load the settings
48
75
  Adapi::Config.load_settings(:in_hash => {
49
76
  :coca_cola => {
50
77
  :authentication => {
@@ -83,14 +110,7 @@ Adapi::Config.set(:coca_cola, :client_customer_id => '777-666-5555')
83
110
  # do some stuff here...
84
111
  ```
85
112
 
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` ###
113
+ #### Configuration by `adapi.yml` ####
94
114
 
95
115
  Stored in `~/adapi.yml`. Supports multiple accounts, which are identifed by
96
116
  aliases. Example:
@@ -119,51 +139,52 @@ aliases. Example:
119
139
  :environment: SANDBOX
120
140
  ```
121
141
 
122
- You tell adapi which account to use by setting an alias:
142
+ To tell adapi which account to use:
123
143
 
124
144
  ```ruby
125
145
  Adapi::Config.set(:sandbox)
126
146
  ```
127
147
 
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.
148
+ `:default` account is, as name implies, used by default. If you don't have
149
+ `:default` account available, you have to manually set account alias to
150
+ `Adapi::Config`.
130
151
 
131
- ### Configuration by adwords_api.yml ###
152
+ ### Authentication workflow ###
132
153
 
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`
154
+ * try to load configuration from `~/adapi.yml`
155
+ * if `~/adapi.yml`doesn't exist, try to load configuration from
156
+ `~/adwords_api.yml` (used by adwords-api gem)
157
+ * if there are no configuration files available, set configuration directly to
158
+ `Adapi::Config` (overrides previous settings)
135
159
 
136
- ### Configuration directly in code ###
160
+ ## API Version Support ##
137
161
 
138
- Before logging into the Adwords API, you can set global settings through
139
- `Adapi::Config`:
162
+ Adapi 0.0.5 and higher supports only the latest version of Google AdWords API: *v201109*
140
163
 
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
- })
164
+ Older versions of adapi supporting older versions of AdWords API will still be
165
+ available (adapi 0.0.4 supports only v201101), marked by AdWords API version tag.
158
166
 
159
- Adapi::Config.set(:sandbox)
160
- ```
167
+ ## Unsupported AdWords services ##
161
168
 
162
- ## API Version Support ##
169
+ Following AdWords services are not supported by adapi at the moment. However,
170
+ they will be implemented (this also serves as TODO list):
171
+
172
+ * Campaign Data Management
173
+ * ConversionTrackerService
174
+ * UserListService
175
+
176
+ * Optimization
177
+ * BulkOpportunityService
178
+ * ReportDefinitionService
179
+ * TargetingIdeaService
180
+ * TrafficEstimatorService
163
181
 
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
182
+ * Account Management
183
+ * CustomerSyncService
184
+
185
+ * Utility
186
+ * MutateJobService
187
+ * BulkMutateJobService
167
188
 
168
189
  ## Examples ##
169
190
 
@@ -171,6 +192,19 @@ Example are available in [examples directory](./master/examples/). For now, they
171
192
  are mostly just uninspired rewrites of examples from `google-adwords-api` gem,
172
193
  but that's going to change when proper UI to AdWords models will be implemented.
173
194
 
195
+ ## Logging ##
196
+
197
+ *STILL IN BETA* By default, nothing is logged. If you set `library/log_level` in
198
+ configuration, SOAP messages will be logged to `~/adapi.log` file according to
199
+ give log level.
200
+
201
+ Example of logger configuration:
202
+
203
+ ```
204
+ :library:
205
+ :log_level: DEBUG
206
+ ```
207
+
174
208
  ## Author ##
175
209
 
176
- Lukas Stejskal
210
+ 2011-2012 Lukas Stejskal
data/Rakefile CHANGED
@@ -1,14 +1,42 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rake'
3
3
 
4
- ### Tests ###
4
+ task :default do
5
+ # run examples using current gem environment
6
+ # example: rake example=find_campaigns
7
+ #
8
+ if ENV.keys.include?("example")
9
+ ENV["example"] += ".rb" unless ENV["example"] =~ /\.rb$/
10
+ exec "ruby -Ilib examples/%s" % ENV["example"]
11
+
12
+ # load example into irb using current gem environment
13
+ # example: rake irb=find_campaigns
14
+ #
15
+ elsif ENV.keys.include?("irb")
16
+ exec "irb -Ilib -Iexamples -r%s" % ENV["irb"].gsub(/\.rb$/, '')
17
+
18
+ # run default task: test
19
+ #
20
+ else
21
+ Rake::Task['test'].invoke
22
+ end
23
+ end
5
24
 
6
- task :default => :test
25
+ ### Tests ###
7
26
 
27
+ # run all tests except integrations tests
28
+ #
8
29
  require 'rake/testtask'
9
30
  Rake::TestTask.new(:test) do |test|
10
31
  test.libs << %w{ lib test }
11
- test.pattern = 'test/**/*_test.rb'
32
+ test.pattern = 'test/unit/*_test.rb'
33
+ test.verbose = true
34
+ end
35
+
36
+ require 'rake/testtask'
37
+ Rake::TestTask.new(:"test:integration") do |test|
38
+ test.libs << %w{ lib test }
39
+ test.pattern = 'test/integration/*_test.rb'
12
40
  test.verbose = true
13
41
  end
14
42
 
data/adapi.gemspec CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
7
7
  s.version = Adapi::VERSION
8
8
  s.authors = ["Lukas Stejskal"]
9
9
  s.email = ["lucastej@gmail.com"]
10
- s.homepage = ""
10
+ s.homepage = "https://github.com/lstejskal/adapi"
11
11
  s.summary = %q{User-friendly interface to Google Adwords API}
12
12
  s.description = %q{This gem provides user-friendly interface to Google Adwords API.}
13
13
 
@@ -18,8 +18,15 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.add_dependency "google-ads-common", "~> 0.5.0"
22
- s.add_dependency "google-adwords-api", "~> 0.4.0"
21
+ # require specific version of ad-common and adwords-api gems,
22
+ # they're stil changing a lot and automatic updates through '~>'
23
+ # can easily break something
24
+ #
25
+ # PS: ads-common is "freezed" - required before adwords-api
26
+ #
27
+ s.add_dependency "google-ads-common", "0.6.2"
28
+ s.add_dependency "google-adwords-api", "0.5.0"
29
+
23
30
  s.add_dependency "activemodel", "~> 3.1"
24
31
  s.add_dependency "activesupport", "~> 3.1"
25
32
  s.add_dependency "rake", "~> 0.9.2"
@@ -3,7 +3,7 @@
3
3
  require 'adapi'
4
4
 
5
5
  # create campaign
6
- require File.join(File.dirname(__FILE__), 'add_bare_campaign')
6
+ require_relative 'add_bare_campaign'
7
7
 
8
8
  # create ad group
9
9
 
@@ -3,7 +3,7 @@
3
3
  require 'adapi'
4
4
 
5
5
  # create campaign
6
- require File.join(File.dirname(__FILE__), 'add_bare_campaign')
6
+ require_relative 'add_bare_campaign'
7
7
 
8
8
  # create ad group with basic data only
9
9
  # this script is used as an include in other scripts
@@ -12,9 +12,7 @@ $ad_group_data = {
12
12
  :campaign_id => $campaign[:id],
13
13
  :name => "AdGroup #%d" % (Time.new.to_f * 1000).to_i,
14
14
  :status => 'ENABLED',
15
- # TODO refactor AdGroup.bids DSL
16
15
  :bids => {
17
- # this should be set automatically, it's dependent on Campaign.bids
18
16
  :xsi_type => 'BudgetOptimizerAdGroupBids',
19
17
  :proxy_keyword_max_cpc => 10
20
18
  }
@@ -22,6 +20,5 @@ $ad_group_data = {
22
20
 
23
21
  $ad_group = Adapi::AdGroup.create($ad_group_data)
24
22
 
25
-
26
23
  p "Created ad_group ID #{$ad_group.id} for campaign ID #{$ad_group.campaign_id}"
27
24
  p $ad_group.attributes
@@ -19,6 +19,7 @@ campaign_data = {
19
19
  :target_content_contextual => false
20
20
  },
21
21
 
22
+ # PS: :targets key is obsolete, this should be named :criteria, but it still works
22
23
  :targets => {
23
24
  :language => [ 'en', 'cs' ],
24
25
  # TODO test together with city target
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+
3
+ require 'adapi'
4
+
5
+ # create campaign
6
+ require_relative 'add_bare_campaign'
7
+
8
+ $campaign_criterion = Adapi::CampaignCriterion.new(
9
+ :campaign_id => $campaign[:id],
10
+ :criteria => {
11
+ :language => %w{ en cs },
12
+
13
+ :location => {
14
+ :id => 21137
15
+ # :name => { :city => 'Prague', :region => 'CZ-PR', :country => 'CZ' }
16
+ # :proximity => { :geo_point => '50.083333,14.366667', :radius => '50 km' }
17
+ },
18
+
19
+ # add custom platform criteria
20
+ :platform => [ { :id => 30001} ]
21
+ }
22
+ )
23
+
24
+ $campaign_criterion.create
25
+
26
+ p $campaign_criterion.attributes
27
+
@@ -1,9 +1,11 @@
1
1
  # encoding: utf-8
2
2
 
3
+ # This example should throw an error on ad.url
4
+
3
5
  require 'adapi'
4
6
 
5
7
  # create campaign
6
- require File.join(File.dirname(__FILE__), 'add_bare_campaign')
8
+ require_relative 'add_bare_campaign'
7
9
 
8
10
  # create ad group
9
11
 
@@ -9,7 +9,7 @@ require 'adapi'
9
9
  #pp "Running in #{Adapi::Config.read[:service][:environment]}"
10
10
 
11
11
  # create ad group
12
- require File.join(File.dirname(__FILE__), 'add_bare_ad_group')
12
+ require_relative 'add_bare_ad_group'
13
13
 
14
14
  $ad = Adapi::Ad::TextAd.create(
15
15
  :ad_group_id => $ad_group[:id],
@@ -3,7 +3,7 @@
3
3
  require 'adapi'
4
4
 
5
5
  # create ad group
6
- require File.join(File.dirname(__FILE__), 'add_bare_ad_group')
6
+ require_relative 'add_bare_ad_group'
7
7
 
8
8
  $keywords = Adapi::Keyword.new(
9
9
  :ad_group_id => $ad_group[:id],
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ require 'adapi'
4
+
5
+ # create campaign
6
+ require_relative 'add_bare_campaign'
7
+
8
+ $campaign_criterion = Adapi::CampaignCriterion.new(
9
+ :campaign_id => $campaign[:id],
10
+ :negative => true,
11
+ :criteria => {
12
+ :language => %w{ de },
13
+
14
+ :location => {
15
+ :name => { :city => 'Oslo' }
16
+ }
17
+ }
18
+ )
19
+
20
+ $campaign_criterion.create
21
+
22
+ p $campaign_criterion.attributes
23
+