public async override Task RunAsync(AuthorizationData authorizationData) { try { ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment; CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper( OutputStatusMessageDefault: this.OutputStatusMessage); CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>( authorizationData: authorizationData, environment: environment); // Add an image to your media library. // The image asset is needed later to create the responsive ad. var landscapeImageMedia = GetImageMedia( "Image191x100", MediaFilePath + ResponsiveAdMediaFileName, System.Drawing.Imaging.ImageFormat.Png); var media = new Media[] { landscapeImageMedia, }; OutputStatusMessage("-----\nAddMedia:"); AddMediaResponse addMediaResponse = await CampaignManagementExampleHelper.AddMediaAsync( accountId : authorizationData.AccountId, media : media); long[] mediaIds = addMediaResponse.MediaIds.ToArray(); OutputStatusMessage("MediaIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(mediaIds); // Create an Audience campaign with one ad group and a responsive ad. var campaigns = new[] { new Campaign { BudgetType = BudgetLimitType.DailyBudgetStandard, // CampaignType must be set for Audience campaigns CampaignType = CampaignType.Audience, DailyBudget = 50, Description = "Red shoes line.", // Languages must be set for Audience campaigns Languages = new string[] { "All" }, Name = "Women's Shoes " + DateTime.UtcNow, TimeZone = "PacificTimeUSCanadaTijuana", }, }; OutputStatusMessage("-----\nAddCampaigns:"); AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync( accountId : authorizationData.AccountId, campaigns : campaigns, includeDynamicSearchAdsSource : false); long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray(); BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); OutputStatusMessage("CampaignIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(campaignIds); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(campaignErrors); // Add an ad group within the campaign. var adGroups = new[] { new AdGroup { Name = "Women's Red Shoe Sale", StartDate = null, EndDate = new Date { Month = 12, Day = 31, Year = DateTime.UtcNow.Year + 1 }, CpcBid = new Bid { Amount = 0.09 }, // Network cannot be set for ad groups in Audience campaigns Network = null, } }; OutputStatusMessage("-----\nAddAdGroups:"); AddAdGroupsResponse addAdGroupsResponse = await CampaignManagementExampleHelper.AddAdGroupsAsync( campaignId : (long)campaignIds[0], adGroups : adGroups, returnInheritedBidStrategyTypes : false); long?[] adGroupIds = addAdGroupsResponse.AdGroupIds.ToArray(); BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray(); OutputStatusMessage("AdGroupIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(adGroupIds); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(adGroupErrors); // Add a responsive ad within the ad group. var ads = new Ad[] { new ResponsiveAd { BusinessName = "Contoso", CallToAction = CallToAction.AddToCart, FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, Headline = "Fast & Easy Setup", Images = new [] { // You are only required to provide a landscape image asset. // Optionally you can include additional asset links, i.e., one image asset for each supported sub type. // For any image asset sub types that you do not explicitly set, // the service will automatically create image asset links by cropping the LandscapeImageMedia. new AssetLink { Asset = new ImageAsset { CropHeight = null, CropWidth = null, CropX = null, CropY = null, Id = mediaIds[0], Name = "My LandscapeImageMedia", SubType = "LandscapeImageMedia", }, }, }, LongHeadline = "Find New Customers & Increase Sales!", Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.", }, }; OutputStatusMessage("-----\nAddAds:"); AddAdsResponse addAdsResponse = await CampaignManagementExampleHelper.AddAdsAsync( adGroupId : (long)adGroupIds[0], ads : ads); long?[] adIds = addAdsResponse.AdIds.ToArray(); BatchError[] adErrors = addAdsResponse.PartialErrors.ToArray(); OutputStatusMessage("AdIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(adIds); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(adErrors); // Delete the account's media. OutputStatusMessage("-----\nDeleteMedia:"); await CampaignManagementExampleHelper.DeleteMediaAsync( accountId : authorizationData.AccountId, mediaIds : mediaIds); foreach (var id in mediaIds) { OutputStatusMessage(string.Format("Deleted Media Id {0}", id)); } // Delete the campaign and everything it contains e.g., ad groups and ads. OutputStatusMessage("-----\nDeleteCampaigns:"); await CampaignManagementExampleHelper.DeleteCampaignsAsync( accountId : authorizationData.AccountId, campaignIds : new[] { (long)campaignIds[0] }); OutputStatusMessage(string.Format("Deleted Campaign Id {0}", campaignIds[0])); } // Catch authentication exceptions catch (OAuthTokenRequestException ex) { OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description)); } // Catch Campaign Management service exceptions catch (FaultException <Microsoft.BingAds.V12.CampaignManagement.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <Microsoft.BingAds.V12.CampaignManagement.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 (FaultException <Microsoft.BingAds.V12.CampaignManagement.EditorialApiFaultDetail> 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 (Exception ex) { OutputStatusMessage(ex.Message); } }
public async override Task RunAsync(AuthorizationData authorizationData) { try { ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment; CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage); CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>(authorizationData, environment); #region MediaRepresentations var landscapeImageMedia = GetImageMedia( "Image191x100", MediaFilePath + LandscapeImageMediaFileName, System.Drawing.Imaging.ImageFormat.Png); var landscapeLogoMedia = GetImageMedia( "Image4x1", MediaFilePath + LandscapeLogoMediaFileName, System.Drawing.Imaging.ImageFormat.Png); var squareImageMedia = GetImageMedia( "Image1x1", MediaFilePath + SquareImageMediaFileName, System.Drawing.Imaging.ImageFormat.Png); var squareLogoMedia = GetImageMedia( "Image1x1", MediaFilePath + SquareLogoMediaFileName, System.Drawing.Imaging.ImageFormat.Png); var imageAdExtensionMedia = GetImageMedia( "Image15x10", MediaFilePath + ImageAdExtensionMediaFileName, System.Drawing.Imaging.ImageFormat.Png); var addMedia = new Media[] { landscapeImageMedia, landscapeLogoMedia, squareImageMedia, squareLogoMedia, imageAdExtensionMedia }; CampaignManagementExampleHelper.OutputArrayOfMedia(addMedia); var imageMediaIds = (await CampaignManagementExampleHelper.AddMediaAsync( authorizationData.AccountId, addMedia)).MediaIds; // The index of returned IDs is consistent with the order you submitted them in the request; // however, the sequence of the IDs themselves is not guaranteed. For example you might observe: // - Landscape Image Media Id == imageMediaIds[0] == 1 // - Landscape Logo Media Id == imageMediaIds[1] == 4 // - Square Image Media Id == imageMediaIds[2] == 3 // - Square Logo Media Id == imageMediaIds[3] == 2 // - Image Ad Extension Media Id == imageMediaIds[4] == 0 // You can use the first four Media Ids when you add or update a Responsive Ad // in an Audience campaign e.g., see AudienceCampaigns.cs. var adMediaIds = new List <long> { imageMediaIds[0], imageMediaIds[1], imageMediaIds[2], imageMediaIds[3] }; OutputStatusMessage("Media Ids for Responsive Ad:"); CampaignManagementExampleHelper.OutputArrayOfLong(adMediaIds); // You can use the fifth Media Id when you add or update an Image Ad Extension // in a Search campaign e.g., see AdExtensions.cs. var extensionMediaIds = new List <long> { imageMediaIds[4] }; OutputStatusMessage("Media Ids for Image Ad Extension:"); CampaignManagementExampleHelper.OutputArrayOfLong(extensionMediaIds); // Get the media representations to confirm the stored dimensions // and get the Url where you can later view or download the media. var getResponsiveAdMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByAccountIdAsync( MediaEnabledEntityFilter.ResponsiveAd)).MediaMetaData; CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getResponsiveAdMediaMetaData); var getImageAdExtensionMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByAccountIdAsync( MediaEnabledEntityFilter.ImageAdExtension)).MediaMetaData; CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getImageAdExtensionMediaMetaData); var getMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByIdsAsync(imageMediaIds)).MediaMetaData; CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getMediaMetaData); #endregion MediaRepresentations #region Delete // Comment out (disable) the delete operation if you want to use the media IDs // in another example e.g., AudienceCampaigns.cs. var deleteMediaResponse = (await CampaignManagementExampleHelper.DeleteMediaAsync( authorizationData.AccountId, imageMediaIds)); foreach (var id in imageMediaIds) { OutputStatusMessage(string.Format("Deleted Media Id {0}\n", id)); } #endregion Delete } // Catch authentication exceptions catch (OAuthTokenRequestException ex) { OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description)); } // Catch Campaign Management service exceptions catch (FaultException <Microsoft.BingAds.V12.CampaignManagement.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <Microsoft.BingAds.V12.CampaignManagement.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 (FaultException <Microsoft.BingAds.V12.CampaignManagement.EditorialApiFaultDetail> 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 (Exception ex) { OutputStatusMessage(ex.Message); } }
public async override Task RunAsync(AuthorizationData authorizationData) { try { ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment; CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper( OutputStatusMessageDefault: this.OutputStatusMessage); CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>( authorizationData: authorizationData, environment: environment); // Add a campaign to associate with ad extensions. var campaigns = new[] { new Campaign { BudgetType = BudgetLimitType.DailyBudgetStandard, DailyBudget = 50, Description = "Red shoes line.", Languages = new string[] { "All" }, Name = "Women's Shoes " + DateTime.UtcNow, TimeZone = "PacificTimeUSCanadaTijuana", } }; OutputStatusMessage("-----\nAddCampaigns:"); AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync( accountId : authorizationData.AccountId, campaigns : campaigns, includeDynamicSearchAdsSource : false); long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray(); BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); OutputStatusMessage("CampaignIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(campaignIds); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(campaignErrors); // Create media for the image ad extension that we'll add later. var imageAdExtensionMedia = GetImageMedia( "Image15x10", MediaFilePath + ImageAdExtensionMediaFileName, System.Drawing.Imaging.ImageFormat.Png); var media = new Media[] { imageAdExtensionMedia }; // Add the media to the account's library. OutputStatusMessage("-----\nAddMedia:"); AddMediaResponse addMediaResponse = await CampaignManagementExampleHelper.AddMediaAsync( accountId : authorizationData.AccountId, media : media); long[] mediaIds = addMediaResponse.MediaIds.ToArray(); OutputStatusMessage("MediaIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(mediaIds); // Add the extensions to the account's library. var adExtensions = new AdExtension[] { new ActionAdExtension { ActionType = ActionAdExtensionActionType.ActNow, FinalUrls = new string[] { "http://www.contoso.com/womenshoesale" }, Language = "English", Status = AdExtensionStatus.Active, }, //new AppAdExtension //{ // AppPlatform = "Windows", // AppStoreId = "AppStoreIdGoesHere", // DestinationUrl = "DestinationUrlGoesHere", // DisplayText = "Contoso", //}, new CallAdExtension { CountryCode = "US", PhoneNumber = "2065550100", IsCallOnly = false, // Include the call extension Monday - Friday from 9am - 9pm // in the account's time zone. Scheduling = new Schedule { UseSearcherTimeZone = false, DayTimeRanges = new[] { new DayTime { Day = Day.Monday, StartHour = 9, StartMinute = Minute.Zero, EndHour = 21, EndMinute = Minute.Zero, }, new DayTime { Day = Day.Tuesday, StartHour = 9, StartMinute = Minute.Zero, EndHour = 21, EndMinute = Minute.Zero, }, new DayTime { Day = Day.Wednesday, StartHour = 9, StartMinute = Minute.Zero, EndHour = 21, EndMinute = Minute.Zero, }, new DayTime { Day = Day.Thursday, StartHour = 9, StartMinute = Minute.Zero, EndHour = 21, EndMinute = Minute.Zero, }, new DayTime { Day = Day.Friday, StartHour = 9, StartMinute = Minute.Zero, EndHour = 21, EndMinute = Minute.Zero, }, }, StartDate = null, EndDate = new Microsoft.BingAds.V12.CampaignManagement.Date { Month = 12, Day = 31, Year = DateTime.UtcNow.Year + 1 }, } }, new CalloutAdExtension { Text = "Callout Text" }, new ImageAdExtension { AlternativeText = "Image Extension Alt Text", ImageMediaIds = mediaIds }, new LocationAdExtension { PhoneNumber = "206-555-0100", CompanyName = "Contoso Shoes", Address = new Microsoft.BingAds.V12.CampaignManagement.Address { StreetAddress = "1234 Washington Place", StreetAddress2 = "Suite 1210", CityName = "Woodinville", ProvinceName = "WA", CountryCode = "US", PostalCode = "98608" }, // Include the location extension every Saturday morning // in the search user's time zone. Scheduling = new Schedule { UseSearcherTimeZone = true, DayTimeRanges = new[] { new DayTime { Day = Day.Saturday, StartHour = 9, StartMinute = Minute.Zero, EndHour = 12, EndMinute = Minute.Zero, }, }, StartDate = null, EndDate = new Microsoft.BingAds.V12.CampaignManagement.Date { Month = 12, Day = 31, Year = DateTime.UtcNow.Year + 1 }, } }, new PriceAdExtension { Language = "English", PriceExtensionType = PriceExtensionType.Events, TableRows = new PriceTableRow[] { new PriceTableRow { CurrencyCode = "USD", Description = "Come to the event", FinalUrls = new string[] { "https://contoso.com" }, Header = "New Event", Price = 9.99, PriceQualifier = PriceQualifier.From, PriceUnit = PriceUnit.PerDay, }, new PriceTableRow { CurrencyCode = "USD", Description = "Come to the next event", FinalUrls = new string[] { "https://contoso.com" }, Header = "Next Event", Price = 9.99, PriceQualifier = PriceQualifier.From, PriceUnit = PriceUnit.PerDay, }, new PriceTableRow { CurrencyCode = "USD", Description = "Come to the final event", FinalUrls = new string[] { "https://contoso.com" }, Header = "Final Event", Price = 9.99, PriceQualifier = PriceQualifier.From, PriceUnit = PriceUnit.PerDay, }, }, }, new ReviewAdExtension { IsExact = true, Source = "Review Source Name", Text = "Review Text", // The Url of the third-party review. This is not your business Url. Url = "http://review.contoso.com" }, new SitelinkAdExtension { Description1 = "Simple & Transparent.", Description2 = "No Upfront Cost.", DisplayText = "Women's Shoe Sale", FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, }, new StructuredSnippetAdExtension { Header = "Brands", Values = new [] { "Windows", "Xbox", "Skype" } } }; OutputStatusMessage("-----\nAddAdExtensions:"); var addAdExtensionsResponse = await CampaignManagementExampleHelper.AddAdExtensionsAsync( accountId : authorizationData.AccountId, adExtensions : adExtensions); OutputStatusMessage("AdExtensionIdentities:"); var adExtensionIdentities = addAdExtensionsResponse?.AdExtensionIdentities; OutputStatusMessage("NestedPartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(addAdExtensionsResponse?.NestedPartialErrors); // DeleteAdExtensionsAssociations, SetAdExtensionsAssociations, and GetAdExtensionsEditorialReasons // operations each require a list of type AdExtensionIdToEntityIdAssociation. var adExtensionIdToEntityIdAssociations = new List <AdExtensionIdToEntityIdAssociation>(); // GetAdExtensionsByIds requires a list of type long. var adExtensionIds = new List <long>(); // Loop through the list of extension IDs and build any required data structures // for subsequent operations. foreach (var adExtensionIdentity in adExtensionIdentities) { if (adExtensionIdentity != null) { adExtensionIdToEntityIdAssociations.Add(new AdExtensionIdToEntityIdAssociation { AdExtensionId = adExtensionIdentity.Id, EntityId = (long)campaignIds[0] }); adExtensionIds.Add(adExtensionIdentity.Id); } } // Associate the ad extensions with the campaign. OutputStatusMessage("-----\nSetAdExtensionsAssociations:"); var setAdExtensionsAssociationsResponse = await CampaignManagementExampleHelper.SetAdExtensionsAssociationsAsync( accountId : authorizationData.AccountId, adExtensionIdToEntityIdAssociations : adExtensionIdToEntityIdAssociations, associationType : AssociationType.Campaign); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(setAdExtensionsAssociationsResponse?.PartialErrors); // Get editorial rejection reasons for the ad extension and entity associations. OutputStatusMessage("-----\nGetAdExtensionsEditorialReasons:"); var getAdExtensionsEditorialReasonsResponse = await CampaignManagementExampleHelper.GetAdExtensionsEditorialReasonsAsync( accountId : authorizationData.AccountId, adExtensionIdToEntityIdAssociations : adExtensionIdToEntityIdAssociations, associationType : AssociationType.Campaign); OutputStatusMessage("EditorialReasons:"); var adExtensionEditorialReasonCollection = (AdExtensionEditorialReasonCollection[])getAdExtensionsEditorialReasonsResponse?.EditorialReasons; CampaignManagementExampleHelper.OutputArrayOfAdExtensionEditorialReasonCollection(adExtensionEditorialReasonCollection); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(getAdExtensionsEditorialReasonsResponse?.PartialErrors); // Get only the location ad extensions and then remove scheduling. AdExtensionsTypeFilter adExtensionsTypeFilter = AdExtensionsTypeFilter.LocationAdExtension; // In this example partial errors will be returned for indices where the ad extensions // are not location ad extensions. // This is an example, and ideally you would only send the required ad extension IDs. OutputStatusMessage("-----\nGetAdExtensionsByIds:"); var getAdExtensionsByIdsResponse = (await CampaignManagementExampleHelper.GetAdExtensionsByIdsAsync( accountId: authorizationData.AccountId, adExtensionIds: adExtensionIds, adExtensionType: adExtensionsTypeFilter)); adExtensions = getAdExtensionsByIdsResponse?.AdExtensions.ToArray(); BatchError[] getAdExtensionErrors = getAdExtensionsByIdsResponse?.PartialErrors.ToArray(); OutputStatusMessage("AdExtensions:"); CampaignManagementExampleHelper.OutputArrayOfAdExtension(adExtensions); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(getAdExtensionErrors); var updateExtensions = new List <AdExtension>(); var updateExtensionIds = new List <long>(); foreach (var extension in adExtensions) { // GetAdExtensionsByIds will return a nil element if the request conditions were not met. if (extension != null && extension.Id != null) { // Remove read-only elements that would otherwise cause the update operation to fail. var updateExtension = SetReadOnlyAdExtensionElementsToNull(extension); // If you set the Scheduling element null, any existing scheduling set for the ad extension will remain unchanged. // If you set this to any non-null Schedule object, you are effectively replacing existing scheduling // for the ad extension. In this example, we will remove any existing scheduling by setting this element // to an empty Schedule object. updateExtension.Scheduling = new Schedule { }; updateExtensions.Add(updateExtension); updateExtensionIds.Add((long)updateExtension.Id); } } OutputStatusMessage("-----\nUpdateAdExtensions:"); await CampaignManagementExampleHelper.UpdateAdExtensionsAsync( accountId : authorizationData.AccountId, adExtensions : updateExtensions); OutputStatusMessage("Removed scheduling from the location ad extensions."); // Get only the location extensions to output the result. OutputStatusMessage("-----\nGetAdExtensionsByIds:"); getAdExtensionsByIdsResponse = await CampaignManagementExampleHelper.GetAdExtensionsByIdsAsync( accountId : authorizationData.AccountId, adExtensionIds : updateExtensionIds, adExtensionType : adExtensionsTypeFilter); adExtensions = getAdExtensionsByIdsResponse?.AdExtensions.ToArray(); getAdExtensionErrors = getAdExtensionsByIdsResponse?.PartialErrors.ToArray(); OutputStatusMessage("AdExtensions:"); CampaignManagementExampleHelper.OutputArrayOfAdExtension(adExtensions); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(getAdExtensionErrors); // Delete the ad extension associations, ad extensions, and campaign, that were previously added. // At this point the ad extensions are still available in the account's ad extensions library. OutputStatusMessage("-----\nDeleteAdExtensionsAssociations:"); await CampaignManagementExampleHelper.DeleteAdExtensionsAssociationsAsync( authorizationData.AccountId, adExtensionIdToEntityIdAssociations, AssociationType.Campaign); OutputStatusMessage("Deleted ad extension associations."); // Delete the ad extensions from the account's ad extension library. OutputStatusMessage("-----\nDeleteAdExtensions:"); await CampaignManagementExampleHelper.DeleteAdExtensionsAsync( authorizationData.AccountId, adExtensionIds); OutputStatusMessage("Deleted ad extensions."); // Delete the account's media that was used for the image ad extension. OutputStatusMessage("-----\nDeleteMedia:"); await CampaignManagementExampleHelper.DeleteMediaAsync( accountId : authorizationData.AccountId, mediaIds : mediaIds); foreach (var id in mediaIds) { OutputStatusMessage(string.Format("Deleted Media Id {0}", id)); } // Delete the campaign and everything it contains e.g., ad groups and ads. OutputStatusMessage("-----\nDeleteCampaigns:"); await CampaignManagementExampleHelper.DeleteCampaignsAsync( accountId : authorizationData.AccountId, campaignIds : new[] { (long)campaignIds[0] }); OutputStatusMessage(string.Format("Deleted Campaign Id {0}", campaignIds[0])); } // Catch authentication exceptions catch (OAuthTokenRequestException ex) { OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description)); } // Catch Campaign Management service exceptions catch (FaultException <Microsoft.BingAds.V12.CampaignManagement.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <Microsoft.BingAds.V12.CampaignManagement.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 (FaultException <Microsoft.BingAds.V12.CampaignManagement.EditorialApiFaultDetail> 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 Customer Management service exceptions catch (FaultException <Microsoft.BingAds.V12.CustomerManagement.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <Microsoft.BingAds.V12.CustomerManagement.ApiFault> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (Exception ex) { OutputStatusMessage(ex.Message); } }
public async override Task RunAsync(AuthorizationData authorizationData) { try { ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment; // Media cannot be added via the Bulk service, so we'll use the Campaign Management service // i.e., the AddMedia service operation below. CampaignManagementExampleHelper = new CampaignManagementExampleHelper( OutputStatusMessageDefault: this.OutputStatusMessage); CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>( authorizationData: authorizationData, environment: environment); BulkServiceManager = new BulkServiceManager( authorizationData: authorizationData, apiEnvironment: environment); var progress = new Progress <BulkOperationProgressInfo>(x => OutputStatusMessage(string.Format("{0} % Complete", x.PercentComplete.ToString(CultureInfo.InvariantCulture)))); // Add an image to your media library. // The image asset is needed later to create the responsive ad. var landscapeImageMedia = GetImageMedia( "Image191x100", MediaFilePath + ResponsiveAdMediaFileName, System.Drawing.Imaging.ImageFormat.Png); var media = new Media[] { landscapeImageMedia, }; OutputStatusMessage("-----\nAddMedia:"); AddMediaResponse addMediaResponse = await CampaignManagementExampleHelper.AddMediaAsync( accountId : authorizationData.AccountId, media : media); long[] mediaIds = addMediaResponse.MediaIds.ToArray(); OutputStatusMessage("MediaIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(mediaIds); var uploadEntities = new List <BulkEntity>(); // Create an Audience campaign with one ad group and a responsive ad. var bulkCampaign = new BulkCampaign { Campaign = new Campaign { Id = campaignIdKey, // CampaignType must be set for Audience campaigns CampaignType = CampaignType.Audience, // Languages must be set for Audience campaigns Languages = new string[] { "All" }, Name = "Women's Shoes " + DateTime.UtcNow, DailyBudget = 50, BudgetType = BudgetLimitType.DailyBudgetStandard, Settings = null, TimeZone = "PacificTimeUSCanadaTijuana", } }; uploadEntities.Add(bulkCampaign); // Specify one or more ad groups. var bulkAdGroup = new BulkAdGroup { CampaignId = campaignIdKey, AdGroup = new AdGroup { Id = adGroupIdKey, Name = "Women's Red Shoe Sale", StartDate = null, EndDate = new Microsoft.BingAds.V13.CampaignManagement.Date { Month = 12, Day = 31, Year = DateTime.UtcNow.Year + 1 }, CpcBid = new Bid { Amount = 0.09 }, // Language cannot be set for ad groups in Audience campaigns Language = null, // Network cannot be set for ad groups in Audience campaigns Network = null, }, }; uploadEntities.Add(bulkAdGroup); var bulkResponsiveAd = new BulkResponsiveAd { AdGroupId = adGroupIdKey, ResponsiveAd = new ResponsiveAd { Id = responsiveAdIdKey, BusinessName = "Contoso", CallToAction = CallToAction.AddToCart, FinalUrls = new[] { "https://www.contoso.com/womenshoesale" }, ForwardCompatibilityMap = null, Headline = "Fast & Easy Setup", Images = new[] { // You are only required to provide a landscape image asset. // Optionally you can include additional asset links, i.e., one image asset for each supported sub type. // For any image asset sub types that you do not explicitly set, // the service will automatically create image asset links by cropping the LandscapeImageMedia. new AssetLink { Asset = new ImageAsset { CropHeight = null, CropWidth = null, CropX = null, CropY = null, Id = mediaIds[0], Name = "My LandscapeImageMedia", SubType = "LandscapeImageMedia", Type = null }, }, }, LongHeadlineString = "Find New Customers & Increase Sales!", Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.", }, }; uploadEntities.Add(bulkResponsiveAd); // Upload and write the output OutputStatusMessage("-----\nAdding campaign, ad group, and ad..."); var Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities); var downloadEntities = Reader.ReadEntities().ToList(); OutputStatusMessage("Upload results:"); var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList(); OutputBulkCampaigns(campaignResults); var adGroupResults = downloadEntities.OfType <BulkAdGroup>().ToList(); OutputBulkAdGroups(adGroupResults); var responsiveAdResults = downloadEntities.OfType <BulkResponsiveAd>().ToList(); OutputBulkResponsiveAds(responsiveAdResults); Reader.Dispose(); // Delete the campaign and everything it contains e.g., ad groups and ads. uploadEntities = new List <BulkEntity>(); foreach (var campaignResult in campaignResults) { campaignResult.Campaign.Status = CampaignStatus.Deleted; uploadEntities.Add(campaignResult); } OutputStatusMessage("-----\nDeleting campaign, ad group, and ad..."); Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities); downloadEntities = Reader.ReadEntities().ToList(); OutputStatusMessage("Upload results:"); campaignResults = downloadEntities.OfType <BulkCampaign>().ToList(); OutputBulkCampaigns(campaignResults); Reader.Dispose(); } // 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.V13.Bulk.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <Microsoft.BingAds.V13.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 { ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment; CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper( OutputStatusMessageDefault: this.OutputStatusMessage); CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>( authorizationData: authorizationData, environment: environment); var responsiveAdImageMedia = GetImageMedia( "Image191x100", MediaFilePath + ResponsiveAdMediaFileName, System.Drawing.Imaging.ImageFormat.Png); var imageAdExtensionMedia = GetImageMedia( "Image15x10", MediaFilePath + ImageAdExtensionMediaFileName, System.Drawing.Imaging.ImageFormat.Png); var addMedia = new Media[] { responsiveAdImageMedia, imageAdExtensionMedia }; OutputStatusMessage("Ready to upload image media:"); CampaignManagementExampleHelper.OutputArrayOfMedia(addMedia); OutputStatusMessage("-----\nAddMedia:"); AddMediaResponse addMediaResponse = await CampaignManagementExampleHelper.AddMediaAsync( accountId : authorizationData.AccountId, media : addMedia); long[] mediaIds = addMediaResponse.MediaIds.ToArray(); OutputStatusMessage("MediaIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(mediaIds); // Get the media representations to confirm the stored dimensions // and get the Url where you can later view or download the media. OutputStatusMessage("-----\nGetMediaMetaDataByAccountId:"); var getResponsiveAdMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByAccountIdAsync( mediaEnabledEntities: MediaEnabledEntityFilter.ResponsiveAd, pageInfo: null)).MediaMetaData; OutputStatusMessage("MediaMetaData:"); CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getResponsiveAdMediaMetaData); OutputStatusMessage("-----\nGetMediaMetaDataByAccountId:"); var getImageAdExtensionMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByAccountIdAsync( mediaEnabledEntities: MediaEnabledEntityFilter.ImageAdExtension, pageInfo: null)).MediaMetaData; OutputStatusMessage("MediaMetaData:"); CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getImageAdExtensionMediaMetaData); OutputStatusMessage("-----\nGetMediaMetaDataByIds:"); var getMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByIdsAsync( mediaIds: mediaIds)).MediaMetaData; OutputStatusMessage("MediaMetaData:"); CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getMediaMetaData); // Delete the account's media. OutputStatusMessage("-----\nDeleteMedia:"); await CampaignManagementExampleHelper.DeleteMediaAsync( accountId : authorizationData.AccountId, mediaIds : mediaIds); foreach (var id in mediaIds) { OutputStatusMessage(string.Format("Deleted Media Id {0}", id)); } } // Catch authentication exceptions catch (OAuthTokenRequestException ex) { OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description)); } // Catch Campaign Management service exceptions catch (FaultException <AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <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 (FaultException <EditorialApiFaultDetail> 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 (Exception ex) { OutputStatusMessage(ex.Message); } }