package com.crealytics.google.adwords import java.util.zip.GZIPInputStream import javax.xml.parsers.DocumentBuilderFactory import com.google.api.ads.adwords.axis.factory.AdWordsServices import com.google.api.ads.adwords.axis.v201806.cm.{ReportDefinitionField, ReportDefinitionServiceInterface} import com.google.api.ads.adwords.axis.v201806.cm.{ ReportDefinitionField, ReportDefinitionReportType, ReportDefinitionServiceInterface } import com.google.api.ads.adwords.lib.client.AdWordsSession import com.google.api.ads.adwords.lib.jaxb.v201806.{DownloadFormat} import com.google.api.ads.adwords.lib.jaxb.v201806.DownloadFormat import com.google.api.ads.adwords.lib.utils.v201806.ReportDownloader import com.google.api.ads.adwords.lib.utils.v201806.ReportDownloader import com.google.api.ads.common.lib.auth.OfflineCredentials import com.google.api.client.auth.oauth2.Credential class AdWordsClient(credential: Credential, developerToken: String, userAgent: String, clientCustomerId: String) { // The Adwords API Session private lazy val session = new AdWordsSession.Builder() .withDeveloperToken(developerToken) .withUserAgent(userAgent) .withOAuth2Credential(credential) .withClientCustomerId(clientCustomerId) .build // Factory for all AdWords Services private lazy val services = new AdWordsServices() // Report Definition Service: Provides Metadata about Reports (Column Names, Data Types...) private lazy val reportDefinitionService = services.get(session, classOf[ReportDefinitionServiceInterface]) // Returns Field Descriptors for all possible Fields of this Report def getFieldsForReportType(report: String): Array[ReportDefinitionField] = reportDefinitionService.getReportFields(ReportDefinitionReportType.fromValue(report)) // Executes the Query, downloads the Report and parses the XML into a Sequence of Rows def downloadReport(query: String): Seq[Map[String, String]] = { // download the report val reportResponse = new ReportDownloader(session) .downloadReport(query, DownloadFormat.GZIPPED_XML) val inputStream = reportResponse.getInputStream val zipStream = new GZIPInputStream(inputStream) val xmlDocument = DocumentBuilderFactory.newInstance.newDocumentBuilder().parse(zipStream) val nodes = xmlDocument.getElementsByTagName("row") // Loop over the nodes (0 until nodes.getLength) .map(i => { val item = nodes.item(i) // All data is stored in attributes, so put the attributes into a map val attrs = item.getAttributes (0 until attrs.getLength) .map(j => (attrs.item(j).getNodeName, attrs.item(j).getNodeValue)) .toMap }) .toSeq } }