adapi 0.0.8 → 0.0.9

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 (55) hide show
  1. data/.gitignore +1 -1
  2. data/README.markdown +2 -1
  3. data/adapi.gemspec +11 -11
  4. data/examples/add_ad_group.rb +0 -0
  5. data/examples/add_bare_ad_group.rb +3 -1
  6. data/examples/add_bare_campaign.rb +6 -4
  7. data/examples/add_campaign.rb +10 -3
  8. data/examples/add_campaign_criteria.rb +5 -5
  9. data/examples/add_invalid_ad_group.rb +4 -6
  10. data/examples/add_invalid_keywords.rb +40 -0
  11. data/examples/add_invalid_text_ad.rb +6 -6
  12. data/examples/add_keywords.rb +0 -0
  13. data/examples/add_negative_campaign_criteria.rb +0 -0
  14. data/examples/add_text_ad.rb +5 -9
  15. data/examples/custom_settings.yml +8 -0
  16. data/examples/customize_configuration.rb +0 -0
  17. data/examples/delete_ad_group.rb +11 -0
  18. data/examples/delete_keyword.rb +0 -0
  19. data/examples/delete_text_ad.rb +13 -0
  20. data/examples/find_ad_group.rb +10 -0
  21. data/examples/find_all_campaigns.rb +0 -0
  22. data/examples/find_bare_campaign.rb +34 -0
  23. data/examples/find_campaign.rb +0 -0
  24. data/examples/find_campaign_ad_groups.rb +0 -0
  25. data/examples/find_campaign_criteria.rb +0 -0
  26. data/examples/find_locations.rb +0 -0
  27. data/examples/log_to_specific_account.rb +0 -0
  28. data/examples/rollback_campaign.rb +0 -0
  29. data/examples/test_diacritics.rb +0 -0
  30. data/examples/update_ad_group.rb +70 -0
  31. data/examples/update_campaign.rb +34 -9
  32. data/examples/update_campaign_ad_groups.rb +137 -0
  33. data/examples/update_campaign_criteria.rb +33 -0
  34. data/examples/update_complete_campaign.rb +177 -0
  35. data/examples/update_text_ad.rb +18 -0
  36. data/lib/adapi/ad/text_ad.rb +39 -49
  37. data/lib/adapi/ad.rb +30 -19
  38. data/lib/adapi/ad_group.rb +110 -30
  39. data/lib/adapi/api.rb +25 -28
  40. data/lib/adapi/campaign.rb +216 -70
  41. data/lib/adapi/campaign_criterion.rb +44 -5
  42. data/lib/adapi/config.rb +1 -4
  43. data/lib/adapi/constant_data/language.rb +11 -2
  44. data/lib/adapi/keyword.rb +60 -1
  45. data/lib/adapi/version.rb +11 -2
  46. data/lib/adapi.rb +10 -7
  47. data/test/{config/adapi.yml.template → fixtures/adapi.yml} +11 -2
  48. data/test/{config/adwords_api.yml.template → fixtures/adwords_api.yml} +6 -2
  49. data/test/integration/find_location_test.rb +1 -1
  50. data/test/unit/ad_group_test.rb +2 -2
  51. data/test/unit/config_test.rb +8 -27
  52. data/test/unit/constant_data/language_test.rb +34 -0
  53. metadata +52 -108
  54. data/examples/update_campaign_status.rb +0 -15
  55. data/lib/savon_monkeypatch.rb +0 -43
data/.gitignore CHANGED
@@ -5,6 +5,6 @@ pkg/*
5
5
  doc/*
6
6
  coverage/*
7
7
  .yardoc/*
8
- adapi.yml
8
+ ./adapi.yml
9
9
  .rvmrc
10
10
  .idea/
data/README.markdown CHANGED
@@ -423,4 +423,5 @@ Example of logger configuration:
423
423
 
424
424
  ## Author ##
425
425
 
426
- 2011-2012 Lukas Stejskal
426
+ 2011-2012 Lukas Stejskal, Ataxo Interactive, a.s.
427
+
data/adapi.gemspec CHANGED
@@ -18,26 +18,26 @@ 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
- # Requires google-adwords-api gem, which provides low-level interface to
22
- # AdWords API, and its dependecy, google-ads-common gem.
21
+ # google-adwords-api gem provides low-level interface to AdWords API
23
22
  #
24
- # * versions of both gems should be freezed
25
- # * ads-common should be required before adwords-api
26
- #
27
- # PS: versions are freezed because both of these gems change a lot and
23
+ # its core dependency, google-ads-common gem, is also required
24
+ # (before google-adwords-api gem, so the clash of our version
25
+ # with version required by google-adwords api is less probable)
26
+ #
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.7.0"
31
- s.add_dependency "google-adwords-api", "0.6.0"
30
+ s.add_dependency "google-ads-common", "0.7.3"
31
+ s.add_dependency "google-adwords-api", "0.6.2"
32
32
 
33
- s.add_dependency "activemodel", "~> 3.1"
34
- s.add_dependency "activesupport", "~> 3.1"
33
+ s.add_dependency "activemodel", "~> 3.0"
34
+ s.add_dependency "activesupport", "~> 3.0"
35
35
  s.add_dependency "rake", "~> 0.9.2"
36
36
  s.add_dependency "curb", "~> 0.8.0"
37
37
 
38
38
  s.add_development_dependency "yard", "~> 0.7"
39
39
  s.add_development_dependency "rcov", "~> 0.9"
40
- s.add_development_dependency "turn", "0.8.2" # PS: 0.8.3 is broken
40
+ s.add_development_dependency "turn", "~> 0.9.6"
41
41
  s.add_development_dependency "shoulda"
42
42
  s.add_development_dependency "fakeweb"
43
43
  s.add_development_dependency "factory_girl", "~> 3.3.0"
File without changes
@@ -14,7 +14,9 @@ $ad_group_data = {
14
14
  :status => 'ENABLED',
15
15
  :bids => {
16
16
  :xsi_type => 'BudgetOptimizerAdGroupBids',
17
- :proxy_keyword_max_cpc => 10
17
+ # FIXME this probably can't be set
18
+ :proxy_keyword_max_cpc => 15,
19
+ :proxy_site_max_cpc => 30
18
20
  }
19
21
  }
20
22
 
@@ -8,15 +8,17 @@ require 'adapi'
8
8
  $campaign_data = {
9
9
  :name => "Campaign #%d" % (Time.new.to_f * 1000).to_i,
10
10
  :status => 'PAUSED',
11
- # :bidding_strategy => 'ManualCPC',
12
- :bidding_strategy => { :xsi_type => 'BudgetOptimizer', :bid_ceiling => 55 },
11
+ :bidding_strategy => {
12
+ :xsi_type => 'BudgetOptimizer',
13
+ :bid_ceiling => 20
14
+ },
13
15
  :budget => 50,
14
-
15
16
  :network_setting => {
16
17
  :target_google_search => true,
17
18
  :target_search_network => true,
18
19
  :target_content_network => false,
19
- :target_content_contextual => false
20
+ :target_content_contextual => false,
21
+ :target_partner_search_network => false
20
22
  }
21
23
  }
22
24
 
@@ -20,7 +20,7 @@ campaign_data = {
20
20
  },
21
21
 
22
22
  # PS: :targets key is obsolete, this should be named :criteria, but it still works
23
- :targets => {
23
+ :criteria => {
24
24
  :language => [ :en, :cs ],
25
25
  # TODO test together with city target
26
26
  :geo => { :proximity => { :geo_point => '38.89859,-77.035971', :radius => '10 km' } }
@@ -49,5 +49,12 @@ campaign_data = {
49
49
 
50
50
  $campaign = Adapi::Campaign.create(campaign_data)
51
51
 
52
- p "Created campaign ID #{$campaign.id}"
53
- p $campaign.attributes
52
+ $campaign = Adapi::Campaign.find($campaign.id)
53
+
54
+ p "\nCAMPAIGN #{$campaign.id} DATA:"
55
+ pp $campaign.attributes
56
+
57
+ $campaign_criterion = Adapi::CampaignCriterion.find( :campaign_id => $campaign.id )
58
+
59
+ p "\nCAMPAIGN CRITERIA:"
60
+ pp $campaign_criterion
@@ -6,14 +6,14 @@ require 'adapi'
6
6
  require_relative 'add_bare_campaign'
7
7
 
8
8
  $campaign_criterion = Adapi::CampaignCriterion.new(
9
- :campaign_id => $campaign[:id],
9
+ :campaign_id => $campaign.id,
10
10
  :targets => { # obsolete, use :criteria instead
11
11
  :language => %w{ en cs },
12
12
 
13
13
  :location => {
14
- :id => 21137
14
+ # :id => 21137
15
15
  # :name => { :city => 'Prague', :region => 'CZ-PR', :country => 'CZ' }
16
- # :proximity => { :geo_point => '50.083333,14.366667', :radius => '50 km' }
16
+ :proximity => { :geo_point => '50.083333,14.366667', :radius => '50 km' }
17
17
  },
18
18
 
19
19
  # add custom platform criteria
@@ -23,5 +23,5 @@ $campaign_criterion = Adapi::CampaignCriterion.new(
23
23
 
24
24
  $campaign_criterion.create
25
25
 
26
- p $campaign_criterion.attributes
27
-
26
+ $campaign_criterion = Adapi::CampaignCriterion.find( :campaign_id => $campaign.id)
27
+ pp $campaign_criterion
@@ -4,11 +4,8 @@
4
4
 
5
5
  require 'adapi'
6
6
 
7
- # create campaign
8
7
  require_relative 'add_bare_campaign'
9
8
 
10
- # create ad group
11
-
12
9
  ad_group_data = {
13
10
  :name => "AdGroup #%d" % (Time.new.to_f * 1000).to_i,
14
11
  :status => 'ENABLED',
@@ -31,8 +28,9 @@ ad_group_data = {
31
28
  $ad_group = Adapi::AdGroup.create(ad_group_data)
32
29
 
33
30
  if $ad_group.errors.empty?
34
- p $ad_group.data
31
+ puts "OK"
32
+ pp $ad_group.attributes
35
33
  else
36
- p "ERRORS:"
37
- p $ad_group.errors.to_a
34
+ puts "ERROR:"
35
+ puts $ad_group.errors.full_messages.join("\n")
38
36
  end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+
3
+ require 'adapi'
4
+
5
+ # Errors will appear only in production, not in sandbox
6
+ #
7
+ #Adapi::Config.load_settings
8
+ #Adapi::Config.set(:production_settings)
9
+ #
10
+ #pp "Running in #{Adapi::Config.read[:service][:environment]}"
11
+
12
+ # create ad group
13
+ require_relative 'add_bare_ad_group'
14
+
15
+ $keywords = Adapi::Keyword.new(
16
+ :ad_group_id => $ad_group[:id],
17
+ :keywords => [ 'lékárna', 'lekarna', 'leky' ]
18
+ )
19
+
20
+ $result = $keywords.create
21
+
22
+ if $keywords.errors.empty?
23
+ puts "OK"
24
+
25
+ # get array of keywords from Keyword instance
26
+ $google_keywords = Adapi::Keyword.find(:all, :ad_group_id => $ad_group[:id]).keywords
27
+
28
+ $params_keywords = Adapi::Keyword.parameterized($google_keywords)
29
+
30
+ $short_keywords = Adapi::Keyword.shortened($google_keywords)
31
+
32
+ puts "PARAMS:"
33
+ pp $params_keywords
34
+
35
+ puts "\nSHORT:"
36
+ pp $short_keywords
37
+ else
38
+ puts "ERROR"
39
+ puts $keywords.errors.full_messages.join("\n")
40
+ end
@@ -1,14 +1,13 @@
1
1
 
2
2
  require 'adapi'
3
3
 
4
- # PolicyViolations will appread only in production, not in sandbox
4
+ # PolicyViolations will appear only in production, not in sandbox
5
5
  #
6
6
  #Adapi::Config.load_settings
7
7
  #Adapi::Config.set(:production_settings)
8
8
  #
9
9
  #pp "Running in #{Adapi::Config.read[:service][:environment]}"
10
10
 
11
- # create ad group
12
11
  require_relative 'add_bare_ad_group'
13
12
 
14
13
  $ad = Adapi::Ad::TextAd.create(
@@ -22,9 +21,10 @@ $ad = Adapi::Ad::TextAd.create(
22
21
  )
23
22
 
24
23
  if $ad.errors.empty?
25
- p "OK"
26
- p $ad.data
24
+ puts "OK"
25
+ $fresh_ad = Adapi::Ad::TextAd.find(:first, :id => $ad.id, :ad_group_id => $ad_group[:id])
26
+ pp $fresh_ad.attributes
27
27
  else
28
- p "ERROR"
29
- p $ad.errors.messages
28
+ puts "ERROR"
29
+ puts $ad.errors.full_messages.join("\n")
30
30
  end
File without changes
File without changes
@@ -1,10 +1,9 @@
1
1
 
2
2
  require 'adapi'
3
3
 
4
- # create ad group
5
4
  require_relative 'add_bare_ad_group'
6
5
 
7
- ad = Adapi::Ad::TextAd.create(
6
+ $ad = Adapi::Ad::TextAd.create(
8
7
  :ad_group_id => $ad_group[:id],
9
8
  :headline => "Code like Neo",
10
9
  :description1 => 'Need mad coding skills?',
@@ -14,10 +13,7 @@ ad = Adapi::Ad::TextAd.create(
14
13
  :status => 'PAUSED'
15
14
  )
16
15
 
17
- if ad
18
- p "OK"
19
- p ad.data
20
- else
21
- p "ERROR"
22
- p ad.errors.messages
23
- end
16
+ $ad = Adapi::Ad::TextAd.find(:first, :ad_group_id => $ad_group.id, :id => $ad.id )
17
+
18
+ puts "\nCREATED (AND RELOADED) AD:"
19
+ pp $ad.attributes
@@ -9,6 +9,10 @@
9
9
  :user_agent: My Adwords API Client
10
10
  :service:
11
11
  :environment: PRODUCTION
12
+ :library:
13
+ :log_level: WARN
14
+ :log_path: /tmp/adapi_production.log
15
+ # :log_pretty_format is set to :false by default
12
16
 
13
17
  :sandbox:
14
18
  :authentication:
@@ -20,3 +24,7 @@
20
24
  :user_agent: Adwords API Test
21
25
  :service:
22
26
  :environment: SANDBOX
27
+ :library:
28
+ :log_level: DEBUG
29
+ :log_path: /tmp/adapi_sandbox.log
30
+ :log_pretty_format: true
File without changes
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ require 'adapi'
4
+
5
+ require_relative 'add_bare_ad_group'
6
+
7
+ $ad_group.delete
8
+
9
+ $ad_group = Adapi::AdGroup.find(:first, :id => $ad_group.id, :campaign_id => $campaign.id)
10
+
11
+ puts "AdGroup status is now set to: " + $ad_group.status
File without changes
@@ -0,0 +1,13 @@
1
+
2
+ require 'adapi'
3
+
4
+ # create ad group
5
+ require_relative 'add_text_ad'
6
+
7
+ $ad_id = $ad.id
8
+
9
+ puts "\nDELETED AD #{$ad_id}: " + ($ad.destroy ? "true" : "false")
10
+
11
+ $ad = Adapi::Ad::TextAd.find(:first, :ad_group_id => $ad_group.id, :id => $ad_id )
12
+
13
+ puts "TRYING TO FIND IT: " + ($ad.present? ? $ad.attributes : "nil")
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ require 'adapi'
4
+
5
+ require_relative 'add_bare_ad_group'
6
+
7
+ $ad_group = Adapi::AdGroup.find(:first, :campaign_id => $ad_group.campaign_id)
8
+
9
+ pp "\nAD GROUP DATA:"
10
+ pp $ad_group.attributes
File without changes
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ require 'adapi'
4
+
5
+ # create campaign
6
+ require_relative 'add_bare_campaign'
7
+
8
+ $campaign = Adapi::Campaign.find($campaign.id)
9
+
10
+ puts "Campaign data:"
11
+ %w{ id name status serving_status ad_serving_optimization_status start_date end_date }.each do |param_name|
12
+ puts " %s: %s" % [ param_name.to_s.humanize, $campaign[param_name] ]
13
+ end
14
+
15
+ puts "\nBudget:"
16
+ %w{ amount period delivery_method }.each do |param_name|
17
+ puts " %s: %s" % [ param_name.to_s.humanize, $campaign[:budget][param_name.to_sym] ]
18
+ end
19
+
20
+ puts "\nBidding strategy:"
21
+ %w{ xsi_type bid_ceiling enhanced_cpc_enabled }.each do |param_name|
22
+ next unless $campaign[:bidding_strategy].has_key?(param_name.to_sym)
23
+ puts " %s: %s" % [ param_name.to_s.humanize, $campaign[:bidding_strategy][param_name.to_sym] ]
24
+ end
25
+
26
+ puts "\nCampaign stats:"
27
+ %w{ clicks impressions cost ctr }.each do |param_name|
28
+ puts " %s: %s" % [ param_name.to_s.humanize, $campaign[:campaign_stats][param_name.to_sym] ]
29
+ end
30
+
31
+ puts "\nNetwork setting:"
32
+ Adapi::Campaign::NETWORK_SETTING_KEYS.each do |param_name|
33
+ puts " %s: %s" % [ param_name.to_s.humanize, $campaign[:network_setting][param_name.to_sym] ]
34
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,70 @@
1
+ # encoding: utf-8
2
+
3
+ require 'adapi'
4
+
5
+ # create campaign
6
+ require_relative 'add_bare_campaign'
7
+
8
+ $campaign_id = $campaign.id
9
+
10
+ $ad_group = Adapi::AdGroup.create(
11
+ :campaign_id => $campaign_id,
12
+ :name => "AdGroup #%d" % (Time.new.to_f * 1000).to_i,
13
+ :status => 'PAUSED',
14
+
15
+ :keywords => [ 'dem codez', 'trinity', 'morpheus', '"top coder"', "[-code]" ],
16
+
17
+ :ads => [
18
+ {
19
+ :headline => "Code like Trinity",
20
+ :description1 => 'The power of awesomeness?',
21
+ :description2 => 'Check out my new blog!',
22
+ :url => 'http://www.demcodez.com',
23
+ :display_url => 'http://www.demcodez.com'
24
+ },
25
+
26
+ {
27
+ :headline => "Code like Morpheus",
28
+ :description1 => 'Unleash the power of Matrix',
29
+ :description2 => 'Check out my new blog',
30
+ :url => 'http://www.demcodez.com',
31
+ :display_url => 'http://www.demcodez.com'
32
+ }
33
+ ]
34
+ )
35
+
36
+ $ad_group_id = $ad_group.id
37
+
38
+ # fetch ids of ad_group and ads
39
+ $ad_group = Adapi::AdGroup.find(:first, :id => $ad_group_id, :campaign_id => $campaign_id)
40
+
41
+ p "CREATED ad_group #{$ad_group.id} for campaign #{$ad_group.campaign_id}"
42
+ pp $ad_group.attributes
43
+
44
+ result = $ad_group.update(
45
+ :name => "UPDATED #{$ad_group.name}",
46
+ :status => 'ENABLED',
47
+
48
+ :keywords => ['dem updatez', '"neo coder"', '[-trinity]', '[-morpheus]' ],
49
+
50
+ :ads => [
51
+ {
52
+ :headline => "Code like Neo",
53
+ :description1 => 'Need mad coding skills?',
54
+ :description2 => 'Check out my new blog!',
55
+ :url => 'http://www.demcodez.com',
56
+ :display_url => 'http://www.demcodez.com'
57
+ }
58
+ ]
59
+ )
60
+
61
+ unless result
62
+ puts "ERRORS:"
63
+ puts $ad_group.errors.full_messages.join("\n")
64
+ else
65
+ # fetch ids of ad_group and ads
66
+ $ad_group = Adapi::AdGroup.find(:first, :id => $ad_group_id, :campaign_id => $campaign_id)
67
+
68
+ p "UPDATED ad_group #{$ad_group.id} for campaign #{$ad_group.campaign_id}"
69
+ pp $ad_group.attributes
70
+ end
@@ -1,22 +1,47 @@
1
1
  require 'adapi'
2
2
 
3
- # create campaign
4
- require_relative 'add_bare_campaign'
3
+ # create campaign with criteria
4
+ require_relative 'add_campaign'
5
5
 
6
- p "ORIGINAL CAMPAIGN:"
7
- pp $campaign.attributes
8
-
9
- $updated_campaign = Adapi::Campaign.update(
10
- :id => $campaign[:id],
6
+ $campaign = Adapi::Campaign.update(
7
+ :id => $campaign.id,
11
8
  :status => 'ACTIVE',
12
9
  :name => "UPDATED_#{$campaign[:name]}",
10
+ :bidding_strategy => 'ManualCPC',
11
+ :budget => 75,
13
12
  :network_setting => {
14
13
  :target_google_search => false,
15
14
  :target_search_network => false,
16
15
  :target_content_network => true,
17
16
  :target_content_contextual => true
17
+ # FIXME returns error which is not trapped:
18
+ # TargetError.CANNOT_TARGET_PARTNER_SEARCH_NETWORK
19
+ # :target_partner_search_network => true
20
+ },
21
+
22
+ # deletes all criteria (except :platform) and create these new ones
23
+ :criteria => {
24
+ :language => [ :sk ],
18
25
  }
19
26
  )
20
27
 
21
- p "UPDATED CAMPAIGN:"
22
- pp $updated_campaign.attributes
28
+ unless $campaign.errors.empty?
29
+
30
+ puts "ERROR WHEN UPDATING CAMPAIGN #{$campaign.id}:"
31
+ pp $campaign.errors.full_messages
32
+
33
+ else
34
+
35
+ puts "\nUPDATED CAMPAIGN #{$campaign.id}\n"
36
+
37
+ $campaign = Adapi::Campaign.find($campaign.id)
38
+
39
+ puts "\nCAMPAIGN DATA:"
40
+ pp $campaign.attributes
41
+
42
+ $campaign_criteria = Adapi::CampaignCriterion.find( :campaign_id => $campaign.id )
43
+
44
+ puts "\nCRITERIA:"
45
+ pp $campaign_criteria
46
+
47
+ end
@@ -0,0 +1,137 @@
1
+ # encoding: utf-8
2
+
3
+ require 'adapi'
4
+
5
+ # create campaign by single command, with campaing targets, with ad_groups
6
+ # including keywords and ads
7
+
8
+ $ad_group_names = [
9
+ "AdGroup 01 #%d" % (Time.new.to_f * 1000).to_i,
10
+ "AdGroup 02 #%d" % (Time.new.to_f * 1000).to_i
11
+ ]
12
+
13
+ campaign_data = {
14
+ :name => "Campaign #%d" % (Time.new.to_f * 1000).to_i,
15
+ :status => 'PAUSED',
16
+ :bidding_strategy => 'ManualCPC',
17
+ :budget => 50,
18
+
19
+ :ad_groups => [
20
+ {
21
+ :name => $ad_group_names[0],
22
+ :status => 'ENABLED',
23
+
24
+ :keywords => [ 'neo', 'dem codez', '"top coder"', "[-code]" ],
25
+
26
+ :ads => [
27
+ {
28
+ :headline => "Code like Neo",
29
+ :description1 => 'Need mad coding skills?',
30
+ :description2 => 'Check out my new blog!',
31
+ :url => 'http://www.demcodez.com',
32
+ :display_url => 'http://www.demcodez.com'
33
+ }
34
+ ]
35
+ },
36
+
37
+ {
38
+ :name => $ad_group_names[1],
39
+ :status => 'PAUSED',
40
+
41
+ :keywords => [ 'dem codez', 'trinity', 'morpheus', '"top coder"', "[-code]" ],
42
+
43
+ :ads => [
44
+ {
45
+ :headline => "Code like Trinity",
46
+ :description1 => 'The power of awesomeness?',
47
+ :description2 => 'Check out my new blog!',
48
+ :url => 'http://www.demcodez.com',
49
+ :display_url => 'http://www.demcodez.com'
50
+ },
51
+
52
+ {
53
+ :headline => "Code like Morpheus",
54
+ :description1 => 'Unleash the power of Matrix',
55
+ :description2 => 'Check out my new blog',
56
+ :url => 'http://www.demcodez.com',
57
+ :display_url => 'http://www.demcodez.com'
58
+ }
59
+ ]
60
+ }
61
+ ]
62
+
63
+ }
64
+
65
+ $campaign = Adapi::Campaign.create(campaign_data)
66
+ p "Created campaign ID #{$campaign.id}"
67
+
68
+ # PS: changes in ad_groups:
69
+ # * delete first ad_group
70
+ # * change second ad_group
71
+ # * add new ad_group
72
+
73
+ $campaign.update_ad_groups!( [
74
+ # no match here for $ad_group_names[0], so it's going to be deleted
75
+
76
+ # this ad_group will be created
77
+ {
78
+ :name => "UPDATED " + $ad_group_names[0],
79
+ :status => 'ENABLED',
80
+
81
+ :keywords => [ 'neo update', 'dem codezzz', '"top coder"' ],
82
+
83
+ :ads => [
84
+ {
85
+ :headline => "Update like Neo",
86
+ :description1 => 'Need mad coding skills?',
87
+ :description2 => 'Check out my new blog!',
88
+ :url => 'http://www.demcodez.com',
89
+ :display_url => 'http://www.demcodez.com'
90
+ }
91
+ ]
92
+ },
93
+
94
+ # this ad_group is going to be updated
95
+ {
96
+ :name => $ad_group_names[1],
97
+ :status => 'ENABLED', # from PAUSED
98
+
99
+ :keywords => [ 'dem updatez', 'update trinity', 'update morpheus' ],
100
+
101
+ :ads => [
102
+ {
103
+ :headline => "Update like Trinity",
104
+ :description1 => 'The power of updates?',
105
+ :description2 => 'Check out my new blog!',
106
+ :url => 'http://www.demcodez.com',
107
+ :display_url => 'http://www.demcodez.com'
108
+ },
109
+
110
+ {
111
+ :headline => "Update like Morpheus",
112
+ :description1 => 'Unleash the power of updates',
113
+ :description2 => 'Check out my new blog',
114
+ :url => 'http://www.demcodez.com',
115
+ :display_url => 'http://www.demcodez.com'
116
+ }
117
+ ]
118
+ }
119
+ ] )
120
+
121
+ unless $campaign.errors.empty?
122
+
123
+ puts "ERROR WHEN UPDATING AD GROUPS:"
124
+ puts $campaign.errors.full_messages.join("\n")
125
+
126
+ else
127
+ # reload ad groups
128
+ $ad_groups = Adapi::AdGroup.find(:all, :campaign_id => $campaign[:id])
129
+
130
+ puts "\nAD GROUPS UPDATED\n"
131
+
132
+ puts "\nAD GROUPS (#{$ad_groups.size}):"
133
+ $ad_groups.each_with_index do |ad_group, i|
134
+ puts "\nAD GROUP #{i + 1}:\n"
135
+ pp ad_group.attributes
136
+ end
137
+ end