#!/usr/bin/python # # Copyright 2009 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """Methods to access CriterionService service.""" __author__ = 'api.sgrinberg@gmail.com (Stan Grinberg)' from aw_api import SanityCheck as glob_sanity_check from aw_api import SOAPPY from aw_api import ZSI from aw_api.Errors import ValidationError from aw_api.WebService import WebService class CriterionService(object): """Wrapper for CriterionService. The Criterion Service provides operations for accessing, modifying, and creating criteria (Keywords and Websites) in an AdGroup. """ def __init__(self, headers, config, op_config, lock, logger): """Inits CriterionService. Args: headers: dict dictionary object with populated authentication credentials. config: dict dictionary object with populated configuration values. lock: thread.lock the thread lock. logger: Logger the instance of Logger """ url = [op_config['server'], 'api/adwords', op_config['version'], self.__class__.__name__] if config['access']: url.insert(len(url) - 1, config['access']) self.__service = WebService(headers, config, op_config, '/'.join(url), lock, logger) self.__config = config if self.__config['soap_lib'] == SOAPPY: from aw_api.soappy_toolkit import SanityCheck elif self.__config['soap_lib'] == ZSI: from aw_api import API_VERSIONS from aw_api.zsi_toolkit import SanityCheck if op_config['version'] in API_VERSIONS: module = '%s_services' % self.__class__.__name__ try: web_services = __import__('aw_api.zsi_toolkit.%s.%s' % (op_config['version'], module), globals(), locals(), ['']) except ImportError, e: # If one of library's required modules is missing, re raise exception. if str(e).find(module) < 0: raise ImportError(e) msg = ('The version \'%s\' is not compatible with \'%s\'.' % (op_config['version'], self.__class__.__name__)) raise ValidationError(msg) else: msg = 'Invalid API version, not one of %s.' % str(list(API_VERSIONS)) raise ValidationError(msg) self.__web_services = web_services self.__loc = eval('web_services.%sLocator()' % self.__class__.__name__) self.__sanity_check = SanityCheck def AddCriteria(self, criteria): """Add new criteria to an AdGroup. Args: criteria: list information for the new criteria. Ex: criteria = [ { 'adGroupId': '1234567890', 'criterionType': 'Keyword' or 'Website', 'destinationUrl': 'http://www.example.com', 'exemptionRequest': 'Exemption request goes here.', 'id': '1234567890', 'language': 'en', 'maxCpc': '1000000', 'negative': 'False', 'paused': 'False', 'status': 'Active', # Keyword only 'firstPageCpc': '1000000', 'proxyMaxCpc': '1000000', 'text': 'car insurance', 'qualityScore': '5', 'type': 'Broad' # Website only 'maxCpm': '1000000', 'url': 'example.com' } ] Returns: tuple response from the API method. """ glob_sanity_check.ValidateTypes(((criteria, list),)) method_name = 'addCriteria' if self.__config['soap_lib'] == SOAPPY: for item in criteria: self.__sanity_check.ValidateCriterionV13(item) return self.__service.CallMethod(method_name, (criteria)) elif self.__config['soap_lib'] == ZSI: web_services = self.__web_services new_criteria = [] for item in criteria: new_criteria.append(self.__sanity_check.ValidateCriterion( '', item, web_services)) request = eval('web_services.%sRequest()' % method_name) return self.__service.CallMethod(method_name, (({'criteria': new_criteria},)), 'Criterion', self.__loc, request) def CheckCriteria(self, criteria, language_target, geo_target): """Check a batch of criteria for policy errors. Args: criteria: list criteria to be checked. language_target: list overriding language context. geo_target: dict overriding geographical context. Ex: criteria = [ { 'adGroupId': '1234567890', 'criterionType': 'Keyword' or 'Website', 'destinationUrl': 'http://www.example.com', 'exemptionRequest': 'Exemption request goes here.', 'id': '1234567890', 'language': 'en', 'maxCpc': '1000000', 'negative': 'False', 'paused': 'False', 'status': 'Active', # Keyword only 'firstPageCpc': '1000000', 'proxyMaxCpc': '1000000', 'text': 'car insurance', 'qualityScore': '5', 'type': 'Broad', # Website only 'maxCpm': '1000000', 'url': 'example.com' } ] language_target = ['en'] 'geoTargeting': { 'cityTargets': { 'cities': ['New York, NY US'], 'excludedCities': ['New York, NY US'] }, 'countryTargets': { 'countries': ['US'], 'excludedCountries': ['US'] }, 'metroTargets': { 'excludedMetros': ['501'], 'metros': ['501'] }, 'regionTargets': { 'excludedRegions': ['US-NY'], 'regions': ['US-NY'] } 'proximityTargets': { 'circles': [ { 'latitudeMicroDegrees': '12345678', 'longitudeMicroDegrees': '-12345678', 'radiusMeters': '1000' } ] }, 'targetAll': 'False' }, Returns: tuple response from the API method. """ glob_sanity_check.ValidateTypes(((criteria, list), (language_target, list), (geo_target, dict))) method_name = 'checkCriteria' if self.__config['soap_lib'] == SOAPPY: for item in criteria: self.__sanity_check.ValidateCriterionV13(item) language_target = self.__sanity_check.UnType( self.__sanity_check.ValidateLanguageTargetV13(language_target)) geo_target = self.__sanity_check.UnType( self.__sanity_check.ValidateGeoTargetV13(geo_target)) return self.__service.CallMethod(method_name, (criteria, language_target, geo_target)) elif self.__config['soap_lib'] == ZSI: web_services = self.__web_services new_criteria = [] for item in criteria: new_criteria.append(self.__sanity_check.ValidateCriterion( '', item, web_services)) language_target = self.__sanity_check.ValidateLanguageTargetV13( language_target) geo_target = self.__sanity_check.ValidateGeoTargetV13(geo_target) request = eval('web_services.%sRequest()' % method_name) return self.__service.CallMethod(method_name, (({'criteria': new_criteria}, {'languageTarget': language_target}, {'geoTarget': geo_target})), 'Criterion', self.__loc, request) def GetAllCriteria(self, ad_group_id): """Return a list of criteria associated with this AdGroup. Args: ad_group_id: str ID of the AdGroup. Ex: ad_group_id = '1234567890' Returns: tuple response from the API method. """ glob_sanity_check.ValidateTypes(((ad_group_id, (str, unicode)),)) method_name = 'getAllCriteria' if self.__config['soap_lib'] == SOAPPY: return self.__service.CallMethod(method_name, (ad_group_id)) elif self.__config['soap_lib'] == ZSI: web_services = self.__web_services request = eval('web_services.%sRequest()' % method_name) return self.__service.CallMethod(method_name, (({'adGroupId': ad_group_id},)), 'Criterion', self.__loc, request) def GetCampaignNegativeCriteria(self, campaign_id): """Gets a list of the negative criteria associated with a campaign. Args: campaign_id: str campaign ID. Ex: campaign_id = '1234567890' Returns: tuple response from the API method. """ glob_sanity_check.ValidateTypes(((campaign_id, (str, unicode)),)) method_name = 'getCampaignNegativeCriteria' if self.__config['soap_lib'] == SOAPPY: return self.__service.CallMethod(method_name, (campaign_id)) elif self.__config['soap_lib'] == ZSI: web_services = self.__web_services request = eval('web_services.%sRequest()' % method_name) return self.__service.CallMethod(method_name, (({'campaignId': campaign_id},)), 'Criterion', self.__loc, request) def GetCriteria(self, ad_group_id, criterion_ids): """Return a list of criteria with the specified IDs. Specified IDs are associated with this AdGroup. Args: ad_group_id: str ID of the AdGroup. criterion_ids: list IDs of the criteria. Ex: ad_group_id = '1234567890' criterion_ids = ['1234567890'] Returns: tuple response from the API method. """ glob_sanity_check.ValidateTypes(((ad_group_id, (str, unicode)), (criterion_ids, list))) for item in criterion_ids: glob_sanity_check.ValidateTypes(((item, (str, unicode)),)) method_name = 'getCriteria' if self.__config['soap_lib'] == SOAPPY: return self.__service.CallMethod(method_name, (ad_group_id, criterion_ids)) elif self.__config['soap_lib'] == ZSI: web_services = self.__web_services request = eval('web_services.%sRequest()' % method_name) return self.__service.CallMethod(method_name, (({'adGroupId': ad_group_id}, {'criterionIds': criterion_ids})), 'Criterion', self.__loc, request) def GetCriterionStats(self, ad_group_id, criterion_ids, start_day, end_day): """Get statistics for a list of criteria in an ad group. Args: ad_group_id: str ID of the AdGroup. criterion_ids: list IDs of the criteria. start_day: str starting day of the period for which statistics are to be collected. end_dat: str ending day of the period for which statistics are to be collected, inclusive. Ex: ad_group_id = '1234567890' criterion_ids = ['1234567890'] start_day = '2008-01-01' end_day = '2008-01-31' Returns: tuple response from the API method. """ glob_sanity_check.ValidateTypes(((ad_group_id, (str, unicode)), (criterion_ids, list), (start_day, (str, unicode)), (end_day, (str, unicode)))) for item in criterion_ids: glob_sanity_check.ValidateTypes(((item, (str, unicode)),)) method_name = 'getCriterionStats' if self.__config['soap_lib'] == SOAPPY: return self.__service.CallMethod(method_name, (ad_group_id, criterion_ids, start_day, end_day)) elif self.__config['soap_lib'] == ZSI: web_services = self.__web_services request = eval('web_services.%sRequest()' % method_name) return self.__service.CallMethod(method_name, (({'adGroupId': ad_group_id}, {'criterionIds': criterion_ids}, {'startDay': start_day}, {'endDay': end_day})), 'Criterion', self.__loc, request) def RemoveCriteria(self, ad_group_id, criterion_ids): """Remove a list of criteria from an AdGroup. Args: ad_group_id: str ID of the AdGroup. criterion_ids: list IDs of the criteria. Ex: ad_group_id = '1234567890' criterion_ids = ['1234567890'] """ glob_sanity_check.ValidateTypes(((ad_group_id, (str, unicode)), (criterion_ids, list))) for item in criterion_ids: glob_sanity_check.ValidateTypes(((item, (str, unicode)),)) method_name = 'removeCriteria' if self.__config['soap_lib'] == SOAPPY: self.__service.CallMethod(method_name, (ad_group_id, criterion_ids)) elif self.__config['soap_lib'] == ZSI: web_services = self.__web_services request = eval('web_services.%sRequest()' % method_name) self.__service.CallMethod(method_name, (({'adGroupId': ad_group_id}, {'criterionIds': criterion_ids})), 'Criterion', self.__loc, request) def SetCampaignNegativeCriteria(self, campaign_id, criteria): """Set campaign negative criteria. Removes all existing negative criteria from a campaign and sets new negative criteria for the specified campaign. Args: campaign_id: str campaign ID. criteria: list negative criteria to be associated with the Campaign. Ex: campaign_id = '1234567890' criteria = [ { 'adGroupId': '1234567890', 'criterionType': 'Keyword' or 'Website', 'destinationUrl': 'http://www.example.com', 'exemptionRequest': 'Exemption request goes here.', 'id': '1234567890', 'language': 'en', 'maxCpc': '1000000', 'negative': 'True', 'paused': 'False', 'status': 'Active', # Keyword only 'firstPageCpc': '1000000', 'proxyMaxCpc': '1000000', 'text': 'car insurance', 'qualityScore': '5', 'type': 'Broad', # Website only 'maxCpm': '1000000', 'url': 'example.com' } ] """ glob_sanity_check.ValidateTypes(((campaign_id, (str, unicode)), (criteria, list))) method_name = 'setCampaignNegativeCriteria' if self.__config['soap_lib'] == SOAPPY: for item in criteria: self.__sanity_check.ValidateCriterionV13(item) self.__service.CallMethod(method_name, (campaign_id, criteria)) elif self.__config['soap_lib'] == ZSI: web_services = self.__web_services new_criteria = [] for item in criteria: new_criteria.append(self.__sanity_check.ValidateCriterion( '', item, web_services)) request = eval('web_services.%sRequest()' % method_name) self.__service.CallMethod(method_name, (({'campaignId': campaign_id}, {'criteria': new_criteria})), 'Criterion', self.__loc, request) def UpdateCriteria(self, criteria): """Update all mutable fields associated with these criteria. Args: criteria: list criteria to be update. Ex: criteria = [ { 'adGroupId': '1234567890', 'criterionType': 'Keyword' or 'Website', 'destinationUrl': 'http://www.example.com', 'id': '1234567890', 'maxCpc': '1000000', 'paused': 'False', # Website only 'maxCpm': '1000000' } ] """ glob_sanity_check.ValidateTypes(((criteria, list),)) method_name = 'updateCriteria' if self.__config['soap_lib'] == SOAPPY: for item in criteria: self.__sanity_check.ValidateCriterionV13(item) self.__service.CallMethod(method_name, (criteria)) elif self.__config['soap_lib'] == ZSI: web_services = self.__web_services new_criteria = [] for item in criteria: new_criteria.append(self.__sanity_check.ValidateCriterion( '', item, web_services)) request = eval('web_services.%sRequest()' % method_name) self.__service.CallMethod(method_name, (({'criteria': new_criteria},)), 'Criterion', self.__loc, request)