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.
Files changed (41) hide show
  1. data/.gitignore +3 -0
  2. data/README.markdown +176 -0
  3. data/Rakefile +32 -0
  4. data/adapi.gemspec +7 -4
  5. data/examples/add_ad_group.rb +1 -0
  6. data/examples/add_bare_ad_group.rb +2 -6
  7. data/examples/add_bare_campaign.rb +1 -0
  8. data/examples/add_campaign.rb +1 -0
  9. data/examples/add_campaign_targets.rb +1 -0
  10. data/examples/add_invalid_ad_group.rb +1 -0
  11. data/examples/add_keywords.rb +13 -1
  12. data/examples/custom_settings.yml +2 -2
  13. data/examples/customize_configuration.rb +2 -0
  14. data/examples/delete_keyword.rb +27 -0
  15. data/examples/find_all_campaigns.rb +13 -0
  16. data/examples/find_campaign.rb +39 -0
  17. data/examples/find_campaign_ad_groups.rb +25 -0
  18. data/examples/log_to_specific_account.rb +1 -0
  19. data/examples/rollback_campaign.rb +1 -0
  20. data/lib/adapi.rb +8 -5
  21. data/lib/adapi/ad.rb +2 -0
  22. data/lib/adapi/ad/text_ad.rb +15 -0
  23. data/lib/adapi/ad_group.rb +45 -6
  24. data/lib/adapi/ad_group_criterion.rb +14 -0
  25. data/lib/adapi/api.rb +6 -0
  26. data/lib/adapi/campaign.rb +48 -5
  27. data/lib/adapi/campaign_target.rb +67 -8
  28. data/lib/adapi/config.rb +1 -0
  29. data/lib/adapi/keyword.rb +78 -11
  30. data/lib/adapi/version.rb +9 -1
  31. data/lib/httpi_request_monkeypatch.rb +1 -0
  32. data/test/factories/ad_group_factory.rb +4 -13
  33. data/test/factories/ad_text_factory.rb +1 -0
  34. data/test/test_helper.rb +3 -0
  35. data/test/unit/ad/ad_text_test.rb +2 -0
  36. data/test/unit/ad_group_test.rb +11 -2
  37. data/test/unit/ad_test.rb +2 -0
  38. data/test/unit/campaign_target_test.rb +15 -0
  39. metadata +67 -32
  40. data/README.rdoc +0 -162
  41. data/lib/collection.rb +0 -429
data/.gitignore CHANGED
@@ -2,3 +2,6 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+ doc/*
6
+ coverage/*
7
+ .yardoc/*
@@ -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
@@ -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.0" # , :require => "active_model"
24
- s.add_dependency "activesupport", "~> 3.1.0" #, :require => "active_support"
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.15"
26
+ s.add_dependency "curb", "~> 0.7"
27
27
 
28
- s.add_development_dependency "turn"
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
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
 
2
3
  require 'adapi'
3
4
 
@@ -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
- # :keyword_max_cpc => 10
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
 
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
 
2
3
  require 'adapi'
3
4
 
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
 
2
3
  require 'adapi'
3
4
 
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
 
2
3
  require 'adapi'
3
4
 
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
 
2
3
  require 'adapi'
3
4
 
@@ -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
- p $keywords
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
- :client_email: default_client_email@gmail.com
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
- :client_email: sandbox_client_email@gmail.com
19
+ :client_customer_id: 555-666-7777
20
20
  :user_agent: Adwords API Test
21
21
  :service:
22
22
  :environment: SANDBOX
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'adapi'
2
4
 
3
5
  # this example shows how to load custom settings
@@ -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