adapi 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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