private static void CsvToBudget(RowValues values, BulkCampaign c) { string budgetTypeRowValue; BudgetLimitType?budgetType; if (!values.TryGetValue(StringTable.BudgetType, out budgetTypeRowValue) || (budgetType = budgetTypeRowValue.ParseOptional <BudgetLimitType>()) == null) { return; } string budgetRowValue; if (!values.TryGetValue(StringTable.Budget, out budgetRowValue)) { return; } var budgetValue = budgetRowValue.ParseOptional <double>(); c.Campaign.BudgetType = budgetType; if (budgetType == BudgetLimitType.DailyBudgetAccelerated || budgetType == BudgetLimitType.DailyBudgetStandard) { c.Campaign.DailyBudget = budgetValue; } else { c.Campaign.MonthlyBudget = budgetValue; } }
private static void BudgetToCsv(BulkCampaign c, RowValues values) { var budgetType = c.Campaign.BudgetType; if (budgetType == null) { return; } values[StringTable.Budget] = budgetType == BudgetLimitType.DailyBudgetAccelerated || budgetType == BudgetLimitType.DailyBudgetStandard ? c.Campaign.DailyBudget.ToBulkString() : c.Campaign.MonthlyBudget.ToBulkString(); }
public async override Task RunAsync(AuthorizationData authorizationData) { try { BulkService = new BulkServiceManager(authorizationData); var progress = new Progress<BulkOperationProgressInfo>(x => OutputStatusMessage(String.Format("{0} % Complete", x.PercentComplete.ToString(CultureInfo.InvariantCulture)))); #region Add const int appAdExtensionIdKey = -11; const int callAdExtensionIdKey = -12; const int locationAdExtensionIdKey = -13; const int siteLinksAdExtensionIdKey = -14; const int campaignIdKey = -123; // Prepare the bulk entities that you want to upload. Each bulk entity contains the corresponding campaign management object, // and additional elements needed to read from and write to a bulk file. var bulkCampaign = new BulkCampaign { // ClientId may be used to associate records in the bulk upload file with records in the results file. The value of this field // is not used or stored by the server; it is simply copied from the uploaded record to the corresponding result record. // Note: This bulk file Client Id is not related to an application Client Id for OAuth. ClientId = "YourClientIdGoesHere", Campaign = new Campaign { // When using the Campaign Management service, the Id cannot be set. In the context of a BulkCampaign, the Id is optional // and may be used as a negative reference key during bulk upload. For example the same negative value set for the campaign Id // will be used when associating this new campaign with a new call ad extension in the BulkCampaignCallAdExtension object below. Id = campaignIdKey, Name = "Women's Shoes " + DateTime.UtcNow, Description = "Red shoes line.", BudgetType = BudgetLimitType.MonthlyBudgetSpendUntilDepleted, MonthlyBudget = 1000.00, TimeZone = "PacificTimeUSCanadaTijuana", } }; // Prepare ad extensions for upload var bulkAppAdExtension = new BulkAppAdExtension { AccountId = authorizationData.AccountId, AppAdExtension = new AppAdExtension { AppPlatform = "Windows", AppStoreId = "AppStoreIdGoesHere", DestinationUrl = "DestinationUrlGoesHere", DisplayText = "Contoso", Id = appAdExtensionIdKey, } }; var bulkCallAdExtension = new BulkCallAdExtension { AccountId = authorizationData.AccountId, CallAdExtension = new CallAdExtension { CountryCode = "US", PhoneNumber = "2065550100", IsCallOnly = false, Id = callAdExtensionIdKey } }; var bulkLocationAdExtension = new BulkLocationAdExtension { AccountId = authorizationData.AccountId, LocationAdExtension = new LocationAdExtension { Id = locationAdExtensionIdKey, PhoneNumber = "206-555-0100", CompanyName = "Contoso Shoes", IconMediaId = null, ImageMediaId = null, Address = new Address { StreetAddress = "1234 Washington Place", StreetAddress2 = "Suite 1210", CityName = "Woodinville", ProvinceName = "WA", CountryCode = "US", PostalCode = "98608" } } }; // Note that when written to file using the BulkFileWriter, an extra Sitelink Ad Extension record with Deleted // status precedes the actual site link record or records that you want to upload. All bulk entities // that are derived from MultiRecordBulkEntiy are preceded with a Deleted record using the BulkFileWriter. // In this example it is a moot point because we are creating a new ad extension. If the specified // ad extension Id already exists in your account, the Deleted record effectively deletes the existing // extension and replaces it with the SiteLinksAdExtension specified below. var bulkSiteLinkAdExtension = new BulkSiteLinkAdExtension { AccountId = authorizationData.AccountId, SiteLinksAdExtension = new SiteLinksAdExtension { // Note that if you do not specify a negative Id as reference key, each of SiteLinks items will // be split during upload into separate sitelink ad extensions with unique ad extension identifiers. Id = siteLinksAdExtensionIdKey, SiteLinks = new List<SiteLink> { new SiteLink { DestinationUrl = "Contoso.com", DisplayText = "Women's Shoe Sale 1" }, new SiteLink { DestinationUrl = "Contoso.com/WomenShoeSale/2", DisplayText = "Women's Shoe Sale 2" } } } // Note that BulkSiteLinkAdExtension.SiteLinks is read only and only // accessible when reading results from the download or upload results file. // To upload new site links for a new site links ad extension, you should specify // BulkSiteLinkAdExtension.SiteLinksAdExtension.SiteLinks as shown above. }; // Prepare ad extension associations for upload var bulkCampaignAppAdExtension = new BulkCampaignAppAdExtension { AdExtensionIdToEntityIdAssociation = new AdExtensionIdToEntityIdAssociation { AdExtensionId = appAdExtensionIdKey, EntityId = campaignIdKey } }; var bulkCampaignCallAdExtension = new BulkCampaignCallAdExtension { AdExtensionIdToEntityIdAssociation = new AdExtensionIdToEntityIdAssociation { AdExtensionId = callAdExtensionIdKey, EntityId = campaignIdKey } }; var bulkCampaignLocationAdExtension = new BulkCampaignLocationAdExtension { AdExtensionIdToEntityIdAssociation = new AdExtensionIdToEntityIdAssociation { AdExtensionId = locationAdExtensionIdKey, EntityId = campaignIdKey } }; var bulkCampaignSiteLinkAdExtension = new BulkCampaignSiteLinkAdExtension { AdExtensionIdToEntityIdAssociation = new AdExtensionIdToEntityIdAssociation { AdExtensionId = siteLinksAdExtensionIdKey, EntityId = campaignIdKey } }; // Write the entities created above, to the specified file. // Dependent entities such as BulkCampaignCallAdExtension must be written after any dependencies, // for example the BulkCampaign and BulkCallAdExtension. Writer = new BulkFileWriter(FileDirectory + UploadFileName); Writer.WriteEntity(bulkCampaign); Writer.WriteEntity(bulkAppAdExtension); Writer.WriteEntity(bulkCallAdExtension); Writer.WriteEntity(bulkLocationAdExtension); Writer.WriteEntity(bulkSiteLinkAdExtension); Writer.WriteEntity(bulkCampaignAppAdExtension); Writer.WriteEntity(bulkCampaignCallAdExtension); Writer.WriteEntity(bulkCampaignLocationAdExtension); Writer.WriteEntity(bulkCampaignSiteLinkAdExtension); Writer.Dispose(); var fileUploadParameters = new FileUploadParameters { ResultFileDirectory = FileDirectory, ResultFileName = ResultFileName, OverwriteResultFile = true, UploadFilePath = FileDirectory + UploadFileName, ResponseMode = ResponseMode.ErrorsAndResults }; // UploadFileAsync will upload the file you finished writing and will download the results file OutputStatusMessage("\nAdding campaign, ad extensions, and associations . . .\n"); var bulkFilePath = await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None); Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType); OutputStatusMessage("Upload Results Bulk File Path: " + Reader.BulkFilePath + "\n"); // Write the upload output var bulkEntities = Reader.ReadEntities().ToList(); var campaignResults = bulkEntities.OfType<BulkCampaign>().ToList(); OutputBulkCampaigns(campaignResults); var appAdExtensionResults = bulkEntities.OfType<BulkAppAdExtension>().ToList(); OutputBulkAppAdExtensions(appAdExtensionResults); var callAdExtensionResults = bulkEntities.OfType<BulkCallAdExtension>().ToList(); OutputBulkCallAdExtensions(callAdExtensionResults); var locationAdExtensionResults = bulkEntities.OfType<BulkLocationAdExtension>().ToList(); OutputBulkLocationAdExtensions(locationAdExtensionResults); var siteLinkAdExtensionResults = bulkEntities.OfType<BulkSiteLinkAdExtension>().ToList(); OutputBulkSiteLinkAdExtensions(siteLinkAdExtensionResults); OutputBulkCampaignAppAdExtensions(bulkEntities.OfType<BulkCampaignAppAdExtension>().ToList()); OutputBulkCampaignCallAdExtensions(bulkEntities.OfType<BulkCampaignCallAdExtension>().ToList()); OutputBulkCampaignLocationAdExtensions(bulkEntities.OfType<BulkCampaignLocationAdExtension>().ToList()); OutputBulkCampaignSiteLinkAdExtensions(bulkEntities.OfType<BulkCampaignSiteLinkAdExtension>().ToList()); Reader.Dispose(); #endregion Add #region Update // Update the site links ad extension. // Do not create a BulkSiteLinkAdExtension for update, unless you want to replace all existing SiteLinks // with the specified SiteLinks for the specified ad extension. // Instead you should upload one or more site links as a list of BulkSiteLink. var bulkSiteLinks = new List<BulkSiteLink> { new BulkSiteLink { SiteLink = new SiteLink { DestinationUrl = "Contoso.com", DisplayText = "Red Shoe Sale" } } }; // Add an additional site link, and update an existing site link if (siteLinkAdExtensionResults.ToArray().Any() && siteLinkAdExtensionResults.ToArray()[0].SiteLinks.ToArray().Any()) { var existingSiteLink = siteLinkAdExtensionResults.ToArray()[0].SiteLinks[0]; existingSiteLink.SiteLink.DisplayText = "Red Shoes Super Sale"; // Associate the new site links with the identifier of the existing site links ad extension foreach (var bulkSiteLink in bulkSiteLinks) { bulkSiteLink.AdExtensionId = existingSiteLink.AdExtensionId; } bulkSiteLinks.Add(existingSiteLink); } // Write the new site link and updated site link to the file Writer = new BulkFileWriter(FileDirectory + UploadFileName); foreach (var bulkSiteLink in bulkSiteLinks) { Writer.WriteEntity(bulkSiteLink); } Writer.Dispose(); fileUploadParameters = new FileUploadParameters { ResultFileDirectory = FileDirectory, ResultFileName = ResultFileName, OverwriteResultFile = true, UploadFilePath = FileDirectory + UploadFileName, ResponseMode = ResponseMode.ErrorsAndResults }; // UploadFileAsync will upload the file you finished writing and will download the results file OutputStatusMessage("\nUpdating sitelinks . . .\n"); bulkFilePath = await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None); Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType); OutputStatusMessage("Upload Results Bulk File Path: " + Reader.BulkFilePath + "\n"); // Write any upload errors bulkEntities = Reader.ReadEntities().ToList(); var siteLinkResults = bulkEntities.OfType<BulkSiteLink>().ToList(); OutputBulkSiteLinks(siteLinkResults); Reader.Dispose(); #endregion Update #region Delete // Prepare the bulk entities that you want to delete. You must set the Id field to the corresponding // entity identifier, and the Status field to Deleted. var campaignId = campaignResults[0].Campaign.Id; bulkCampaign = new BulkCampaign { Campaign = new Campaign { Id = campaignId, Status = CampaignStatus.Deleted } }; var appAdExtensionId = appAdExtensionResults[0].AppAdExtension.Id; bulkAppAdExtension = new BulkAppAdExtension { AppAdExtension = new AppAdExtension { Id = appAdExtensionId, Status = AdExtensionStatus.Deleted } }; var callAdExtensionId = callAdExtensionResults[0].CallAdExtension.Id; bulkCallAdExtension = new BulkCallAdExtension { CallAdExtension = new CallAdExtension { Id = callAdExtensionId, Status = AdExtensionStatus.Deleted } }; var locationAdExtensionId = locationAdExtensionResults[0].LocationAdExtension.Id; bulkLocationAdExtension = new BulkLocationAdExtension { LocationAdExtension = new LocationAdExtension { Id = locationAdExtensionId, Status = AdExtensionStatus.Deleted } }; var siteLinkAdExtensionId = siteLinkAdExtensionResults[0].SiteLinksAdExtension.Id; bulkSiteLinkAdExtension = new BulkSiteLinkAdExtension { SiteLinksAdExtension = new SiteLinksAdExtension { Id = siteLinkAdExtensionId, Status = AdExtensionStatus.Deleted } }; // Write the entities that you want deleted, to the specified file. // Dependent entities such as BulkCampaignCallAdExtension are deleted without being specified explicitly. // For example, if you delete either BulkCampaign or BulkCallAdExtension, then the equivalent of // BulkCampaignCallAdExtension is effectively deleted. Writer = new BulkFileWriter(FileDirectory + UploadFileName); Writer.WriteEntity(bulkCampaign); Writer.WriteEntity(bulkAppAdExtension); Writer.WriteEntity(bulkCallAdExtension); Writer.WriteEntity(bulkLocationAdExtension); Writer.WriteEntity(bulkSiteLinkAdExtension); Writer.Dispose(); fileUploadParameters = new FileUploadParameters { ResultFileDirectory = FileDirectory, ResultFileName = ResultFileName, OverwriteResultFile = true, UploadFilePath = FileDirectory + UploadFileName, ResponseMode = ResponseMode.ErrorsAndResults }; // UploadFileAsync will upload the file you finished writing and will download the results file OutputStatusMessage("\nDeleting campaign and ad extensions . . .\n"); bulkFilePath = await BulkService.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None); Reader = new BulkFileReader(bulkFilePath, ResultFileType.Upload, FileType); OutputStatusMessage("Upload Results Bulk File Path: " + Reader.BulkFilePath + "\n"); // Write the upload output bulkEntities = Reader.ReadEntities().ToList(); campaignResults = bulkEntities.OfType<BulkCampaign>().ToList(); OutputBulkCampaigns(campaignResults); appAdExtensionResults = bulkEntities.OfType<BulkAppAdExtension>().ToList(); OutputBulkAppAdExtensions(appAdExtensionResults); callAdExtensionResults = bulkEntities.OfType<BulkCallAdExtension>().ToList(); OutputBulkCallAdExtensions(callAdExtensionResults); locationAdExtensionResults = bulkEntities.OfType<BulkLocationAdExtension>().ToList(); OutputBulkLocationAdExtensions(locationAdExtensionResults); siteLinkAdExtensionResults = bulkEntities.OfType<BulkSiteLinkAdExtension>().ToList(); OutputBulkSiteLinkAdExtensions(siteLinkAdExtensionResults); OutputBulkCampaignAppAdExtensions(bulkEntities.OfType<BulkCampaignAppAdExtension>().ToList()); OutputBulkCampaignCallAdExtensions(bulkEntities.OfType<BulkCampaignCallAdExtension>().ToList()); OutputBulkCampaignLocationAdExtensions(bulkEntities.OfType<BulkCampaignLocationAdExtension>().ToList()); OutputBulkCampaignSiteLinkAdExtensions(bulkEntities.OfType<BulkCampaignSiteLinkAdExtension>().ToList()); Reader.Dispose(); #endregion Delete } // Catch Microsoft Account authorization exceptions. catch (OAuthTokenRequestException ex) { OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description)); } // Catch Bulk service exceptions catch (FaultException<Microsoft.BingAds.Bulk.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException<Microsoft.BingAds.Bulk.ApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (BulkOperationInProgressException ex) { OutputStatusMessage("The result file for the bulk operation is not yet available for download."); OutputStatusMessage(ex.Message); } catch (BulkOperationCouldNotBeCompletedException<DownloadStatus> ex) { OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (BulkOperationCouldNotBeCompletedException<UploadStatus> ex) { OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (Exception ex) { OutputStatusMessage(ex.Message); } finally { if (Reader != null) { Reader.Dispose(); } if (Writer != null) { Writer.Dispose(); } } }
public async override Task RunAsync(AuthorizationData authorizationData) { try { #region CampaignThroughAdGroupSetup // You will need to use the Campaign Management service to get the Bing Merchant Center Store Id. This will be used // when creating a new Bing Shopping Campaign. // For other operations such as adding product conditions, you can manage Bing Shopping Campaigns solely with the Bulk Service. CampaignService = new ServiceClient<ICampaignManagementService>(authorizationData); // Get a list of all Bing Merchant Center stores associated with your CustomerId IList<BMCStore> stores = await GetBMCStoresByCustomerIdAsync(); if (stores == null) { OutputStatusMessage( String.Format("You do not have any BMC stores registered for CustomerId {0}.\n", authorizationData.CustomerId) ); return; } BulkService = new BulkServiceManager(authorizationData); var progress = new Progress<BulkOperationProgressInfo>(x => OutputStatusMessage(String.Format("{0} % Complete", x.PercentComplete.ToString(CultureInfo.InvariantCulture)))); const int campaignIdKey = -123; const int adGroupIdKey = -1234; var uploadEntities = new List<BulkEntity>(); /* Add a new Bing Shopping campaign that will be associated with a ProductScope criterion. * - Set the CampaignType element of the Campaign to Shopping. * - Create a ShoppingSetting instance and set its Priority (0, 1, or 2), SalesCountryCode, and StoreId elements. * Add this shopping setting to the Settings list of the Campaign. */ var bulkCampaign = new BulkCampaign { // ClientId may be used to associate records in the bulk upload file with records in the results file. The value of this field // is not used or stored by the server; it is simply copied from the uploaded record to the corresponding result record. // Note: This bulk file Client Id is not related to an application Client Id for OAuth. ClientId = "YourClientIdGoesHere", Campaign = new Campaign { // When using the Campaign Management service, the Id cannot be set. In the context of a BulkCampaign, the Id is optional // and may be used as a negative reference key during bulk upload. For example the same negative value set for the campaign Id // will be used when associating this new campaign with a new campaign product scope in the BulkCampaignProductScope object below. Id = campaignIdKey, CampaignType = CampaignType.Shopping, Settings = new[] { new ShoppingSetting() { Priority = 0, SalesCountryCode = "US", StoreId = (int)stores[0].Id } }, Name = "Bing Shopping Campaign " + DateTime.UtcNow, Description = "Bing Shopping Campaign Example.", BudgetType = BudgetLimitType.MonthlyBudgetSpendUntilDepleted, MonthlyBudget = 1000.00, TimeZone = "PacificTimeUSCanadaTijuana", } }; /* Optionally, you can create a ProductScope criterion that will be associated with your Bing Shopping campaign. * Use the product scope criterion to include a subset of your product catalog, for example a specific brand, * category, or product type. A campaign can only be associated with one ProductScope, which contains a list * of up to 7 ProductCondition. You'll also be able to specify more specific product conditions for each ad group. */ var bulkCampaignProductScope = new BulkCampaignProductScope { CampaignCriterion = new CampaignCriterion() { CampaignId = campaignIdKey, BidAdjustment = null, // Reserved for future use Criterion = new ProductScope() { Conditions = new ProductCondition[] { new ProductCondition { Operand = "Condition", Attribute = "New" }, new ProductCondition { Operand = "CustomLabel0", Attribute = "MerchantDefinedCustomLabel" }, } }, }, Status = Status.Active, }; // Specify one or more ad groups. var bulkAdGroup = new BulkAdGroup{ CampaignId = campaignIdKey, AdGroup = new AdGroup { Id = adGroupIdKey, Name = "Product Categories", AdDistribution = AdDistribution.Search, BiddingModel = BiddingModel.Keyword, PricingModel = PricingModel.Cpc, StartDate = null, EndDate = new Microsoft.BingAds.CampaignManagement.Date { Month = 12, Day = 31, Year = 2016 }, Language = "English" }, }; /* * Create a product ad. You must add at least one ProductAd to the corresponding ad group. * A ProductAd is not used directly for delivered ad copy. Instead, the delivery engine generates * product ads from the product details that it finds in your Bing Merchant Center store's product catalog. * The primary purpose of the ProductAd object is to provide promotional text that the delivery engine * adds to the product ads that it generates. For example, if the promotional text is set to * “Free shipping on $99 purchases”, the delivery engine will set the product ad’s description to * “Free shipping on $99 purchases.” */ var bulkProductAd = new BulkProductAd { AdGroupId = adGroupIdKey, ProductAd = new ProductAd { PromotionalText = "Free shipping on $99 purchases." } }; uploadEntities.Add(bulkCampaign); uploadEntities.Add(bulkAdGroup); uploadEntities.Add(bulkCampaignProductScope); uploadEntities.Add(bulkProductAd); // Write the upload output var Reader = await UploadEntities(uploadEntities); var bulkEntities = Reader.ReadEntities().ToList(); var campaignResults = bulkEntities.OfType<BulkCampaign>().ToList(); OutputBulkCampaigns(campaignResults); var adGroupResults = bulkEntities.OfType<BulkAdGroup>().ToList(); OutputBulkAdGroups(adGroupResults); var productAdResults = bulkEntities.OfType<BulkProductAd>().ToList(); OutputBulkProductAds(productAdResults); var campaignProductScopeResults = bulkEntities.OfType<BulkCampaignProductScope>().ToList(); OutputBulkCampaignProductScopes(campaignProductScopeResults); Reader.Dispose(); #endregion CampaignThroughAdGroupSetup #region BidAllProducts var adGroupId = (long)adGroupResults[0].AdGroup.Id; var helper = new ProductPartitionHelper(adGroupId); var root = helper.AddUnit( null, new ProductCondition { Operand = "All", Attribute = null }, 0.35, false, "root" ); OutputStatusMessage("Applying only the root as a Unit with a bid . . . \n"); var applyBulkProductPartitionActionsResults = await ApplyBulkProductPartitionActions(helper.PartitionActions); var productPartitions = await GetBulkAdGroupProductPartitionTree(adGroupId); OutputStatusMessage("The ad group's product partition only has a tree root node: \n"); OutputProductPartitions(productPartitions); /* * Let's update the bid of the root Unit we just added. */ var updatedRoot = GetNodeByClientId(applyBulkProductPartitionActionsResults, "root"); var bid = new FixedBid { Bid = new Bid { Amount = 0.45 } }; ((BiddableAdGroupCriterion)(updatedRoot.AdGroupCriterion)).CriterionBid = bid; helper = new ProductPartitionHelper(adGroupId); helper.UpdatePartition(updatedRoot); OutputStatusMessage("Updating the bid for the tree root node . . . \n"); await ApplyBulkProductPartitionActions(helper.PartitionActions); productPartitions = await GetBulkAdGroupProductPartitionTree(adGroupId); OutputStatusMessage("Updated the bid for the tree root node: \n"); OutputProductPartitions(productPartitions); #endregion BidAllProducts #region InitializeTree /* * Now we will overwrite any existing tree root, and build a product partition group tree structure in multiple steps. * You could build the entire tree in a single call since there are less than 20,000 nodes; however, * we will build it in steps to demonstrate how to use the results from bulk upload to update the tree. * * For a list of validation rules, see the Bing Shopping Campaigns technical guide: * https://msdn.microsoft.com/en-US/library/bing-ads-campaign-management-bing-shopping-campaigns.aspx */ helper = new ProductPartitionHelper(adGroupId); /* * Check whether a root node exists already. */ var existingRoot = GetNodeByClientId(applyBulkProductPartitionActionsResults, "root"); if (existingRoot != null) { existingRoot.ClientId = "deletedroot"; helper.DeletePartition(existingRoot); } root = helper.AddSubdivision( null, new ProductCondition { Operand = "All", Attribute = null }, "root" ); /* * The direct children of any node must have the same Operand. * For this example we will use CategoryL1 nodes as children of the root. * For a list of valid CategoryL1 through CategoryL5 values, see the Bing Category Taxonomy: * http://advertise.bingads.microsoft.com/en-us/WWDocs/user/search/en-us/Bing_Category_Taxonomy.txt */ var animalsSubdivision = helper.AddSubdivision( root, new ProductCondition { Operand = "CategoryL1", Attribute = "Animals & Pet Supplies" }, "animalsSubdivision" ); /* * If you use a CategoryL2 node, it must be a descendant (child or later) of a CategoryL1 node. * In other words you cannot have a CategoryL2 node as parent of a CategoryL1 node. * For this example we will a CategoryL2 node as child of the CategoryL1 Animals & Pet Supplies node. */ var petSuppliesSubdivision = helper.AddSubdivision( animalsSubdivision, new ProductCondition { Operand = "CategoryL2", Attribute = "Pet Supplies" }, "petSuppliesSubdivision" ); var brandA = helper.AddUnit( petSuppliesSubdivision, new ProductCondition { Operand = "Brand", Attribute = "Brand A" }, 0.35, false, "brandA" ); /* * If you won't bid on Brand B, set the helper method's bidAmount to '0' and isNegative to true. * The helper method will create a NegativeAdGroupCriterion and apply the condition. */ var brandB = helper.AddUnit( petSuppliesSubdivision, new ProductCondition { Operand = "Brand", Attribute = "Brand B" }, 0, true, "brandB" ); var otherBrands = helper.AddUnit( petSuppliesSubdivision, new ProductCondition { Operand = "Brand", Attribute = null }, 0.35, false, "otherBrands" ); var otherPetSupplies = helper.AddUnit( animalsSubdivision, new ProductCondition { Operand = "CategoryL2", Attribute = null }, 0.35, false, "otherPetSupplies" ); var electronics = helper.AddUnit( root, new ProductCondition { Operand = "CategoryL1", Attribute = "Electronics" }, 0.35, false, "electronics" ); var otherCategoryL1 = helper.AddUnit( root, new ProductCondition { Operand = "CategoryL1", Attribute = null }, 0.35, false, "otherCategoryL1" ); OutputStatusMessage("Applying product partitions to the ad group . . . \n"); applyBulkProductPartitionActionsResults = await ApplyBulkProductPartitionActions(helper.PartitionActions); productPartitions = await GetBulkAdGroupProductPartitionTree(adGroupId); /* * The product partition group tree now has 9 nodes. All other (Root Node) | +-- Animals & Pet Supplies (CategoryL1) | | | +-- Pet Supplies (CategoryL2) | | | | | +-- Brand A | | | | | +-- Brand B | | | | | +-- All other (Brand) | | | +-- All other (CategoryL2) | +-- Electronics (CategoryL1) | +-- All other (CategoryL1) */ OutputStatusMessage("The product partition group tree now has 9 nodes: \n"); OutputProductPartitions(productPartitions); #endregion InitializeTree #region UpdateTree /* * Let's replace the Electronics (CategoryL1) node created above with an Electronics (CategoryL1) node that * has children i.e. Brand C (Brand), Brand D (Brand), and All other (Brand) as follows: Electronics (CategoryL1) | +-- Brand C (Brand) | +-- Brand D (Brand) | +-- All other (Brand) */ helper = new ProductPartitionHelper(adGroupId); /* * To replace a node we must know its Id and its ParentCriterionId. In this case the parent of the node * we are replacing is All other (Root Node). The node that we are replacing is Electronics (CategoryL1). */ var rootId = GetNodeByClientId(applyBulkProductPartitionActionsResults,"root").AdGroupCriterion.Id; electronics.AdGroupCriterion.Id = GetNodeByClientId(applyBulkProductPartitionActionsResults, "electronics").AdGroupCriterion.Id; helper.DeletePartition(electronics); var parent = new BulkAdGroupProductPartition { AdGroupCriterion = new BiddableAdGroupCriterion() { Id = rootId } }; var electronicsSubdivision = helper.AddSubdivision( parent, new ProductCondition { Operand = "CategoryL1", Attribute = "Electronics" }, "electronicsSubdivision" ); var brandC = helper.AddUnit( electronicsSubdivision, new ProductCondition { Operand = "Brand", Attribute = "Brand C" }, 0.35, false, "brandC" ); var brandD = helper.AddUnit( electronicsSubdivision, new ProductCondition { Operand = "Brand", Attribute = "Brand D" }, 0.35, false, "brandD" ); var otherElectronicsBrands = helper.AddUnit( electronicsSubdivision, new ProductCondition { Operand = "Brand", Attribute = null }, 0.35, false, "otherElectronicsBrands" ); OutputStatusMessage( "Updating the product partition group to refine Electronics (CategoryL1) with 3 child nodes . . . \n" ); applyBulkProductPartitionActionsResults = await ApplyBulkProductPartitionActions(helper.PartitionActions); productPartitions = await GetBulkAdGroupProductPartitionTree(adGroupId); /* * The product partition group tree now has 12 nodes, including the children of Electronics (CategoryL1): All other (Root Node) | +-- Animals & Pet Supplies (CategoryL1) | | | +-- Pet Supplies (CategoryL2) | | | | | +-- Brand A | | | | | +-- Brand B | | | | | +-- All other (Brand) | | | +-- All other (CategoryL2) | +-- Electronics (CategoryL1) | | | +-- Brand C (Brand) | | | +-- Brand D (Brand) | | | +-- All other (Brand) | +-- All other (CategoryL1) */ OutputStatusMessage( "The product partition group tree now has 12 nodes, including the children of Electronics (CategoryL1): \n" ); OutputProductPartitions(productPartitions); #endregion UpdateTree #region CleanUp /* Delete the campaign, ad group, criterion, and ad that were previously added. * You should remove this region if you want to view the added entities in the * Bing Ads web application or another tool. */ var campaignId = campaignResults[0].Campaign.Id; bulkCampaign = new BulkCampaign { Campaign = new Campaign { Id = campaignId, Status = CampaignStatus.Deleted } }; uploadEntities = new List<BulkEntity>(); uploadEntities.Add(bulkCampaign); // Write the upload output Reader = await UploadEntities(uploadEntities); bulkEntities = Reader.ReadEntities().ToList(); campaignResults = bulkEntities.OfType<BulkCampaign>().ToList(); OutputBulkCampaigns(campaignResults); Reader.Dispose(); OutputStatusMessage(String.Format("Deleted CampaignId {0}\n", campaignResults[0].Campaign.Id)); #endregion Cleanup } // Catch Microsoft Account authorization exceptions. catch (OAuthTokenRequestException ex) { OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description)); } // Catch Bulk service exceptions catch (FaultException<Microsoft.BingAds.Bulk.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException<Microsoft.BingAds.Bulk.ApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (BulkOperationInProgressException ex) { OutputStatusMessage("The result file for the bulk operation is not yet available for download."); OutputStatusMessage(ex.Message); } catch (BulkOperationCouldNotBeCompletedException<DownloadStatus> ex) { OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (BulkOperationCouldNotBeCompletedException<UploadStatus> ex) { OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (Exception ex) { OutputStatusMessage(ex.Message); } finally { if (Reader != null) { Reader.Dispose(); } if (Writer != null) { Writer.Dispose(); } } }
public async override Task RunAsync(AuthorizationData authorizationData) { try { BulkService = new BulkServiceManager(authorizationData); var progress = new Progress<BulkOperationProgressInfo>(x => OutputStatusMessage(String.Format("{0} % Complete", x.PercentComplete.ToString(CultureInfo.InvariantCulture)))); var uploadEntities = new List<BulkEntity>(); #region Add // Prepare the bulk entities that you want to upload. Each bulk entity contains the corresponding campaign management object, // and additional elements needed to read from and write to a bulk file. var bulkCampaign = new BulkCampaign { // ClientId may be used to associate records in the bulk upload file with records in the results file. The value of this field // is not used or stored by the server; it is simply copied from the uploaded record to the corresponding result record. // Note: This bulk file Client Id is not related to an application Client Id for OAuth. ClientId = "YourClientIdGoesHere", Campaign = new Campaign { // When using the Campaign Management service, the Id cannot be set. In the context of a BulkCampaign, the Id is optional // and may be used as a negative reference key during bulk upload. For example the same negative value set for the campaign Id // will be used when associating this new campaign with a new call ad extension in the BulkCampaignCallAdExtension object below. Id = campaignIdKey, Name = "Women's Shoes " + DateTime.UtcNow, Description = "Red shoes line.", BudgetType = BudgetLimitType.MonthlyBudgetSpendUntilDepleted, MonthlyBudget = 1000.00, TimeZone = "PacificTimeUSCanadaTijuana", // DaylightSaving is not supported in the Bulk file schema. Whether or not you specify it in a BulkCampaign, // the value is not written to the Bulk file, and by default DaylightSaving is set to true. DaylightSaving = true, } }; // Specify one or more ad groups. var bulkAdGroup = new BulkAdGroup { CampaignId = campaignIdKey, AdGroup = new AdGroup { Id = adGroupIdKey, Name = "Women's Red Shoe Sale", AdDistribution = AdDistribution.Search, BiddingModel = BiddingModel.Keyword, PricingModel = PricingModel.Cpc, StartDate = null, EndDate = new Microsoft.BingAds.CampaignManagement.Date { Month = 12, Day = 31, Year = 2016 }, Language = "English", Status = AdGroupStatus.Active, }, }; // In this example only the second keyword should succeed. The Text of the first keyword exceeds the limit, // and the third keyword is a duplicate of the second keyword. var bulkKeywords = new[] { new BulkKeyword{ AdGroupId = adGroupIdKey, Keyword = new Keyword { Bid = new Bid { Amount = 0.47 }, Param2 = "10% Off", MatchType = MatchType.Broad, Text = "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes " + "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes " + "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes" }, }, new BulkKeyword{ AdGroupId = adGroupIdKey, Keyword = new Keyword { Bid = new Bid { Amount = 0.47 }, Param2 = "10% Off", MatchType = MatchType.Phrase, Text = "Brand-A Shoes" }, }, new BulkKeyword{ AdGroupId = adGroupIdKey, Keyword = new Keyword { Bid = new Bid { Amount = 0.47 }, Param2 = "10% Off", MatchType = MatchType.Phrase, Text = "Brand-A Shoes" }, }, }; // In this example only the first 3 ads should succeed. // The Title of the fourth ad is empty and not valid, // and the fifth ad is a duplicate of the second ad. var bulkTextAds = new[] { new BulkTextAd { AdGroupId = adGroupIdKey, TextAd = new TextAd { Title = "Women's Shoe Sale", Text = "Huge Savings on red shoes.", DisplayUrl = "Contoso.com", // If you are currently using the Destination URL, you must use Bing Ads // Campaign Management service version 10 and upgrade to Final URLs. // Here is an example of a DestinationUrl in version 9. DestinationUrl = "http://www.contoso.com/womenshoesale/?season=spring&promocode=PROMO123", }, }, new BulkTextAd { AdGroupId = adGroupIdKey, TextAd = new TextAd { Title = "Women's Super Shoe Sale", Text = "Huge Savings on red shoes.", DisplayUrl = "Contoso.com", // If you are currently using the Destination URL, you must use Bing Ads // Campaign Management service version 10 and upgrade to Final URLs. // Here is an example of a DestinationUrl in version 9. DestinationUrl = "http://www.contoso.com/womenshoesale/?season=spring&promocode=PROMO123", }, }, new BulkTextAd { AdGroupId = adGroupIdKey, TextAd = new TextAd { Title = "Women's Red Shoe Sale", Text = "Huge Savings on red shoes.", DisplayUrl = "Contoso.com", // If you are currently using the Destination URL, you must use Bing Ads // Campaign Management service version 10 and upgrade to Final URLs. // Here is an example of a DestinationUrl in version 9. DestinationUrl = "http://www.contoso.com/womenshoesale/?season=spring&promocode=PROMO123", }, }, new BulkTextAd { AdGroupId = adGroupIdKey, TextAd = new TextAd { Title = "", Text = "Huge Savings on red shoes.", DisplayUrl = "Contoso.com", // If you are currently using the Destination URL, you must use Bing Ads // Campaign Management service version 10 and upgrade to Final URLs. // Here is an example of a DestinationUrl in version 9. DestinationUrl = "http://www.contoso.com/womenshoesale/?season=spring&promocode=PROMO123", }, }, new BulkTextAd { AdGroupId = adGroupIdKey, TextAd = new TextAd { Title = "Women's Super Shoe Sale", Text = "Huge Savings on red shoes.", DisplayUrl = "Contoso.com", // If you are currently using the Destination URL, you must use Bing Ads // Campaign Management service version 10 and upgrade to Final URLs. // Here is an example of a DestinationUrl in version 9. DestinationUrl = "http://www.contoso.com/womenshoesale/?season=spring&promocode=PROMO123", }, }, }; uploadEntities.Add(bulkCampaign); uploadEntities.Add(bulkAdGroup); foreach (var bulkKeyword in bulkKeywords) { uploadEntities.Add(bulkKeyword); } foreach (var bulkTextAd in bulkTextAds) { uploadEntities.Add(bulkTextAd); } // Write the upload output var Reader = await UploadEntities(uploadEntities); var bulkEntities = Reader.ReadEntities().ToList(); var campaignResults = bulkEntities.OfType<BulkCampaign>().ToList(); OutputBulkCampaigns(campaignResults); var adGroupResults = bulkEntities.OfType<BulkAdGroup>().ToList(); OutputBulkAdGroups(adGroupResults); var keywordResults = bulkEntities.OfType<BulkKeyword>().ToList(); OutputBulkKeywords(keywordResults); var textAdResults = bulkEntities.OfType<BulkTextAd>().ToList(); OutputBulkTextAds(textAdResults); Reader.Dispose(); #endregion Add #region CleanUp /* Delete the campaign, ad group, keywords, and ads that were previously added. * You should remove this region if you want to view the added entities in the * Bing Ads web application or another tool. */ var campaignId = campaignResults[0].Campaign.Id; bulkCampaign = new BulkCampaign { Campaign = new Campaign { Id = campaignId, Status = CampaignStatus.Deleted } }; uploadEntities = new List<BulkEntity>(); uploadEntities.Add(bulkCampaign); // Write the upload output Reader = await UploadEntities(uploadEntities); bulkEntities = Reader.ReadEntities().ToList(); campaignResults = bulkEntities.OfType<BulkCampaign>().ToList(); OutputBulkCampaigns(campaignResults); Reader.Dispose(); OutputStatusMessage(String.Format("Deleted CampaignId {0}\n", campaignResults[0].Campaign.Id)); #endregion Cleanup } // Catch Microsoft Account authorization exceptions. catch (OAuthTokenRequestException ex) { OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description)); } // Catch Bulk service exceptions catch (FaultException<Microsoft.BingAds.V10.Bulk.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException<Microsoft.BingAds.V10.Bulk.ApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (BulkOperationInProgressException ex) { OutputStatusMessage("The result file for the bulk operation is not yet available for download."); OutputStatusMessage(ex.Message); } catch (BulkOperationCouldNotBeCompletedException<DownloadStatus> ex) { OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (BulkOperationCouldNotBeCompletedException<UploadStatus> ex) { OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (Exception ex) { OutputStatusMessage(ex.Message); } finally { if (Reader != null) { Reader.Dispose(); } if (Writer != null) { Writer.Dispose(); } } }
public async override Task RunAsync(AuthorizationData authorizationData) { try { BulkService = new BulkServiceManager(authorizationData); var progress = new Progress<BulkOperationProgressInfo>(x => OutputStatusMessage(String.Format("{0} % Complete", x.PercentComplete.ToString(CultureInfo.InvariantCulture)))); #region Add const int targetIdKey = -1; const int campaignIdKey = -123; var uploadEntities = new List<BulkEntity>(); // Prepare the bulk entities that you want to upload. Each bulk entity contains the corresponding campaign management object, // and additional elements needed to read from and write to a bulk file. var bulkCampaign = new BulkCampaign { // ClientId may be used to associate records in the bulk upload file with records in the results file. The value of this field // is not used or stored by the server; it is simply copied from the uploaded record to the corresponding result record. // Note: This bulk file Client Id is not related to an application Client Id for OAuth. ClientId = "YourClientIdGoesHere", Campaign = new Campaign { // When using the Campaign Management service, the Id cannot be set. In the context of a BulkCampaign, the Id is optional // and may be used as a negative reference key during bulk upload. For example the same negative value set for the campaign Id // will be used when associating this new campaign with a new call ad extension in the BulkCampaignCallAdExtension object below. Id = campaignIdKey, Name = "Women's Shoes " + DateTime.UtcNow, Description = "Red shoes line.", BudgetType = BudgetLimitType.MonthlyBudgetSpendUntilDepleted, MonthlyBudget = 1000.00, TimeZone = "PacificTimeUSCanadaTijuana", // DaylightSaving is not supported in the Bulk file schema. Whether or not you specify it in a BulkCampaign, // the value is not written to the Bulk file, and by default DaylightSaving is set to true. DaylightSaving = true, } }; // Prepare targets for upload var bulkCampaignDayTimeTarget = new BulkCampaignDayTimeTarget { CampaignId = campaignIdKey, TargetId = targetIdKey, DayTimeTarget = new DayTimeTarget { Bids = new List<DayTimeTargetBid> { new DayTimeTargetBid { BidAdjustment = 10, Day = Day.Friday, FromHour = 11, FromMinute = Minute.Zero, ToHour = 13, ToMinute = Minute.Fifteen }, new DayTimeTargetBid { BidAdjustment = 20, Day = Day.Saturday, FromHour = 11, FromMinute = Minute.Zero, ToHour = 13, ToMinute = Minute.Fifteen } } } }; var bulkCampaignLocationTarget = new BulkCampaignLocationTarget { CampaignId = campaignIdKey, TargetId = targetIdKey, IntentOption = IntentOption.PeopleIn, CityTarget = new CityTarget { Bids = new List<CityTargetBid> { new CityTargetBid { BidAdjustment = 15, City = "Toronto, Toronto ON CA", IsExcluded = false } } }, CountryTarget = new CountryTarget { Bids = new List<CountryTargetBid> { new CountryTargetBid { BidAdjustment = 15, CountryAndRegion = "CA", IsExcluded = false } } }, MetroAreaTarget = new MetroAreaTarget { Bids = new List<MetroAreaTargetBid> { new MetroAreaTargetBid { BidAdjustment = 15, MetroArea = "Seattle-Tacoma, WA, WA US", IsExcluded = false } } }, StateTarget = new StateTarget { Bids = new List<StateTargetBid> { new StateTargetBid { BidAdjustment = 15, State = "US-WA", IsExcluded = false } } }, PostalCodeTarget = new PostalCodeTarget { Bids = new List<PostalCodeTargetBid> { new PostalCodeTargetBid { // Bid adjustments are not allowed for location exclusions. // If IsExcluded is true, this element will be ignored. BidAdjustment = 10, PostalCode = "98052, WA US", IsExcluded = false } } } }; var bulkCampaignRadiusTarget = new BulkCampaignRadiusTarget { CampaignId = campaignIdKey, TargetId = targetIdKey, RadiusTarget = new RadiusTarget2 { Bids = new List<RadiusTargetBid2> { new RadiusTargetBid2 { BidAdjustment = 50, LatitudeDegrees = 47.755367, LongitudeDegrees = -122.091827, Radius = 11, RadiusUnit = DistanceUnit.Kilometers, Name = "radius1" }, new RadiusTargetBid2 { BidAdjustment = 20, LatitudeDegrees = 49.755367, LongitudeDegrees = -129.091827, Radius = 12, RadiusUnit = DistanceUnit.Kilometers, Name = "radius2" } } } }; // Write the entities created above, to the specified file. uploadEntities.Add(bulkCampaign); uploadEntities.Add(bulkCampaignDayTimeTarget); uploadEntities.Add(bulkCampaignLocationTarget); uploadEntities.Add(bulkCampaignRadiusTarget); // Write the upload output var Reader = await UploadEntities(uploadEntities); var bulkEntities = Reader.ReadEntities().ToList(); var campaignResults = bulkEntities.OfType<BulkCampaign>().ToList(); OutputBulkCampaigns(campaignResults); var campaignDayTimeTargetResults = bulkEntities.OfType<BulkCampaignDayTimeTarget>().ToList(); OutputBulkCampaignDayTimeTargets(campaignDayTimeTargetResults); var campaignLocationTargetResults = bulkEntities.OfType<BulkCampaignLocationTarget>().ToList(); OutputBulkCampaignLocationTargets(campaignLocationTargetResults); var campaignRadiusTargetResults = bulkEntities.OfType<BulkCampaignRadiusTarget>().ToList(); OutputBulkCampaignRadiusTargets(campaignRadiusTargetResults); Reader.Dispose(); #endregion Add #region Update // Update the day and time target. // Do not create a BulkCampaignDayTimeTarget for update, unless you want to replace all existing DayTime target bids // with the specified day and time target set for the current bulk upload. // Instead you should upload one or more BulkCampaignDayTimeTargetBid. var bulkCampaignDayTimeTargetBids = new List<BulkCampaignDayTimeTargetBid> { new BulkCampaignDayTimeTargetBid { CampaignId = campaignDayTimeTargetResults[0].CampaignId, TargetId = campaignDayTimeTargetResults[0].TargetId, DayTimeTargetBid = new DayTimeTargetBid { BidAdjustment = 15, Day = Day.Friday, FromHour = 11, FromMinute = Minute.Zero, ToHour = 13, ToMinute = Minute.Fifteen } } }; // Write the updated target to the file uploadEntities = new List<BulkEntity>(); foreach (var bulkCampaignDayTimeTargetBid in bulkCampaignDayTimeTargetBids) { uploadEntities.Add(bulkCampaignDayTimeTargetBid); } // Write the upload output Reader = await UploadEntities(uploadEntities); OutputStatusMessage("Upload Results Bulk File Path" + Reader.BulkFilePath + "\n"); OutputStatusMessage("Updated Entities\n"); bulkEntities = Reader.ReadEntities().ToList(); var campaignDayTimeTargetBidResults = bulkEntities.OfType<BulkCampaignDayTimeTargetBid>().ToList(); OutputBulkCampaignDayTimeTargetBids(campaignDayTimeTargetBidResults); Reader.Dispose(); #endregion Update #region CleanUp /* Delete the campaign and target associations that were previously added. * Note that the targets are not deleted. Deleting targets is not supported using the * Bulk service. To delete targets you can use the DeleteTargetsFromLibrary operation * via the Campaign Management service. * You should remove this region if you want to view the added entities in the * Bing Ads web application or another tool. */ var campaignId = campaignResults[0].Campaign.Id; bulkCampaign = new BulkCampaign { Campaign = new Campaign { Id = campaignId, Status = CampaignStatus.Deleted } }; uploadEntities = new List<BulkEntity>(); uploadEntities.Add(bulkCampaign); // Write the upload output Reader = await UploadEntities(uploadEntities); bulkEntities = Reader.ReadEntities().ToList(); campaignResults = bulkEntities.OfType<BulkCampaign>().ToList(); OutputBulkCampaigns(campaignResults); Reader.Dispose(); OutputStatusMessage(String.Format("Deleted CampaignId {0}\n", campaignResults[0].Campaign.Id)); #endregion Cleanup } // Catch Microsoft Account authorization exceptions. catch (OAuthTokenRequestException ex) { OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description)); } // Catch Bulk service exceptions catch (FaultException<Microsoft.BingAds.Bulk.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException<Microsoft.BingAds.Bulk.ApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (BulkOperationInProgressException ex) { OutputStatusMessage("The result file for the bulk operation is not yet available for download."); OutputStatusMessage(ex.Message); } catch (BulkOperationCouldNotBeCompletedException<DownloadStatus> ex) { OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (BulkOperationCouldNotBeCompletedException<UploadStatus> ex) { OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (Exception ex) { OutputStatusMessage(ex.Message); } finally { if (Reader != null) { Reader.Dispose(); } if (Writer != null) { Writer.Dispose(); } } }
private static void CsvToBudget(RowValues values, BulkCampaign c) { string budgetTypeRowValue; BudgetLimitType? budgetType; if (!values.TryGetValue(StringTable.BudgetType, out budgetTypeRowValue) || (budgetType = budgetTypeRowValue.ParseOptional<BudgetLimitType>()) == null) { return; } string budgetRowValue; if (!values.TryGetValue(StringTable.Budget, out budgetRowValue)) { return; } var budgetValue = budgetRowValue.ParseOptional<double>(); c.Campaign.BudgetType = budgetType; if (budgetType == BudgetLimitType.DailyBudgetAccelerated || budgetType == BudgetLimitType.DailyBudgetStandard) { c.Campaign.DailyBudget = budgetValue; } else { c.Campaign.MonthlyBudget = budgetValue; } }