Skip to content

Instantly share code, notes, and snippets.

@superchris
Created April 9, 2012 20:06
Show Gist options
  • Save superchris/2346241 to your computer and use it in GitHub Desktop.
Save superchris/2346241 to your computer and use it in GitHub Desktop.
Adcenter savon example
module Microsoft
class Adcenter
MAX_RETRIES = 10
REPORT_WSDL_URL = "https://adcenterapi.microsoft.com/Api/Advertiser/v8/Reporting/ReportingService.svc?wsdl"
CUSTOMER_MANAGEMENT_WSDL_URL = "https://sharedservices.adcenterapi.microsoft.com/Api/CustomerManagement/v8/CustomerManagementService.svc?wsdl"
def credentials
@credentials ||= YAML::load(ERB.new(File.open(Rails.root.join("config", "adcenter.yml")).read).result)[Rails.env]
end
def build_header
{
"DeveloperToken" => credentials["developerToken"],
"UserName" => credentials["username"],
"Password" => credentials["password"]
}
end
def build_date(date)
{"Day" => date.day, "Month" => date.month, "Year" => date.year, :order! => ["Day", "Month", "Year"]}
end
def build_client(wsdl_url)
client = Savon::Client.new do
wsdl.document = wsdl_url
end
client
end
def get_account_infos
response = build_client(CUSTOMER_MANAGEMENT_WSDL_URL).request("GetAccountsInfoRequest") do
soap.namespaces["xmlns"] = "https://adcenter.microsoft.com/api/customermanagement"
soap.header = build_header
soap.body = {}
http.headers["SOAPAction"] = "GetAccountsInfo"
end
response.to_hash[:get_accounts_info_response][:accounts_info][:account_info]
end
def submit_daily_report_job(account_id, date)
submitJobResponse = build_client(REPORT_WSDL_URL).request("SubmitGenerateReportRequest") do
soap.namespaces["xmlns"] = "https://adcenter.microsoft.com/v8"
soap.namespaces["xmlns:i"] = "http://www.w3.org/2001/XMLSchema-instance"
soap.namespaces["xmlns:a"] = "http://schemas.microsoft.com/2003/10/Serialization/Arrays"
soap.header = build_header
soap.body = {
:attributes! => {"ReportRequest" => {"i:type" => "AccountPerformanceReportRequest"} },
"ReportRequest" => {
"Format" => "Xml",
"ReportName" => Report::DAILY_REPORT_NAME,
"Aggregation" => "Daily",
"Columns" => {
"AccountPerformanceReportColumn" => %w{Impressions Clicks Ctr AverageCpc Spend AveragePosition AccountName TimePeriod}
},
"Time" => {
"CustomDateRangeEnd" => build_date(date.to_date),
"CustomDateRangeStart" => build_date(date.to_date),
},
"Filter" => "",
"Scope" => {
"AccountIds" => {
"a:long" => account_id
}
},
:order! => ["Format", "ReportName", "Aggregation", "Columns", "Filter", "Scope","Time"]
}
}
http.headers["SOAPAction"] = "SubmitGenerateReport"
end
submitJobResponse[:submit_generate_report_response][:report_request_id]
end
def poll_report_job(job_id)
poll_response = build_client(REPORT_WSDL_URL).request("PollGenerateReportRequest") do
soap.namespaces["xmlns"] = "https://adcenter.microsoft.com/v8"
soap.header = build_header
soap.body = {
"ReportRequestId" => job_id
}
http.headers["SOAPAction"] = "PollGenerateReport"
end
poll_response.to_hash[:poll_generate_report_response][:report_request_status]
end
def download_report_zip(download_url)
begin
client = HTTPClient.new
return client.get_content(download_url)
rescue Errno::ECONNRESET, SOAP::HTTPStreamError, SocketError => e
# This exception indicates a connection-level error.
# In general, it is likely to be transitory.
raise AdWords::Error::Error, "Connection Error: %s\nSource: %s" %
[e, e.backtrace.first]
end
end
def download_daily_report(account_id, date)
job_id = submit_daily_report_job(account_id, date)
poll_response = poll_report_job(job_id)
retries = 0
while poll_response[:status] == "Pending"
sleep 5
retries += 1
raise "Timed out downloading report" if retries >= MAX_RETRIES
poll_response = poll_report_job(job_id)
end
if poll_response[:status] == "Success"
tempfile = Tempfile.new("adcenter_report_#{job_id}", :encoding => "ascii-8bit")
tempfile.write download_report_zip(poll_response[:report_download_url])
tempfile.close
xml = ""
Zip::ZipInputStream::open(tempfile.path) do |io|
entry = io.get_next_entry
xml = io.read
end
return xml
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment