Adapi Code Climate

Description

Adapi (ADwords API) is a Ruby library for easy and painless work with Google Adwords API. Its users shouldn't bother with SOAP and tangle of XML- and API-specific objects, inputs and outputs are plain Ruby arrays and hashes.

Adapi is built on google-adwords-api gem. Arrays and hashes instead of objects come from there, but adapi takes it several steps further:

  • AdWords services are represented by ActiveModel-compatible models with relations. Among other things it's possible to create whole campaign in single method call: Adapi::Campaign.create(campaign_data).

  • Various convenience methods are added to the models, for example: campaign.pause! (pauses campaign).

  • Adapi enables you to easily work with multiple AdWords accounts at the same time.

Adapi is still in development and not nearly done yet! Version 1.0.0 should have all planned functionality.

Adapi supports the latest version of AdWords API: v201209.

Installation

gem install adapi

from git repository

git clone git@github.com:lstejskal/adapi.git
cd adapi
bundle install
rake install

Configuration

This section explains how to connect to specific AdWords account and client. The configuration structure is quite similar to the configuration of google-adwords-api gem.

There are several options to choose from:

Single account set directly in code

Adapi::Config.load_settings( in_hash: {
  production: {
    authentication: {
      method:                 "OAuth2",
      oauth2_client_id:       "abc",
      oauth2_client_secret:   "def",
      oauth2_token: {
        access_token:         "123",
        refresh_token:        "456",
        issued_at:            "2013-03-03 13:33:39.734203841 +01:00",
        expires_in:           3600,
        id_token:             nil
      },
      developer_token:        "789",
      user_agent:             "My Adwords API Client",
      client_customer_id:     "555-666-7777"
    },
    service: {
      environment: "PRODUCTION"
    }
  }
})

Adapi::Config.set(:production)

Multiple accounts set directly in code

You can set many AdWords accounts to connect to and switch between while running the application. You can even update single values of the settings on-the-fly.

Adapi::Config.load_settings( in_hash: {
  coca_cola:  config_hash_for_coca_cola,
  pepsi:      config_hash_for_pepsi
})

# set to pepsi and specific client       
Adapi::Config.set(:pepsi, :client_customer_id => '555-666-7777')

# do some stuff here...

# set to coca-cola and another client       
Adapi::Config.set(:coca_cola, :client_customer_id => '777-666-5555')

# do some stuff here...

Configuration by adapi.yml

Stored in ~/adapi.yml. Supports multiple accounts, which are identifed by aliases. Example:


:default:
  :authentication:
    :method: OAuth2
    :oauth2_client_id: "abc"
    :oauth2_client_secret: "def"
    :oauth2_token:
        :access_token: "123"
        :refresh_token: "456"
        :issued_at: 2013-03-03 13:33:39.734203841 +01:00
        :expires_in: 3600
        :id_token:
    :developer_token: "789"
    :user_agent: My Adwords API Client
    :client_customer_id: 555-666-7777
  :service:
    :environment: PRODUCTION
  :library:
    :log_level: WARN
    :log_path: /tmp/adapi.log
    :log_pretty_format: true

To tell adapi which account to use:

Adapi::Config.set(:production)

:default account is, as name implies, used by default. If you don't have :default account available, you have to manually set account alias to Adapi::Config.

How to get OAuth2 token

require 'adapi'
require 'yaml'

adapi_object = Adapi::Location.new() # load any adapi object
adwords_api = adapi_object.adwords # get adwords object

# got to url and paste verification code to the script
oauth2_token = adwords.authorize() do |auth_url|
  puts "Go to URL:\n\t%s" % auth_url
  print 'log in and type the verification code: '
  gets.chomp
end

puts oauth2_token.to_yaml 
  • put oauth2_token hash adapi configuration file

Code taken from this google-adwords-api example: [https://code.google.com/p/google-api-ads-ruby/source/browse/adwords_api/examples/v201209/misc/use_oauth2.rb][https://code.google.com/p/google-api-ads-ruby/source/browse/adwords_api/examples/v201209/misc/use_oauth2.rb]

API Version Support

Adapi supports the latest version of AdWords API: v201209.

For support of earlier versions of AdWords API, downgrade to earlier versions of adapi: 0.1.5 for v201206, 0.0.9 for v201109_1, 0.07 for v201109. (You shoudn't need it though, older versions of AdWords API are eventually shut down.) Latest revision for specific AdWords API version is also marked by a tag.

Adapi tries to not to bother users with AdWords API low-level specifics as much as possible, if you're upgrading to newer version of AdWords API, please be cautious, check the release notes and update your code accordingly. Adapi won't accept obsolete attributes etc.

Unsupported AdWords services

Following AdWords services are not supported by adapi at the moment, and exist only on my TODO list:

  • Campaign Data Management

    • ConversionTrackerService
    • UserListService
  • Optimization

    • BulkOpportunityService
    • ReportDefinitionService
    • TargetingIdeaService
    • TrafficEstimatorService
  • Account Management

    • CustomerSyncService
  • Utility

    • MutateJobService
    • BulkMutateJobService

Examples

Examples are available in examples directory. For now, they are mostly just uninspired rewrites of examples from google-adwords-api gem, but that's going to change when proper UI to AdWords models will be implemented.

Getting started

Here are some examples to get you started with adapi. (All this is also available in examples directory.)

Create complete campaign

Creates a campaign with ad_groups and ad_texts from hash - by single method call.

campaign = Adapi::Campaign.create(
  :name => "Campaign #%d" % (Time.new.to_f * 1000).to_i,
  :status => 'PAUSED',
  :bidding_strategy => {
    :xsi_type => 'BudgetOptimizer',
    :bid_ceiling => 100
  },
  :budget => {
    :amount => 50,
    :delivery_method => 'STANDARD'
  },

  :criteria => {
    :language => [ :en, :cs ],
    :location => {
      # PS: province and country codes are now obsolete in AdWords API,
      # but they still work in adapi
      :name => { :city => 'Prague', :region => 'CZ-PR', :country => 'CZ' }
    }
  },

  :ad_groups => [
    {
      :name => "AdGroup #%d" % (Time.new.to_f * 1000).to_i,
      :status => 'ENABLED',

      :keywords => [ 'dem codez', '"top coder"', "[-code]" ],

      :ads => [
        {
          :headline => "Code like Neo",
          :description1 => 'Need mad coding skills?',
          :description2 => 'Check out my new blog!',
          :url => 'http://www.demcodez.com',
          :display_url => 'http://www.demcodez.com'
        }
      ]
    }
  ]
)

Create campaign step by step

Creates a campaign with ad_groups and ad_texts step by step.

campaign = Adapi::Campaign.create(
  :name => "Campaign #%d" % (Time.new.to_f * 1000).to_i,
  :status => 'PAUSED',
  :bidding_strategy => { :xsi_type => 'BudgetOptimizer', :bid_ceiling => 100 },
  :budget => { :amount => 50, :delivery_method => 'STANDARD' }
)

Adapi::CampaignCriterion.create(
  :campaign_id => campaign.id,
  :criteria => { 
    :language => %w{ en cs },
    :location => {
      :name => { :city => 'Prague', :region => 'CZ-PR', :country => 'CZ' }
    }
  }
)

ad_group = Adapi::AdGroup.create(
  :campaign_id => campaign.id,
  :name => "AdGroup #%d" % (Time.new.to_f * 1000).to_i,
  :status => 'ENABLED'
)

Adapi::Keyword.create(
  :ad_group_id => ad_group.id,
  :keywords => [ 'dem codez', '"top coder"', '[-code]' ]
)

Adapi::Ad::TextAd.create(
  :ad_group_id => ad_group.id,
  :headline => "Code like Neo",
  :description1 => 'Need mad coding skills?',
  :description2 => 'Check out my new blog!',
  :url => 'http://www.demcodez.com',
  :display_url => 'http://www.demcodez.com'
)

# find complete campaign
new_campaign = Adapi::Campaign.find_complete(campaign.id)

# display campaign as hash
puts new_campaign.to_hash.inspect

Create campaign criteria

Campaign criteria (formerly targets) have been rewritten from the scratch for v201109. The goal is to provide a simple DSL for criteria so user doesn't have to deal with somewhat convoluted AdWords API syntax made for machines, not humans. So far, this has been done only for language and location criterion. You can use any other criteria, you just have to enter them in AdWords format.

Language
Adapi::CampaignCriterion.create(
  :campaign_id => campaign.id,
  :criteria => { 
    :language => %w{ en cs },
  }
)

:language parameter accepts string or symbols for single language target or array of strings/symbols for several language targets.

Location
Adapi::CampaignCriterion.create(
  :campaign_id => campaign.id,
  :criteria => { 
    :location => { 
      :name => { :city => 'Prague', :region => 'CZ-PR', :country => 'CZ' }
    }    
)

This criterion has been heavily customized in adapi to comply with legacy interfaces (pre-v201109). In other words, you don't have to enter locations as ids (although you can). :location accepts following parameters:

  • :id - this is standard location interface of AdWords v201109_1
:location => location_id
:location => { :id => location_id }
:location => { :id => [ location_id ] }
  • :proximity
    • :geo_point: "longitude,lattitude"
    • :radius: "radius_in_units radius_units"
:location => { :proximity => { :geo_point => '50.083333,14.366667', :radius => '50 km' } }
  • :name - hash with parameters specifying location name:
    • :city
    • :region (also :province) - as name ("New York") or code ("US-NY")
    • :country - as name ("Czech Republic") or code ("CZ")
:location => { :name => { :country => 'Czech Republic' } }
:location => { :name => { :city => 'Prague' } }
:location => { :name => { :city => 'Prague', :region => 'CZ-PR', :country => 'CZ' } }

Unfortunately, at the moment you can't target more locations in one CampaignCriterion request. This is going to be fixed in the next version, but for now please use following workaround - call CampaignCriterion several times:

Adapi::CampaignCriterion.create(
  :campaign_id => campaign.id,
  :criteria => { 
    :location => { 
      :name => { :city => 'Prague', :region => 'CZ-PR', :country => 'CZ' }
    }    
)

Adapi::CampaignCriterion.create(
  :campaign_id => campaign.id,
  :criteria => { 
    :location => {
      :name => { :city => 'Brno', :region => 'CZ-JM', :country => 'CZ' }
    }
  }
)
Criterion in AdWords format

Convenient shortcuts for other criteria besides language and location are not yet implemented. However, you can use any other criteria, you just have to enter them as ids.

Adapi::CampaignCriterion.create(
  :campaign_id => campaign.id,
  :criteria => {
    :platform => [ { :id => 30001} ]
  }
)

Logging

By default, communication with AdWords API is not logged. In order to log messages of certain log level or above, set library/log_level in configuration (INFO or DEBUG setting is recommended for local development).

Default log path is "~/adapi.log". You can set custom log path in: library/log_path.

By default, SOAP messages are logged in ugly format - everything fits on single line. It's fast, but quite difficult to read. To log SOAP requests and responses in pretty format, set library/log_pretty_format in configuration to true.

Example of logger configuration:

  :library:
    :log_level: DEBUG
    :log_path: /home/username/log/adapi.log
    :log_pretty_format: true

Author

2011-2013 Lukas Stejskal, Ataxo Interactive, a.s.