adapi 0.0.8 → 0.0.9

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