diff --git a/HISTORY.rst b/HISTORY.rst
index ab335629..a15a657d 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -1,6 +1,16 @@
.. :changelog:
Release History
+13.0.21(2024-07-18)
++++++++++++++++++++++++++
+* 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 new AudienceType:ImpressionBasedRemarketingList i.e., BulkImpressionBasedRemarketingList, BulkAdGroupImpressionBasedRemarketingListAssociation, BulkAdGroupNegativeImpressionBasedRemarketingListAssociation, BulkCampaignImpressionBasedRemarketingListAssociation and BulkCampaignNegativeImpressionBasedRemarketingListAssociation.
+* Added bulk mappings for Goals i.e., BulkAppInstallGoal, BulkDurationGoal, BulkEventGoal, BulkInStoreTransactionGoal, BulkInStoreVisitGoal, BulkOfflineConversionGoal, BulkPagesViewedPerVisitGoal, BulkProductGoal and BulkUrlGoal.
+* Added bulk mappings for BulkBrandItem, BulkBrandList and BulkCampaignBrandListAssociation.
+* Added bulk mappings for BulkAssetGroupSearchTheme.
+* Added mappings for new field in BulkCampaign: CostPerSaleOptOut.
+* Changed DeviceTypeFilter to enum list in BulkSeasonlityAdjustment and BulkDataExclusion.
+
13.0.19.1(2024-04-09)
+++++++++++++++++++++++++
* 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.
diff --git a/bingads/manifest.py b/bingads/manifest.py
index 6dd47e39..53448925 100644
--- a/bingads/manifest.py
+++ b/bingads/manifest.py
@@ -1,5 +1,5 @@
import sys
-VERSION = '13.0.19.1'
+VERSION = '13.0.21'
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 b9022fc6..db4ace73 100644
--- a/bingads/v13/bulk/entities/__init__.py
+++ b/bingads/v13/bulk/entities/__init__.py
@@ -50,3 +50,8 @@
from .bulk_seasonality_adjustment import *
from .bulk_data_exclusion import *
from .bulk_account_negative_keyword_list import *
+from .bulk_asset_group_search_theme import *
+from .bulk_campaign_brand_list_association import *
+from .bulk_brand_item import *
+from .bulk_brand_list import *
+from .goals import *
diff --git a/bingads/v13/bulk/entities/ad_extensions/bulk_image_ad_extensions.py b/bingads/v13/bulk/entities/ad_extensions/bulk_image_ad_extensions.py
index 9b06980e..3d274aa8 100644
--- a/bingads/v13/bulk/entities/ad_extensions/bulk_image_ad_extensions.py
+++ b/bingads/v13/bulk/entities/ad_extensions/bulk_image_ad_extensions.py
@@ -74,7 +74,7 @@ def image_ad_extension(self, value):
),
_SimpleBulkMapping(
header=_StringTable.TrackingTemplate,
- field_to_csv=lambda c: bulk_str(c.image_ad_extension.TrackingUrlTemplate),
+ field_to_csv=lambda c: bulk_optional_str(c.image_ad_extension.TrackingUrlTemplate, c.image_ad_extension.Id),
csv_to_field=lambda c, v: setattr(c.image_ad_extension, 'TrackingUrlTemplate', v if v else None)
),
_SimpleBulkMapping(
diff --git a/bingads/v13/bulk/entities/audiences/__init__.py b/bingads/v13/bulk/entities/audiences/__init__.py
index 5f18f653..a4784b0b 100644
--- a/bingads/v13/bulk/entities/audiences/__init__.py
+++ b/bingads/v13/bulk/entities/audiences/__init__.py
@@ -41,4 +41,9 @@
from .bulk_ad_group_negative_customer_list_association import *
from .bulk_campaign_customer_list_association import *
from .bulk_campaign_negative_customer_list_association import *
-from .bulk_customer_list_item import *
\ No newline at end of file
+from .bulk_customer_list_item import *
+from .bulk_ad_group_impression_based_remarketing_list_association import *
+from .bulk_ad_group_negative_impression_based_remarketing_list_association import *
+from .bulk_campaign_impression_based_remarketing_list_association import *
+from .bulk_campaign_negative_impression_based_remarketing_list_association import *
+from .bulk_impression_based_remarketing_list import *
diff --git a/bingads/v13/bulk/entities/audiences/bulk_ad_group_impression_based_remarketing_list_association.py b/bingads/v13/bulk/entities/audiences/bulk_ad_group_impression_based_remarketing_list_association.py
new file mode 100644
index 00000000..f63f3582
--- /dev/null
+++ b/bingads/v13/bulk/entities/audiences/bulk_ad_group_impression_based_remarketing_list_association.py
@@ -0,0 +1,14 @@
+from bingads.v13.bulk.entities.audiences.bulk_ad_group_audience_association import BulkAdGroupAudienceAssociation
+
+class BulkAdGroupImpressionBasedRemarketingListAssociation(BulkAdGroupAudienceAssociation):
+ """ Represents an Ad Group Impression Based Remarketing List Association that can be read or written in a bulk file.
+
+ For more information, see Ad Group Impression Based Remarketing List Association at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
diff --git a/bingads/v13/bulk/entities/audiences/bulk_ad_group_negative_impression_based_remarketing_list_association.py b/bingads/v13/bulk/entities/audiences/bulk_ad_group_negative_impression_based_remarketing_list_association.py
new file mode 100644
index 00000000..179dd160
--- /dev/null
+++ b/bingads/v13/bulk/entities/audiences/bulk_ad_group_negative_impression_based_remarketing_list_association.py
@@ -0,0 +1,14 @@
+from bingads.v13.bulk.entities.audiences.bulk_ad_group_negative_audience_association import BulkAdGroupNegativeAudienceAssociation
+
+class BulkAdGroupNegativeImpressionBasedRemarketingListAssociation(BulkAdGroupNegativeAudienceAssociation):
+ """ Represents an Ad Group Negative Impression Based Remarketing List Association that can be read or written in a bulk file.
+
+ For more information, see Ad Group Negative Impression Based Remarketing List Association at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
diff --git a/bingads/v13/bulk/entities/audiences/bulk_campaign_impression_based_remarketing_list_association.py b/bingads/v13/bulk/entities/audiences/bulk_campaign_impression_based_remarketing_list_association.py
new file mode 100644
index 00000000..0d7796b2
--- /dev/null
+++ b/bingads/v13/bulk/entities/audiences/bulk_campaign_impression_based_remarketing_list_association.py
@@ -0,0 +1,14 @@
+from bingads.v13.bulk.entities.audiences.bulk_campaign_audience_association import BulkCampaignAudienceAssociation
+
+class BulkCampaignImpressionBasedRemarketingListAssociation(BulkCampaignAudienceAssociation):
+ """ Represents a Campaign Impression Based Remarketing List Association that can be read or written in a bulk file.
+
+ For more information, see Campaign Impression Based Remarketing List Association at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
diff --git a/bingads/v13/bulk/entities/audiences/bulk_campaign_negative_impression_based_remarketing_list_association.py b/bingads/v13/bulk/entities/audiences/bulk_campaign_negative_impression_based_remarketing_list_association.py
new file mode 100644
index 00000000..658a91a6
--- /dev/null
+++ b/bingads/v13/bulk/entities/audiences/bulk_campaign_negative_impression_based_remarketing_list_association.py
@@ -0,0 +1,14 @@
+from bingads.v13.bulk.entities.audiences.bulk_campaign_negative_audience_association import BulkCampaignNegativeAudienceAssociation
+
+class BulkCampaignNegativeImpressionBasedRemarketingListAssociation(BulkCampaignNegativeAudienceAssociation):
+ """ Represents a Campaign Negative Impression Based Remarketing List Association that can be read or written in a bulk file.
+
+ For more information, see Campaign Negative Impression Based Remarketing List Association at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
diff --git a/bingads/v13/bulk/entities/audiences/bulk_impression_based_remarketing_list.py b/bingads/v13/bulk/entities/audiences/bulk_impression_based_remarketing_list.py
new file mode 100644
index 00000000..f2709c73
--- /dev/null
+++ b/bingads/v13/bulk/entities/audiences/bulk_impression_based_remarketing_list.py
@@ -0,0 +1,67 @@
+from bingads.v13.bulk.entities import *
+from bingads.service_client import _CAMPAIGN_OBJECT_FACTORY_V13
+from bingads.v13.internal.bulk.entities.single_record_bulk_entity import _SingleRecordBulkEntity
+from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping
+from bingads.v13.internal.bulk.string_table import _StringTable
+from bingads.v13.internal.extensions import *
+from .bulk_audience import BulkAudience
+
+class BulkImpressionBasedRemarketingList(BulkAudience):
+ """ Represents a Impression Based Remarketing List that can be read or written in a bulk file.
+
+ This class exposes the :attr:`impression_based_remarketing_list` property that can be read and written as fields of the
+ Impression Based Remarketing List record in a bulk file.
+
+ For more information, see Impression Based Remarketing List at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self,
+ impression_based_remarketing_list=None,
+ status=None,):
+ super(BulkImpressionBasedRemarketingList, self).__init__(audience = impression_based_remarketing_list, status = status)
+
+ _MAPPINGS = [
+ _SimpleBulkMapping(
+ _StringTable.ImpressionCampaignId,
+ field_to_csv=lambda c: bulk_str(c.impression_based_remarketing_list.CampaignId),
+ csv_to_field=lambda c, v: setattr(c.impression_based_remarketing_list, 'CampaignId', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ _StringTable.ImpressionAdGroupId,
+ field_to_csv=lambda c: bulk_str(c.impression_based_remarketing_list.AdGroupId),
+ csv_to_field=lambda c, v: setattr(c.impression_based_remarketing_list, 'AdGroupId', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.EntityType,
+ field_to_csv=lambda c: bulk_str(c.impression_based_remarketing_list.EntityType),
+ csv_to_field=lambda c, v: setattr(c.impression_based_remarketing_list, 'EntityType', v)
+ ),
+ ]
+
+ @property
+ def impression_based_remarketing_list(self):
+ """ Defines a Impression Based Remarketing List """
+
+ return self._audience
+
+ @impression_based_remarketing_list.setter
+ def impression_based_remarketing_list(self, impression_based_remarketing_list):
+ self._audience = impression_based_remarketing_list
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self.impression_based_remarketing_list, 'impression_based_remarketing_list')
+ super(BulkImpressionBasedRemarketingList, self).process_mappings_to_row_values(row_values, exclude_readonly_data)
+ self.convert_to_values(row_values, BulkImpressionBasedRemarketingList._MAPPINGS)
+
+ def process_mappings_from_row_values(self, row_values):
+ self.impression_based_remarketing_list = _CAMPAIGN_OBJECT_FACTORY_V13.create('ImpressionBasedRemarketingList')
+ super(BulkImpressionBasedRemarketingList, self).process_mappings_from_row_values(row_values)
+ row_values.convert_to_entity(self, BulkImpressionBasedRemarketingList._MAPPINGS)
+
diff --git a/bingads/v13/bulk/entities/bulk_account.py b/bingads/v13/bulk/entities/bulk_account.py
index 8d80bf7d..29b67e9f 100644
--- a/bingads/v13/bulk/entities/bulk_account.py
+++ b/bingads/v13/bulk/entities/bulk_account.py
@@ -191,7 +191,7 @@ def business_attributes(self, v):
),
_SimpleBulkMapping(
header=_StringTable.TrackingTemplate,
- field_to_csv=lambda c: bulk_str(c.tracking_url_template),
+ field_to_csv=lambda c: bulk_optional_str(c.tracking_url_template, c.id),
csv_to_field=lambda c, v: setattr(c, '_tracking_url_template', v)
),
_SimpleBulkMapping(
diff --git a/bingads/v13/bulk/entities/bulk_ad_group.py b/bingads/v13/bulk/entities/bulk_ad_group.py
index 758c1bec..f820234d 100644
--- a/bingads/v13/bulk/entities/bulk_ad_group.py
+++ b/bingads/v13/bulk/entities/bulk_ad_group.py
@@ -215,7 +215,7 @@ def quality_score_data(self):
),
_SimpleBulkMapping(
header=_StringTable.TrackingTemplate,
- field_to_csv=lambda c: bulk_str(c.ad_group.TrackingUrlTemplate),
+ field_to_csv=lambda c: bulk_optional_str(c.ad_group.TrackingUrlTemplate, c.ad_group.Id),
csv_to_field=lambda c, v: setattr(c.ad_group, 'TrackingUrlTemplate', v if v else None)
),
_SimpleBulkMapping(
diff --git a/bingads/v13/bulk/entities/bulk_asset_group_search_theme.py b/bingads/v13/bulk/entities/bulk_asset_group_search_theme.py
new file mode 100644
index 00000000..5bbdf222
--- /dev/null
+++ b/bingads/v13/bulk/entities/bulk_asset_group_search_theme.py
@@ -0,0 +1,87 @@
+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 BulkAssetGroupSearchTheme(_SingleRecordBulkEntity):
+ """ Represents an asset group search theme.
+
+ This class exposes the property :attr:`asset_group_search_theme` that can be read and written as fields of the asset group search theme record
+ in a bulk file.
+
+ For more information, see asset group search theme at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self, asset_group_id=None, asset_group_search_theme=None):
+ super(BulkAssetGroupSearchTheme, self).__init__()
+
+ self._asset_group_search_theme = asset_group_search_theme
+ self._asset_group_id = asset_group_id
+
+ @property
+ def asset_group_search_theme(self):
+ """ The AssetGroupSearchTheme Data Object of the Campaign Management Service.
+
+ A subset of AssetGroupSearchTheme properties are available in the Ad Group record.
+ For more information, see Ad Group at https://go.microsoft.com/fwlink/?linkid=846127.
+ """
+ return self._asset_group_search_theme
+
+ @asset_group_search_theme.setter
+ def asset_group_search_theme(self, asset_group_search_theme):
+ self._asset_group_search_theme = asset_group_search_theme
+
+ @property
+ def asset_group_id(self):
+ """ The identifier of the asset group that contains the search theme.
+
+ Corresponds to the 'Parent Id' field in the bulk file.
+
+ :rtype: int
+ """
+
+ return self._asset_group_id
+
+ @asset_group_id.setter
+ def asset_group_id(self, asset_group_id):
+ self._asset_group_id = asset_group_id
+
+
+ _MAPPINGS = [
+ _SimpleBulkMapping(
+ header=_StringTable.Id,
+ field_to_csv=lambda c: bulk_str(c.asset_group_search_theme.Id),
+ csv_to_field=lambda c, v: setattr(c.asset_group_search_theme, 'Id', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.ParentId,
+ field_to_csv=lambda c: bulk_str(c.asset_group_id),
+ csv_to_field=lambda c, v: setattr(c, 'asset_group_id', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.SearchTheme,
+ field_to_csv=lambda c: bulk_str(c.asset_group_search_theme.SearchTheme),
+ csv_to_field=lambda c, v: setattr(c.asset_group_search_theme, 'SearchTheme', v)
+ ),
+ ]
+
+ def process_mappings_from_row_values(self, row_values):
+ self.asset_group_search_theme = _CAMPAIGN_OBJECT_FACTORY_V13.create('AssetGroupSearchTheme')
+
+ row_values.convert_to_entity(self, BulkAssetGroupSearchTheme._MAPPINGS)
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self._asset_group_search_theme, 'AssetGroupSearchTheme')
+ self.convert_to_values(row_values, BulkAssetGroupSearchTheme._MAPPINGS)
+
+ def read_additional_data(self, stream_reader):
+ super(BulkAssetGroupSearchTheme, self).read_additional_data(stream_reader)
diff --git a/bingads/v13/bulk/entities/bulk_brand_item.py b/bingads/v13/bulk/entities/bulk_brand_item.py
new file mode 100644
index 00000000..30a93fcb
--- /dev/null
+++ b/bingads/v13/bulk/entities/bulk_brand_item.py
@@ -0,0 +1,207 @@
+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 BulkBrandItem(_SingleRecordBulkEntity):
+ """ Represents a brand item.
+
+ This class exposes the property :attr:`brand_item` that can be read and written as fields of the brand item record
+ in a bulk file.
+
+ For more information, see brand item at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self, id=None, brand_list_id=None, name=None, brand_name=None, brand_url=None, editorial_status=None, editorial_status_date=None, brand_item=None):
+ super(BulkBrandItem, self).__init__()
+
+ self._id = id
+ self._brand_list_id = brand_list_id
+ self._name = name
+ self._brand_name = brand_name
+ self._brand_url = brand_url
+ self._editorial_status = editorial_status
+ self._editorial_status_date = editorial_status_date
+ self._brand_item = brand_item
+
+ @property
+ def brand_item(self):
+ """ The BrandItem Data Object of the Campaign Management Service.
+
+ A subset of BrandItem properties are available in the Brand Item record.
+ For more information, see Brand Item at https://go.microsoft.com/fwlink/?linkid=846127.
+ """
+ return self._brand_item
+
+ @brand_item.setter
+ def brand_item(self, brand_item):
+ self._brand_item = brand_item
+
+ @property
+ def id(self):
+ """ The identifier of the brand item.
+
+ Corresponds to the 'Id' field in the bulk file.
+
+ :rtype: int
+ """
+
+ return self._id
+
+ @id.setter
+ def id(self, id):
+ self._id = id
+
+ @property
+ def brand_list_id(self):
+ """ The identifier of the brand list that contains the brand item.
+
+ Corresponds to the 'Parent Id' field in the bulk file.
+
+ :rtype: int
+ """
+
+ return self._brand_list_id
+
+ @brand_list_id.setter
+ def brand_list_id(self, brand_list_id):
+ self._brand_list_id = brand_list_id
+
+ @property
+ def name(self):
+ """ The name of the brand item.
+
+ Corresponds to the 'Name' field in the bulk file.
+
+ :rtype: str
+ """
+
+ return self._name
+
+ @name.setter
+ def name(self, name):
+ self._name = name
+
+ @property
+ def brand_name(self):
+ """ The name of the brand.
+
+ Corresponds to the 'Brand Name' field in the bulk file.
+
+ :rtype: str
+ """
+
+ return self._brand_name
+
+ @brand_name.setter
+ def brand_name(self, brand_name):
+ self._brand_name = brand_name
+
+ @property
+ def brand_url(self):
+ """ The url of the brand.
+
+ Corresponds to the 'Brand Url' field in the bulk file.
+
+ :rtype: str
+ """
+
+ return self._brand_url
+
+ @brand_url.setter
+ def brand_url(self, brand_url):
+ self._brand_url = brand_url
+
+ @property
+ def editorial_status(self):
+ """ The editorial status
+
+ Corresponds to the 'Editorial Status' field in the bulk file.
+
+ :rtype: str
+ """
+
+ return self._editorial_status
+
+ @editorial_status.setter
+ def editorial_status(self, editorial_status):
+ self._editorial_status = editorial_status
+
+ @property
+ def editorial_status_date(self):
+ """ The editorial status date
+
+ Corresponds to the 'Editorial Status Date' field in the bulk file.
+
+ :rtype: str
+ """
+
+ return self._editorial_status_date
+
+ @editorial_status_date.setter
+ def editorial_status_date(self, editorial_status_date):
+ self._editorial_status_date = editorial_status_date
+
+ _MAPPINGS = [
+ _SimpleBulkMapping(
+ header=_StringTable.Id,
+ field_to_csv=lambda c: bulk_str(c.id),
+ csv_to_field=lambda c, v: setattr(c, 'id', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.Name,
+ field_to_csv=lambda c: bulk_str(c.name),
+ csv_to_field=lambda c, v: setattr(c, 'name', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.ParentId,
+ field_to_csv=lambda c: bulk_str(c.brand_list_id),
+ csv_to_field=lambda c, v: setattr(c, 'brand_list_id', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.BrandId,
+ field_to_csv=lambda c: bulk_str(c.brand_item.BrandId),
+ csv_to_field=lambda c, v: setattr(c.brand_item, 'BrandId', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.BrandName,
+ field_to_csv=lambda c: bulk_str(c.brand_name),
+ csv_to_field=lambda c, v: setattr(c, 'brand_name', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.BrandUrl,
+ field_to_csv=lambda c: bulk_str(c.brand_url),
+ csv_to_field=lambda c, v: setattr(c, 'brand_url', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.EditorialStatus,
+ field_to_csv=lambda c: bulk_str(c.editorial_status),
+ csv_to_field=lambda c, v: setattr(c, 'editorial_status', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.StatusDateTime,
+ field_to_csv=lambda c: bulk_datetime_str2(c.editorial_status_date),
+ csv_to_field=lambda c, v: setattr(c, 'editorial_status_date', parse_datetime2(v))
+ ),
+ ]
+
+ def process_mappings_from_row_values(self, row_values):
+ self.brand_item = _CAMPAIGN_OBJECT_FACTORY_V13.create('BrandItem')
+
+ row_values.convert_to_entity(self, BulkBrandItem._MAPPINGS)
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self.brand_item, 'BrandItem')
+ self.convert_to_values(row_values, BulkBrandItem._MAPPINGS)
+
+ def read_additional_data(self, stream_reader):
+ super(BulkBrandItem, self).read_additional_data(stream_reader)
diff --git a/bingads/v13/bulk/entities/bulk_brand_list.py b/bingads/v13/bulk/entities/bulk_brand_list.py
new file mode 100644
index 00000000..ae0c9964
--- /dev/null
+++ b/bingads/v13/bulk/entities/bulk_brand_list.py
@@ -0,0 +1,88 @@
+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 BulkBrandList(_SingleRecordBulkEntity):
+ """ Represents a campaign brand list association.
+
+ This class exposes the property :attr:`campaign_brand_list_association` that can be read and written as fields of the campaign brand list association record
+ in a bulk file.
+
+ For more information, see campaign brand list association at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self, account_id=None, brand_list=None):
+ super(BulkBrandList, self).__init__()
+
+ self._account_id = account_id
+ self._brand_list = brand_list
+
+ @property
+ def brand_list(self):
+ """ The BrandList Data Object of the Campaign Management Service.
+
+ A subset of BrandList properties are available in the Brand List record.
+ For more information, see Brand Item at https://go.microsoft.com/fwlink/?linkid=846127.
+ """
+ return self._brand_list
+
+ @brand_list.setter
+ def brand_list(self, brand_list):
+ self._brand_list = brand_list
+
+ @property
+ def account_id(self):
+ """ The identifier of the account that contains the brand list.
+
+ Corresponds to the 'Parent Id' field in the bulk file.
+
+ :rtype: int
+ """
+
+ return self._account_id
+
+ @account_id.setter
+ def account_id(self, account_id):
+ self._account_id = account_id
+
+
+ _MAPPINGS = [
+ _SimpleBulkMapping(
+ header=_StringTable.Id,
+ field_to_csv=lambda c: bulk_str(c.brand_list.Id),
+ csv_to_field=lambda c, v: setattr(c.brand_list, 'Id', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.Name,
+ field_to_csv=lambda c: bulk_str(c.brand_list.Name),
+ csv_to_field=lambda c, v: setattr(c.brand_list, 'Name', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.ParentId,
+ field_to_csv=lambda c: bulk_str(c.account_id),
+ csv_to_field=lambda c, v: setattr(c, 'account_id', int(v) if v else None)
+ ),
+
+ ]
+
+ def process_mappings_from_row_values(self, row_values):
+ self.brand_list = _CAMPAIGN_OBJECT_FACTORY_V13.create('BrandList')
+
+ row_values.convert_to_entity(self, BulkBrandList._MAPPINGS)
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self.brand_list, 'BrandList')
+ self.convert_to_values(row_values, BulkBrandList._MAPPINGS)
+
+ def read_additional_data(self, stream_reader):
+ super(BulkBrandList, 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 7907b0a9..e9d9bfcb 100644
--- a/bingads/v13/bulk/entities/bulk_campaign.py
+++ b/bingads/v13/bulk/entities/bulk_campaign.py
@@ -477,6 +477,28 @@ def _write_text_opt_out(c):
return None
return bulk_str(performance_max_setting.AutoGeneratedTextOptOut)
+ @staticmethod
+ def _read_cost_per_sale_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.CostPerSaleOptOut = parse_bool(v)
+
+ @staticmethod
+ def _write_cost_per_sale_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.CostPerSaleOptOut)
+
@staticmethod
def _read_image_opt_out(c, v):
if not c.campaign.CampaignType:
@@ -600,7 +622,7 @@ def _write_website(c):
),
_SimpleBulkMapping(
header=_StringTable.TrackingTemplate,
- field_to_csv=lambda c: bulk_str(c.campaign.TrackingUrlTemplate),
+ field_to_csv=lambda c: bulk_optional_str(c.campaign.TrackingUrlTemplate, c.campaign.Id),
csv_to_field=lambda c, v: setattr(c.campaign, 'TrackingUrlTemplate', v if v else None)
),
_SimpleBulkMapping(
@@ -724,6 +746,11 @@ def _write_website(c):
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.CostPerSaleOptOut,
+ field_to_csv=lambda c: BulkCampaign._write_cost_per_sale_opt_out(c),
+ csv_to_field=lambda c, v: BulkCampaign._read_cost_per_sale_opt_out(c, v)
+ ),
_SimpleBulkMapping(
header=_StringTable.ShouldServeOnMSAN,
field_to_csv=lambda c: field_to_csv_bool(c.should_serve_on_msan),
diff --git a/bingads/v13/bulk/entities/bulk_campaign_brand_list_association.py b/bingads/v13/bulk/entities/bulk_campaign_brand_list_association.py
new file mode 100644
index 00000000..36da8e8c
--- /dev/null
+++ b/bingads/v13/bulk/entities/bulk_campaign_brand_list_association.py
@@ -0,0 +1,120 @@
+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 BulkCampaignBrandListAssociation(_SingleRecordBulkEntity):
+ """ Represents a campaign brand list association.
+
+ This class exposes the property :attr:`campaign_brand_list_association` that can be read and written as fields of the campaign brand list association record
+ in a bulk file.
+
+ For more information, see campaign brand list association at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self, id=None, campaign_id=None, name=None, is_excluded=None):
+ super(BulkCampaignBrandListAssociation, self).__init__()
+
+ self._id = id
+ self._campaign_id = campaign_id
+ self._name = name
+ self._is_excluded = is_excluded
+
+ @property
+ def id(self):
+ """ The identifier of the campaign brand list association.
+
+ Corresponds to the 'Id' field in the bulk file.
+
+ :rtype: int
+ """
+
+ return self._id
+
+ @id.setter
+ def id(self, id):
+ self._id = id
+
+ @property
+ def campaign_id(self):
+ """ The identifier of the campaign that contains the brand list association.
+
+ Corresponds to the 'Parent Id' field in the bulk file.
+
+ :rtype: int
+ """
+
+ return self._campaign_id
+
+ @campaign_id.setter
+ def campaign_id(self, campaign_id):
+ self._campaign_id = campaign_id
+
+ @property
+ def name(self):
+ """ The name of the brand list association.
+
+ Corresponds to the 'Name' field in the bulk file.
+
+ :rtype: str
+ """
+
+ return self._name
+
+ @name.setter
+ def name(self, name):
+ self._name = name
+
+ @property
+ def is_excluded(self):
+ """ Corresponds to the 'Is Excluded' field in the bulk file.
+
+ :rtype: bool
+ """
+
+ return self._is_excluded
+
+ @is_excluded.setter
+ def is_excluded(self, is_excluded):
+ self._is_excluded = is_excluded
+
+ _MAPPINGS = [
+ _SimpleBulkMapping(
+ header=_StringTable.Id,
+ field_to_csv=lambda c: bulk_str(c.id),
+ csv_to_field=lambda c, v: setattr(c, 'id', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.Name,
+ field_to_csv=lambda c: bulk_str(c.name),
+ csv_to_field=lambda c, v: setattr(c, 'name', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.ParentId,
+ field_to_csv=lambda c: bulk_str(c.campaign_id),
+ csv_to_field=lambda c, v: setattr(c, 'campaign_id', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.IsExcluded,
+ field_to_csv=lambda c: bulk_str(c.is_excluded),
+ csv_to_field=lambda c, v: setattr(c, 'is_excluded', parse_bool(v))
+ ),
+ ]
+
+ def process_mappings_from_row_values(self, row_values):
+ row_values.convert_to_entity(self, BulkCampaignBrandListAssociation._MAPPINGS)
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self.convert_to_values(row_values, BulkCampaignBrandListAssociation._MAPPINGS)
+
+ def read_additional_data(self, stream_reader):
+ super(BulkCampaignBrandListAssociation, self).read_additional_data(stream_reader)
diff --git a/bingads/v13/bulk/entities/bulk_data_exclusion.py b/bingads/v13/bulk/entities/bulk_data_exclusion.py
index b55276d6..d887eab7 100644
--- a/bingads/v13/bulk/entities/bulk_data_exclusion.py
+++ b/bingads/v13/bulk/entities/bulk_data_exclusion.py
@@ -21,7 +21,7 @@ class BulkDataExclusion(_SingleRecordBulkEntity):
* :class:`.BulkFileWriter`
"""
- def __init__(self, campaign_id=None, campaign_name=None, data_exclusion=None):
+ def __init__(self, data_exclusion=None):
super(BulkDataExclusion, self).__init__()
self._data_exclusion = data_exclusion
@@ -30,8 +30,8 @@ def __init__(self, campaign_id=None, campaign_name=None, data_exclusion=None):
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.
+ A subset of DataExclusion properties are available in the Data Exclusion record.
+ For more information, see Data Exclusion at https://go.microsoft.com/fwlink/?linkid=846127.
"""
return self._data_exclusion
@@ -72,8 +72,8 @@ def data_exclusion(self, data_exclusion):
),
_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)
+ field_to_csv=lambda c: field_to_csv_DeviceType(c.data_exclusion),
+ csv_to_field=lambda c, v: csv_to_field_DeviceType(c.data_exclusion, v)
),
_SimpleBulkMapping(
header=_StringTable.CampaignAssociations,
diff --git a/bingads/v13/bulk/entities/bulk_keyword.py b/bingads/v13/bulk/entities/bulk_keyword.py
index 9b727921..2caa6bff 100644
--- a/bingads/v13/bulk/entities/bulk_keyword.py
+++ b/bingads/v13/bulk/entities/bulk_keyword.py
@@ -250,7 +250,7 @@ def bid_suggestions(self):
),
_SimpleBulkMapping(
header=_StringTable.TrackingTemplate,
- field_to_csv=lambda c: bulk_str(c.keyword.TrackingUrlTemplate),
+ field_to_csv=lambda c: bulk_optional_str(c.keyword.TrackingUrlTemplate, c.keyword.Id),
csv_to_field=lambda c, v: setattr(c.keyword, 'TrackingUrlTemplate', v if v else None)
),
_SimpleBulkMapping(
diff --git a/bingads/v13/bulk/entities/bulk_seasonality_adjustment.py b/bingads/v13/bulk/entities/bulk_seasonality_adjustment.py
index 111148ba..f03079ee 100644
--- a/bingads/v13/bulk/entities/bulk_seasonality_adjustment.py
+++ b/bingads/v13/bulk/entities/bulk_seasonality_adjustment.py
@@ -21,7 +21,7 @@ class BulkSeasonalityAdjustment(_SingleRecordBulkEntity):
* :class:`.BulkFileWriter`
"""
- def __init__(self, campaign_id=None, campaign_name=None, seasonality_adjustment=None):
+ def __init__(self, seasonality_adjustment=None):
super(BulkSeasonalityAdjustment, self).__init__()
self._seasonality_adjustment = seasonality_adjustment
@@ -30,8 +30,8 @@ def __init__(self, campaign_id=None, campaign_name=None, seasonality_adjustment=
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.
+ A subset of SeasonalityAdjustment properties are available in the Seasonality Adjustment record.
+ For more information, see Seasonality Adjustment at https://go.microsoft.com/fwlink/?linkid=846127.
"""
return self._seasonality_adjustment
@@ -74,8 +74,8 @@ def seasonality_adjustment(self, seasonality_adjustment):
),
_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)
+ field_to_csv=lambda c: field_to_csv_DeviceType(c.seasonality_adjustment),
+ csv_to_field=lambda c, v: csv_to_field_DeviceType(c.seasonality_adjustment, v)
),
_SimpleBulkMapping(
header=_StringTable.AdjustmentValue,
diff --git a/bingads/v13/bulk/entities/goals/__init__.py b/bingads/v13/bulk/entities/goals/__init__.py
new file mode 100644
index 00000000..473d18cb
--- /dev/null
+++ b/bingads/v13/bulk/entities/goals/__init__.py
@@ -0,0 +1,13 @@
+__author__ = 'Bing Ads SDK Team'
+__email__ = 'bing_ads_sdk@microsoft.com'
+
+from .bulk_conversion_goal import *
+from .bulk_app_install_goal import *
+from .bulk_event_goal import *
+from .bulk_duration_goal import *
+from .bulk_in_store_transaction_goal import *
+from .bulk_in_store_visit_goal import *
+from .bulk_offline_conversion_goal import *
+from .bulk_pages_viewed_per_visit_goal import *
+from .bulk_product_goal import *
+from .bulk_url_goal import *
diff --git a/bingads/v13/bulk/entities/goals/bulk_app_install_goal.py b/bingads/v13/bulk/entities/goals/bulk_app_install_goal.py
new file mode 100644
index 00000000..89decb0b
--- /dev/null
+++ b/bingads/v13/bulk/entities/goals/bulk_app_install_goal.py
@@ -0,0 +1,64 @@
+from bingads.v13.bulk.entities import *
+from bingads.service_client import _CAMPAIGN_OBJECT_FACTORY_V13
+from bingads.v13.internal.bulk.entities.single_record_bulk_entity import _SingleRecordBulkEntity
+from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping
+from bingads.v13.internal.bulk.string_table import _StringTable
+from bingads.v13.internal.extensions import *
+from .bulk_conversion_goal import BulkConversionGoal
+
+class BulkAppInstallGoal(BulkConversionGoal):
+ """ Represents an AppInstall Goal that can be read or written in a bulk file.
+
+ This class exposes the :attr:`app_install_goal` property that can be read and written as fields of the
+ AppInstall Goal record in a bulk file.
+
+ For more information, see AppInstall Goal at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self,
+ app_install_goal=None):
+ super(BulkAppInstallGoal, self).__init__(conversion_goal = app_install_goal)
+
+ _MAPPINGS = [
+
+ _SimpleBulkMapping(
+ header=_StringTable.AppPlatform,
+ field_to_csv=lambda c: bulk_str(c.app_install_goal.AppPlatform),
+ csv_to_field=lambda c, v: setattr(c.app_install_goal, 'AppPlatform', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.AppStoreId,
+ field_to_csv=lambda c: bulk_str(c.app_install_goal.AppStoreId),
+ csv_to_field=lambda c, v: setattr(c.app_install_goal, 'AppStoreId', v)
+ ),
+
+ ]
+
+ @property
+ def app_install_goal(self):
+ """ Defines a AppInstall Goal """
+
+ return self._conversion_goal
+
+ @app_install_goal.setter
+ def app_install_goal(self, app_install_goal):
+ self._conversion_goal = app_install_goal
+
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self.app_install_goal, 'app_install_goal')
+ super(BulkAppInstallGoal, self).process_mappings_to_row_values(row_values, exclude_readonly_data)
+ self.convert_to_values(row_values, BulkAppInstallGoal._MAPPINGS)
+
+ def process_mappings_from_row_values(self, row_values):
+ self.app_install_goal = _CAMPAIGN_OBJECT_FACTORY_V13.create('AppInstallGoal')
+ super(BulkAppInstallGoal, self).process_mappings_from_row_values(row_values)
+ row_values.convert_to_entity(self, BulkAppInstallGoal._MAPPINGS)
+
diff --git a/bingads/v13/bulk/entities/goals/bulk_conversion_goal.py b/bingads/v13/bulk/entities/goals/bulk_conversion_goal.py
new file mode 100644
index 00000000..e3c90b8a
--- /dev/null
+++ b/bingads/v13/bulk/entities/goals/bulk_conversion_goal.py
@@ -0,0 +1,125 @@
+from bingads.v13.bulk.entities import *
+from bingads.v13.internal.bulk.entities.single_record_bulk_entity import _SingleRecordBulkEntity
+from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping
+from bingads.v13.internal.bulk.string_table import _StringTable
+from bingads.v13.internal.extensions import *
+from decimal import Decimal
+
+class BulkConversionGoal(_SingleRecordBulkEntity):
+ """ Represents a ConversionGoal that can be read or written in a bulk file.
+
+ This class exposes the :attr:`conversion_goal` property that can be read and written as fields of the
+ ConversionGoal record in a bulk file.
+
+ For more information, see ConversionGoal at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self,
+ conversion_goal=None):
+ super(BulkConversionGoal, self).__init__()
+
+ self._conversion_goal = conversion_goal
+
+ _MAPPINGS = [
+ _SimpleBulkMapping(
+ header=_StringTable.Status,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.Status),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal, 'Status', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.Id,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.Id),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal, 'Id', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.Name,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.Name),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal, 'Name', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.AttributionModelType,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.AttributionModelType),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal, 'AttributionModelType', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.ConversionWindowInMinutes,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.ConversionWindowInMinutes),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal, 'ConversionWindowInMinutes', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.CountType,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.CountType),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal, 'CountType', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.ExcludeFromBidding,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.ExcludeFromBidding),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal, 'ExcludeFromBidding', parse_bool(v))
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.GoalCategory,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.GoalCategory),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal, 'GoalCategory', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.IsEnhancedConversionsEnabled,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.IsEnhancedConversionsEnabled),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal, 'IsEnhancedConversionsEnabled', parse_bool(v))
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.CurrencyCode,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.Revenue.CurrencyCode),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal.Revenue, 'CurrencyCode', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.RevenueValue,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.Revenue.Value),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal.Revenue, 'Value', Decimal(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.RevenueType,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.Revenue.Type),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal.Revenue, 'Type', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.Scope,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.Scope),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal, 'Scope', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.TagId,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.TagId),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal, 'TagId', int(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.ViewThroughConversionWindowInMinutes,
+ field_to_csv=lambda c: bulk_str(c.conversion_goal.ViewThroughConversionWindowInMinutes),
+ csv_to_field=lambda c, v: setattr(c.conversion_goal, 'ViewThroughConversionWindowInMinutes', int(v) if v else None)
+ ),
+ ]
+
+ @property
+ def conversion_goal(self):
+ """ Defines a ConversionGoal """
+
+ return self._conversion_goal
+
+ @conversion_goal.setter
+ def conversion_goal(self, conversion_goal):
+ self._conversion_goal = conversion_goal
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self.convert_to_values(row_values, BulkConversionGoal._MAPPINGS)
+
+ def process_mappings_from_row_values(self, row_values):
+ row_values.convert_to_entity(self, BulkConversionGoal._MAPPINGS)
+
+ def read_additional_data(self, stream_reader):
+ super(BulkConversionGoal, self).read_additional_data(stream_reader)
diff --git a/bingads/v13/bulk/entities/goals/bulk_duration_goal.py b/bingads/v13/bulk/entities/goals/bulk_duration_goal.py
new file mode 100644
index 00000000..d72738e5
--- /dev/null
+++ b/bingads/v13/bulk/entities/goals/bulk_duration_goal.py
@@ -0,0 +1,57 @@
+from bingads.v13.bulk.entities import *
+from bingads.service_client import _CAMPAIGN_OBJECT_FACTORY_V13
+from bingads.v13.internal.bulk.entities.single_record_bulk_entity import _SingleRecordBulkEntity
+from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping
+from bingads.v13.internal.bulk.string_table import _StringTable
+from bingads.v13.internal.extensions import *
+from .bulk_conversion_goal import BulkConversionGoal
+
+class BulkDurationGoal(BulkConversionGoal):
+ """ Represents an Duration Goal that can be read or written in a bulk file.
+
+ This class exposes the :attr:`duration_goal` property that can be read and written as fields of the
+ Duration Goal record in a bulk file.
+
+ For more information, see Duration Goal at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self,
+ duration_goal=None):
+ super(BulkDurationGoal, self).__init__(conversion_goal = duration_goal)
+
+ _MAPPINGS = [
+ _SimpleBulkMapping(
+ header=_StringTable.MinimumDurationInSecond,
+ field_to_csv=lambda c: bulk_str(c.duration_goal.MinimumDurationInSeconds),
+ csv_to_field=lambda c, v: setattr(c.duration_goal, 'MinimumDurationInSeconds', int(v) if v else None)
+ ),
+ ]
+
+ @property
+ def duration_goal(self):
+ """ Defines a Duration Goal """
+
+ return self._conversion_goal
+
+ @duration_goal.setter
+ def duration_goal(self, duration_goal):
+ self._conversion_goal = duration_goal
+
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self.duration_goal, 'duration_goal')
+ super(BulkDurationGoal, self).process_mappings_to_row_values(row_values, exclude_readonly_data)
+ self.convert_to_values(row_values, BulkDurationGoal._MAPPINGS)
+
+ def process_mappings_from_row_values(self, row_values):
+ self.duration_goal = _CAMPAIGN_OBJECT_FACTORY_V13.create('DurationGoal')
+ super(BulkDurationGoal, self).process_mappings_from_row_values(row_values)
+ row_values.convert_to_entity(self, BulkDurationGoal._MAPPINGS)
+
diff --git a/bingads/v13/bulk/entities/goals/bulk_event_goal.py b/bingads/v13/bulk/entities/goals/bulk_event_goal.py
new file mode 100644
index 00000000..007409b7
--- /dev/null
+++ b/bingads/v13/bulk/entities/goals/bulk_event_goal.py
@@ -0,0 +1,94 @@
+from bingads.v13.bulk.entities import *
+from bingads.service_client import _CAMPAIGN_OBJECT_FACTORY_V13
+from bingads.v13.internal.bulk.entities.single_record_bulk_entity import _SingleRecordBulkEntity
+from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping
+from bingads.v13.internal.bulk.string_table import _StringTable
+from bingads.v13.internal.extensions import *
+from .bulk_conversion_goal import BulkConversionGoal
+from decimal import Decimal
+
+class BulkEventGoal(BulkConversionGoal):
+ """ Represents an Event Goal that can be read or written in a bulk file.
+
+ This class exposes the :attr:`event_goal` property that can be read and written as fields of the
+ Event Goal record in a bulk file.
+
+ For more information, see Event Goal at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self,
+ event_goal=None):
+ super(BulkEventGoal, self).__init__(conversion_goal = event_goal)
+
+ _MAPPINGS = [
+
+ _SimpleBulkMapping(
+ header=_StringTable.CategoryExpression,
+ field_to_csv=lambda c: bulk_str(c.event_goal.CategoryExpression),
+ csv_to_field=lambda c, v: setattr(c.event_goal, 'CategoryExpression', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.CategoryOperator,
+ field_to_csv=lambda c: bulk_str(c.event_goal.CategoryOperator),
+ csv_to_field=lambda c, v: setattr(c.event_goal, 'CategoryOperator', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.ActionExpression,
+ field_to_csv=lambda c: bulk_str(c.event_goal.ActionExpression),
+ csv_to_field=lambda c, v: setattr(c.event_goal, 'ActionExpression', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.ActionOperator,
+ field_to_csv=lambda c: bulk_str(c.event_goal.ActionOperator),
+ csv_to_field=lambda c, v: setattr(c.event_goal, 'ActionOperator', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.LabelExpression,
+ field_to_csv=lambda c: bulk_str(c.event_goal.LabelExpression),
+ csv_to_field=lambda c, v: setattr(c.event_goal, 'LabelExpression', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.LabelOperator,
+ field_to_csv=lambda c: bulk_str(c.event_goal.LabelOperator),
+ csv_to_field=lambda c, v: setattr(c.event_goal, 'LabelOperator', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.EventValue,
+ field_to_csv=lambda c: bulk_str(c.event_goal.Value),
+ csv_to_field=lambda c, v: setattr(c.event_goal, 'Value', Decimal(v) if v else None)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.EventValueOperator,
+ field_to_csv=lambda c: bulk_str(c.event_goal.ValueOperator),
+ csv_to_field=lambda c, v: setattr(c.event_goal, 'ValueOperator', v)
+ ),
+ ]
+
+ @property
+ def event_goal(self):
+ """ Defines a Event Goal """
+
+ return self._conversion_goal
+
+ @event_goal.setter
+ def event_goal(self, event_goal):
+ self._conversion_goal = event_goal
+
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self.event_goal, 'event_goal')
+ super(BulkEventGoal, self).process_mappings_to_row_values(row_values, exclude_readonly_data)
+ self.convert_to_values(row_values, BulkEventGoal._MAPPINGS)
+
+ def process_mappings_from_row_values(self, row_values):
+ self.event_goal = _CAMPAIGN_OBJECT_FACTORY_V13.create('EventGoal')
+ super(BulkEventGoal, self).process_mappings_from_row_values(row_values)
+ row_values.convert_to_entity(self, BulkEventGoal._MAPPINGS)
+
diff --git a/bingads/v13/bulk/entities/goals/bulk_in_store_transaction_goal.py b/bingads/v13/bulk/entities/goals/bulk_in_store_transaction_goal.py
new file mode 100644
index 00000000..8bf057f7
--- /dev/null
+++ b/bingads/v13/bulk/entities/goals/bulk_in_store_transaction_goal.py
@@ -0,0 +1,53 @@
+from bingads.v13.bulk.entities import *
+from bingads.service_client import _CAMPAIGN_OBJECT_FACTORY_V13
+from bingads.v13.internal.bulk.entities.single_record_bulk_entity import _SingleRecordBulkEntity
+from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping
+from bingads.v13.internal.bulk.string_table import _StringTable
+from bingads.v13.internal.extensions import *
+from .bulk_conversion_goal import BulkConversionGoal
+
+class BulkInStoreTransactionGoal(BulkConversionGoal):
+ """ Represents an InStoreTransaction Goal that can be read or written in a bulk file.
+
+ This class exposes the :attr:`in_store_transaction_goal` property that can be read and written as fields of the
+ InStoreTransaction Goal record in a bulk file.
+
+ For more information, see InStoreTransaction Goal at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self,
+ in_store_transaction_goal=None):
+ super(BulkInStoreTransactionGoal, self).__init__(conversion_goal = in_store_transaction_goal)
+
+ _MAPPINGS = [
+
+ ]
+
+ @property
+ def in_store_transaction_goal(self):
+ """ Defines a InStoreTransaction Goal """
+
+ return self._conversion_goal
+
+ @in_store_transaction_goal.setter
+ def in_store_transaction_goal(self, in_store_transaction_goal):
+ self._conversion_goal = in_store_transaction_goal
+
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self.in_store_transaction_goal, 'in_store_transaction_goal')
+ super(BulkInStoreTransactionGoal, self).process_mappings_to_row_values(row_values, exclude_readonly_data)
+ self.convert_to_values(row_values, BulkInStoreTransactionGoal._MAPPINGS)
+
+ def process_mappings_from_row_values(self, row_values):
+ self.in_store_transaction_goal = _CAMPAIGN_OBJECT_FACTORY_V13.create('InStoreTransactionGoal')
+ super(BulkInStoreTransactionGoal, self).process_mappings_from_row_values(row_values)
+ row_values.convert_to_entity(self, BulkInStoreTransactionGoal._MAPPINGS)
+
diff --git a/bingads/v13/bulk/entities/goals/bulk_in_store_visit_goal.py b/bingads/v13/bulk/entities/goals/bulk_in_store_visit_goal.py
new file mode 100644
index 00000000..b7cf5770
--- /dev/null
+++ b/bingads/v13/bulk/entities/goals/bulk_in_store_visit_goal.py
@@ -0,0 +1,53 @@
+from bingads.v13.bulk.entities import *
+from bingads.service_client import _CAMPAIGN_OBJECT_FACTORY_V13
+from bingads.v13.internal.bulk.entities.single_record_bulk_entity import _SingleRecordBulkEntity
+from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping
+from bingads.v13.internal.bulk.string_table import _StringTable
+from bingads.v13.internal.extensions import *
+from .bulk_conversion_goal import BulkConversionGoal
+
+class BulkInStoreVisitGoal(BulkConversionGoal):
+ """ Represents an InStoreVisit Goal that can be read or written in a bulk file.
+
+ This class exposes the :attr:`in_store_visit_goal` property that can be read and written as fields of the
+ InStoreVisit Goal record in a bulk file.
+
+ For more information, see InStoreVisit Goal at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self,
+ in_store_visit_goal=None,):
+ super(BulkInStoreVisitGoal, self).__init__(conversion_goal = in_store_visit_goal)
+
+ _MAPPINGS = [
+
+ ]
+
+ @property
+ def in_store_visit_goal(self):
+ """ Defines a InStoreVisit Goal """
+
+ return self._conversion_goal
+
+ @in_store_visit_goal.setter
+ def in_store_visit_goal(self, in_store_visit_goal):
+ self._conversion_goall = in_store_visit_goal
+
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self.in_store_visit_goal, 'in_store_visit_goal')
+ super(BulkInStoreVisitGoal, self).process_mappings_to_row_values(row_values, exclude_readonly_data)
+ self.convert_to_values(row_values, BulkInStoreVisitGoal._MAPPINGS)
+
+ def process_mappings_from_row_values(self, row_values):
+ self.in_store_visit_goal = _CAMPAIGN_OBJECT_FACTORY_V13.create('ConversionGoal')
+ super(BulkInStoreVisitGoal, self).process_mappings_from_row_values(row_values)
+ row_values.convert_to_entity(self, BulkInStoreVisitGoal._MAPPINGS)
+
diff --git a/bingads/v13/bulk/entities/goals/bulk_offline_conversion_goal.py b/bingads/v13/bulk/entities/goals/bulk_offline_conversion_goal.py
new file mode 100644
index 00000000..b4ed023c
--- /dev/null
+++ b/bingads/v13/bulk/entities/goals/bulk_offline_conversion_goal.py
@@ -0,0 +1,53 @@
+from bingads.v13.bulk.entities import *
+from bingads.service_client import _CAMPAIGN_OBJECT_FACTORY_V13
+from bingads.v13.internal.bulk.entities.single_record_bulk_entity import _SingleRecordBulkEntity
+from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping
+from bingads.v13.internal.bulk.string_table import _StringTable
+from bingads.v13.internal.extensions import *
+from .bulk_conversion_goal import BulkConversionGoal
+
+class BulkOfflineConversionGoal(BulkConversionGoal):
+ """ Represents an OfflineConversion Goal that can be read or written in a bulk file.
+
+ This class exposes the :attr:`offline_conversion_goal` property that can be read and written as fields of the
+ OfflineConversion Goal record in a bulk file.
+
+ For more information, see OfflineConversion Goal at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self,
+ offline_conversion_goal=None):
+ super(BulkOfflineConversionGoal, self).__init__(conversion_goal = offline_conversion_goal)
+
+ _MAPPINGS = [
+
+ ]
+
+ @property
+ def offline_conversion_goal(self):
+ """ Defines a OfflineConversion Goal """
+
+ return self._conversion_goal
+
+ @offline_conversion_goal.setter
+ def offline_conversion_goal(self, offline_conversion_goal):
+ self._conversion_goal = offline_conversion_goal
+
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self.offline_conversion_goal, 'offline_conversion_goal')
+ super(BulkOfflineConversionGoal, self).process_mappings_to_row_values(row_values, exclude_readonly_data)
+ self.convert_to_values(row_values, BulkOfflineConversionGoal._MAPPINGS)
+
+ def process_mappings_from_row_values(self, row_values):
+ self.offline_conversion_goal = _CAMPAIGN_OBJECT_FACTORY_V13.create('OfflineConversionGoal')
+ super(BulkOfflineConversionGoal, self).process_mappings_from_row_values(row_values)
+ row_values.convert_to_entity(self, BulkOfflineConversionGoal._MAPPINGS)
+
diff --git a/bingads/v13/bulk/entities/goals/bulk_pages_viewed_per_visit_goal.py b/bingads/v13/bulk/entities/goals/bulk_pages_viewed_per_visit_goal.py
new file mode 100644
index 00000000..464872fa
--- /dev/null
+++ b/bingads/v13/bulk/entities/goals/bulk_pages_viewed_per_visit_goal.py
@@ -0,0 +1,57 @@
+from bingads.v13.bulk.entities import *
+from bingads.service_client import _CAMPAIGN_OBJECT_FACTORY_V13
+from bingads.v13.internal.bulk.entities.single_record_bulk_entity import _SingleRecordBulkEntity
+from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping
+from bingads.v13.internal.bulk.string_table import _StringTable
+from bingads.v13.internal.extensions import *
+from .bulk_conversion_goal import BulkConversionGoal
+
+class BulkPagesViewedPerVisitGoal(BulkConversionGoal):
+ """ Represents an PagesViewedPerVisit Goal that can be read or written in a bulk file.
+
+ This class exposes the :attr:`pages_viewed_per_visit_goal` property that can be read and written as fields of the
+ PagesViewedPerVisit Goal record in a bulk file.
+
+ For more information, see PagesViewedPerVisit Goal at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self,
+ pages_viewed_per_visit_goal=None):
+ super(BulkPagesViewedPerVisitGoal, self).__init__(conversion_goal = pages_viewed_per_visit_goal)
+
+ _MAPPINGS = [
+ _SimpleBulkMapping(
+ header=_StringTable.MinimumPagesViewed,
+ field_to_csv=lambda c: bulk_str(c.pages_viewed_per_visit_goal.MinimumPagesViewed),
+ csv_to_field=lambda c, v: setattr(c.pages_viewed_per_visit_goal, 'MinimumPagesViewed', int(v) if v else None)
+ ),
+ ]
+
+ @property
+ def pages_viewed_per_visit_goal(self):
+ """ Defines a PagesViewedPerVisit Goal """
+
+ return self._conversion_goal
+
+ @pages_viewed_per_visit_goal.setter
+ def pages_viewed_per_visit_goal(self, pages_viewed_per_visit_goal):
+ self._conversion_goal = pages_viewed_per_visit_goal
+
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self.pages_viewed_per_visit_goal, 'pages_viewed_per_visit_goal')
+ super(BulkPagesViewedPerVisitGoal, self).process_mappings_to_row_values(row_values, exclude_readonly_data)
+ self.convert_to_values(row_values, BulkPagesViewedPerVisitGoal._MAPPINGS)
+
+ def process_mappings_from_row_values(self, row_values):
+ self.pages_viewed_per_visit_goal = _CAMPAIGN_OBJECT_FACTORY_V13.create('PagesViewedPerVisitGoal')
+ super(BulkPagesViewedPerVisitGoal, self).process_mappings_from_row_values(row_values)
+ row_values.convert_to_entity(self, BulkPagesViewedPerVisitGoal._MAPPINGS)
+
diff --git a/bingads/v13/bulk/entities/goals/bulk_product_goal.py b/bingads/v13/bulk/entities/goals/bulk_product_goal.py
new file mode 100644
index 00000000..2d453dc0
--- /dev/null
+++ b/bingads/v13/bulk/entities/goals/bulk_product_goal.py
@@ -0,0 +1,53 @@
+from bingads.v13.bulk.entities import *
+from bingads.service_client import _CAMPAIGN_OBJECT_FACTORY_V13
+from bingads.v13.internal.bulk.entities.single_record_bulk_entity import _SingleRecordBulkEntity
+from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping
+from bingads.v13.internal.bulk.string_table import _StringTable
+from bingads.v13.internal.extensions import *
+from .bulk_conversion_goal import BulkConversionGoal
+
+class BulkProductGoal(BulkConversionGoal):
+ """ Represents an ProductGoal Goal that can be read or written in a bulk file.
+
+ This class exposes the :attr:`product_goal` property that can be read and written as fields of the
+ ProductGoal Goal record in a bulk file.
+
+ For more information, see ProductGoal Goal at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self,
+ product_goal=None):
+ super(BulkProductGoal, self).__init__(conversion_goal = product_goal)
+
+ _MAPPINGS = [
+
+ ]
+
+ @property
+ def product_goal(self):
+ """ Defines a ProductGoal Goal """
+
+ return self._conversion_goal
+
+ @product_goal.setter
+ def product_goal(self, product_goal):
+ self._conversion_goall = product_goal
+
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self.product_goal, 'product_goal')
+ super(BulkProductGoal, self).process_mappings_to_row_values(row_values, exclude_readonly_data)
+ self.convert_to_values(row_values, BulkProductGoal._MAPPINGS)
+
+ def process_mappings_from_row_values(self, row_values):
+ self.product_goal = _CAMPAIGN_OBJECT_FACTORY_V13.create('ConversionGoal')
+ super(BulkProductGoal, self).process_mappings_from_row_values(row_values)
+ row_values.convert_to_entity(self, BulkProductGoal._MAPPINGS)
+
diff --git a/bingads/v13/bulk/entities/goals/bulk_url_goal.py b/bingads/v13/bulk/entities/goals/bulk_url_goal.py
new file mode 100644
index 00000000..92513a21
--- /dev/null
+++ b/bingads/v13/bulk/entities/goals/bulk_url_goal.py
@@ -0,0 +1,64 @@
+from bingads.v13.bulk.entities import *
+from bingads.service_client import _CAMPAIGN_OBJECT_FACTORY_V13
+from bingads.v13.internal.bulk.entities.single_record_bulk_entity import _SingleRecordBulkEntity
+from bingads.v13.internal.bulk.mappings import _SimpleBulkMapping
+from bingads.v13.internal.bulk.string_table import _StringTable
+from bingads.v13.internal.extensions import *
+from .bulk_conversion_goal import BulkConversionGoal
+
+class BulkUrlGoal(BulkConversionGoal):
+ """ Represents an Url Goal that can be read or written in a bulk file.
+
+ This class exposes the :attr:`url_goal` property that can be read and written as fields of the
+ Url Goal record in a bulk file.
+
+ For more information, see Url Goal at https://go.microsoft.com/fwlink/?linkid=846127.
+
+ *See also:*
+
+ * :class:`.BulkServiceManager`
+ * :class:`.BulkOperation`
+ * :class:`.BulkFileReader`
+ * :class:`.BulkFileWriter`
+ """
+
+ def __init__(self,
+ url_goal=None):
+ super(BulkUrlGoal, self).__init__(conversion_goal = url_goal)
+
+ _MAPPINGS = [
+
+ _SimpleBulkMapping(
+ header=_StringTable.UrlExpression,
+ field_to_csv=lambda c: bulk_str(c.url_goal.UrlExpression),
+ csv_to_field=lambda c, v: setattr(c.url_goal, 'UrlExpression', v)
+ ),
+ _SimpleBulkMapping(
+ header=_StringTable.UrlOperator,
+ field_to_csv=lambda c: bulk_str(c.url_goal.UrlOperator),
+ csv_to_field=lambda c, v: setattr(c.url_goal, 'UrlOperator', v)
+ ),
+
+ ]
+
+ @property
+ def url_goal(self):
+ """ Defines a Url Goal """
+
+ return self._conversion_goal
+
+ @url_goal.setter
+ def url_goal(self, url_goal):
+ self._conversion_goal = url_goal
+
+
+ def process_mappings_to_row_values(self, row_values, exclude_readonly_data):
+ self._validate_property_not_null(self.url_goal, 'url_goal')
+ super(BulkUrlGoal, self).process_mappings_to_row_values(row_values, exclude_readonly_data)
+ self.convert_to_values(row_values, BulkUrlGoal._MAPPINGS)
+
+ def process_mappings_from_row_values(self, row_values):
+ self.url_goal = _CAMPAIGN_OBJECT_FACTORY_V13.create('UrlGoal')
+ super(BulkUrlGoal, self).process_mappings_from_row_values(row_values)
+ row_values.convert_to_entity(self, BulkUrlGoal._MAPPINGS)
+
diff --git a/bingads/v13/internal/bulk/bulk_object_factory.py b/bingads/v13/internal/bulk/bulk_object_factory.py
index b3d925da..236eec61 100644
--- a/bingads/v13/internal/bulk/bulk_object_factory.py
+++ b/bingads/v13/internal/bulk/bulk_object_factory.py
@@ -166,6 +166,11 @@ class _BulkObjectFactory():
_StringTable.CampaignNegativeCombinedListAssociation: _EntityInfo(lambda: BulkCampaignNegativeCombinedListAssociation()),
_StringTable.CampaignCustomerListAssociation: _EntityInfo(lambda: BulkCampaignCustomerListAssociation()),
_StringTable.CampaignNegativeCustomerListAssociation: _EntityInfo(lambda: BulkCampaignNegativeCustomerListAssociation()),
+ _StringTable.ImpressionBasedRemarketingList: _EntityInfo(lambda: BulkImpressionBasedRemarketingList()),
+ _StringTable.CampaignImpressionBasedRemarketingListAssociation: _EntityInfo(lambda: BulkCampaignImpressionBasedRemarketingListAssociation()),
+ _StringTable.CampaignNegativeImpressionBasedRemarketingListAssociation: _EntityInfo(lambda: BulkCampaignNegativeImpressionBasedRemarketingListAssociation()),
+ _StringTable.AdGroupImpressionBasedRemarketingListAssociation: _EntityInfo(lambda: BulkAdGroupImpressionBasedRemarketingListAssociation()),
+ _StringTable.AdGroupNegativeImpressionBasedRemarketingListAssociation: _EntityInfo(lambda: BulkAdGroupNegativeImpressionBasedRemarketingListAssociation()),
_StringTable.AdGroupIndustryCriterion: _EntityInfo(lambda: BulkAdGroupIndustryCriterion()),
_StringTable.AdGroupCompanyNameCriterion: _EntityInfo(lambda: BulkAdGroupCompanyNameCriterion()),
_StringTable.AdGroupJobFunctionCriterion: _EntityInfo(lambda: BulkAdGroupJobFunctionCriterion()),
@@ -214,6 +219,19 @@ class _BulkObjectFactory():
'Account Negative Keyword List': _EntityInfo(lambda: BulkAccountNegativeKeywordList()),
'Account Negative Keyword List Association': _EntityInfo(lambda: BulkAccountNegativeKeywordListAssociation()),
'Account Shared Negative Keyword': _EntityInfo(lambda: BulkAccountSharedNegativeKeyword()),
+ _StringTable.EventGoal: _EntityInfo(lambda: BulkEventGoal()),
+ _StringTable.AppInstallGoal: _EntityInfo(lambda: BulkAppInstallGoal()),
+ _StringTable.DurationGoal: _EntityInfo(lambda: BulkDurationGoal()),
+ _StringTable.OfflineConversionGoal: _EntityInfo(lambda: BulkOfflineConversionGoal()),
+ _StringTable.UrlGoal: _EntityInfo(lambda: BulkUrlGoal()),
+ _StringTable.InStoreTransactionGoal: _EntityInfo(lambda: BulkInStoreTransactionGoal()),
+ _StringTable.PagesViewedPerVisitGoal: _EntityInfo(lambda: BulkPagesViewedPerVisitGoal()),
+ _StringTable.InStoreVisitGoal: _EntityInfo(lambda: BulkInStoreVisitGoal()),
+ _StringTable.ProductGoal: _EntityInfo(lambda: BulkProductGoal()),
+ _StringTable.AssetGroupSearchTheme: _EntityInfo(lambda: BulkAssetGroupSearchTheme()),
+ _StringTable.BrandList: _EntityInfo(lambda: BulkBrandList()),
+ _StringTable.BrandItem: _EntityInfo(lambda: BulkBrandItem()),
+ _StringTable.CampaignBrandList: _EntityInfo(lambda: BulkCampaignBrandListAssociation()),
}
ADDITIONAL_OBJECT_MAP = {
diff --git a/bingads/v13/internal/bulk/csv_headers.py b/bingads/v13/internal/bulk/csv_headers.py
index 0fca20f9..704abb9c 100644
--- a/bingads/v13/internal/bulk/csv_headers.py
+++ b/bingads/v13/internal/bulk/csv_headers.py
@@ -348,6 +348,9 @@ class _CsvHeaders:
_StringTable.ProductAudienceType,
_StringTable.SourceId,
_StringTable.CombinationRule,
+ _StringTable.EntityType,
+ _StringTable.ImpressionCampaignId,
+ _StringTable.ImpressionAdGroupId,
# Expanded Text Ad
@@ -472,6 +475,8 @@ class _CsvHeaders:
_StringTable.AudienceGroupAssetGroupAssociation,
_StringTable.AutoGeneratedTextOptOut,
_StringTable.AutoGeneratedImageOptOut,
+ _StringTable.CostPerSaleOptOut,
+ _StringTable.SearchTheme,
# Seasonality Adjustment
_StringTable.SeasonalityAdjustment,
@@ -481,6 +486,37 @@ class _CsvHeaders:
# DNV Serving on MSAN
_StringTable.ShouldServeOnMSAN,
+
+ # Goal
+ _StringTable.AttributionModelType,
+ _StringTable.ConversionWindowInMinutes,
+ _StringTable.CountType,
+ _StringTable.ExcludeFromBidding,
+ _StringTable.GoalCategory,
+ _StringTable.IsEnhancedConversionsEnabled,
+ _StringTable.RevenueType,
+ _StringTable.RevenueValue,
+ _StringTable.TrackingStatus,
+ _StringTable.ViewThroughConversionWindowInMinutes,
+ _StringTable.MinimumDurationInSecond,
+ _StringTable.ActionExpression,
+ _StringTable.ActionOperator,
+ _StringTable.CategoryExpression,
+ _StringTable.CategoryOperator,
+ _StringTable.LabelExpression,
+ _StringTable.LabelOperator,
+ _StringTable.EventValue,
+ _StringTable.EventValueOperator,
+ _StringTable.IsExternallyAttributed,
+ _StringTable.MinimumPagesViewed,
+ _StringTable.UrlExpression,
+ _StringTable.UrlOperator,
+
+ # Brand List
+ _StringTable.BrandId,
+ _StringTable.BrandUrl,
+ _StringTable.BrandName,
+ _StringTable.StatusDateTime,
]
@staticmethod
diff --git a/bingads/v13/internal/bulk/string_table.py b/bingads/v13/internal/bulk/string_table.py
index 60c58410..28e239c4 100644
--- a/bingads/v13/internal/bulk/string_table.py
+++ b/bingads/v13/internal/bulk/string_table.py
@@ -101,7 +101,7 @@ class _StringTable:
MultiMediaAdBidAdjustment = "Multi Media Ad Bid Adjustment"
UseOptimizedTargeting = "Use Optimized Targeting"
BusinessAttributes = "Business Attributes"
- Schedule = "Schedule";
+ Schedule = "Schedule"
# Entity Types
SemanticVersion = "Format Version"
@@ -489,6 +489,14 @@ class _StringTable:
AdGroupNegativeCustomerListAssociation = "Ad Group Negative Customer List Association"
CampaignCustomerListAssociation = "Campaign Customer List Association"
CampaignNegativeCustomerListAssociation = "Campaign Negative Customer List Association"
+ ImpressionBasedRemarketingList = "Impression Based Remarketing List"
+ AdGroupImpressionBasedRemarketingListAssociation = "Ad Group Impression Based Remarketing List Association"
+ AdGroupNegativeImpressionBasedRemarketingListAssociation = "Ad Group Negative Impression Based Remarketing List Association"
+ CampaignImpressionBasedRemarketingListAssociation = "Campaign Impression Based Remarketing List Association"
+ CampaignNegativeImpressionBasedRemarketingListAssociation = "Campaign Negative Impression Based Remarketing List Association"
+ EntityType = "Entity Type"
+ ImpressionCampaignId = "Impression Campaign Id"
+ ImpressionAdGroupId = "Impression Ad Group Id"
# Expanded Text Ad
TitlePart1 = "Title Part 1"
@@ -650,6 +658,9 @@ class _StringTable:
ParentListingGroupId = "Parent Listing Group Id"
AutoGeneratedTextOptOut = "Auto Generated Text Assets Opt Out"
AutoGeneratedImageOptOut = "Auto Generated Image Assets Opt Out"
+ CostPerSaleOptOut = "Cost Per Sale Opt Out"
+ AssetGroupSearchTheme = "Asset Group Search Theme"
+ SearchTheme = "Search Theme"
# MultiChannel Campaign
DestinationChannel = "Destination Channel"
@@ -663,3 +674,49 @@ class _StringTable:
# DNV Serving on MSAN
ShouldServeOnMSAN = "Should Serve On MSAN"
+
+ # Conversion Goal
+ AttributionModelType = "Attribution Model Type"
+ ConversionWindowInMinutes = "Conversion Window In Minutes"
+ CountType = "Count Type"
+ ExcludeFromBidding = "Exclude From Bidding"
+ GoalCategory = "Goal Category"
+ IsEnhancedConversionsEnabled = "Is Enhanced Conversions Enabled"
+ RevenueType = "Revenue Type"
+ RevenueValue = "Revenue Value"
+ TrackingStatus = "Tracking Status"
+ ViewThroughConversionWindowInMinutes = "View Through Conversion Window In Minutes"
+ MinimumDurationInSecond = "Minimum Duration In Second"
+ ActionExpression = "Action Expression"
+ ActionOperator = "Action Operator"
+ CategoryExpression = "Category Expression"
+ CategoryOperator = "Category Operator"
+ LabelExpression = "Label Expression"
+ LabelOperator = "Label Operator"
+ EventValue = "Event Value"
+ EventValueOperator = "Event Value Operator"
+ IsExternallyAttributed = "Is Externally Attributed"
+ MinimumPagesViewed = "Minimum Pages Viewed"
+ UrlExpression = "URL Expression"
+ UrlOperator = "URL Operator"
+ ConversionGoal = "Conversion Goal"
+ EventGoal = "Event Goal"
+ AppInstallGoal = "AppInstall Goal"
+ MultiStageGoal = "MultiStage Goal"
+ DurationGoal = "Duration Goal"
+ OfflineConversionGoal = "OfflineConversion Goal"
+ UrlGoal = "URL Goal"
+ InStoreTransactionGoal = "InStoreTransaction Goal"
+ PagesViewedPerVisitGoal = "PagesViewedPerVisit Goal"
+ SmartGoal = "Smart Goal"
+ InStoreVisitGoal = "InStoreVisit Goal"
+ ProductGoal = "Product Goal"
+
+ # Brand List
+ BrandList = "Brand List"
+ BrandItem = "Brand Item"
+ CampaignBrandList = "Campaign Brand List Association"
+ BrandId = "Brand Id"
+ BrandUrl = "Brand Url"
+ BrandName = "Brand Name"
+ StatusDateTime = "Editorial Status Date"
diff --git a/bingads/v13/internal/extensions.py b/bingads/v13/internal/extensions.py
index 228587e5..78915182 100644
--- a/bingads/v13/internal/extensions.py
+++ b/bingads/v13/internal/extensions.py
@@ -378,6 +378,17 @@ def csv_to_field_CampaignType(entity, value):
return
entity.CampaignTypeFilter = [None if i == 'None' else i for i in value.split(',')]
+def field_to_csv_DeviceType(entity):
+ device_type = entity.DeviceTypeFilter
+ if device_type is None or len(device_type) == 0:
+ return None
+ return ','.join(type for type in device_type)
+
+def csv_to_field_DeviceType(entity, value):
+ if value is None or value.strip() == '':
+ return
+ entity.DeviceTypeFilter = [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:
diff --git a/bingads/v13/proxies/production/bulk_service.xml b/bingads/v13/proxies/production/bulk_service.xml
index 48d9fde5..edd75799 100644
--- a/bingads/v13/proxies/production/bulk_service.xml
+++ b/bingads/v13/proxies/production/bulk_service.xml
@@ -1289,6 +1289,69 @@
+
+
+
+ 175
+
+
+
+
+
+
+ 176
+
+
+
+
+
+
+ 177
+
+
+
+
+
+
+ 178
+
+
+
+
+
+
+ 179
+
+
+
+
+
+
+ 180
+
+
+
+
+
+
+ 181
+
+
+
+
+
+
+ 182
+
+
+
+
+
+
+ 183
+
+
+
diff --git a/bingads/v13/proxies/production/campaignmanagement_service.xml b/bingads/v13/proxies/production/campaignmanagement_service.xml
index 5ba6e7f9..876c51e3 100644
--- a/bingads/v13/proxies/production/campaignmanagement_service.xml
+++ b/bingads/v13/proxies/production/campaignmanagement_service.xml
@@ -233,6 +233,13 @@
+
+
+
+
+
+
+
@@ -276,6 +283,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -961,6 +979,13 @@
+
+
+
+
+
+
+
@@ -984,6 +1009,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1234,7 +1319,15 @@
-
+
+
+
+
+
+
+
+
+
@@ -1289,6 +1382,13 @@
+
+
+
+ 128
+
+
+
@@ -1409,6 +1509,9 @@
+
+
+
@@ -2008,6 +2111,7 @@
+
@@ -2735,6 +2839,13 @@
+
+
+
+
+
+
+
@@ -3193,6 +3304,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -3277,6 +3401,7 @@
+
@@ -3292,6 +3417,7 @@
+
@@ -3540,6 +3666,13 @@
+
+
+
+
+
+
+
@@ -3581,6 +3714,7 @@
+
@@ -3602,6 +3736,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -3620,6 +3764,13 @@
+
+
+
+
+
+
+
@@ -3653,6 +3804,7 @@
+
@@ -3910,6 +4062,13 @@
+
+
+
+ 536870912
+
+
+
@@ -4319,6 +4478,7 @@
+
@@ -5364,6 +5524,13 @@
+
+
+
+ 8388608
+
+
+
@@ -5769,6 +5936,13 @@
+
+
+
+
+
+
+
@@ -5789,6 +5963,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -5850,9 +6037,20 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -5865,6 +6063,7 @@
+
@@ -6331,6 +6530,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -6382,6 +6601,7 @@
+
@@ -8030,25 +8250,47 @@
-
-
-
-
-
-
-
- 4
-
-
-
-
-
-
- 7
-
-
-
-
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+ 4
+
+
+
+
+
+
+ 7
+
+
+
+
+
+
diff --git a/bingads/v13/proxies/production/customerbilling_service.xml b/bingads/v13/proxies/production/customerbilling_service.xml
index 3ce72efa..cb7ff9d7 100644
--- a/bingads/v13/proxies/production/customerbilling_service.xml
+++ b/bingads/v13/proxies/production/customerbilling_service.xml
@@ -290,6 +290,13 @@
+
+
+
+
+
+
+
@@ -323,6 +330,13 @@
+
+
+
+
+
+
+
diff --git a/bingads/v13/proxies/production/customermanagement_service.xml b/bingads/v13/proxies/production/customermanagement_service.xml
index e2f40888..06c0ab22 100644
--- a/bingads/v13/proxies/production/customermanagement_service.xml
+++ b/bingads/v13/proxies/production/customermanagement_service.xml
@@ -865,6 +865,9 @@
+
+
+
@@ -1998,6 +2001,20 @@
+
+
+
+ 1055
+
+
+
+
+
+
+ 1124
+
+
+
diff --git a/bingads/v13/proxies/production/reporting_service.xml b/bingads/v13/proxies/production/reporting_service.xml
index 569f9b80..637444b6 100644
--- a/bingads/v13/proxies/production/reporting_service.xml
+++ b/bingads/v13/proxies/production/reporting_service.xml
@@ -4287,6 +4287,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -4304,7 +4407,7 @@
-
+
diff --git a/bingads/v13/proxies/sandbox/bulk_service.xml b/bingads/v13/proxies/sandbox/bulk_service.xml
index 59f5c4c4..697ae86c 100644
--- a/bingads/v13/proxies/sandbox/bulk_service.xml
+++ b/bingads/v13/proxies/sandbox/bulk_service.xml
@@ -1289,6 +1289,69 @@
+
+
+
+ 175
+
+
+
+
+
+
+ 176
+
+
+
+
+
+
+ 177
+
+
+
+
+
+
+ 178
+
+
+
+
+
+
+ 179
+
+
+
+
+
+
+ 180
+
+
+
+
+
+
+ 181
+
+
+
+
+
+
+ 182
+
+
+
+
+
+
+ 183
+
+
+
diff --git a/bingads/v13/proxies/sandbox/campaignmanagement_service.xml b/bingads/v13/proxies/sandbox/campaignmanagement_service.xml
index 3499ae96..3077f0f4 100644
--- a/bingads/v13/proxies/sandbox/campaignmanagement_service.xml
+++ b/bingads/v13/proxies/sandbox/campaignmanagement_service.xml
@@ -233,6 +233,13 @@
+
+
+
+
+
+
+
@@ -276,6 +283,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -961,6 +979,13 @@
+
+
+
+
+
+
+
@@ -984,6 +1009,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1234,7 +1319,15 @@
-
+
+
+
+
+
+
+
+
+
@@ -1289,6 +1382,13 @@
+
+
+
+ 128
+
+
+
@@ -1409,6 +1509,9 @@
+
+
+
@@ -2008,6 +2111,7 @@
+
@@ -2735,6 +2839,13 @@
+
+
+
+
+
+
+
@@ -3193,6 +3304,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -3277,6 +3401,7 @@
+
@@ -3292,6 +3417,7 @@
+
@@ -3540,6 +3666,13 @@
+
+
+
+
+
+
+
@@ -3581,6 +3714,7 @@
+
@@ -3602,6 +3736,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -3620,6 +3764,13 @@
+
+
+
+
+
+
+
@@ -3653,6 +3804,7 @@
+
@@ -3910,6 +4062,13 @@
+
+
+
+ 536870912
+
+
+
@@ -4319,6 +4478,7 @@
+
@@ -5364,6 +5524,13 @@
+
+
+
+ 8388608
+
+
+
@@ -5769,6 +5936,13 @@
+
+
+
+
+
+
+
@@ -5789,6 +5963,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -5850,9 +6037,20 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -5865,6 +6063,7 @@
+
@@ -6331,6 +6530,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -6382,6 +6601,7 @@
+
@@ -8030,25 +8250,47 @@
-
-
-
-
-
-
-
- 4
-
-
-
-
-
-
- 7
-
-
-
-
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+ 4
+
+
+
+
+
+
+ 7
+
+
+
+
+
+
diff --git a/bingads/v13/proxies/sandbox/customerbilling_service.xml b/bingads/v13/proxies/sandbox/customerbilling_service.xml
index 3542f4e1..28794ee3 100644
--- a/bingads/v13/proxies/sandbox/customerbilling_service.xml
+++ b/bingads/v13/proxies/sandbox/customerbilling_service.xml
@@ -36,6 +36,7 @@
+
@@ -290,6 +291,13 @@
+
+
+
+
+
+
+
@@ -323,6 +331,13 @@
+
+
+
+
+
+
+
diff --git a/bingads/v13/proxies/sandbox/customermanagement_service.xml b/bingads/v13/proxies/sandbox/customermanagement_service.xml
index d493ae1d..2f81d61b 100644
--- a/bingads/v13/proxies/sandbox/customermanagement_service.xml
+++ b/bingads/v13/proxies/sandbox/customermanagement_service.xml
@@ -865,6 +865,9 @@
+
+
+
@@ -1998,6 +2001,20 @@
+
+
+
+ 1055
+
+
+
+
+
+
+ 1124
+
+
+
diff --git a/bingads/v13/proxies/sandbox/reporting_service.xml b/bingads/v13/proxies/sandbox/reporting_service.xml
index 6d5cdf40..8fee965a 100644
--- a/bingads/v13/proxies/sandbox/reporting_service.xml
+++ b/bingads/v13/proxies/sandbox/reporting_service.xml
@@ -4287,6 +4287,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -4304,7 +4407,7 @@
-
+
diff --git a/setup.py b/setup.py
index 99afcfdd..2ff1d58a 100644
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,7 @@
except ImportError:
from distutils.core import setup
-VERSION = '13.0.19.1'
+VERSION = '13.0.21'
with open('README.rst', 'r') as f:
readme = f.read()