diff --git a/HISTORY.rst b/HISTORY.rst
index 4fc6d232..e8342b70 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -1,6 +1,15 @@
.. :changelog:
Release History
+13.0.19(2024-03-25)
++++++++++++++++++++++++++
+* Update Bing Ads API Version 13 service proxies to reflect recent interface changes. For details please see the Bing Ads API Release Notes: https://learn.microsoft.com/en-us/advertising/guides/release-notes?view=bingads-13.
+* Added bulk mappings for Account Level Negative Keyword List i.e., BulkAccountNegativeKeywordList, BulkAccountNegativeKeywordListAssociation and BulkAccountSharedNegativeKeyword.
+* Added bulk mappings for BulkSeasonalityAdjustment and BulkDataExclusion.
+* Removed mappings for VerifiedTrackingSetting field in BulkCampaign.
+* Added mappings for new field in BulkCampaign: AutoGeneratedImageOptOut and AutoGeneratedTextOptOut.
+* Added PerformanceMaxsetting for PageFeedIds field in BulkCampaign.
+* Added mappings for new BiddingScheme: CostPerSaleBiddingScheme.
13.0.18.1(2024-01-30)
+++++++++++++++++++++++++
diff --git a/bingads/manifest.py b/bingads/manifest.py
index 43f9e22c..55facdf3 100644
--- a/bingads/manifest.py
+++ b/bingads/manifest.py
@@ -1,5 +1,5 @@
import sys
-VERSION = '13.0.18.1'
+VERSION = '13.0.19'
BULK_FORMAT_VERSION_6 = '6.0'
WORKING_NAME = 'BingAdsSDKPython'
USER_AGENT = '{0} {1} {2}'.format(WORKING_NAME, VERSION, sys.version_info[0:3])
diff --git a/bingads/v13/bulk/entities/__init__.py b/bingads/v13/bulk/entities/__init__.py
index e466cd25..b9022fc6 100644
--- a/bingads/v13/bulk/entities/__init__.py
+++ b/bingads/v13/bulk/entities/__init__.py
@@ -47,3 +47,6 @@
from .bulk_asset_group_listing_group import *
from .bulk_audience_group_asset_group_association import *
from .bulk_campaign_negative_webpage import *
+from .bulk_seasonality_adjustment import *
+from .bulk_data_exclusion import *
+from .bulk_account_negative_keyword_list import *
diff --git a/bingads/v13/bulk/entities/bulk_account_negative_keyword_list.py b/bingads/v13/bulk/entities/bulk_account_negative_keyword_list.py
new file mode 100644
index 00000000..f786f8c5
--- /dev/null
+++ b/bingads/v13/bulk/entities/bulk_account_negative_keyword_list.py
@@ -0,0 +1,164 @@
+from bingads.service_client import _CAMPAIGN_OBJECT_FACTORY_V13
+from bingads.v13.internal.bulk.string_table import _StringTable
+from bingads.v13.internal.bulk.entities.single_record_bulk_entity import _SingleRecordBulkEntity
+from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping
+from bingads.v13.internal.extensions import bulk_str
+
+class BulkAccountNegativeKeywordList(_SingleRecordBulkEntity):
+ """ Represents an account negative keyword list association that can be read or written in a bulk file.
+
+ This class exposes the :attr:`.BulkAccountNegativeKeywordList.account_negative_keyword_list` property that can be read and
+ written as fields of the account negative keyword list association record in a bulk file.
+
+ For more information, see account negative keyword list association at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self, status=None, account_negative_keyword_list=None):
+ super(BulkAccountNegativeKeywordList, self).__init__()
+
+ self._status = status
+ self._account_negative_keyword_list = account_negative_keyword_list
+
+ @property
+ def account_negative_keyword_list(self):
+ """ The account negative keyword list association.
+
+ see account negative keyword list association at https://go.microsoft.com/fwlink/?linkid=846127.
+ """
+
+ return self._account_negative_keyword_list
+
+ @account_negative_keyword_list.setter
+ def account_negative_keyword_list(self, account_negative_keyword_list):
+ self._account_negative_keyword_list = account_negative_keyword_list
+
+ @property
+ def status(self):
+ """ The status of the account negative keyword list association.
+
+ :rtype: str
+ """
+
+ return self._status
+
+ @status.setter
+ def status(self, status):
+ self._status = status
+
+ _MAPPINGS = [
+ _SimpleBulkMapping(
+ header=_StringTable.Id,
+ field_to_csv=lambda c: bulk_str(c.account_negative_keyword_list.Id),
+ csv_to_field=lambda c, v: setattr(c.account_negative_keyword_list, 'Id', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.Status,
+ field_to_csv=lambda c: bulk_str(c.status),
+ csv_to_field=lambda c, v: setattr(c, 'status', v if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.Name,
+ field_to_csv=lambda c: c.account_negative_keyword_list.Name,
+ csv_to_field=lambda c, v: setattr(c.account_negative_keyword_list, 'Name', v)
+ )
+ ]
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self._account_negative_keyword_list, 'account_negative_keyword_list')
+ self.convert_to_values(row_values, BulkAccountNegativeKeywordList._MAPPINGS)
+
+ def process_mappings_from_row_values(self, row_values):
+ self._account_negative_keyword_list = _CAMPAIGN_OBJECT_FACTORY_V13.create('AccountNegativeKeywordList')
+ self._account_negative_keyword_list.Type = 'AccountNegativeKeywordList'
+ row_values.convert_to_entity(self, BulkAccountNegativeKeywordList._MAPPINGS)
+
+ def read_additional_data(self, stream_reader):
+ super(BulkAccountNegativeKeywordList, self).read_additional_data(stream_reader)
+
+class BulkAccountNegativeKeywordListAssociation(_SingleRecordBulkEntity):
+ """ Represents an account negative keyword list association that is assigned to a campaign. Each account negative keyword list association can be read or written in a bulk file.
+
+ This class exposes the :attr:`BulkAccountNegativeKeywordListAssociation.SharedEntityAssociation` property that can be read
+ and written as fields of the account negative keyword list association record in a bulk file.
+
+ For more information, see account negative keyword list association at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self, status=None, shared_entity_association=None):
+ super(BulkAccountNegativeKeywordListAssociation, self).__init__()
+
+ self._shared_entity_association = shared_entity_association
+ self._status = status
+
+ @property
+ def status(self):
+ """ The status of the account negative keyword list association.
+
+ :rtype: str
+ """
+
+ return self._status
+
+ @status.setter
+ def status(self, status):
+ self._status = status
+
+ @property
+ def shared_entity_association(self):
+ """ The campaign and account negative keyword list association identifiers.
+
+ see Campaign account negative keyword list association at https://go.microsoft.com/fwlink/?linkid=846127.
+ """
+
+ return self._shared_entity_association
+
+ @shared_entity_association.setter
+ def shared_entity_association(self, shared_entity_association):
+ self._shared_entity_association = shared_entity_association
+
+ _MAPPINGS = [
+ _SimpleBulkMapping(
+ header=_StringTable.Status,
+ field_to_csv=lambda c: c.status,
+ csv_to_field=lambda c, v: setattr(c, 'status', v if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.Id,
+ field_to_csv=lambda c: bulk_str(c.shared_entity_association.SharedEntityId),
+ csv_to_field=lambda c, v: setattr(c.shared_entity_association, 'SharedEntityId', int(v))
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.ParentId,
+ field_to_csv=lambda c: bulk_str(c.shared_entity_association.EntityId),
+ csv_to_field=lambda c, v: setattr(c.shared_entity_association, 'EntityId', int(v))
+ ),
+ ]
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self._shared_entity_association, 'shared_entity_association')
+ self.convert_to_values(row_values, BulkAccountNegativeKeywordListAssociation._MAPPINGS)
+
+ def process_mappings_from_row_values(self, row_values):
+ self._shared_entity_association = _CAMPAIGN_OBJECT_FACTORY_V13.create('SharedEntityAssociation')
+ self._shared_entity_association.EntityType = 'Account'
+ self._shared_entity_association.SharedEntityType = 'NegativeKeywordList'
+ row_values.convert_to_entity(self, BulkAccountNegativeKeywordListAssociation._MAPPINGS)
+
+ def read_additional_data(self, stream_reader):
+ super(BulkAccountNegativeKeywordListAssociation, self).read_additional_data(stream_reader)
+
+
diff --git a/bingads/v13/bulk/entities/bulk_campaign.py b/bingads/v13/bulk/entities/bulk_campaign.py
index 3ddc712a..7907b0a9 100644
--- a/bingads/v13/bulk/entities/bulk_campaign.py
+++ b/bingads/v13/bulk/entities/bulk_campaign.py
@@ -41,6 +41,7 @@ def __init__(self, account_id=None, campaign=None):
self._verified_tracking_data = None
self._destination_channel = None
self._is_multi_channel_campaign = None
+ self._should_serve_on_msan = None
@property
def account_id(self):
@@ -137,6 +138,14 @@ def is_multi_channel_campaign(self):
def is_multi_channel_campaign(self, value):
self._is_multi_channel_campaign = value
+ @property
+ def should_serve_on_msan(self):
+ return self._should_serve_on_msan
+
+ @should_serve_on_msan.setter
+ def should_serve_on_msan(self, value):
+ self._should_serve_on_msan = value
+
def _get_dynamic_feed_setting(self):
return self._get_setting(_DynamicFeedSetting, 'DynamicFeedSetting')
@@ -419,20 +428,76 @@ def _read_page_feed_ids(c, v):
if not c.campaign.CampaignType:
return None
campgaign_types = [campaign_type.lower() for campaign_type in c.campaign.CampaignType]
- dsa_setting = c._get_dsa_setting()
- if not dsa_setting:
- return None
- dsa_setting.PageFeedIds.long = csv_to_field_PageFeedIds(v)
+ if 'performancemax' in campgaign_types:
+ performance_max_setting = c._get_performance_max_setting()
+ if not performance_max_setting:
+ return None
+ performance_max_setting.PageFeedIds.long = csv_to_field_PageFeedIds(v)
+ else:
+ dsa_setting = c._get_dsa_setting()
+ if not dsa_setting:
+ return None
+ dsa_setting.PageFeedIds.long = csv_to_field_PageFeedIds(v)
@staticmethod
def _write_page_feed_ids(c):
if not c.campaign.CampaignType:
return None
campgaign_types = [campaign_type.lower() for campaign_type in c.campaign.CampaignType]
- dsa_setting = c._get_dsa_setting()
- if not dsa_setting:
+ if 'performancemax' in campgaign_types:
+ performance_max_setting = c._get_performance_max_setting()
+ if not performance_max_setting:
+ return None
+ return field_to_csv_Ids(performance_max_setting.PageFeedIds, c.campaign.Id)
+ else:
+ dsa_setting = c._get_dsa_setting()
+ if not dsa_setting:
+ return None
+ return field_to_csv_Ids(dsa_setting.PageFeedIds, c.campaign.Id)
+
+ @staticmethod
+ def _read_text_opt_out(c, v):
+ if not c.campaign.CampaignType:
return None
- return field_to_csv_Ids(dsa_setting.PageFeedIds, c.campaign.Id)
+ campgaign_types = [campaign_type.lower() for campaign_type in c.campaign.CampaignType]
+ if 'performancemax' in campgaign_types:
+ performance_max_setting = c._get_performance_max_setting()
+ if not performance_max_setting:
+ return None
+ performance_max_setting.AutoGeneratedTextOptOut = parse_bool(v)
+
+ @staticmethod
+ def _write_text_opt_out(c):
+ if not c.campaign.CampaignType:
+ return None
+ campgaign_types = [campaign_type.lower() for campaign_type in c.campaign.CampaignType]
+ if 'performancemax' in campgaign_types:
+ performance_max_setting = c._get_performance_max_setting()
+ if not performance_max_setting:
+ return None
+ return bulk_str(performance_max_setting.AutoGeneratedTextOptOut)
+
+ @staticmethod
+ def _read_image_opt_out(c, v):
+ if not c.campaign.CampaignType:
+ return None
+ campgaign_types = [campaign_type.lower() for campaign_type in c.campaign.CampaignType]
+ if 'performancemax' in campgaign_types:
+ performance_max_setting = c._get_performance_max_setting()
+ if not performance_max_setting:
+ return None
+ performance_max_setting.AutoGeneratedImageOptOut = parse_bool(v)
+
+ @staticmethod
+ def _write_image_opt_out(c):
+ if not c.campaign.CampaignType:
+ return None
+ campgaign_types = [campaign_type.lower() for campaign_type in c.campaign.CampaignType]
+ if 'performancemax' in campgaign_types:
+ performance_max_setting = c._get_performance_max_setting()
+ if not performance_max_setting:
+ return None
+ return bulk_str(performance_max_setting.AutoGeneratedImageOptOut)
@staticmethod
def _read_website(c, v):
@@ -639,11 +704,6 @@ def _write_website(c):
field_to_csv=lambda c: BulkCampaign._write_DynamicDescriptionEnabled(c),
csv_to_field=lambda c, v: BulkCampaign._read_DynamicDescriptionEnabled(c, v)
),
- _SimpleBulkMapping(
- header=_StringTable.Details,
- field_to_csv=lambda c: to_verified_tracking_setting_string(c.verified_tracking_data),
- csv_to_field=lambda c, v: setattr(c, 'verified_tracking_data', parse_verified_tracking_setting(v) if v else None)
- ),
_SimpleBulkMapping(
header=_StringTable.DestinationChannel,
field_to_csv=lambda c: c.destination_channel,
@@ -654,6 +714,21 @@ def _write_website(c):
field_to_csv=lambda c: field_to_csv_bool(c.is_multi_channel_campaign),
csv_to_field=lambda c, v: setattr(c, 'is_multi_channel_campaign', parse_bool(v))
),
+ _SimpleBulkMapping(
+ header=_StringTable.AutoGeneratedTextOptOut,
+ field_to_csv=lambda c: BulkCampaign._write_text_opt_out(c),
+ csv_to_field=lambda c, v: BulkCampaign._read_text_opt_out(c, v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.AutoGeneratedImageOptOut,
+ field_to_csv=lambda c: BulkCampaign._write_image_opt_out(c),
+ csv_to_field=lambda c, v: BulkCampaign._read_image_opt_out(c, v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.ShouldServeOnMSAN,
+ field_to_csv=lambda c: field_to_csv_bool(c.should_serve_on_msan),
+ csv_to_field=lambda c, v: setattr(c, 'should_serve_on_msan', parse_bool(v))
+ ),
]
def read_additional_data(self, stream_reader):
diff --git a/bingads/v13/bulk/entities/bulk_data_exclusion.py b/bingads/v13/bulk/entities/bulk_data_exclusion.py
new file mode 100644
index 00000000..b55276d6
--- /dev/null
+++ b/bingads/v13/bulk/entities/bulk_data_exclusion.py
@@ -0,0 +1,95 @@
+from bingads.service_client import _CAMPAIGN_OBJECT_FACTORY_V13
+
+from bingads.v13.internal.bulk.string_table import _StringTable
+from bingads.v13.internal.bulk.entities.single_record_bulk_entity import _SingleRecordBulkEntity
+from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping
+from bingads.v13.internal.extensions import *
+
+class BulkDataExclusion(_SingleRecordBulkEntity):
+ """ Represents an data exclusion.
+
+ This class exposes the property :attr:`data_exclusion` that can be read and written as fields of the data exclusion record
+ in a bulk file.
+
+ For more information, see data exclusion at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self, campaign_id=None, campaign_name=None, data_exclusion=None):
+ super(BulkDataExclusion, self).__init__()
+
+ self._data_exclusion = data_exclusion
+
+ @property
+ def data_exclusion(self):
+ """ The DataExclusion Data Object of the Campaign Management Service.
+
+ A subset of DataExclusion properties are available in the Ad Group record.
+ For more information, see Ad Group at https://go.microsoft.com/fwlink/?linkid=846127.
+ """
+ return self._data_exclusion
+
+ @data_exclusion.setter
+ def data_exclusion(self, data_exclusion):
+ self._data_exclusion = data_exclusion
+
+ _MAPPINGS = [
+ _SimpleBulkMapping(
+ header=_StringTable.Id,
+ field_to_csv=lambda c: bulk_str(c.data_exclusion.Id),
+ csv_to_field=lambda c, v: setattr(c.data_exclusion, 'Id', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.DataExclusion,
+ field_to_csv=lambda c: bulk_str(c.data_exclusion.Name),
+ csv_to_field=lambda c, v: setattr(c.data_exclusion, 'Name', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.StartDate,
+ field_to_csv=lambda c: bulk_datetime_str2(c.data_exclusion.StartDate),
+ csv_to_field=lambda c, v: setattr(c.data_exclusion, 'StartDate', parse_datetime2(v))
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.EndDate,
+ field_to_csv=lambda c: bulk_datetime_str2(c.data_exclusion.EndDate),
+ csv_to_field=lambda c, v: setattr(c.data_exclusion, 'EndDate', parse_datetime2(v))
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.Description,
+ field_to_csv=lambda c: c.data_exclusion.Description,
+ csv_to_field=lambda c, v: setattr(c.data_exclusion, 'Description', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.CampaignType,
+ field_to_csv=lambda c: field_to_csv_CampaignType(c.data_exclusion),
+ csv_to_field=lambda c, v: csv_to_field_CampaignType(c.data_exclusion, v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.DeviceType,
+ field_to_csv=lambda c: bulk_str(c.data_exclusion.DeviceTypeFilter),
+ csv_to_field=lambda c, v: setattr(c.data_exclusion, 'DeviceTypeFilter', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.CampaignAssociations,
+ field_to_csv=lambda c: field_to_csv_CampaignAssociations(c.data_exclusion),
+ csv_to_field=lambda c, v: csv_to_field_CampaignAssociations(c.data_exclusion, v)
+ ),
+ ]
+
+ def process_mappings_from_row_values(self, row_values):
+ self.data_exclusion = _CAMPAIGN_OBJECT_FACTORY_V13.create('DataExclusion')
+
+ row_values.convert_to_entity(self, BulkDataExclusion._MAPPINGS)
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self._data_exclusion, 'DataExclusion')
+ self.convert_to_values(row_values, BulkDataExclusion._MAPPINGS)
+
+ def read_additional_data(self, stream_reader):
+ super(BulkDataExclusion, self).read_additional_data(stream_reader)
diff --git a/bingads/v13/bulk/entities/bulk_negative_keywords.py b/bingads/v13/bulk/entities/bulk_negative_keywords.py
index a20bceb3..bce51892 100644
--- a/bingads/v13/bulk/entities/bulk_negative_keywords.py
+++ b/bingads/v13/bulk/entities/bulk_negative_keywords.py
@@ -373,7 +373,6 @@ def process_mappings_from_row_values(self, row_values):
def read_additional_data(self, stream_reader):
super(BulkCampaignNegativeKeywordList, self).read_additional_data(stream_reader)
-
class BulkNegativeKeywordList(_SingleRecordBulkEntity):
""" Represents a negative keyword list that can be read or written in a bulk file.
@@ -480,3 +479,31 @@ def negative_keyword_list_id(self):
@negative_keyword_list_id.setter
def negative_keyword_list_id(self, value):
self._parent_id = value
+
+class BulkAccountSharedNegativeKeyword(_BulkNegativeKeyword):
+ """ Represents an account negative keyword that is shared in a negative keyword list.
+
+ Each shared negative keyword can be read or written in a bulk file.
+ This class exposes the :attr:`.BulkNegativeKeyword.NegativeKeyword` property that
+ can be read and written as fields of the Account Shared Negative Keyword record in a bulk file.
+
+ For more information, see Account Shared Negative Keyword at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self, status=None, negative_keyword=None, negative_keyword_list_id=None):
+ super(BulkAccountSharedNegativeKeyword, self).__init__(status, negative_keyword, negative_keyword_list_id)
+
+ @property
+ def negative_keyword_list_id(self):
+ return self._parent_id
+
+ @negative_keyword_list_id.setter
+ def negative_keyword_list_id(self, value):
+ self._parent_id = value
diff --git a/bingads/v13/bulk/entities/bulk_seasonality_adjustment.py b/bingads/v13/bulk/entities/bulk_seasonality_adjustment.py
new file mode 100644
index 00000000..111148ba
--- /dev/null
+++ b/bingads/v13/bulk/entities/bulk_seasonality_adjustment.py
@@ -0,0 +1,102 @@
+from bingads.service_client import _CAMPAIGN_OBJECT_FACTORY_V13
+
+from bingads.v13.internal.bulk.string_table import _StringTable
+from bingads.v13.internal.bulk.entities.single_record_bulk_entity import _SingleRecordBulkEntity
+from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping
+from bingads.v13.internal.extensions import *
+
+class BulkSeasonalityAdjustment(_SingleRecordBulkEntity):
+ """ Represents an seasonality adjustment.
+
+ This class exposes the property :attr:`seasonality_adjustment` that can be read and written as fields of the seasonality adjustment record
+ in a bulk file.
+
+ For more information, see seasonality adjustment at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self, campaign_id=None, campaign_name=None, seasonality_adjustment=None):
+ super(BulkSeasonalityAdjustment, self).__init__()
+
+ self._seasonality_adjustment = seasonality_adjustment
+
+ @property
+ def seasonality_adjustment(self):
+ """ The SeasonalityAdjustment Data Object of the Campaign Management Service.
+
+ A subset of SeasonalityAdjustment properties are available in the Ad Group record.
+ For more information, see Ad Group at https://go.microsoft.com/fwlink/?linkid=846127.
+ """
+ return self._seasonality_adjustment
+
+ @seasonality_adjustment.setter
+ def seasonality_adjustment(self, seasonality_adjustment):
+ self._seasonality_adjustment = seasonality_adjustment
+
+
+
+ _MAPPINGS = [
+ _SimpleBulkMapping(
+ header=_StringTable.Id,
+ field_to_csv=lambda c: bulk_str(c.seasonality_adjustment.Id),
+ csv_to_field=lambda c, v: setattr(c.seasonality_adjustment, 'Id', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.SeasonalityAdjustment,
+ field_to_csv=lambda c: bulk_str(c.seasonality_adjustment.Name),
+ csv_to_field=lambda c, v: setattr(c.seasonality_adjustment, 'Name', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.StartDate,
+ field_to_csv=lambda c: bulk_datetime_str2(c.seasonality_adjustment.StartDate),
+ csv_to_field=lambda c, v: setattr(c.seasonality_adjustment, 'StartDate', parse_datetime2(v))
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.EndDate,
+ field_to_csv=lambda c: bulk_datetime_str2(c.seasonality_adjustment.EndDate),
+ csv_to_field=lambda c, v: setattr(c.seasonality_adjustment, 'EndDate', parse_datetime2(v))
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.Description,
+ field_to_csv=lambda c: c.seasonality_adjustment.Description,
+ csv_to_field=lambda c, v: setattr(c.seasonality_adjustment, 'Description', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.CampaignType,
+ field_to_csv=lambda c: field_to_csv_CampaignType(c.seasonality_adjustment),
+ csv_to_field=lambda c, v: csv_to_field_CampaignType(c.seasonality_adjustment, v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.DeviceType,
+ field_to_csv=lambda c: bulk_str(c.seasonality_adjustment.DeviceTypeFilter),
+ csv_to_field=lambda c, v: setattr(c.seasonality_adjustment, 'DeviceTypeFilter', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.AdjustmentValue,
+ field_to_csv=lambda c: c.seasonality_adjustment.AdjustmentPercentage,
+ csv_to_field=lambda c, v: setattr(c.seasonality_adjustment, 'AdjustmentPercentage', float(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.CampaignAssociations,
+ field_to_csv=lambda c: field_to_csv_CampaignAssociations(c.seasonality_adjustment),
+ csv_to_field=lambda c, v: csv_to_field_CampaignAssociations(c.seasonality_adjustment, v)
+ ),
+ ]
+
+ def process_mappings_from_row_values(self, row_values):
+ self.seasonality_adjustment = _CAMPAIGN_OBJECT_FACTORY_V13.create('SeasonalityAdjustment')
+
+ row_values.convert_to_entity(self, BulkSeasonalityAdjustment._MAPPINGS)
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self._seasonality_adjustment, 'SeasonalityAdjustment')
+ self.convert_to_values(row_values, BulkSeasonalityAdjustment._MAPPINGS)
+
+ def read_additional_data(self, stream_reader):
+ super(BulkSeasonalityAdjustment, self).read_additional_data(stream_reader)
diff --git a/bingads/v13/internal/bulk/bulk_object_factory.py b/bingads/v13/internal/bulk/bulk_object_factory.py
index 837804ae..b3d925da 100644
--- a/bingads/v13/internal/bulk/bulk_object_factory.py
+++ b/bingads/v13/internal/bulk/bulk_object_factory.py
@@ -209,6 +209,11 @@ class _BulkObjectFactory():
_StringTable.CampaignNegativeWebpage: _EntityInfo(lambda: BulkCampaignNegativeWebpage()),
_StringTable.AssetGroupListingGroup: _EntityInfo(lambda: BulkAssetGroupListingGroup()),
_StringTable.AudienceGroupAssetGroupAssociation: _EntityInfo(lambda: BulkAudienceGroupAssetGroupAssociation()),
+ _StringTable.SeasonalityAdjustment: _EntityInfo(lambda: BulkSeasonalityAdjustment()),
+ _StringTable.DataExclusion: _EntityInfo(lambda: BulkDataExclusion()),
+ 'Account Negative Keyword List': _EntityInfo(lambda: BulkAccountNegativeKeywordList()),
+ 'Account Negative Keyword List Association': _EntityInfo(lambda: BulkAccountNegativeKeywordListAssociation()),
+ 'Account Shared Negative Keyword': _EntityInfo(lambda: BulkAccountSharedNegativeKeyword()),
}
ADDITIONAL_OBJECT_MAP = {
diff --git a/bingads/v13/internal/bulk/csv_headers.py b/bingads/v13/internal/bulk/csv_headers.py
index 2a8b96e1..0fca20f9 100644
--- a/bingads/v13/internal/bulk/csv_headers.py
+++ b/bingads/v13/internal/bulk/csv_headers.py
@@ -328,6 +328,7 @@ class _CsvHeaders:
_StringTable.BidStrategyTargetImpressionShare,
_StringTable.BidStrategyCommissionRate,
_StringTable.BidStrategyPercentMaxCpc,
+ _StringTable.BidStrategyTargetCostPerSale,
# Ad Format Preference
_StringTable.AdFormatPreference,
@@ -469,6 +470,17 @@ class _CsvHeaders:
_StringTable.CampaignNegativeWebpage,
_StringTable.AssetGroupListingGroup,
_StringTable.AudienceGroupAssetGroupAssociation,
+ _StringTable.AutoGeneratedTextOptOut,
+ _StringTable.AutoGeneratedImageOptOut,
+
+ # Seasonality Adjustment
+ _StringTable.SeasonalityAdjustment,
+ _StringTable.DataExclusion,
+ _StringTable.DeviceType,
+ _StringTable.CampaignAssociations,
+
+ # DNV Serving on MSAN
+ _StringTable.ShouldServeOnMSAN,
]
@staticmethod
diff --git a/bingads/v13/internal/bulk/string_table.py b/bingads/v13/internal/bulk/string_table.py
index 44c75f93..60c58410 100644
--- a/bingads/v13/internal/bulk/string_table.py
+++ b/bingads/v13/internal/bulk/string_table.py
@@ -435,6 +435,7 @@ class _StringTable:
BidStrategyTargetImpressionShare = "Bid Strategy TargetImpressionShare"
BidStrategyPercentMaxCpc = "Bid Strategy PercentMaxCpc"
BidStrategyCommissionRate = "Bid Strategy CommissionRate"
+ BidStrategyTargetCostPerSale = "Bid Strategy TargetCostPerSale"
# Remarketing
Audience = "Audience"
@@ -647,8 +648,18 @@ class _StringTable:
AgeRanges = "Age Ranges"
GenderTypes = "Gender Types"
ParentListingGroupId = "Parent Listing Group Id"
+ AutoGeneratedTextOptOut = "Auto Generated Text Assets Opt Out"
+ AutoGeneratedImageOptOut = "Auto Generated Image Assets Opt Out"
# MultiChannel Campaign
DestinationChannel = "Destination Channel"
IsMultiChannelCampaign = "Is Multi Channel Campaign"
+ # Seasonality Adjustment
+ SeasonalityAdjustment = "Seasonality Adjustment"
+ DataExclusion = "Data Exclusion"
+ DeviceType = "Device Type"
+ CampaignAssociations = "Campaign Associations"
+
+ # DNV Serving on MSAN
+ ShouldServeOnMSAN = "Should Serve On MSAN"
diff --git a/bingads/v13/internal/extensions.py b/bingads/v13/internal/extensions.py
index 82f95bfc..228587e5 100644
--- a/bingads/v13/internal/extensions.py
+++ b/bingads/v13/internal/extensions.py
@@ -55,6 +55,7 @@
TextAsset_Type = type(_CAMPAIGN_OBJECT_FACTORY_V13.create('TextAsset'))
ImageAsset_Type = type(_CAMPAIGN_OBJECT_FACTORY_V13.create('ImageAsset'))
VideoAsset_Type = type(_CAMPAIGN_OBJECT_FACTORY_V13.create('VideoAsset'))
+CampaignAssociation = type(_CAMPAIGN_OBJECT_FACTORY_V13.create('CampaignAssociation'))
KeyValuePairOfstringstring = type(_CAMPAIGN_OBJECT_FACTORY_V13.create('ns1:KeyValuePairOfstringstring'))
ArrayOfKeyValuePairOfstringstring = type(_CAMPAIGN_OBJECT_FACTORY_V13.create('ns1:ArrayOfKeyValuePairOfstringstring'))
ArrayOfArrayOfKeyValuePairOfstringstring = type(_CAMPAIGN_OBJECT_FACTORY_V13.create('ns1:ArrayOfArrayOfKeyValuePairOfstringstring'))
@@ -188,6 +189,9 @@ def entity_csv_to_biddingscheme(row_values, entity):
success, target_ad_position_value = row_values.try_get_value(_StringTable.BidStrategyTargetAdPosition)
+ success, target_cost_per_sale_row_value = row_values.try_get_value(_StringTable.BidStrategyTargetCostPerSale)
+ target_cost_per_sale_value = float(target_cost_per_sale_row_value) if target_cost_per_sale_row_value else None
+
if bid_strategy_type == 'MaxConversions':
entity.BiddingScheme.MaxCpc = max_cpc_value
entity.BiddingScheme.TargetCpa = target_cpa_value
@@ -217,6 +221,9 @@ def entity_csv_to_biddingscheme(row_values, entity):
elif bid_strategy_type == "Commission":
entity.BiddingScheme.MaxPercentCpc = commission_rate_value
entity.BiddingScheme.Type = "Commission"
+ elif bid_strategy_type == "CostPerSale":
+ entity.BiddingScheme.TargetCostPerSale = target_cost_per_sale_value
+ entity.BiddingScheme.Type = "CostPerSale"
def bid_strategy_biddingscheme_to_csv(bulk_bid_strategy, row_values):
entity_biddingscheme_to_csv(bulk_bid_strategy.bid_strategy, row_values)
@@ -256,6 +263,8 @@ def entity_biddingscheme_to_csv(entity, row_values):
row_values[_StringTable.BidStrategyPercentMaxCpc] = bulk_str(entity.BiddingScheme.MaxPercentCpc)
elif bid_strategy_type == 'Commission':
row_values[_StringTable.BidStrategyCommissionRate] = bulk_str(entity.BiddingScheme.CommissionRate)
+ elif bid_strategy_type == 'CostPerSale':
+ row_values[_StringTable.BidStrategyTargetCostPerSale] = bulk_str(entity.BiddingScheme.TargetCostPerSale)
def bulk_optional_str(value, id):
@@ -358,6 +367,37 @@ def csv_to_field_GenderTypes(entity, value):
return
entity.gender_types = [None if i == 'None' else i for i in value.split(';')]
+def field_to_csv_CampaignType(entity):
+ campaign_type = entity.CampaignTypeFilter
+ if campaign_type is None or len(campaign_type) == 0:
+ return None
+ return ','.join(type for type in campaign_type)
+
+def csv_to_field_CampaignType(entity, value):
+ if value is None or value.strip() == '':
+ return
+ entity.CampaignTypeFilter = [None if i == 'None' else i for i in value.split(',')]
+
+def field_to_csv_CampaignAssociations(entity):
+ associations = entity.CampaignAssociations
+ if associations is None or len(associations.CampaignAssociation) == 0:
+ return None
+ result = ""
+ for association in associations.CampaignAssociation:
+ result += str(association.CampaignId) + ";"
+ return result[:-1]
+
+def csv_to_field_CampaignAssociations(entity, value):
+ if value is None or value.strip() == '':
+ return
+ result = []
+ strs = value.split(';')
+ for str in strs:
+ association = CampaignAssociation()
+ association.CampaignId = int(str)
+ result.append(association)
+ entity.CampaignAssociations = result
+
def field_to_csv_MediaIds(entity):
"""
MediaIds field to csv content
@@ -2027,3 +2067,18 @@ def to_operation(op):
if op.lower() == 'or': return 'Or'
if op.lower() == 'not': return 'Not'
return none
+
+def bulk_datetime_str2(value):
+ if value is None:
+ return None
+
+ return value.strftime('%Y/%m/%d %H:%M:%S')
+
+def parse_datetime2(value):
+
+ if not value:
+ return None
+ try:
+ return datetime.strptime(value, '%Y/%m/%d %H:%M:%S')
+ except Exception:
+ return parse_datetime(value)
diff --git a/bingads/v13/proxies/production/adinsight_service.xml b/bingads/v13/proxies/production/adinsight_service.xml
index f1ac8dc9..f1cc7426 100644
--- a/bingads/v13/proxies/production/adinsight_service.xml
+++ b/bingads/v13/proxies/production/adinsight_service.xml
@@ -3246,6 +3246,506 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 23
+
+
+
+
+
+
+ 15
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ 78
+
+
+
+
+
+
+ 87
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+ 16
+
+
+
+
+
+
+ 18
+
+
+
+
+
+
+ 20
+
+
+
+
+
+
+ 5
+
+
+
+
+
+
+ 88
+
+
+
+
+
+
+ 25
+
+
+
+
+
+
+ 6
+
+
+
+
+
+
+ 33
+
+
+
+
+
+
+ 30
+
+
+
+
+
+
+ 36
+
+
+
+
+
+
+ 8
+
+
+
+
+
+
+ 48
+
+
+
+
+
+
+ 58
+
+
+
+
+
+
+ 57
+
+
+
+
+
+
+ 52
+
+
+
+
+
+
+ 82
+
+
+
+
+
+
+ 10
+
+
+
+
+
+
+ 9
+
+
+
+
+
+
+ 64
+
+
+
+
+
+
+ 65
+
+
+
+
+
+
+ 69
+
+
+
+
+
+
+ 34
+
+
+
+
+
+
+ 72
+
+
+
+
+
+
+ 74
+
+
+
+
+
+
+ 13
+
+
+
+
+
+
+ 11
+
+
+
+
+
+
+ 4
+
+
+
+
+
+
+ 93
+
+
+
+
+
+
+ 7
+
+
+
+
+
+
+ 12
+
+
+
+
+
+
+ 45
+
+
+
+
+
+
+ 17
+
+
+
+
+
+
+ 67
+
+
+
+
+
+
+ 21
+
+
+
+
+
+
+ 35
+
+
+
+
+
+
+ 99
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -4080,6 +4580,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -4267,6 +4791,12 @@
+
+
+
+
+
+
@@ -4984,6 +5514,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bingads/v13/proxies/production/bulk_service.xml b/bingads/v13/proxies/production/bulk_service.xml
index 5cc722a2..fad72b2e 100644
--- a/bingads/v13/proxies/production/bulk_service.xml
+++ b/bingads/v13/proxies/production/bulk_service.xml
@@ -1191,6 +1191,90 @@
+
+
+
+ 161
+
+
+
+
+
+
+ 162
+
+
+
+
+
+
+ 163
+
+
+
+
+
+
+ 164
+
+
+
+
+
+
+ 165
+
+
+
+
+
+
+ 166
+
+
+
+
+
+
+ 167
+
+
+
+
+
+
+ 168
+
+
+
+
+
+
+ 169
+
+
+
+
+
+
+ 170
+
+
+
+
+
+
+ 171
+
+
+
+
+
+
+ 172
+
+
+
diff --git a/bingads/v13/proxies/production/campaignmanagement_service.xml b/bingads/v13/proxies/production/campaignmanagement_service.xml
index c4bfb83d..a3711e86 100644
--- a/bingads/v13/proxies/production/campaignmanagement_service.xml
+++ b/bingads/v13/proxies/production/campaignmanagement_service.xml
@@ -947,6 +947,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1394,6 +1408,7 @@
+
@@ -4766,6 +4781,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -4881,6 +4906,14 @@
+
+
+
+
+
+
+
+
@@ -7286,6 +7319,13 @@
+
+
+
+
+
+
+
@@ -7377,6 +7417,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -7643,6 +7697,27 @@
+
+
+
+ 32768
+
+
+
+
+
+
+ 65536
+
+
+
+
+
+
+ 131072
+
+
+
@@ -7887,6 +7962,233 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 4
+
+
+
+
+
+
+ 7
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -11471,6 +11773,246 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -12336,6 +12878,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -15652,6 +16254,236 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bingads/v13/proxies/production/reporting_service.xml b/bingads/v13/proxies/production/reporting_service.xml
index a6162b12..fd612003 100644
--- a/bingads/v13/proxies/production/reporting_service.xml
+++ b/bingads/v13/proxies/production/reporting_service.xml
@@ -4113,6 +4113,7 @@
+
@@ -4195,6 +4196,7 @@
+
diff --git a/bingads/v13/proxies/sandbox/adinsight_service.xml b/bingads/v13/proxies/sandbox/adinsight_service.xml
index 19468a03..a85e68f5 100644
--- a/bingads/v13/proxies/sandbox/adinsight_service.xml
+++ b/bingads/v13/proxies/sandbox/adinsight_service.xml
@@ -3246,6 +3246,506 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 23
+
+
+
+
+
+
+ 15
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ 78
+
+
+
+
+
+
+ 87
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+ 16
+
+
+
+
+
+
+ 18
+
+
+
+
+
+
+ 20
+
+
+
+
+
+
+ 5
+
+
+
+
+
+
+ 88
+
+
+
+
+
+
+ 25
+
+
+
+
+
+
+ 6
+
+
+
+
+
+
+ 33
+
+
+
+
+
+
+ 30
+
+
+
+
+
+
+ 36
+
+
+
+
+
+
+ 8
+
+
+
+
+
+
+ 48
+
+
+
+
+
+
+ 58
+
+
+
+
+
+
+ 57
+
+
+
+
+
+
+ 52
+
+
+
+
+
+
+ 82
+
+
+
+
+
+
+ 10
+
+
+
+
+
+
+ 9
+
+
+
+
+
+
+ 64
+
+
+
+
+
+
+ 65
+
+
+
+
+
+
+ 69
+
+
+
+
+
+
+ 34
+
+
+
+
+
+
+ 72
+
+
+
+
+
+
+ 74
+
+
+
+
+
+
+ 13
+
+
+
+
+
+
+ 11
+
+
+
+
+
+
+ 4
+
+
+
+
+
+
+ 93
+
+
+
+
+
+
+ 7
+
+
+
+
+
+
+ 12
+
+
+
+
+
+
+ 45
+
+
+
+
+
+
+ 17
+
+
+
+
+
+
+ 67
+
+
+
+
+
+
+ 21
+
+
+
+
+
+
+ 35
+
+
+
+
+
+
+ 99
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -4080,6 +4580,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -4267,6 +4791,12 @@
+
+
+
+
+
+
@@ -4984,6 +5514,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bingads/v13/proxies/sandbox/bulk_service.xml b/bingads/v13/proxies/sandbox/bulk_service.xml
index 8ba6e837..cc383e37 100644
--- a/bingads/v13/proxies/sandbox/bulk_service.xml
+++ b/bingads/v13/proxies/sandbox/bulk_service.xml
@@ -1191,6 +1191,90 @@
+
+
+
+ 161
+
+
+
+
+
+
+ 162
+
+
+
+
+
+
+ 163
+
+
+
+
+
+
+ 164
+
+
+
+
+
+
+ 165
+
+
+
+
+
+
+ 166
+
+
+
+
+
+
+ 167
+
+
+
+
+
+
+ 168
+
+
+
+
+
+
+ 169
+
+
+
+
+
+
+ 170
+
+
+
+
+
+
+ 171
+
+
+
+
+
+
+ 172
+
+
+
diff --git a/bingads/v13/proxies/sandbox/campaignmanagement_service.xml b/bingads/v13/proxies/sandbox/campaignmanagement_service.xml
index 612c5333..4054fabf 100644
--- a/bingads/v13/proxies/sandbox/campaignmanagement_service.xml
+++ b/bingads/v13/proxies/sandbox/campaignmanagement_service.xml
@@ -947,6 +947,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1394,6 +1408,7 @@
+
@@ -4766,6 +4781,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -4881,6 +4906,14 @@
+
+
+
+
+
+
+
+
@@ -7391,6 +7424,13 @@
+
+
+
+
+
+
+
@@ -7671,6 +7711,13 @@
+
+
+
+ 131072
+
+
+
@@ -7915,6 +7962,233 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 4
+
+
+
+
+
+
+ 7
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -11499,6 +11773,246 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -12364,6 +12878,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -15680,6 +16254,236 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bingads/v13/proxies/sandbox/reporting_service.xml b/bingads/v13/proxies/sandbox/reporting_service.xml
index c82f45f9..4b5a9a0b 100644
--- a/bingads/v13/proxies/sandbox/reporting_service.xml
+++ b/bingads/v13/proxies/sandbox/reporting_service.xml
@@ -4113,6 +4113,7 @@
+
@@ -4195,6 +4196,7 @@
+
diff --git a/setup.py b/setup.py
index 6dbf0672..88f52c54 100644
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,7 @@
except ImportError:
from distutils.core import setup
-VERSION = '13.0.18.1'
+VERSION = '13.0.19'
with open('README.rst', 'r') as f:
readme = f.read()