Hi All, Every day we almost spend 10K+ dollar in Google Ads in order to advertise our APPs in the whole world. In business side, our App operation team want to analysis the advertising effect about the different country current and history performance of every App. We need make the advertising strategy about which country can offer us high quality users recently. We know that there are country performance reports of the account cost in the Google Ads backstage, but we want history data in order to analysis the data. So we decide to get the country performance report and store them in our own database. We found that the 'Location' and 'Geo' API can realize this idea, but both of them have some issues. The issue situation is : 1. When we call the 'Location' API, we can almost get all account cost data. The cost of every account is almost as same as the report of Google Ads backstage. It only has no more than 1% error rate and we can accept it. We have a location-country dimension table. Through this table, we can transfer the location to country. But, when we drill down the data to location level, we found that a lot of account have the issue situation that the location is '--'. Correct cost and meanless location. Example: We use one account to spend 1K in US and 2K in India and 3K in Japan. When we see the data through 'Location' API, the data maybe is 1k in US and 5K in '--'.
With this return data, we can not have a view about the advertising performance of country. 2. When we call the 'Geo' API, the country field won't be '--' and the cost of account is correct. But, a lot of account is missing. If we can have 10 accounts data from 'Location' API, maybe we can only have 3-5 accounts data from 'Geo' API in same time period. We have no idea about how to solve these problems.Our target is just to get one correct cost report of all account and all country everyday. ---------------------------------------------------------------------------------------------------------------------------------------------------------- The following is the result date of calling the 2 APIs : account_id information: $mcc = '945-959-2387'; $account_id = '9929989200'; 1. The information from 'location' API relative parameter : $report_type = 'CAMPAIGN_LOCATION_TARGET_REPORT'; $fields = array('Impressions', 'Clicks', 'Conversions', 'Cost', 'Date', 'ExternalCustomerId', 'CampaignId', 'Id'); $report_name = 'adwords_location_report'; The log from 'location' API: [2019-07-23 17:40:53] AW_REPORT_DOWNLOADER.INFO: clientCustomerId=9929989200 Teebik (AwApi-PHP, googleads-php-lib/40.0.0, PHP/7.1.7, GuzzleHttp/6.2.1, curl/7.29.0) "POST /api/adwords/reportdownload/v201809 HTTP/1.1" Status: 200 bool(true) The return data from 'location' API cat /tmp/adwords_location_report_LAST_30_DAYS.csv Impressions,Clicks,Conversions,Cost,Day,Customer ID,Campaign ID,Location 1,1,0.00,170000,2019-07-09,9929989200,2038668410, -- 1,1,0.00,50000,2019-06-29,9929989200,2038668902, -- 1,0,0.00,0,2019-07-03,9929989200,2038668902, -- 1,0,0.00,0,2019-07-01,9929989200,2038668410, -- 1,0,0.00,0,2019-07-10,9929989200,2038668902, -- 2,0,0.00,0,2019-07-09,9929989200,2039512296, -- 1,0,0.00,0,2019-06-26,9929989200,2038668410, -- 1,0,0.00,0,2019-07-15,9929989200,2038668902, -- 2. The information from 'geo' API relative parameter : $report_type = 'GEO_PERFORMANCE_REPORT'; $fields = array('Impressions', 'Clicks', 'Conversions', 'Cost', 'Date', 'ExternalCustomerId', 'CountryCriteriaId'); $report_name = 'adwords_geo_report'; The return data from 'geo' API head /tmp/adwords_geo_report_LAST_30_DAYS.csv Impressions,Clicks,Conversions,Cost,Day,Customer ID,Country/Territory 1,0,0.00,0,2019-07-20,9929989200,2462 3,0,0.00,0,2019-07-16,9929989200,2462 1,0,0.00,0,2019-07-03,9929989200,2462 4,0,0.00,0,2019-07-12,9929989200,2462 1,0,0.00,0,2019-07-04,9929989200,2554 2,0,0.00,0,2019-07-14,9929989200,2462 1,0,0.00,0,2019-06-27,9929989200,2462 1,0,0.00,0,2019-07-11,9929989200,2462 2,0,0.00,0,2019-06-28,9929989200,2462 --------------------------------------------------------------------------------------------------------------------------- The following is our PHP code. //$mcc = '945-959-2387'; $mccConfigPath = "/tmp/adsapi_php.ini"; $customerId = '9929989200'; $date_range_type = 'LAST_30_DAYS'; $report_type = 'geo'; downloadReport($mccConfigPath, $customerId, $date_range_type, $report_type)); public function downloadReport($mccConfigPath, $customerId, $date_range_type, $report_type) { if ($report_type == 'geo') { $report_type = 'GEO_PERFORMANCE_REPORT'; $fields = array('Impressions', 'Clicks', 'Conversions', 'Cost', 'Date', 'ExternalCustomerId', 'CountryCriteriaId','CampaignId'); $report_name = 'adwords_geo_report'; $file_path = '/tmp/adwords_geo_report_' . $date_range_type . '.csv'; } elseif ($report_type == 'location') { // https://developers.google.com/adwords/api/docs/appendix/reports/campaign-location-target-report // Id = location $report_type = 'CAMPAIGN_LOCATION_TARGET_REPORT'; $fields = array('Impressions', 'Clicks', 'Conversions', 'Cost', 'Date', 'ExternalCustomerId', 'CampaignId', 'Id'); $report_name = 'adwords_location_report'; $file_path = '/tmp/adwords_location_report_' . $date_range_type . '.csv'; } else { $report_type = 'ACCOUNT_PERFORMANCE_REPORT'; $fields = array('Impressions', 'Clicks', 'Conversions', 'Cost', 'Date', 'ExternalCustomerId'); $report_name = 'adwords_account_report'; $file_path = '/tmp/adwords_account_report_' . $date_range_type . '.csv'; } return $this->downloadCriteriaReport($mccConfigPath, $customerId, $report_type, $fields, $report_name, $date_range_type, 'CSV', $file_path, FALSE, TRUE, TRUE); } public function downloadCriteriaReport($mccConfigPath, $customerId, $reportType, $fields, $reportName, $dateRangeType, $downloadFormat, $filePath, $includeZeroImpressions = FALSE, $skipReportHeader = FALSE, $skipReportSummary = FALSE) { $filterErrMessage = array( "503 Service Unavailable", "500 Internal Server Error", "502 Bad Gateway", "Temporary problem with the server. Please retry the request after a few moments", "AuthorizationError.CUSTOMER_NOT_ACTIVE", // https://ads-developers.googleblog.com/2018/03/changes-to-inactive-adwords-accounts.html "looks like we got no XML document", // https://stackoverflow.com/questions/4313952/soap-looks-like-we-got-no-xml-document ); try { // Construct an API session for the client customer ID specified in the // configuration file. /** @var AdWordsSessionBuilder $sessionBuilder */ $sessionBuilder = F::$f->Helper_AdwordsSession->getMccSessionBuilder($mccConfigPath); // Create selector. $selector = new Selector(); $selector->setFields($fields); // Create report definition. $reportDefinition = new ReportDefinition(); $reportDefinition->setSelector($selector); $reportDefinition->setReportName($reportName); $reportDefinition->setDateRangeType($dateRangeType); $reportDefinition->setReportType($reportType); $reportDefinition->setDownloadFormat($downloadFormat); // Construct an API session for the specified client customer ID. $customerSession = $sessionBuilder->withClientCustomerId($customerId)->build(); $reportDownloader = new ReportDownloader($customerSession); $retryCount = 0; $doContinue = true; do { $retryCount++; try { // Optional: If you need to adjust report settings just for this one // request, you can create and supply the settings override here. // Otherwise, default values from the configuration file // (adsapi_php.ini) are used. $reportSettingsOverride = (new ReportSettingsBuilder())->includeZeroImpressions($includeZeroImpressions)->skipReportSummary($skipReportSummary)->skipReportHeader($skipReportHeader)->build(); $reportDownloadResult = $reportDownloader->downloadReport($reportDefinition, $reportSettingsOverride); $reportDownloadResult->saveToFile($filePath); $doContinue = false; } catch (ApiException $e) { // echo 'error with download report, retry. error message:' . $e->getMessage() . PHP_EOL; log_message('error with download report, retry. error message:' . $e->getMessage(), LOG_ERR); // If this is a server error, retry up to the defined maximum number // of retries. if ($e->getErrors() === null && $retryCount < self::MAX_RETRIES) { // F::$f->Helper_Monitor->addCacheLog('API warning with download report, warning message:' . $e->getMessage()); log_message('warning with download report, retry. error message:' . $e->getMessage(), LOG_ERR); $sleepTime = $retryCount * self::BACKOFF_FACTOR; sleep($sleepTime); } else { $errMessage = $e->getMessage(); // If the error message include the following information, Skip $isSkip = false; foreach($filterErrMessage as $temp) { if (stripos($errMessage, $temp) !== false) { $isSkip = true; break; } } if (!$isSkip) { F::$f->Helper_Monitor->addCacheLog('API error with download report, error message: ' . $e->getMessage()); } log_message('error with download report, exit. error message:' . $e->getMessage(), LOG_ERR); return false; } } } while ($doContinue === true); } catch (Exception $e) { echo 'error with download report, retry. error message:' . $e->getMessage() . PHP_EOL; F::$f->Helper_Monitor->addCacheLog('API error with download report, error message:' . $e->getMessage()); log_message('error with download report,customerId:'.$customerId.'. error message:' . $e->getMessage(), LOG_ERR); return FALSE; } return TRUE; } <?php use Google\AdsApi\AdWords\AdWordsSessionBuilder; use Google\AdsApi\Common\OAuth2TokenBuilder; /** * Date: 2016/3/15 * Time: 12:36 */ class Helper_AdwordsSession { /** * @param $mccConfigPath * @return AdWordsSessionBuilder */ public function getMccSessionBuilder($mccConfigPath) { // Generate a refreshable OAuth2 credential for authentication. $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile($mccConfigPath)->build(); // See: AdWordsSessionBuilder for setting a client customer ID that is // different from that specified in your adsapi_php.ini file. $sessionBuilder = (new AdWordsSessionBuilder())->fromFile($mccConfigPath)->withOAuth2Credential($oAuth2Credential); return $sessionBuilder; } } Looking forward for your help. Best regards. -- -- =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ Also find us on our blog: https://googleadsdeveloper.blogspot.com/ =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ You received this message because you are subscribed to the Google Groups "AdWords API and Google Ads API Forum" group. To post to this group, send email to adwords-api@googlegroups.com To unsubscribe from this group, send email to adwords-api+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/adwords-api?hl=en --- You received this message because you are subscribed to the Google Groups "AdWords API and Google Ads API Forum" group. To unsubscribe from this group and stop receiving emails from it, send an email to adwords-api+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/adwords-api/a8581400-7291-4aca-b1f9-a8cc51f21a5e%40googlegroups.com.