public async override Task RunAsync(AuthorizationData authorizationData) { try { CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage); CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>(authorizationData); // Before you can track conversions or target audiences using a remarketing list, // you need to create a UET tag in Bing Ads (web application or API) and then // add the UET tag tracking code to every page of your website. For more information, please see // Universal Event Tracking at https://docs.microsoft.com/en-us/bingads/guides/universal-event-tracking. // First you should call the GetUetTagsByIds operation to check whether a tag has already been created. // You can leave the TagIds element null or empty to request all UET tags available for the customer. var uetTags = (await CampaignManagementExampleHelper.GetUetTagsByIdsAsync(null))?.UetTags; // If you do not already have a UET tag that can be used, or if you need another UET tag, // call the AddUetTags service operation to create a new UET tag. If the call is successful, // the tracking script that you should add to your website is included in a corresponding // UetTag within the response message. if (uetTags == null || uetTags.Count < 1) { var uetTag = new UetTag { Description = "My First Uet Tag", Name = "New Uet Tag", }; uetTags = (await CampaignManagementExampleHelper.AddUetTagsAsync(new[] { uetTag })).UetTags; } if (uetTags == null || uetTags.Count < 1) { OutputStatusMessage( string.Format("You do not have any UET tags registered for CustomerId {0}.\n", authorizationData.CustomerId) ); return; } OutputStatusMessage("List of all UET Tags:\n"); foreach (var uetTag in uetTags) { CampaignManagementExampleHelper.OutputUetTag(uetTag); } // After you retreive the tracking script from the AddUetTags or GetUetTagsByIds operation, // the next step is to add the UET tag tracking code to your website. We recommend that you, // or your website administrator, add it to your entire website in either the head or body sections. // If your website has a master page, then that is the best place to add it because you add it once // and it is included on all pages. For more information, please see // Universal Event Tracking at https://docs.microsoft.com/en-us/bingads/guides/universal-event-tracking. // We will use the same UET tag for the remainder of this example. var tagId = uetTags[0].Id; // Add a remarketing list that depend on the UET Tag Id retreived above. var addAudiences = new[] { new RemarketingList { Description = "New list with CustomEventsRule", MembershipDuration = 30, Name = "Remarketing List with CustomEventsRule " + DateTime.UtcNow, ParentId = authorizationData.AccountId, Rule = new CustomEventsRule { // The type of user interaction you want to track. Action = "play", ActionOperator = StringOperator.Contains, // The category of event you want to track. Category = "video", CategoryOperator = StringOperator.Contains, // The name of the element that caused the action. Label = "trailer", LabelOperator = StringOperator.Contains, // A numerical value associated with that event. // Could be length of the video played etc. Value = 5.00m, ValueOperator = NumberOperator.Equals, }, Scope = EntityScope.Account, TagId = tagId }, new RemarketingList { Description = "New list with PageVisitorsRule", MembershipDuration = 30, Name = "Remarketing List with PageVisitorsRule " + DateTime.UtcNow, ParentId = authorizationData.AccountId, // The rule definition is translated to the following logical expression: // ((Url Contains X) and (ReferrerUrl DoesNotContain Z)) or ((Url DoesNotBeginWith Y)) // or ((ReferrerUrl Equals Z)) Rule = new PageVisitorsRule { RuleItemGroups = new [] { new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.Contains, Value = "X" }, new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.DoesNotContain, Value = "Z" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.DoesNotBeginWith, Value = "Y" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.Equals, Value = "Z" }, } }, }, }, Scope = EntityScope.Account, TagId = tagId }, new RemarketingList { Description = "New list with PageVisitorsWhoDidNotVisitAnotherPageRule", MembershipDuration = 30, Name = "Remarketing List with PageVisitorsWhoDidNotVisitAnotherPageRule " + DateTime.UtcNow, ParentId = authorizationData.AccountId, // The rule definition is translated to the following logical expression: // (((Url Contains X) and (ReferrerUrl DoesNotContain Z)) or ((Url DoesNotBeginWith Y)) // or ((ReferrerUrl Equals Z))) // and not (((Url BeginsWith A) and (ReferrerUrl BeginsWith B)) or ((Url Contains C))) Rule = new PageVisitorsWhoDidNotVisitAnotherPageRule { ExcludeRuleItemGroups = new [] { new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.BeginsWith, Value = "A" }, new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.BeginsWith, Value = "B" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.Contains, Value = "C" }, } }, }, IncludeRuleItemGroups = new [] { new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.Contains, Value = "X" }, new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.DoesNotContain, Value = "Z" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.DoesNotBeginWith, Value = "Y" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.Equals, Value = "Z" }, } }, }, }, Scope = EntityScope.Account, TagId = tagId }, new RemarketingList { Description = "New list with PageVisitorsWhoVisitedAnotherPageRule", MembershipDuration = 30, Name = "Remarketing List with PageVisitorsWhoVisitedAnotherPageRule " + DateTime.UtcNow, ParentId = authorizationData.AccountId, // The rule definition is translated to the following logical expression: // (((Url Contains X) and (ReferrerUrl NotEquals Z)) or ((Url DoesNotBeginWith Y)) or // ((ReferrerUrl Equals Z))) // and (((Url BeginsWith A) and (ReferrerUrl BeginsWith B)) or ((Url Contains C))) Rule = new PageVisitorsWhoVisitedAnotherPageRule { AnotherRuleItemGroups = new [] { new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.BeginsWith, Value = "A" }, new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.BeginsWith, Value = "B" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.Contains, Value = "C" }, } }, }, RuleItemGroups = new [] { new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.Contains, Value = "X" }, new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.DoesNotContain, Value = "Z" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.DoesNotBeginWith, Value = "Y" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.Equals, Value = "Z" }, } }, }, }, Scope = EntityScope.Account, TagId = tagId }, }; // RemarketingList extends the Audience base class. // We manage remarketing lists with Audience operations. var addAudiencesResponse = await CampaignManagementExampleHelper.AddAudiencesAsync(addAudiences); var audienceIds = addAudiencesResponse.AudienceIds; // You must already have at least one remarketing list for the remainder of this example. if (audienceIds.Count < 1) { return; } var updateAudiences = new[] { new RemarketingList { Id = audienceIds[0], // The ParentId cannot be updated, even if you update the rule type. // You can either send the same value or leave ParentId empty. ParentId = authorizationData.AccountId, Rule = new CustomEventsRule { // For both add and update remarketing list operations, you must include one or more // of the following events: // Action, Category, Label, or Value. // For example if you do not include Action during update, // any existing ActionOperator and Action settings will be deleted. Action = null, //ActionOperator = null, Category = "video", CategoryOperator = StringOperator.Equals, // You cannot update the operator unless you also include the expression. // The following attempt to update LabelOperator will result in an error. Label = null, LabelOperator = StringOperator.Equals, // You must specify the previous settings unless you want // them replaced during the update conversion goal operation. Value = 5.00m, ValueOperator = NumberOperator.Equals, }, // The Scope cannot be updated, even if you update the rule type. // You can either send the same value or leave Scope empty. Scope = EntityScope.Account, // You can update the tag as needed. In this example we will explicitly use the same UET tag. // To keep the UET tag unchanged, you can also leave this element nil or empty. TagId = tagId, }, new RemarketingList { // You can change the remarketing rule type e.g. in this example a remarketing list // with the PageVisitorsRule had been created above at index 1. // Now we are using the returned identifier at index 1 to update the type from // PageVisitorsRule to PageVisitorsWhoDidNotVisitAnotherPageRule. Id = audienceIds[1], Rule = new PageVisitorsWhoDidNotVisitAnotherPageRule { // If you want to keep any of the previous rule items, // then you must explicitly set them again during update. ExcludeRuleItemGroups = new [] { new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.Contains, Value = "C" }, } }, }, // If you leave the entire list of rule item groups null, // then previous settings will be retained. IncludeRuleItemGroups = null, }, }, new RemarketingList { Id = audienceIds[2], Rule = new PageVisitorsRule { // If you want to keep any of the previous rule items, // then you must explicitly set them again during update. RuleItemGroups = new [] { new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.Contains, Value = "X" }, new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.DoesNotContain, Value = "Z" }, } }, }, }, }, new RemarketingList { Id = audienceIds[3], MembershipDuration = 20, // If not specified during update, the previous rule settings are retained. Rule = null, }, }; var updateAudiencesResponse = await CampaignManagementExampleHelper.UpdateAudiencesAsync(updateAudiences); OutputStatusMessage("Updated audiences. List of errors (if applicable):\n"); CampaignManagementExampleHelper.OutputArrayOfBatchError(updateAudiencesResponse.PartialErrors); // Add an ad group in a campaign. The ad group will later be associated with remarketing lists. var campaigns = new[] { new Campaign { Name = "Women's Shoes " + DateTime.UtcNow, Description = "Red shoes line.", // You must choose to set either the shared budget ID or daily amount. // You can set one or the other, but you may not set both. BudgetId = null, DailyBudget = 50, BudgetType = BudgetLimitType.DailyBudgetStandard, BiddingScheme = new EnhancedCpcBiddingScheme(), TimeZone = "PacificTimeUSCanadaTijuana", }, }; var adGroups = new[] { new AdGroup { Name = "Women's Red Shoe Sale", AdDistribution = AdDistribution.Search, PricingModel = PricingModel.Cpc, StartDate = null, EndDate = new Date { Month = 12, Day = 31, Year = DateTime.UtcNow.Year + 1 }, SearchBid = new Bid { Amount = 0.09 }, Language = "English", TrackingUrlTemplate = null, // Applicable for all remarketing lists that are associated with this ad group. TargetAndBid indicates // that you want to show ads only to people included in the remarketing list, with the option to change // the bid amount. Ads in this ad group will only show to people included in the remarketing list. RemarketingTargetingSetting = RemarketingTargetingSetting.TargetAndBid } }; AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync(authorizationData.AccountId, campaigns); long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray(); BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); CampaignManagementExampleHelper.OutputArrayOfLong(campaignIds); CampaignManagementExampleHelper.OutputArrayOfBatchError(campaignErrors); AddAdGroupsResponse addAdGroupsResponse = await CampaignManagementExampleHelper.AddAdGroupsAsync((long)campaignIds[0], adGroups); long?[] adGroupIds = addAdGroupsResponse.AdGroupIds.ToArray(); BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray(); CampaignManagementExampleHelper.OutputArrayOfLong(adGroupIds); CampaignManagementExampleHelper.OutputArrayOfBatchError(adGroupErrors); // If the campaign or ad group add operations failed then we cannot continue this example. if (adGroupIds == null || adGroupIds.Length < 1) { return; } var adGroupRemarketingListAssociations = new List <AdGroupCriterion>(); // This example associates all of the remarketing lists with the new ad group. var getAudienceIds = new List <long>(); foreach (var listId in audienceIds) { getAudienceIds.Add((long)listId); } var remarketingLists = (await CampaignManagementExampleHelper.GetAudiencesByIdsAsync( getAudienceIds, AudienceType.RemarketingList, AudienceAdditionalField.AudienceNetworkSize | AudienceAdditionalField.SearchSize, true)).Audiences; foreach (var remarketingList in remarketingLists) { if (remarketingList.Id != null) { var biddableAdGroupCriterion = new BiddableAdGroupCriterion { AdGroupId = (long)adGroupIds[0], Criterion = new AudienceCriterion { AudienceId = (long)remarketingList.Id, AudienceType = AudienceType.RemarketingList, }, CriterionBid = new BidMultiplier { Multiplier = 20.00, }, Status = AdGroupCriterionStatus.Active, }; adGroupRemarketingListAssociations.Add(biddableAdGroupCriterion); OutputStatusMessage(string.Format("Associating the following remarketing list with AdGroup Id {0}.\n", (long)adGroupIds[0])); CampaignManagementExampleHelper.OutputRemarketingList((RemarketingList)remarketingList); } } var addAdGroupCriterionsResponse = await CampaignManagementExampleHelper.AddAdGroupCriterionsAsync( adGroupRemarketingListAssociations, AdGroupCriterionType.Audience); var adGroupCriterionIds = new List <long>(); foreach (long id in addAdGroupCriterionsResponse.AdGroupCriterionIds) { adGroupCriterionIds.Add(id); } var getAdGroupCriterionsByIdsResponse = await CampaignManagementExampleHelper.GetAdGroupCriterionsByIdsAsync( adGroupCriterionIds, true, (long)adGroupIds[0], AdGroupCriterionType.RemarketingList); foreach (var adGroupRemarketingListAssociation in getAdGroupCriterionsByIdsResponse.AdGroupCriterions) { OutputStatusMessage("The following ad group remarketing list association was added.\n"); CampaignManagementExampleHelper.OutputArrayOfAdGroupCriterion(new AdGroupCriterion[] { adGroupRemarketingListAssociation }); } // You can store the association IDs which can be used to update or delete associations later. var nullableAdGroupCriterionIds = addAdGroupCriterionsResponse.AdGroupCriterionIds; // If the associations were added and retrieved successfully let's practice updating and deleting one of them. if (nullableAdGroupCriterionIds != null && nullableAdGroupCriterionIds.Count > 0) { var updateAdGroupRemarketingListAssociation = new BiddableAdGroupCriterion { AdGroupId = (long)adGroupIds[0], Criterion = new AudienceCriterion { AudienceType = AudienceType.RemarketingList, }, CriterionBid = new BidMultiplier { Multiplier = 10.00, }, Id = nullableAdGroupCriterionIds[0], Status = AdGroupCriterionStatus.Active, }; var updateAdGroupCriterionsResponse = await CampaignManagementExampleHelper.UpdateAdGroupCriterionsAsync( new BiddableAdGroupCriterion[] { updateAdGroupRemarketingListAssociation }, AdGroupCriterionType.Audience ); var deleteAdGroupCriterionsResponse = await CampaignManagementExampleHelper.DeleteAdGroupCriterionsAsync( adGroupCriterionIds, (long)adGroupIds[0], AdGroupCriterionType.Audience ); } // Delete the campaign, ad group, and ad group remarketing list associations that were previously added. var deleteCampaignsResponse = (await CampaignManagementExampleHelper.DeleteCampaignsAsync(authorizationData.AccountId, new[] { (long)campaignIds[0] })); OutputStatusMessage(string.Format("Deleted Campaign Id {0}\n", campaignIds[0])); // Delete the remarketing list. var deleteAudiencesResponse = (await CampaignManagementExampleHelper.DeleteAudiencesAsync(new[] { (long)audienceIds[0] })); OutputStatusMessage(string.Format("Deleted Audience Id {0}\n", audienceIds[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.V11.CampaignManagement.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <Microsoft.BingAds.V11.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.V11.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 { Service = new ServiceClient <ICampaignManagementService>(authorizationData); // Specify one or more campaigns. var campaigns = new[] { new Campaign { Name = "Women's Shoes" + DateTime.UtcNow, Description = "Red shoes line.", BudgetType = BudgetLimitType.MonthlyBudgetSpendUntilDepleted, MonthlyBudget = 1000.00, TimeZone = "PacificTimeUSCanadaTijuana", DaylightSaving = true, } }; // Specify one or more ad groups. var adGroups = new[] { new AdGroup { Name = "Women's Red Shoe Sale", AdDistribution = AdDistribution.Search, BiddingModel = BiddingModel.Keyword, PricingModel = PricingModel.Cpc, StartDate = null, EndDate = new Microsoft.BingAds.V10.CampaignManagement.Date { Month = 12, Day = 31, Year = DateTime.UtcNow.Year + 1 }, SearchBid = new Bid { Amount = 0.09 }, Language = "English", } }; // Add the campaign and ad group AddCampaignsResponse addCampaignsResponse = await AddCampaignsAsync(authorizationData.AccountId, campaigns); long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray(); BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); long campaignId = (long)campaignIds[0]; AddAdGroupsResponse addAdGroupsResponse = await AddAdGroupsAsync((long)campaignId, adGroups); long?[] adGroupIds = addAdGroupsResponse.AdGroupIds.ToArray(); BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray(); long adGroupId = (long)adGroupIds[0]; // Print the new assigned campaign and ad group identifiers OutputCampaignsWithPartialErrors(campaigns, campaignIds, campaignErrors); OutputAdGroupsWithPartialErrors(adGroups, adGroupIds, adGroupErrors); // Create targets to associate with the campaign and ad group. var campaignTarget = new Target { Name = "My Campaign Target", DeviceOS = new DeviceOSTarget { Bids = new[] { new DeviceOSTargetBid { BidAdjustment = 10, DeviceName = "Tablets", OSNames = new string[] { "Windows" } }, new DeviceOSTargetBid { BidAdjustment = 10, DeviceName = "Smartphones", OSNames = new string[] { "Windows" } }, }, }, DayTime = new DayTimeTarget { Bids = new[] { new DayTimeTargetBid { BidAdjustment = 10, Day = Day.Monday, FromHour = 1, ToHour = 12, FromMinute = Minute.Zero, ToMinute = Minute.FortyFive } } }, Location = new LocationTarget { IntentOption = IntentOption.PeopleIn, MetroAreaTarget = new MetroAreaTarget { Bids = new List <MetroAreaTargetBid> { new MetroAreaTargetBid { BidAdjustment = 15, MetroArea = "Seattle-Tacoma, WA, WA US", IsExcluded = false } } }, RadiusTarget = new RadiusTarget { Bids = new[] { new RadiusTargetBid { BidAdjustment = 50, LatitudeDegrees = 47.755367, LongitudeDegrees = -122.091827, Radius = 5, RadiusUnit = DistanceUnit.Miles } } } } }; var adGroupTarget = new Target { Name = "My Ad Group Target", DayTime = new DayTimeTarget { Bids = new[] { new DayTimeTargetBid { BidAdjustment = 10, Day = Day.Friday, FromHour = 1, ToHour = 12, FromMinute = Minute.Zero, ToMinute = Minute.FortyFive } } }, }; // Each customer has a target library that can be used to set up targeting for any campaign // or ad group within the specified customer. // Add a target to the library and associate it with the campaign. var campaignTargetId = (await AddTargetsToLibraryAsync(new[] { campaignTarget }))[0]; OutputStatusMessage(String.Format("Added Target Id: {0}\n", campaignTargetId)); await SetTargetToCampaignAsync(campaignId, campaignTargetId); OutputStatusMessage(String.Format("Associated CampaignId {0} with TargetId {1}.\n", campaignId, campaignTargetId)); // Add a target to the library and associate it with the ad group. var adGroupTargetId = (await AddTargetsToLibraryAsync(new[] { adGroupTarget }))[0]; OutputStatusMessage(String.Format("Added Target Id: {0}\n", adGroupTargetId)); await SetTargetToAdGroupAsync(adGroupId, adGroupTargetId); OutputStatusMessage(String.Format("Associated AdGroupId {0} with TargetId {1}.\n", adGroupId, adGroupTargetId)); // Get and print the targets with the GetTargetsByIds operation OutputStatusMessage("Get Campaign and AdGroup targets: \n"); var targets = await GetTargetsByIdsAsync(new[] { campaignTargetId, adGroupTargetId }); foreach (var target in targets) { OutputTarget(target); } // Update the ad group's Target object with additional target types. // Existing target types such as DayTime must be specified // or they will not be included in the updated target. var updateAdGroupTarget = new Target { Id = adGroupTargetId, Name = "My Target", Age = new AgeTarget { Bids = new[] { new AgeTargetBid { BidAdjustment = 10, Age = AgeRange.EighteenToTwentyFive } } }, DayTime = new DayTimeTarget { Bids = new[] { new DayTimeTargetBid { BidAdjustment = 10, Day = Day.Friday, FromHour = 1, ToHour = 12, FromMinute = Minute.Zero, ToMinute = Minute.FortyFive } } }, DeviceOS = new DeviceOSTarget { Bids = new[] { new DeviceOSTargetBid { BidAdjustment = 20, DeviceName = "Tablets", }, }, }, Gender = new GenderTarget { Bids = new[] { new GenderTargetBid { BidAdjustment = 10, Gender = GenderType.Female } } }, Location = new LocationTarget { IntentOption = IntentOption.PeopleSearchingForOrViewingPages, CountryTarget = new CountryTarget { Bids = new[] { new CountryTargetBid { BidAdjustment = 10, CountryAndRegion = "US", IsExcluded = false } } }, MetroAreaTarget = new MetroAreaTarget { Bids = new List <MetroAreaTargetBid> { new MetroAreaTargetBid { BidAdjustment = 15, MetroArea = "Seattle-Tacoma, WA, WA US", IsExcluded = false } } }, PostalCodeTarget = new PostalCodeTarget { Bids = new[] { 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 = true } } }, RadiusTarget = new RadiusTarget { Bids = new[] { new RadiusTargetBid { BidAdjustment = 51, LatitudeDegrees = 47.755367, LongitudeDegrees = -122.091827, Radius = 11, RadiusUnit = DistanceUnit.Miles } } } } }; // Update the Target object associated with the ad group. await UpdateTargetsInLibraryAsync(new[] { updateAdGroupTarget }); OutputStatusMessage("Updated the ad group level target as a Target object.\n"); // Get and print the targets with the GetTargetsByIds operation OutputStatusMessage("Get Campaign and AdGroup targets: \n"); targets = await GetTargetsByIdsAsync(new[] { campaignTargetId, adGroupTargetId }); foreach (var target in targets) { OutputTarget(target); } // Get all new and existing targets in the customer library, whether or not they are // associated with campaigns or ad groups. var allTargetsInfo = await GetTargetsInfoFromLibraryAsync(); OutputStatusMessage("All target identifiers and names from the customer library: \n"); PrintTargetsInfo(allTargetsInfo); // Delete the campaign, ad group, and targets that were previously added. // DeleteCampaigns would remove the campaign and ad group, as well as the association // between ad groups and campaigns. To explicitly delete the association between an entity // and the target, use DeleteTargetFromCampaign and DeleteTargetFromAdGroup respectively. await DeleteTargetFromCampaignAsync(campaignId); await DeleteTargetFromAdGroupAsync(adGroupId); await DeleteCampaignsAsync(authorizationData.AccountId, new[] { campaignId }); OutputStatusMessage(String.Format("Deleted CampaignId {0}\n", campaignId)); // DeleteCampaigns deletes the association between the campaign and target, but does not // delete the target from the customer library. // Call the DeleteTargetsFromLibrary operation for each target that you want to delete. // You must specify an array with exactly one item. await DeleteTargetsFromLibraryAsync(new[] { campaignTargetId }); OutputStatusMessage(String.Format("Deleted TargetId {0}\n", campaignTargetId)); await DeleteTargetsFromLibraryAsync(new[] { adGroupTargetId }); OutputStatusMessage(String.Format("Deleted TargetId {0}\n", adGroupTargetId)); } // 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.V10.CampaignManagement.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <Microsoft.BingAds.V10.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.V10.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); // Get a list of all Bing Merchant Center stores associated with your CustomerId. OutputStatusMessage("-----\nGetBMCStoresByCustomerId:"); IList <BMCStore> stores = (await CampaignManagementExampleHelper.GetBMCStoresByCustomerIdAsync())?.BMCStores; if (stores == null || stores.Count <= 0) { OutputStatusMessage( string.Format("You do not have any BMC stores registered for CustomerId {0}.", authorizationData.CustomerId) ); return; } OutputStatusMessage("BMCStores:"); CampaignManagementExampleHelper.OutputArrayOfBMCStore(stores); // Create a Shopping campaign with product conditions. var campaigns = new[] { new Campaign { CampaignType = CampaignType.Shopping, Languages = new string[] { "All" }, Name = "Women's Shoes " + DateTime.UtcNow, Description = "Red shoes line.", DailyBudget = 50, BudgetType = BudgetLimitType.DailyBudgetStandard, Settings = new[] { new ShoppingSetting() { Priority = 0, SalesCountryCode = "US", StoreId = (int)stores[0].Id } }, 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); long campaignId = (long)campaignIds[0]; // Optionally, you can create a ProductScope criterion that will be associated with your Bing Shopping campaign. // You'll also be able to add more specific product conditions for each ad group. var campaignCriterions = new BiddableCampaignCriterion[] { new BiddableCampaignCriterion() { CampaignId = campaignId, CriterionBid = null, // Not applicable for product scope Criterion = new ProductScope() { Conditions = new ProductCondition[] { new ProductCondition { Operand = "Condition", Attribute = "New" }, new ProductCondition { Operand = "CustomLabel0", Attribute = "MerchantDefinedCustomLabel" }, } }, Status = CampaignCriterionStatus.Active } }; OutputStatusMessage("-----\nAddCampaignCriterions:"); var addCampaignCriterionsResponse = await CampaignManagementExampleHelper.AddCampaignCriterionsAsync( campaignCriterions : campaignCriterions, criterionType : CampaignCriterionType.ProductScope); long?[] campaignCriterionIds = addCampaignCriterionsResponse.CampaignCriterionIds.ToArray(); OutputStatusMessage("CampaignCriterionIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(campaignCriterionIds); BatchErrorCollection[] campaignCriterionErrors = addCampaignCriterionsResponse.NestedPartialErrors.ToArray(); OutputStatusMessage("NestedPartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(campaignCriterionErrors); // Create the ad group that will have the product partitions. 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 }, } }; 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); long adGroupId = (long)adGroupIds[0]; // Bid all products var helper = new PartitionActionHelper(adGroupId); var root = helper.AddUnit( parent: null, condition: new ProductCondition { Operand = "All", Attribute = null }, bidAmount: 0.35, isNegative: false); OutputStatusMessage("-----\nApplyProductPartitionActions:"); OutputStatusMessage("Applying only the root as a Unit with a bid..."); var applyProductPartitionActionsResponse = await CampaignManagementExampleHelper.ApplyProductPartitionActionsAsync( criterionActions : helper.PartitionActions); OutputStatusMessage("-----\nGetAdGroupCriterionsByIds:"); var adGroupCriterions = await CampaignManagementExampleHelper.GetAdGroupCriterionsByIdsAsync( adGroupCriterionIds : null, adGroupId : adGroupId, criterionType : AdGroupCriterionType.ProductPartition, returnAdditionalFields : AdGroupCriterionAdditionalField.FinalUrlSuffix); OutputStatusMessage("The ad group's product partition only has a tree root node: \n"); OutputProductPartitions(adGroupCriterions?.AdGroupCriterions); // Let's update the bid of the root Unit we just added. BiddableAdGroupCriterion updatedRoot = new BiddableAdGroupCriterion { Id = applyProductPartitionActionsResponse.AdGroupCriterionIds[0], CriterionBid = new FixedBid { Amount = 0.45 } }; helper = new PartitionActionHelper(adGroupId); helper.UpdatePartition(updatedRoot); OutputStatusMessage("-----\nApplyProductPartitionActions:"); OutputStatusMessage("Updating the bid for the tree root node..."); await CampaignManagementExampleHelper.ApplyProductPartitionActionsAsync( criterionActions : helper.PartitionActions); OutputStatusMessage("-----\nGetAdGroupCriterionsByIds:"); adGroupCriterions = await CampaignManagementExampleHelper.GetAdGroupCriterionsByIdsAsync( adGroupCriterionIds : null, adGroupId : adGroupId, criterionType : AdGroupCriterionType.ProductPartition, returnAdditionalFields : AdGroupCriterionAdditionalField.FinalUrlSuffix); OutputStatusMessage("Updated the bid for the tree root node: \n"); OutputProductPartitions(adGroupCriterions?.AdGroupCriterions); // Initialize and 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 5,000 nodes; however, // we will build it in steps to demonstrate how to use the results from ApplyProductPartitionActions to update the tree. helper = new PartitionActionHelper(adGroupId); // Check whether a root node exists already. OutputStatusMessage("-----\nGetAdGroupCriterionsByIds:"); adGroupCriterions = await CampaignManagementExampleHelper.GetAdGroupCriterionsByIdsAsync( adGroupCriterionIds : null, adGroupId : adGroupId, criterionType : AdGroupCriterionType.ProductPartition, returnAdditionalFields : AdGroupCriterionAdditionalField.FinalUrlSuffix); var existingRoot = GetRootNode(adGroupCriterions?.AdGroupCriterions); if (existingRoot != null) { helper.DeletePartition(existingRoot); } root = helper.AddSubdivision( null, new ProductCondition { Operand = "All", Attribute = null } ); // 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://go.microsoft.com/fwlink?LinkId=507666 var animalsSubdivision = helper.AddSubdivision( parent: root, condition: new ProductCondition { Operand = "CategoryL1", Attribute = "Animals & Pet Supplies" }); // 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( parent: animalsSubdivision, condition: new ProductCondition { Operand = "CategoryL2", Attribute = "Pet Supplies" }); var brandA = helper.AddUnit( parent: petSuppliesSubdivision, condition: new ProductCondition { Operand = "Brand", Attribute = "Brand A" }, bidAmount: 0.35, isNegative: false); // 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( parent: petSuppliesSubdivision, condition: new ProductCondition { Operand = "Brand", Attribute = "Brand B" }, bidAmount: 0, isNegative: true); var otherBrands = helper.AddUnit( parent: petSuppliesSubdivision, condition: new ProductCondition { Operand = "Brand", Attribute = null }, bidAmount: 0.35, isNegative: false); var otherPetSupplies = helper.AddUnit( parent: animalsSubdivision, condition: new ProductCondition { Operand = "CategoryL2", Attribute = null }, bidAmount: 0.35, isNegative: false); var electronics = helper.AddUnit( parent: root, condition: new ProductCondition { Operand = "CategoryL1", Attribute = "Electronics" }, bidAmount: 0.35, isNegative: false); var otherCategoryL1 = helper.AddUnit( root, new ProductCondition { Operand = "CategoryL1", Attribute = null }, 0.35, false ); OutputStatusMessage("-----\nApplyProductPartitionActions:"); OutputStatusMessage("Applying product partitions to the ad group..."); applyProductPartitionActionsResponse = await CampaignManagementExampleHelper.ApplyProductPartitionActionsAsync( criterionActions : helper.PartitionActions); // To retrieve product partitions after they have been applied, call GetAdGroupCriterionsByIds. // The product partition with ParentCriterionId set to null is the root node. OutputStatusMessage("-----\nGetAdGroupCriterionsByIds:"); adGroupCriterions = await CampaignManagementExampleHelper.GetAdGroupCriterionsByIdsAsync( adGroupCriterionIds : null, adGroupId : adGroupId, criterionType : AdGroupCriterionType.ProductPartition, returnAdditionalFields : AdGroupCriterionAdditionalField.FinalUrlSuffix); // 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(adGroupCriterions?.AdGroupCriterions); // 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 PartitionActionHelper(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), and was created at Index 1 of the previous ApplyProductPartitionActions call. // The node that we are replacing is Electronics (CategoryL1), and was created at Index 8. var rootId = applyProductPartitionActionsResponse.AdGroupCriterionIds[1]; electronics.Id = applyProductPartitionActionsResponse.AdGroupCriterionIds[8]; helper.DeletePartition(electronics); var parent = new BiddableAdGroupCriterion() { Id = rootId }; var electronicsSubdivision = helper.AddSubdivision( parent: parent, condition: new ProductCondition { Operand = "CategoryL1", Attribute = "Electronics" } ); var brandC = helper.AddUnit( parent: electronicsSubdivision, condition: new ProductCondition { Operand = "Brand", Attribute = "Brand C" }, bidAmount: 0.35, isNegative: false); var brandD = helper.AddUnit( parent: electronicsSubdivision, condition: new ProductCondition { Operand = "Brand", Attribute = "Brand D" }, bidAmount: 0.35, isNegative: false); var otherElectronicsBrands = helper.AddUnit( parent: electronicsSubdivision, condition: new ProductCondition { Operand = "Brand", Attribute = null }, bidAmount: 0.35, isNegative: false); OutputStatusMessage("-----\nApplyProductPartitionActions:"); OutputStatusMessage( "Updating the product partition group to refine Electronics (CategoryL1) with 3 child nodes..." ); applyProductPartitionActionsResponse = await CampaignManagementExampleHelper.ApplyProductPartitionActionsAsync( criterionActions : helper.PartitionActions); OutputStatusMessage("-----\nGetAdGroupCriterionsByIds:"); adGroupCriterions = await CampaignManagementExampleHelper.GetAdGroupCriterionsByIdsAsync( adGroupCriterionIds : null, adGroupId : adGroupId, criterionType : AdGroupCriterionType.ProductPartition, returnAdditionalFields : AdGroupCriterionAdditionalField.FinalUrlSuffix); // 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(adGroupCriterions?.AdGroupCriterions); // Create a product ad. You must add at least one product ad to the ad group. // The product ad identifier can be used for reporting analytics. // Use Merchant Promotions if you want tags to appear at the bottom of your product ad // as "special offer" links, helping to increase customer engagement. For details // on Merchant Promotions see https://help.bingads.microsoft.com/#apex/3/en/56805/0. var ads = new Ad[] { new ProductAd { } }; 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 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( OutputStatusMessageDefault: this.OutputStatusMessage); CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>( authorizationData: authorizationData, environment: environment); // Create an Audience campaign with one ad group. 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, Settings = new[] { new TargetSetting { // Sets the "target and bid" option for CompanyName, Industry, and JobFunction. // Microsoft will only deliver ads to people who meet at least one of your criteria. // By default the "bid only" option is set for Audience, Age, and Gender. // Microsoft will deliver ads to all audiences, ages, and genders, if they meet // your company name, industry, or job function criteria. Details = new [] { new TargetSettingDetail { CriterionTypeGroup = CriterionTypeGroup.CompanyName, TargetAndBid = true }, new TargetSettingDetail { CriterionTypeGroup = CriterionTypeGroup.Industry, TargetAndBid = true }, new TargetSettingDetail { CriterionTypeGroup = CriterionTypeGroup.JobFunction, TargetAndBid = true }, } } }, } }; 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); // Whether or not the "target and bid" option has been set for a given // criterion type group, you can set bid adjustments for specific criteria. var adGroupCriterions = new List <AdGroupCriterion>(); var adGroupCompanyNameCriterion = new BiddableAdGroupCriterion { AdGroupId = (long)adGroupIds[0], CriterionBid = new BidMultiplier { Multiplier = 15 }, Criterion = new ProfileCriterion { ProfileId = 808251207, // Microsoft ProfileType = ProfileType.CompanyName }, }; adGroupCriterions.Add(adGroupCompanyNameCriterion); var adGroupIndustryCriterion = new BiddableAdGroupCriterion { AdGroupId = (long)adGroupIds[0], CriterionBid = new BidMultiplier { Multiplier = 20 }, Criterion = new ProfileCriterion { ProfileId = 807658654, // Computer & Network Security ProfileType = ProfileType.Industry }, }; adGroupCriterions.Add(adGroupIndustryCriterion); var adGroupJobFunctionCriterion = new BiddableAdGroupCriterion { AdGroupId = (long)adGroupIds[0], CriterionBid = new BidMultiplier { Multiplier = 25 }, Criterion = new ProfileCriterion { ProfileId = 807658477, // Engineering ProfileType = ProfileType.JobFunction }, }; adGroupCriterions.Add(adGroupJobFunctionCriterion); // Exclude ages twenty-five through thirty-four. var adGroupNegativeAgeCriterion = new NegativeAdGroupCriterion { AdGroupId = (long)adGroupIds[0], Criterion = new AgeCriterion { AgeRange = AgeRange.TwentyFiveToThirtyFour }, }; adGroupCriterions.Add(adGroupNegativeAgeCriterion); OutputStatusMessage("-----\nAddAdGroupCriterions:"); CampaignManagementExampleHelper.OutputArrayOfAdGroupCriterion(adGroupCriterions); AddAdGroupCriterionsResponse addAdGroupCriterionsResponse = await CampaignManagementExampleHelper.AddAdGroupCriterionsAsync( adGroupCriterions : adGroupCriterions, criterionType : AdGroupCriterionType.Targets); long?[] adGroupCriterionIds = addAdGroupCriterionsResponse.AdGroupCriterionIds.ToArray(); OutputStatusMessage("AdGroupCriterionIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(adGroupCriterionIds); BatchErrorCollection[] adGroupCriterionErrors = addAdGroupCriterionsResponse.NestedPartialErrors.ToArray(); OutputStatusMessage("NestedPartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(adGroupCriterionErrors); // 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 <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); } }
public async override Task RunAsync(AuthorizationData authorizationData) { try { AdInsightService = new ServiceClient <IAdInsightService>(authorizationData); CampaignService = new ServiceClient <ICampaignManagementService>(authorizationData); // To get started with dynamic search ads, first you'll need to add a new Campaign // with its type set to DynamicSearchAds. When you create the campaign, you'll need to // include a DynamicSearchAdsSetting that specifies the target website domain and language. var campaigns = new[] { new Campaign { CampaignType = CampaignType.DynamicSearchAds, Settings = new [] { new DynamicSearchAdsSetting { DomainName = "contoso.com", Language = "English" } }, Name = "Women's Shoes " + DateTime.UtcNow, Description = "Red shoes line.", // You must choose to set either the shared budget ID or daily amount. // You can set one or the other, but you may not set both. BudgetId = null, DailyBudget = 50, BudgetType = Microsoft.BingAds.V10.CampaignManagement.BudgetLimitType.DailyBudgetStandard, // You can set your campaign bid strategy to Enhanced CPC (EnhancedCpcBiddingScheme) // and then, at any time, set an individual ad group bid strategy to // Manual CPC (ManualCpcBiddingScheme). BiddingScheme = new EnhancedCpcBiddingScheme { }, TimeZone = "PacificTimeUSCanadaTijuana", DaylightSaving = true, // Used with CustomParameters defined in lower level entities such as ads. TrackingUrlTemplate = "http://tracker.example.com/?season={_season}&promocode={_promocode}&u={lpurl}" }, }; AddCampaignsResponse addCampaignsResponse = await AddCampaignsAsync(authorizationData.AccountId, campaigns); long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray(); Microsoft.BingAds.V10.CampaignManagement.BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); OutputCampaignsWithPartialErrors(campaigns, campaignIds, campaignErrors); // Next, create a new AdGroup within the dynamic search ads campaign. var adGroups = new[] { new AdGroup { Name = "Women's Red Shoe Sale", AdDistribution = AdDistribution.Search, BiddingModel = BiddingModel.Keyword, PricingModel = PricingModel.Cpc, StartDate = null, EndDate = new Date { Month = 12, Day = 31, Year = DateTime.UtcNow.Year + 1 }, SearchBid = new Bid { Amount = 0.09 }, Language = "English", // For ad groups you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. // If you do not set this element, then InheritFromParentBiddingScheme is used by default. BiddingScheme = new ManualCpcBiddingScheme { }, } }; AddAdGroupsResponse addAdGroupsResponse = await AddAdGroupsAsync((long)campaignIds[0], adGroups); long?[] adGroupIds = addAdGroupsResponse.AdGroupIds.ToArray(); Microsoft.BingAds.V10.CampaignManagement.BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray(); OutputAdGroupsWithPartialErrors(adGroups, adGroupIds, adGroupErrors); // You can add one or more Webpage criterion to each ad group that helps determine // whether or not to serve dynamic search ads. var adGroupCriterions = new List <AdGroupCriterion>(); var adGroupWebpagePositivePageContent = new BiddableAdGroupCriterion { AdGroupId = (long)adGroupIds[0], CriterionBid = new FixedBid { Bid = new Bid { Amount = 0.50 } }, Criterion = new Webpage { Parameter = new WebpageParameter { Conditions = new[] { new WebpageCondition { Argument = "flowers", Operand = WebpageConditionOperand.PageContent, } }, CriterionName = "Ad Group Webpage Positive Page Content Criterion" }, }, // DestinationUrl and FinalUrls are not supported with Webpage criterion. // The Final URL is dynamically created at the ad level. DestinationUrl = null, FinalUrls = null, // You could use a tracking template which would override the campaign level // tracking template. Tracking templates defined for lower level entities // override those set for higher level entities. // In this example we are using the campaign level tracking template. TrackingUrlTemplate = null, // Set custom parameters that are specific to this webpage criterion, // and can be used by the criterion, ad group, campaign, or account level tracking template. // In this example we are using the campaign level tracking template. UrlCustomParameters = new CustomParameters { Parameters = new[] { new CustomParameter() { Key = "promoCode", Value = "PROMO1" }, new CustomParameter() { Key = "season", Value = "summer" }, } } }; adGroupCriterions.Add(adGroupWebpagePositivePageContent); // To discover the categories that you can use for Webpage criterion (positive or negative), // use the GetDomainCategories operation with the Ad Insight service. var getDomainCategoriesResponse = await GetDomainCategoriesAsync(DOMAIN_NAME, LANGUAGE); var categories = getDomainCategoriesResponse.Categories; // If any categories are available let's use one as a condition. if (categories.Count > 0) { var adGroupWebpagePositiveCategory = new BiddableAdGroupCriterion { AdGroupId = (long)adGroupIds[0], CriterionBid = new FixedBid { Bid = new Bid { Amount = 0.50 } }, Criterion = new Webpage { Parameter = new WebpageParameter { Conditions = new[] { new WebpageCondition { Argument = categories[0].CategoryName, Operand = WebpageConditionOperand.Category, } }, CriterionName = "Ad Group Webpage Positive Category Criterion" }, } }; adGroupCriterions.Add(adGroupWebpagePositiveCategory); } // If you want to exclude certain portions of your website, you can add negative Webpage // criterion at the campaign and ad group level. var adGroupWebpageNegativeUrl = new NegativeAdGroupCriterion { AdGroupId = (long)adGroupIds[0], Criterion = new Webpage { Parameter = new WebpageParameter { // You can choose whether you want the criterion argument to match partial URLs, // page content, page title, or categories that Bing thinks applies to your website. Conditions = new[] { new WebpageCondition { Argument = DOMAIN_NAME, Operand = WebpageConditionOperand.Url, } }, // If you do not specify any name, then it will be set to a concatenated list of conditions. CriterionName = null } }, }; adGroupCriterions.Add(adGroupWebpageNegativeUrl); OutputStatusMessage("Adding Ad Group Webpage Criterion . . . \n"); OutputAdGroupCriterions(adGroupCriterions); AddAdGroupCriterionsResponse addAdGroupCriterionsResponse = await AddAdGroupCriterionsAsync(adGroupCriterions, CriterionType.Webpage); long?[] adGroupCriterionIds = addAdGroupCriterionsResponse.AdGroupCriterionIds.ToArray(); OutputStatusMessage("New Ad Group Criterion Ids:\n"); OutputIds(adGroupCriterionIds); BatchErrorCollection[] adGroupCriterionErrors = addAdGroupCriterionsResponse.NestedPartialErrors.ToArray(); OutputStatusMessage("\nAddAdGroupCriterions Errors:\n"); OutputBatchErrorCollections(adGroupCriterionErrors); // The negative Webpage criterion at the campaign level applies to all ad groups // within the campaign; however, if you define ad group level negative Webpage criterion, // the campaign criterion is ignored for that ad group. var campaignCriterions = new List <CampaignCriterion>(); var campaignWebpageNegative = new NegativeCampaignCriterion { CampaignId = (long)campaignIds[0], Criterion = new Webpage { Parameter = new WebpageParameter { Conditions = new[] { new WebpageCondition { Argument = DOMAIN_NAME + "\\seattle", Operand = WebpageConditionOperand.Url, } }, CriterionName = "Campaign Negative Webpage Url Criterion" } } }; campaignCriterions.Add(campaignWebpageNegative); OutputStatusMessage("Adding Campaign Webpage Criterion . . . \n"); OutputCampaignCriterions(campaignCriterions); AddCampaignCriterionsResponse addCampaignCriterionsResponse = await AddCampaignCriterionsAsync(campaignCriterions, CampaignCriterionType.Webpage); long?[] campaignCriterionIds = addCampaignCriterionsResponse.CampaignCriterionIds.ToArray(); OutputStatusMessage("\nNew Campaign Criterion Ids:\n"); OutputIds(campaignCriterionIds); BatchErrorCollection[] campaignCriterionErrors = addCampaignCriterionsResponse.NestedPartialErrors.ToArray(); OutputStatusMessage("\nAddCampaignCriterions Errors:\n"); OutputBatchErrorCollections(campaignCriterionErrors); // Finally you can add a DynamicSearchAd into the ad group. The ad title and display URL // are generated automatically based on the website domain and language that you want to target. var ads = new Ad[] { new DynamicSearchAd { Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.", Path1 = "seattle", Path2 = "shoe sale", // You cannot set FinalUrls. The Final URL will be a dynamically selected landing page. // The final URL is distinct from the path that customers will see and click on in your ad. FinalUrls = null, // You could use a tracking template which would override the campaign level // tracking template. Tracking templates defined for lower level entities // override those set for higher level entities. // In this example we are using the campaign level tracking template. TrackingUrlTemplate = null, // Set custom parameters that are specific to this ad, // and can be used by the ad, webpage, ad group, campaign, or account level tracking template. // In this example we are using the campaign level tracking template. UrlCustomParameters = new CustomParameters { Parameters = new[] { new CustomParameter() { Key = "promoCode", Value = "PROMO1" }, new CustomParameter() { Key = "season", Value = "summer" }, } } }, }; AddAdsResponse addAdsResponse = await AddAdsAsync((long)adGroupIds[0], ads); long?[] adIds = addAdsResponse.AdIds.ToArray(); Microsoft.BingAds.V10.CampaignManagement.BatchError[] adErrors = addAdsResponse.PartialErrors.ToArray(); OutputAdsWithPartialErrors(ads, adIds, adErrors); // Retrieve the Webpage criterion for the campaign. var getCampaignCriterionsByIdsResponse = await GetCampaignCriterionsByIdsAsync( (long)campaignIds[0], null, CampaignCriterionType.Webpage ); OutputStatusMessage("Retrieving the Campaign Webpage Criterions that we added . . . \n"); campaignCriterions = getCampaignCriterionsByIdsResponse.CampaignCriterions.ToList(); OutputCampaignCriterions(campaignCriterions); // Retrieve the Webpage criterion for the ad group and then test some update scenarios. var getAdGroupCriterionsByIdsResponse = await GetAdGroupCriterionsByIdsAsync( (long)adGroupIds[0], null, CriterionType.Webpage ); OutputStatusMessage("Retrieving the Ad Group Webpage Criterions that we added . . . \n"); adGroupCriterions = getAdGroupCriterionsByIdsResponse.AdGroupCriterions.ToList(); OutputAdGroupCriterions(adGroupCriterions); // You can update the bid for BiddableAdGroupCriterion var updateBid = new FixedBid { Bid = new Bid { Amount = 0.75 } }; // You can update the Webpage criterion name but cannot update the conditions. // To update the conditions you must delete the criterion and add a new criterion. // This update attempt will return an error. var updateCriterionAttemptFailure = new Webpage { Parameter = new WebpageParameter { Conditions = new[] { new WebpageCondition { Argument = "Books", Operand = WebpageConditionOperand.PageContent, } }, CriterionName = "Update Attempt Failure" }, }; var updateCriterionAttemptSuccess = new Webpage { Parameter = new WebpageParameter { CriterionName = "Update Attempt Success" }, }; foreach (var adGroupCriterion in adGroupCriterions) { var biddableAdGroupCriterion = adGroupCriterion as BiddableAdGroupCriterion; if (biddableAdGroupCriterion != null) { ((BiddableAdGroupCriterion)(adGroupCriterion)).CriterionBid = updateBid; ((BiddableAdGroupCriterion)(adGroupCriterion)).Criterion = updateCriterionAttemptSuccess; } else { var negativeAdGroupCriterion = adGroupCriterion as NegativeAdGroupCriterion; if (negativeAdGroupCriterion != null) { ((NegativeAdGroupCriterion)(adGroupCriterion)).Criterion = updateCriterionAttemptFailure; } } } OutputStatusMessage("Updating Ad Group Webpage Criterion . . . \n"); OutputAdGroupCriterions(adGroupCriterions); UpdateAdGroupCriterionsResponse updateAdGroupCriterionsResponse = await UpdateAdGroupCriterionsAsync(adGroupCriterions, CriterionType.Webpage); adGroupCriterionErrors = updateAdGroupCriterionsResponse.NestedPartialErrors.ToArray(); OutputStatusMessage("UpdateAdGroupCriterions Errors:\n"); OutputBatchErrorCollections(adGroupCriterionErrors); // Delete the campaign, ad group, criterion, and ad that were previously added. // You should remove this operation if you want to view the added entities in the // Bing Ads web application or another tool. await DeleteCampaignsAsync(authorizationData.AccountId, new[] { (long)campaignIds[0] }); OutputStatusMessage(string.Format("\nDeleted Campaign Id {0}\n", 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.V10.CampaignManagement.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <Microsoft.BingAds.V10.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.V10.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 search campaign. var campaigns = new[] { new Campaign { BudgetType = BudgetLimitType.DailyBudgetStandard, DailyBudget = 50, CampaignType = CampaignType.Search, Languages = new string[] { "All" }, Name = "Women's Shoes " + DateTime.UtcNow, TimeZone = "PacificTimeUSCanadaTijuana", }, }; OutputStatusMessage("-----\nAddCampaigns:"); AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync( accountId : authorizationData.AccountId, campaigns : campaigns); 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 }, } }; 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 keywords and ads within the ad group. var keywords = new[] { new Keyword { Bid = new Bid { Amount = 0.47 }, Param2 = "10% Off", MatchType = MatchType.Phrase, Text = "Brand-A Shoes", }, }; OutputStatusMessage("-----\nAddKeywords:"); AddKeywordsResponse addKeywordsResponse = await CampaignManagementExampleHelper.AddKeywordsAsync( adGroupId : (long)adGroupIds[0], keywords : keywords, returnInheritedBidStrategyTypes : false); long?[] keywordIds = addKeywordsResponse.KeywordIds.ToArray(); BatchError[] keywordErrors = addKeywordsResponse.PartialErrors.ToArray(); OutputStatusMessage("KeywordIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(keywordIds); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(keywordErrors); var ads = new Ad[] { new ExpandedTextAd { TitlePart1 = "Contoso", TitlePart2 = "Quick & Easy Setup", TitlePart3 = "Seemless Integration", Text = "Find New Customers & Increase Sales!", TextPart2 = "Start Advertising on Contoso Today.", Path1 = "seattle", Path2 = "shoe sale", FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, }, }; 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 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 <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); } }
public async override Task RunAsync(AuthorizationData authorizationData) { try { Service = new ServiceClient <ICampaignManagementService>(authorizationData); // To discover all remarketing lists that the user can associate with ad groups in the current account (per CustomerAccountId header), // set RemarketingListIds to null when calling the GetRemarketingLists operation. var remarketingLists = (await GetRemarketingListsAsync(null)).RemarketingLists; // You must already have at least one remarketing list for the remainder of this example. // The Bing Ads API does not support remarketing list add, update, or delete operations. if (remarketingLists.Count < 1) { return; } // Add an ad group in a campaign. The ad group will later be associated with remarketing lists. var campaigns = new[] { new Campaign { Name = "Women's Shoes" + DateTime.UtcNow, Description = "Red shoes line.", BudgetType = BudgetLimitType.MonthlyBudgetSpendUntilDepleted, MonthlyBudget = 1000.00, TimeZone = "PacificTimeUSCanadaTijuana", DaylightSaving = true, TrackingUrlTemplate = null }, }; var adGroups = new[] { new AdGroup { Name = "Women's Red Shoe Sale", AdDistribution = AdDistribution.Search, BiddingModel = BiddingModel.Keyword, PricingModel = PricingModel.Cpc, StartDate = null, EndDate = new Date { Month = 12, Day = 31, Year = DateTime.UtcNow.Year + 1 }, SearchBid = new Bid { Amount = 0.09 }, Language = "English", TrackingUrlTemplate = null, // Applicable for all remarketing lists that are associated with this ad group. TargetAndBid indicates // that you want to show ads only to people included in the remarketing list, with the option to change // the bid amount. Ads in this ad group will only show to people included in the remarketing list. RemarketingTargetingSetting = RemarketingTargetingSetting.TargetAndBid } }; AddCampaignsResponse addCampaignsResponse = await AddCampaignsAsync(authorizationData.AccountId, campaigns); long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray(); BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); OutputCampaignsWithPartialErrors(campaigns, campaignIds, campaignErrors); AddAdGroupsResponse addAdGroupsResponse = await AddAdGroupsAsync((long)campaignIds[0], adGroups); long?[] adGroupIds = addAdGroupsResponse.AdGroupIds.ToArray(); BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray(); OutputAdGroupsWithPartialErrors(adGroups, adGroupIds, adGroupErrors); // If the campaign or ad group add operations failed then we cannot continue this example. if (addAdGroupsResponse.AdGroupIds == null || addAdGroupsResponse.AdGroupIds.Count < 1) { return; } var adGroupRemarketingListAssociations = new List <AdGroupRemarketingListAssociation>(); // This example associates all of the remarketing lists with the new ad group. foreach (var remarketingList in remarketingLists) { if (remarketingList.Id != null) { var adGroupRemarketingListAssociation = new AdGroupRemarketingListAssociation { AdGroupId = (long)adGroupIds[0], BidAdjustment = 20.00, RemarketingListId = (long)remarketingList.Id, Status = AdGroupRemarketingListAssociationStatus.Paused }; adGroupRemarketingListAssociations.Add(adGroupRemarketingListAssociation); OutputStatusMessage("\nAssociating the following remarketing list with the ad group.\n"); OutputRemarketingList(remarketingList); } } var addAdGroupRemarketingListAssociationsResponse = await AddAdGroupRemarketingListAssociationsAsync(adGroupRemarketingListAssociations); var getAdGroupRemarketingListAssociationsResponse = await GetAdGroupRemarketingListAssociationsAsync(new[] { (long)adGroupIds[0] }); foreach (var adGroupRemarketingListAssociation in getAdGroupRemarketingListAssociationsResponse.AdGroupRemarketingListAssociations) { OutputStatusMessage("\nThe following ad group remarketing list association was added.\n"); OutputAdGroupRemarketingListAssociation(adGroupRemarketingListAssociation); } // You can store the association IDs which can be used to update or delete associations later. var associationIds = addAdGroupRemarketingListAssociationsResponse.AssociationIds; // If the associations were added and retrieved successfully let's practice updating and deleting one of them. if (associationIds != null && associationIds.Count > 0) { var updateAdGroupRemarketingListAssociation = new AdGroupRemarketingListAssociation { AdGroupId = (long)adGroupIds[0], BidAdjustment = 10.00, Id = associationIds[0], Status = AdGroupRemarketingListAssociationStatus.Active, }; var updateAdGroupRemarketingListAssociationsResponse = await UpdateAdGroupRemarketingListAssociationsAsync(new AdGroupRemarketingListAssociation[] { updateAdGroupRemarketingListAssociation }); var deleteAdGroupRemarketingListAssociationsResponse = await DeleteAdGroupRemarketingListAssociationsAsync(new AdGroupRemarketingListAssociation[] { updateAdGroupRemarketingListAssociation }); } // Delete the campaign, ad group, and ad group remarketing list associations that were previously added. // The remarketing lists will not be deleted. // You should remove this line if you want to view the added entities in the // Bing Ads web application or another tool. await DeleteCampaignsAsync(authorizationData.AccountId, new[] { (long)campaignIds[0] }); OutputStatusMessage(String.Format("Deleted CampaignId {0}\n", 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.V10.CampaignManagement.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <Microsoft.BingAds.V10.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.V10.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 { CampaignService = new ServiceClient <ICampaignManagementService>(authorizationData); // Specify one or more campaigns. var campaigns = new[] { new Campaign { Name = "Women's Shoes " + DateTime.UtcNow, Description = "Red shoes line.", DailyBudget = 50, BudgetType = BudgetLimitType.DailyBudgetStandard, TimeZone = "PacificTimeUSCanadaTijuana", }, }; var adGroups = new[] { new AdGroup { Name = "Women's Red Shoe Sale", AdDistribution = AdDistribution.Search, StartDate = null, EndDate = new Microsoft.BingAds.V11.CampaignManagement.Date { Month = 12, Day = 31, Year = DateTime.UtcNow.Year + 1 }, SearchBid = new Bid { Amount = 0.09 }, Language = "English", } }; var keywords = new[] { new Keyword { Bid = new Bid { Amount = 0.47 }, Param2 = "10% Off", MatchType = MatchType.Phrase, Text = "Brand-A Shoes", }, }; var ads = new Ad[] { new ExpandedTextAd { TitlePart1 = "Contoso", TitlePart2 = "Fast & Easy Setup", Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.", Path1 = "seattle", Path2 = "shoe sale", FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, }, }; var random = new Random(); var labels = new List <Label>(); for (var labelIndex = 0; labelIndex < 50; labelIndex++) { var color = string.Format("#{0:X6}", random.Next(0x100000)); labels.Add(new Label { ColorCode = color, Description = "Label Description", Name = "Label Name " + color + " " + DateTime.UtcNow }); } AddLabelsResponse addLabelsResponse = await AddLabelsAsync(labels); long?[] nullableLabelIds = addLabelsResponse.LabelIds.ToArray(); BatchError[] labelErrors = addLabelsResponse.PartialErrors.ToArray(); OutputStatusMessage("New Label Ids:"); OutputIds(nullableLabelIds); OutputPartialErrors(labelErrors); AddCampaignsResponse addCampaignsResponse = await AddCampaignsAsync(authorizationData.AccountId, campaigns); long?[] nullableCampaignIds = addCampaignsResponse.CampaignIds.ToArray(); BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); OutputStatusMessage("New Campaign Ids:"); OutputIds(nullableCampaignIds); OutputPartialErrors(campaignErrors); AddAdGroupsResponse addAdGroupsResponse = await AddAdGroupsAsync((long)nullableCampaignIds[0], adGroups); long?[] nullableAdGroupIds = addAdGroupsResponse.AdGroupIds.ToArray(); BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray(); OutputStatusMessage("New Ad Group Ids:"); OutputIds(nullableAdGroupIds); OutputPartialErrors(adGroupErrors); AddKeywordsResponse addKeywordsResponse = await AddKeywordsAsync((long)nullableAdGroupIds[0], keywords); long?[] nullableKeywordIds = addKeywordsResponse.KeywordIds.ToArray(); BatchError[] keywordErrors = addKeywordsResponse.PartialErrors.ToArray(); OutputStatusMessage("New Keyword Ids:"); OutputIds(nullableKeywordIds); OutputPartialErrors(keywordErrors); AddAdsResponse addAdsResponse = await AddAdsAsync((long)nullableAdGroupIds[0], ads); long?[] nullableAdIds = addAdsResponse.AdIds.ToArray(); BatchError[] adErrors = addAdsResponse.PartialErrors.ToArray(); OutputStatusMessage("New Ad Ids:"); OutputIds(nullableAdIds); OutputPartialErrors(adErrors); var labelIds = GetNonNullableIds(nullableLabelIds); OutputStatusMessage("\nGet all the labels that we added above..."); var getLabelsByIdsResponse = await GetLabelsByIdsAsync( labelIds, new Paging { Index = 0, Size = MaxGetLabelsByIds } ); OutputLabels(getLabelsByIdsResponse.Labels); OutputStatusMessage("\nUpdate the label color and then retrieve the labels again to confirm the changes...."); var updateLabels = new List <Label>(); foreach (var label in getLabelsByIdsResponse.Labels) { label.ColorCode = string.Format("#{0:X6}", random.Next(0x100000)); updateLabels.Add(label); } var updateLabelsResponse = await UpdateLabelsAsync(updateLabels); getLabelsByIdsResponse = await GetLabelsByIdsAsync( labelIds, new Paging { Index = 0, Size = MaxGetLabelsByIds } ); OutputLabels(getLabelsByIdsResponse.Labels); var campaignLabelAssociations = CreateExampleLabelAssociationsByEntityId((long)nullableCampaignIds[0], labelIds); OutputStatusMessage("\nAssociating all of the labels with a campaign..."); OutputLabelAssociations(campaignLabelAssociations); var setLabelAssociationsResponse = await SetLabelAssociationsAsync(campaignLabelAssociations, EntityType.Campaign); var adGroupLabelAssociations = CreateExampleLabelAssociationsByEntityId((long)nullableAdGroupIds[0], labelIds); OutputStatusMessage("\nAssociating all of the labels with an ad group..."); OutputLabelAssociations(adGroupLabelAssociations); setLabelAssociationsResponse = await SetLabelAssociationsAsync(adGroupLabelAssociations, EntityType.AdGroup); var keywordLabelAssociations = CreateExampleLabelAssociationsByEntityId((long)nullableKeywordIds[0], labelIds); OutputStatusMessage("\nAssociating all of the labels with a keyword..."); OutputLabelAssociations(keywordLabelAssociations); setLabelAssociationsResponse = await SetLabelAssociationsAsync(keywordLabelAssociations, EntityType.Keyword); var adLabelAssociations = CreateExampleLabelAssociationsByEntityId((long)nullableAdIds[0], labelIds); OutputStatusMessage("\nAssociating all of the labels with an ad..."); OutputLabelAssociations(adLabelAssociations); setLabelAssociationsResponse = await SetLabelAssociationsAsync(adLabelAssociations, EntityType.Ad); OutputStatusMessage("\nUse paging to get all campaign label associations..."); var getLabelAssociationsByLabelIds = await GetLabelAssociationsByLabelIdsHelperAsync(labelIds, EntityType.Campaign); OutputLabelAssociations(getLabelAssociationsByLabelIds); OutputStatusMessage("\nUse paging to get all ad group label associations..."); getLabelAssociationsByLabelIds = await GetLabelAssociationsByLabelIdsHelperAsync(labelIds, EntityType.AdGroup); OutputLabelAssociations(getLabelAssociationsByLabelIds); OutputStatusMessage("\nUse paging to get all keyword label associations..."); getLabelAssociationsByLabelIds = await GetLabelAssociationsByLabelIdsHelperAsync(labelIds, EntityType.Keyword); OutputLabelAssociations(getLabelAssociationsByLabelIds); OutputStatusMessage("\nUse paging to get all ad label associations..."); getLabelAssociationsByLabelIds = await GetLabelAssociationsByLabelIdsHelperAsync(labelIds, EntityType.Ad); OutputLabelAssociations(getLabelAssociationsByLabelIds); OutputStatusMessage("\nGet all label associations for all specified campaigns..."); var getLabelAssociationsByEntityIds = await GetLabelAssociationsByEntityIdsHelperAsync( GetNonNullableIds(nullableCampaignIds), EntityType.Campaign ); OutputLabelAssociations(getLabelAssociationsByEntityIds); OutputStatusMessage("\nGet all label associations for all specified ad groups..."); getLabelAssociationsByEntityIds = await GetLabelAssociationsByEntityIdsHelperAsync( GetNonNullableIds(nullableAdGroupIds), EntityType.AdGroup ); OutputLabelAssociations(getLabelAssociationsByEntityIds); OutputStatusMessage("\nGet all label associations for all specified keywords..."); getLabelAssociationsByEntityIds = await GetLabelAssociationsByEntityIdsHelperAsync( GetNonNullableIds(nullableKeywordIds), EntityType.Keyword ); OutputLabelAssociations(getLabelAssociationsByEntityIds); OutputStatusMessage("\nGet all label associations for all specified ads..."); getLabelAssociationsByEntityIds = await GetLabelAssociationsByEntityIdsHelperAsync( GetNonNullableIds(nullableAdIds), EntityType.Ad ); OutputLabelAssociations(getLabelAssociationsByEntityIds); OutputStatusMessage("\nDelete all label associations that we set above...."); // This is not necessary if you are deleting the corresponding campaign(s), as the // contained ad groups, keywords, ads, and associations would also be deleted. var deleteLabelAssociationsResponse = await DeleteLabelAssociationsAsync(campaignLabelAssociations, EntityType.Campaign); deleteLabelAssociationsResponse = await DeleteLabelAssociationsAsync(adGroupLabelAssociations, EntityType.AdGroup); deleteLabelAssociationsResponse = await DeleteLabelAssociationsAsync(keywordLabelAssociations, EntityType.Keyword); deleteLabelAssociationsResponse = await DeleteLabelAssociationsAsync(adLabelAssociations, EntityType.Ad); OutputStatusMessage("\nDelete all labels that we added above...."); // Deleting the campaign(s) removes the corresponding label associations but not remove the labels. var deleteLabelsResponse = await DeleteLabelsAsync(labelIds); OutputStatusMessage("\nDelete the campaign, ad group, keyword, and ad that were added above...."); await DeleteCampaignsAsync(authorizationData.AccountId, new[] { (long)nullableCampaignIds[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.V11.CampaignManagement.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <Microsoft.BingAds.V11.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.V11.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); // Get a list of all Bing Merchant Center stores associated with your CustomerId IList <BMCStore> stores = (await CampaignManagementExampleHelper.GetBMCStoresByCustomerIdAsync())?.BMCStores; if (stores == null) { OutputStatusMessage( string.Format("You do not have any BMC stores registered for CustomerId {0}.\n", authorizationData.CustomerId) ); return; } #region ManageCampaign /* 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 campaigns = new[] { new Campaign { 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.", // You must choose to set either the shared budget ID or daily amount. // You can set one or the other, but you may not set both. BudgetId = null, DailyBudget = 50, BudgetType = BudgetLimitType.DailyBudgetStandard, TimeZone = "PacificTimeUSCanadaTijuana", // Used with CustomParameters defined in lower level entities such as ad group criterion. TrackingUrlTemplate = "http://tracker.example.com/?season={_season}&promocode={_promocode}&u={lpurl}" } }; AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync(authorizationData.AccountId, campaigns); long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray(); BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); CampaignManagementExampleHelper.OutputArrayOfLong(campaignIds); CampaignManagementExampleHelper.OutputArrayOfBatchError(campaignErrors); long campaignId = (long)campaignIds[0]; /* 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 campaignCriterions = new BiddableCampaignCriterion[] { new BiddableCampaignCriterion() { CampaignId = campaignId, CriterionBid = null, // Not applicable for product scope Criterion = new ProductScope() { Conditions = new ProductCondition[] { new ProductCondition { Operand = "Condition", Attribute = "New" }, new ProductCondition { Operand = "CustomLabel0", Attribute = "MerchantDefinedCustomLabel" }, } }, } }; var addCampaignCriterionsResponse = await(CampaignManagementExampleHelper.AddCampaignCriterionsAsync( campaignCriterions, CampaignCriterionType.ProductScope) ); #endregion ManageCampaign #region ManageAdGroup // Create the ad group that will have the product partitions. var adGroups = new[] { new AdGroup { Name = "Product Categories", StartDate = null, EndDate = new Microsoft.BingAds.V12.CampaignManagement.Date { Month = 12, Day = 31, Year = DateTime.UtcNow.Year + 1 }, Language = "English", CpcBid = new Bid { Amount = 0.090 } } }; AddAdGroupsResponse addAdGroupsResponse = await CampaignManagementExampleHelper.AddAdGroupsAsync((long)campaignId, adGroups, null); long?[] adGroupIds = addAdGroupsResponse.AdGroupIds.ToArray(); BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray(); CampaignManagementExampleHelper.OutputArrayOfLong(adGroupIds); CampaignManagementExampleHelper.OutputArrayOfBatchError(adGroupErrors); long adGroupId = (long)adGroupIds[0]; #region BidAllProducts var helper = new PartitionActionHelper(adGroupId); var root = helper.AddUnit( null, new ProductCondition { Operand = "All", Attribute = null }, 0.35, false ); OutputStatusMessage("Applying only the root as a Unit with a bid . . . \n"); var applyProductPartitionActionsResponse = await CampaignManagementExampleHelper.ApplyProductPartitionActionsAsync(helper.PartitionActions); var adGroupCriterions = await CampaignManagementExampleHelper.GetAdGroupCriterionsByIdsAsync( null, adGroupId, AdGroupCriterionType.ProductPartition ); OutputStatusMessage("The ad group's product partition only has a tree root node: \n"); OutputProductPartitions(adGroupCriterions?.AdGroupCriterions); /* * Let's update the bid of the root Unit we just added. */ BiddableAdGroupCriterion updatedRoot = new BiddableAdGroupCriterion { Id = applyProductPartitionActionsResponse.AdGroupCriterionIds[0], CriterionBid = new FixedBid { Amount = 0.45 } }; helper = new PartitionActionHelper(adGroupId); helper.UpdatePartition(updatedRoot); OutputStatusMessage("Updating the bid for the tree root node . . . \n"); await CampaignManagementExampleHelper.ApplyProductPartitionActionsAsync(helper.PartitionActions); adGroupCriterions = await CampaignManagementExampleHelper.GetAdGroupCriterionsByIdsAsync( null, adGroupId, AdGroupCriterionType.ProductPartition ); OutputStatusMessage("Updated the bid for the tree root node: \n"); OutputProductPartitions(adGroupCriterions?.AdGroupCriterions); #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 5,000 nodes; however, * we will build it in steps to demonstrate how to use the results from ApplyProductPartitionActions to update the tree. * * For a list of validation rules, see the Product Ads technical guide: * https://docs.microsoft.com/en-us/bingads/guides/product-ads */ helper = new PartitionActionHelper(adGroupId); /* * Check whether a root node exists already. */ adGroupCriterions = await CampaignManagementExampleHelper.GetAdGroupCriterionsByIdsAsync( null, adGroupId, AdGroupCriterionType.ProductPartition ); var existingRoot = GetRootNode(adGroupCriterions?.AdGroupCriterions); if (existingRoot != null) { helper.DeletePartition(existingRoot); } root = helper.AddSubdivision( null, new ProductCondition { Operand = "All", Attribute = null } ); /* * 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://go.microsoft.com/fwlink?LinkId=507666 */ var animalsSubdivision = helper.AddSubdivision( root, new ProductCondition { Operand = "CategoryL1", Attribute = "Animals & Pet Supplies" } ); /* * 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" } ); var brandA = helper.AddUnit( petSuppliesSubdivision, new ProductCondition { Operand = "Brand", Attribute = "Brand A" }, 0.35, false ); /* * 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 ); var otherBrands = helper.AddUnit( petSuppliesSubdivision, new ProductCondition { Operand = "Brand", Attribute = null }, 0.35, false ); var otherPetSupplies = helper.AddUnit( animalsSubdivision, new ProductCondition { Operand = "CategoryL2", Attribute = null }, 0.35, false ); var electronics = helper.AddUnit( root, new ProductCondition { Operand = "CategoryL1", Attribute = "Electronics" }, 0.35, false ); var otherCategoryL1 = helper.AddUnit( root, new ProductCondition { Operand = "CategoryL1", Attribute = null }, 0.35, false ); OutputStatusMessage("Applying product partitions to the ad group . . . \n"); applyProductPartitionActionsResponse = await CampaignManagementExampleHelper.ApplyProductPartitionActionsAsync(helper.PartitionActions); // To retrieve product partitions after they have been applied, call GetAdGroupCriterionsByIds. // The product partition with ParentCriterionId set to null is the root node. adGroupCriterions = await CampaignManagementExampleHelper.GetAdGroupCriterionsByIdsAsync( null, adGroupId, AdGroupCriterionType.ProductPartition ); /* * 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(adGroupCriterions?.AdGroupCriterions); #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 PartitionActionHelper(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), and was created at Index 1 of the previous ApplyProductPartitionActions call. * The node that we are replacing is Electronics (CategoryL1), and was created at Index 8. */ var rootId = applyProductPartitionActionsResponse.AdGroupCriterionIds[1]; electronics.Id = applyProductPartitionActionsResponse.AdGroupCriterionIds[8]; helper.DeletePartition(electronics); var parent = new BiddableAdGroupCriterion() { Id = rootId }; var electronicsSubdivision = helper.AddSubdivision( parent, new ProductCondition { Operand = "CategoryL1", Attribute = "Electronics" } ); var brandC = helper.AddUnit( electronicsSubdivision, new ProductCondition { Operand = "Brand", Attribute = "Brand C" }, 0.35, false ); var brandD = helper.AddUnit( electronicsSubdivision, new ProductCondition { Operand = "Brand", Attribute = "Brand D" }, 0.35, false ); var otherElectronicsBrands = helper.AddUnit( electronicsSubdivision, new ProductCondition { Operand = "Brand", Attribute = null }, 0.35, false ); OutputStatusMessage( "Updating the product partition group to refine Electronics (CategoryL1) with 3 child nodes . . . \n" ); applyProductPartitionActionsResponse = await CampaignManagementExampleHelper.ApplyProductPartitionActionsAsync(helper.PartitionActions); adGroupCriterions = await CampaignManagementExampleHelper.GetAdGroupCriterionsByIdsAsync( null, adGroupId, AdGroupCriterionType.ProductPartition ); /* * 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(adGroupCriterions?.AdGroupCriterions); #endregion UpdateTree #endregion ManageAdGroup #region ManageAds /* * Create a product ad. You must add at least one product ad to the ad group. * The product ad identifier can be used for reporting analytics. * Use Merchant Promotions if you want tags to appear at the bottom of your product ad * as "special offer" links, helping to increase customer engagement. For details * on Merchant Promotions see https://help.bingads.microsoft.com/#apex/3/en/56805/0. */ var ads = new Ad[] { new ProductAd { } }; AddAdsResponse addAdsResponse = await CampaignManagementExampleHelper.AddAdsAsync((long)adGroupIds[0], ads); long?[] adIds = addAdsResponse.AdIds.ToArray(); BatchError[] adErrors = addAdsResponse.PartialErrors.ToArray(); CampaignManagementExampleHelper.OutputArrayOfLong(adIds); CampaignManagementExampleHelper.OutputArrayOfBatchError(adErrors); #endregion ManageAds #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. */ await CampaignManagementExampleHelper.DeleteCampaignsAsync(authorizationData.AccountId, new[] { campaignId }); OutputStatusMessage(string.Format("Deleted Campaign Id {0}\n", campaignId)); #endregion CleanUp } // 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); // Before you can track conversions or target audiences using a remarketing list // you need to create a UET tag, and then add the UET tag tracking code to every page of your website. // For more information, please see Universal Event Tracking at https://go.microsoft.com/fwlink/?linkid=829965. // First you should call the GetUetTagsByIds operation to check whether a tag has already been created. // You can leave the TagIds element null or empty to request all UET tags available for the customer. OutputStatusMessage("-----\nGetUetTagsByIds:"); var uetTags = (await CampaignManagementExampleHelper.GetUetTagsByIdsAsync( tagIds: null))?.UetTags; // If you do not already have a UET tag that can be used, or if you need another UET tag, // call the AddUetTags service operation to create a new UET tag. If the call is successful, // the tracking script that you should add to your website is included in a corresponding // UetTag within the response message. if (uetTags == null || uetTags.Count < 1) { var uetTag = new UetTag { Description = "My First Uet Tag", Name = "New Uet Tag", }; OutputStatusMessage("-----\nAddUetTags:"); uetTags = (await CampaignManagementExampleHelper.AddUetTagsAsync( uetTags: new[] { uetTag })).UetTags; } if (uetTags == null || uetTags.Count < 1) { OutputStatusMessage( string.Format("You do not have any UET tags registered for CustomerId {0}.", authorizationData.CustomerId) ); return; } OutputStatusMessage("List of all UET Tags:"); CampaignManagementExampleHelper.OutputArrayOfUetTag(uetTags); // After you retreive the tracking script from the AddUetTags or GetUetTagsByIds operation, // the next step is to add the UET tag tracking code to your website. // We will use the same UET tag for the remainder of this example. var tagId = uetTags[0].Id; // Add remarketing lists that depend on the UET Tag Id retreived above. var addAudiences = new[] { new RemarketingList { Description = "New list with CustomEventsRule", MembershipDuration = 30, Name = "Remarketing List with CustomEventsRule " + DateTime.UtcNow, ParentId = authorizationData.AccountId, // The rule definition is translated to the following logical expression: // (Category Equals video) and (Action Equals play) and (Label Equals trailer) // and (Value Equals 5) Rule = new CustomEventsRule { // The type of user interaction you want to track. Action = "play", ActionOperator = StringOperator.Equals, // The category of event you want to track. Category = "video", CategoryOperator = StringOperator.Equals, // The name of the element that caused the action. Label = "trailer", LabelOperator = StringOperator.Equals, // A numerical value associated with that event. // Could be length of the video played etc. Value = 5.00m, ValueOperator = NumberOperator.Equals, }, Scope = EntityScope.Account, TagId = tagId }, new RemarketingList { Description = "New list with PageVisitorsRule", MembershipDuration = 30, Name = "Remarketing List with PageVisitorsRule " + DateTime.UtcNow, ParentId = authorizationData.AccountId, // The rule definition is translated to the following logical expression: // ((Url Contains X) and (ReferrerUrl DoesNotContain Z)) or ((Url DoesNotBeginWith Y)) // or ((ReferrerUrl Equals Z)) Rule = new PageVisitorsRule { RuleItemGroups = new [] { new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.Contains, Value = "X" }, new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.DoesNotContain, Value = "Z" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.DoesNotBeginWith, Value = "Y" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.Equals, Value = "Z" }, } }, }, }, Scope = EntityScope.Account, TagId = tagId }, new RemarketingList { Description = "New list with PageVisitorsWhoDidNotVisitAnotherPageRule", MembershipDuration = 30, Name = "Remarketing List with PageVisitorsWhoDidNotVisitAnotherPageRule " + DateTime.UtcNow, ParentId = authorizationData.AccountId, // The rule definition is translated to the following logical expression: // (((Url Contains X) and (ReferrerUrl DoesNotContain Z)) or ((Url DoesNotBeginWith Y)) // or ((ReferrerUrl Equals Z))) // and not (((Url BeginsWith A) and (ReferrerUrl BeginsWith B)) or ((Url Contains C))) Rule = new PageVisitorsWhoDidNotVisitAnotherPageRule { ExcludeRuleItemGroups = new [] { new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.BeginsWith, Value = "A" }, new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.BeginsWith, Value = "B" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.Contains, Value = "C" }, } }, }, IncludeRuleItemGroups = new [] { new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.Contains, Value = "X" }, new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.DoesNotContain, Value = "Z" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.DoesNotBeginWith, Value = "Y" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.Equals, Value = "Z" }, } }, }, }, Scope = EntityScope.Account, TagId = tagId }, new RemarketingList { Description = "New list with PageVisitorsWhoVisitedAnotherPageRule", MembershipDuration = 30, Name = "Remarketing List with PageVisitorsWhoVisitedAnotherPageRule " + DateTime.UtcNow, ParentId = authorizationData.AccountId, // The rule definition is translated to the following logical expression: // (((Url Contains X) and (ReferrerUrl NotEquals Z)) or ((Url DoesNotBeginWith Y)) or // ((ReferrerUrl Equals Z))) // and (((Url BeginsWith A) and (ReferrerUrl BeginsWith B)) or ((Url Contains C))) Rule = new PageVisitorsWhoVisitedAnotherPageRule { AnotherRuleItemGroups = new [] { new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.BeginsWith, Value = "A" }, new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.BeginsWith, Value = "B" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.Contains, Value = "C" }, } }, }, RuleItemGroups = new [] { new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.Contains, Value = "X" }, new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.DoesNotContain, Value = "Z" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "Url", Operator = StringOperator.DoesNotBeginWith, Value = "Y" }, } }, new RuleItemGroup { Items = new [] { new StringRuleItem { Operand = "ReferrerUrl", Operator = StringOperator.Equals, Value = "Z" }, } }, }, }, Scope = EntityScope.Account, TagId = tagId }, }; // RemarketingList extends the Audience base class. // We manage remarketing lists with Audience operations. OutputStatusMessage("-----\nAddAudiences:"); var addAudiencesResponse = await CampaignManagementExampleHelper.AddAudiencesAsync( audiences : addAudiences); long?[] audienceIds = addAudiencesResponse.AudienceIds.ToArray(); BatchError[] audienceErrors = addAudiencesResponse.PartialErrors.ToArray(); OutputStatusMessage("AudienceIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(audienceIds); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(audienceErrors); // Add an ad group in a campaign. The ad group will later be associated with remarketing lists. 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); 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 }, // Applicable for all remarketing lists that are associated with this ad group. TargetAndBid indicates // that you want to show ads only to people included in the remarketing list, with the option to change // the bid amount. Ads in this ad group will only show to people included in the remarketing list. Settings = new[] { new TargetSetting { Details = new [] { new TargetSettingDetail { CriterionTypeGroup = CriterionTypeGroup.Audience, TargetAndBid = true } } } }, } }; 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); // Associate all of the remarketing lists created above with the new ad group. var adGroupRemarketingListAssociations = new List <AdGroupCriterion>(); foreach (var audienceId in audienceIds) { if (audienceId != null) { var biddableAdGroupCriterion = new BiddableAdGroupCriterion { AdGroupId = (long)adGroupIds[0], Criterion = new AudienceCriterion { AudienceId = audienceId, AudienceType = AudienceType.RemarketingList, }, CriterionBid = new BidMultiplier { Multiplier = 20.00, }, Status = AdGroupCriterionStatus.Active, }; adGroupRemarketingListAssociations.Add(biddableAdGroupCriterion); } } OutputStatusMessage("-----\nAddAdGroupCriterions:"); CampaignManagementExampleHelper.OutputArrayOfAdGroupCriterion(adGroupRemarketingListAssociations); AddAdGroupCriterionsResponse addAdGroupCriterionsResponse = await CampaignManagementExampleHelper.AddAdGroupCriterionsAsync( adGroupCriterions : adGroupRemarketingListAssociations, criterionType : AdGroupCriterionType.Audience); long?[] nullableAdGroupCriterionIds = addAdGroupCriterionsResponse.AdGroupCriterionIds.ToArray(); OutputStatusMessage("AdGroupCriterionIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(nullableAdGroupCriterionIds); BatchErrorCollection[] adGroupCriterionErrors = addAdGroupCriterionsResponse.NestedPartialErrors.ToArray(); OutputStatusMessage("NestedPartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(adGroupCriterionErrors); // 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])); // Delete the remarketing lists. OutputStatusMessage("-----\nDeleteAudiences:"); await CampaignManagementExampleHelper.DeleteAudiencesAsync( audienceIds : new[] { (long)audienceIds[0] }); OutputStatusMessage(string.Format("Deleted Audience Id {0}", audienceIds[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( OutputStatusMessageDefault: this.OutputStatusMessage); CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>( authorizationData: authorizationData, environment: environment); // Setup a campaign with one ad group. var campaigns = new[] { new Campaign { Name = "Women's Shoes " + DateTime.UtcNow, BudgetId = null, DailyBudget = 50, BudgetType = BudgetLimitType.DailyBudgetStandard, Languages = new string[] { "All" }, TimeZone = "PacificTimeUSCanadaTijuana", }, }; OutputStatusMessage("-----\nAddCampaigns:"); AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync( accountId : authorizationData.AccountId, campaigns : campaigns); 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 }, } }; 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); // When you first create a campaign or ad group using the Bing Ads API, it will not have any // target criteria. Effectively, the brand new campaign and ad group target all ages, days, hours, // devices, genders, and locations. As a best practice, you should consider at a minimum // adding a campaign location criterion corresponding to the customer market country. var campaignCriterions = new List <CampaignCriterion>(); var campaignLocationCriterion = new BiddableCampaignCriterion { CampaignId = (long)campaignIds[0], Criterion = new LocationCriterion { // United States LocationId = 190, Type = "LocationCriterion" }, CriterionBid = new BidMultiplier { Multiplier = 20 }, }; campaignCriterions.Add(campaignLocationCriterion); OutputStatusMessage("-----\nAddCampaignCriterions:"); var addCampaignCriterionsResponse = await CampaignManagementExampleHelper.AddCampaignCriterionsAsync( campaignCriterions : campaignCriterions, criterionType : CampaignCriterionType.Targets); long?[] campaignCriterionIds = addCampaignCriterionsResponse.CampaignCriterionIds.ToArray(); OutputStatusMessage("CampaignCriterionIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(campaignCriterionIds); BatchErrorCollection[] campaignCriterionErrors = addCampaignCriterionsResponse.NestedPartialErrors.ToArray(); OutputStatusMessage("NestedPartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(campaignCriterionErrors); // A negative location criterion is an excluded location. // Ads in this ad group will not be shown to people in Redmond, WA. var adGroupCriterions = new List <AdGroupCriterion>(); var adGroupNegativeAgeCriterion = new NegativeAdGroupCriterion { AdGroupId = (long)adGroupIds[0], Criterion = new LocationCriterion { // Redmond|Washington|United States LocationId = 67555, Type = "LocationCriterion" }, }; adGroupCriterions.Add(adGroupNegativeAgeCriterion); OutputStatusMessage("-----\nAddAdGroupCriterions:"); var addAdGroupCriterionsResponse = await CampaignManagementExampleHelper.AddAdGroupCriterionsAsync( adGroupCriterions : adGroupCriterions, criterionType : AdGroupCriterionType.Targets); long?[] adGroupCriterionIds = addAdGroupCriterionsResponse.AdGroupCriterionIds.ToArray(); OutputStatusMessage("AdGroupCriterionIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(adGroupCriterionIds); BatchErrorCollection[] adGroupCriterionErrors = addAdGroupCriterionsResponse.NestedPartialErrors.ToArray(); OutputStatusMessage("NestedPartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(adGroupCriterionErrors); // 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 <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); } }
public async override Task RunAsync(AuthorizationData authorizationData) { try { ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment; AdInsightExampleHelper AdInsightExampleHelper = new AdInsightExampleHelper( OutputStatusMessageDefault: this.OutputStatusMessage); AdInsightExampleHelper.AdInsightService = new ServiceClient <IAdInsightService>( authorizationData: authorizationData, environment: environment); CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper( OutputStatusMessageDefault: this.OutputStatusMessage); CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>( authorizationData: authorizationData, environment: environment); // To get started with dynamic search ads, first you'll need to add a new Campaign // with its type set to DynamicSearchAds. When you create the campaign, you'll need to // include a DynamicSearchAdsSetting that specifies the target website domain and language. var campaigns = new[] { new Campaign { BudgetType = Microsoft.BingAds.V13.CampaignManagement.BudgetLimitType.DailyBudgetStandard, DailyBudget = 50, CampaignType = CampaignType.DynamicSearchAds, Languages = new string[] { "All" }, Name = "Women's Shoes " + DateTime.UtcNow, TimeZone = "PacificTimeUSCanadaTijuana", Settings = new [] { new DynamicSearchAdsSetting { DomainName = "contoso.com", Language = "English" } }, }, }; OutputStatusMessage("-----\nAddCampaigns:"); AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync( accountId : authorizationData.AccountId, campaigns : campaigns); long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray(); Microsoft.BingAds.V13.CampaignManagement.BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); OutputStatusMessage("CampaignIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(campaignIds); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(campaignErrors); // Create a new ad group within the dynamic search ads 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 }, } }; OutputStatusMessage("-----\nAddAdGroups:"); AddAdGroupsResponse addAdGroupsResponse = await CampaignManagementExampleHelper.AddAdGroupsAsync( campaignId : (long)campaignIds[0], adGroups : adGroups, returnInheritedBidStrategyTypes : false); long?[] adGroupIds = addAdGroupsResponse.AdGroupIds.ToArray(); Microsoft.BingAds.V13.CampaignManagement.BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray(); OutputStatusMessage("AdGroupIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(adGroupIds); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(adGroupErrors); // You can add one or more Webpage criteria to each ad group that helps determine // whether or not to serve dynamic search ads. var adGroupCriterions = new List <AdGroupCriterion>(); var adGroupWebpagePositivePageContent = new BiddableAdGroupCriterion { AdGroupId = (long)adGroupIds[0], CriterionBid = new FixedBid { Amount = 0.50 }, Criterion = new Webpage { Parameter = new WebpageParameter { Conditions = new[] { new WebpageCondition { Argument = "flowers", Operand = WebpageConditionOperand.PageContent, } }, CriterionName = "Ad Group Webpage Positive Page Content Criterion" }, }, }; adGroupCriterions.Add(adGroupWebpagePositivePageContent); // To discover the categories that you can use for Webpage criteria (positive or negative), // use the GetDomainCategories operation with the Ad Insight service. OutputStatusMessage("-----\nGetDomainCategories:"); var getDomainCategoriesResponse = await AdInsightExampleHelper.GetDomainCategoriesAsync( categoryName : null, domainName : DOMAIN_NAME, language : LANGUAGE); var categories = getDomainCategoriesResponse.Categories; OutputStatusMessage("Categories:"); AdInsightExampleHelper.OutputArrayOfDomainCategory(categories); // If any categories are available let's use one as a condition. if (categories.Count > 0) { var adGroupWebpagePositiveCategory = new BiddableAdGroupCriterion { AdGroupId = (long)adGroupIds[0], CriterionBid = new FixedBid { Amount = 0.50 }, Criterion = new Webpage { Parameter = new WebpageParameter { Conditions = new[] { new WebpageCondition { Argument = categories[0].CategoryName, Operand = WebpageConditionOperand.Category, } }, CriterionName = "Ad Group Webpage Positive Category Criterion" }, } }; adGroupCriterions.Add(adGroupWebpagePositiveCategory); } // If you want to exclude certain portions of your website, you can add negative Webpage // criterion at the campaign and ad group level. var adGroupWebpageNegativeUrl = new NegativeAdGroupCriterion { AdGroupId = (long)adGroupIds[0], Criterion = new Webpage { Parameter = new WebpageParameter { // You can choose whether you want the criterion argument to match partial URLs, // page content, page title, or categories that Bing thinks applies to your website. Conditions = new[] { new WebpageCondition { Argument = DOMAIN_NAME, Operand = WebpageConditionOperand.Url, } }, // If you do not specify any name, then it will be set to a concatenated list of conditions. CriterionName = null } }, }; adGroupCriterions.Add(adGroupWebpageNegativeUrl); OutputStatusMessage("-----\nAddAdGroupCriterions:"); CampaignManagementExampleHelper.OutputArrayOfAdGroupCriterion(adGroupCriterions); AddAdGroupCriterionsResponse addAdGroupCriterionsResponse = await CampaignManagementExampleHelper.AddAdGroupCriterionsAsync( adGroupCriterions : adGroupCriterions, criterionType : AdGroupCriterionType.Webpage); long?[] adGroupCriterionIds = addAdGroupCriterionsResponse.AdGroupCriterionIds.ToArray(); OutputStatusMessage("AdGroupCriterionIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(adGroupCriterionIds); BatchErrorCollection[] adGroupCriterionErrors = addAdGroupCriterionsResponse.NestedPartialErrors.ToArray(); OutputStatusMessage("NestedPartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(adGroupCriterionErrors); // The negative Webpage criterion at the campaign level applies to all ad groups // within the campaign; however, if you define ad group level negative Webpage criterion, // the campaign criterion is ignored for that ad group. var campaignCriterions = new List <CampaignCriterion>(); var campaignWebpageNegative = new NegativeCampaignCriterion { CampaignId = (long)campaignIds[0], Criterion = new Webpage { Parameter = new WebpageParameter { Conditions = new[] { new WebpageCondition { Argument = DOMAIN_NAME + "\\seattle", Operand = WebpageConditionOperand.Url, } }, CriterionName = "Campaign Negative Webpage Url Criterion" } } }; campaignCriterions.Add(campaignWebpageNegative); OutputStatusMessage("-----\nAddCampaignCriterions:"); CampaignManagementExampleHelper.OutputArrayOfCampaignCriterion(campaignCriterions); AddCampaignCriterionsResponse addCampaignCriterionsResponse = await CampaignManagementExampleHelper.AddCampaignCriterionsAsync( campaignCriterions : campaignCriterions, criterionType : CampaignCriterionType.Webpage); long?[] campaignCriterionIds = addCampaignCriterionsResponse.CampaignCriterionIds.ToArray(); OutputStatusMessage("CampaignCriterionIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(campaignCriterionIds); BatchErrorCollection[] campaignCriterionErrors = addCampaignCriterionsResponse.NestedPartialErrors.ToArray(); OutputStatusMessage("NestedPartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(campaignCriterionErrors); // Finally you must add at least one DynamicSearchAd into the ad group. The ad title and display URL // are generated automatically based on the website domain and language that you want to target. var ads = new Ad[] { new DynamicSearchAd { Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.", Path1 = "seattle", Path2 = "shoe sale", // You cannot set FinalUrls for dynamic search ads. // The Final URL will be a dynamically selected landing page. // The final URL is distinct from the path that customers will see and click on in your ad. FinalUrls = null, }, }; OutputStatusMessage("-----\nAddAds:"); AddAdsResponse addAdsResponse = await CampaignManagementExampleHelper.AddAdsAsync( adGroupId : (long)adGroupIds[0], ads : ads); long?[] adIds = addAdsResponse.AdIds.ToArray(); Microsoft.BingAds.V13.CampaignManagement.BatchError[] adErrors = addAdsResponse.PartialErrors.ToArray(); OutputStatusMessage("AdIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(adIds); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(adErrors); // 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.V13.CampaignManagement.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <Microsoft.BingAds.V13.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.V13.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 { CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage); CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>(authorizationData); // Setup an Audience campaign with one ad group and a responsive ad. var campaigns = new[] { new Campaign { // 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, Description = "Red shoes line.", DailyBudget = 50, BudgetType = BudgetLimitType.DailyBudgetStandard, TimeZone = "PacificTimeUSCanadaTijuana", }, }; 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 }, // Language cannot be set for ad groups in Audience campaigns Language = null, // Network cannot be set for ad groups in Audience campaigns Network = null, Settings = new[] { new TargetSetting { // By including the corresponding TargetSettingDetail, // this example sets the "target and bid" option for // CompanyName, Industry, and JobFunction. We will only deliver ads to // people who meet at least one of your criteria. // By default the "bid only" option is set for Audience, Age, and Gender. // We will deliver ads to all audiences, ages, and genders, if they meet // your company name, industry, or job function criteria. Details = new [] { new TargetSettingDetail { CriterionTypeGroup = CriterionTypeGroup.CompanyName, TargetAndBid = true }, new TargetSettingDetail { CriterionTypeGroup = CriterionTypeGroup.Industry, TargetAndBid = true }, new TargetSettingDetail { CriterionTypeGroup = CriterionTypeGroup.JobFunction, TargetAndBid = true }, } } }, } }; var ads = new Ad[] { new ResponsiveAd { // Not applicable for responsive ads AdFormatPreference = null, BusinessName = "Contoso", CallToAction = CallToAction.AddToCart, // Not applicable for responsive ads DevicePreference = null, EditorialStatus = null, FinalAppUrls = null, FinalMobileUrls = new[] { "http://mobile.contoso.com/womenshoesale" }, FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, ForwardCompatibilityMap = null, Headline = "Fast & Easy Setup", Id = null, LandscapeImageMediaId = LandscapeImageMediaId, LandscapeLogoMediaId = LandscapeLogoMediaId, LongHeadline = "Find New Customers & Increase Sales!", SquareImageMediaId = SquareImageMediaId, SquareLogoMediaId = SquareLogoMediaId, Status = null, Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.", TrackingUrlTemplate = null, Type = null, UrlCustomParameters = null, } }; // Add the campaign, ad group, and ad AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync(authorizationData.AccountId, campaigns); long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray(); BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); CampaignManagementExampleHelper.OutputArrayOfLong(campaignIds); CampaignManagementExampleHelper.OutputArrayOfBatchError(campaignErrors); AddAdGroupsResponse addAdGroupsResponse = await CampaignManagementExampleHelper.AddAdGroupsAsync( (long)campaignIds[0], adGroups, false); long?[] adGroupIds = addAdGroupsResponse.AdGroupIds.ToArray(); BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray(); CampaignManagementExampleHelper.OutputArrayOfLong(adGroupIds); CampaignManagementExampleHelper.OutputArrayOfBatchError(adGroupErrors); AddAdsResponse addAdsResponse = await CampaignManagementExampleHelper.AddAdsAsync((long)adGroupIds[0], ads); long?[] adIds = addAdsResponse.AdIds.ToArray(); BatchError[] adErrors = addAdsResponse.PartialErrors.ToArray(); CampaignManagementExampleHelper.OutputArrayOfLong(adIds); CampaignManagementExampleHelper.OutputArrayOfBatchError(adErrors); // Whether or not the "target and bid" option has been set for a given // criterion type group, you can set bid adjustments for specific criteria. var adGroupCriterions = new List <AdGroupCriterion>(); var adGroupCompanyNameCriterion = new BiddableAdGroupCriterion { AdGroupId = (long)adGroupIds[0], CriterionBid = new FixedBid { Amount = 0.50 }, Criterion = new ProfileCriterion { ProfileId = 808251207, // Microsoft ProfileType = ProfileType.CompanyName }, }; adGroupCriterions.Add(adGroupCompanyNameCriterion); var adGroupIndustryCriterion = new BiddableAdGroupCriterion { AdGroupId = (long)adGroupIds[0], CriterionBid = new FixedBid { Amount = 0.50 }, Criterion = new ProfileCriterion { ProfileId = 807658654, // Computer & Network Security ProfileType = ProfileType.Industry }, }; adGroupCriterions.Add(adGroupIndustryCriterion); var adGroupJobFunctionCriterion = new BiddableAdGroupCriterion { AdGroupId = (long)adGroupIds[0], CriterionBid = new FixedBid { Amount = 0.50 }, Criterion = new ProfileCriterion { ProfileId = 807658477, // Engineering ProfileType = ProfileType.JobFunction }, }; adGroupCriterions.Add(adGroupJobFunctionCriterion); // Exclude ages twenty-five through thirty-four. var adGroupNegativeAgeCriterion = new NegativeAdGroupCriterion { AdGroupId = (long)adGroupIds[0], Criterion = new AgeCriterion { AgeRange = AgeRange.TwentyFiveToThirtyFour }, }; adGroupCriterions.Add(adGroupNegativeAgeCriterion); OutputStatusMessage("Adding Ad Group Criteria . . . \n"); CampaignManagementExampleHelper.OutputArrayOfAdGroupCriterion(adGroupCriterions); AddAdGroupCriterionsResponse addAdGroupCriterionsResponse = await CampaignManagementExampleHelper.AddAdGroupCriterionsAsync( adGroupCriterions, AdGroupCriterionType.Targets); long?[] adGroupCriterionIds = addAdGroupCriterionsResponse.AdGroupCriterionIds.ToArray(); OutputStatusMessage("New Ad Group Criterion Ids:\n"); CampaignManagementExampleHelper.OutputArrayOfLong(adGroupCriterionIds); BatchErrorCollection[] adGroupCriterionErrors = addAdGroupCriterionsResponse.NestedPartialErrors.ToArray(); OutputStatusMessage("\nAddAdGroupCriterions Errors:\n"); CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(adGroupCriterionErrors); // Delete the campaign, ad group, criteria, and ad that were previously added. // You should remove this line if you want to view the added entities in the // Bing Ads web application or another tool. await CampaignManagementExampleHelper.DeleteCampaignsAsync(authorizationData.AccountId, new[] { (long)campaignIds[0] }); OutputStatusMessage(string.Format("\nDeleted Campaign Id {0}\n", 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 { Service = 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; } #region ManageCampaign /* 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 campaigns = new [] { new Campaign { 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", DaylightSaving = true, // Used with FinalUrls shown in the product partitions that we will add below. TrackingUrlTemplate = "http://tracker.example.com/?season={_season}&promocode={_promocode}&u={lpurl}" } }; AddCampaignsResponse addCampaignsResponse = await AddCampaignsAsync(authorizationData.AccountId, campaigns); long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray(); BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); OutputCampaignsWithPartialErrors(campaigns, campaignIds, campaignErrors); long campaignId = (long)campaignIds[0]; /* 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 campaignCriterions = new CampaignCriterion[] { new CampaignCriterion() { CampaignId = campaignId, BidAdjustment = null, // Reserved for future use Criterion = new ProductScope() { Conditions = new ProductCondition[] { new ProductCondition { Operand = "Condition", Attribute = "New" }, new ProductCondition { Operand = "CustomLabel0", Attribute = "MerchantDefinedCustomLabel" }, } }, } }; var addCampaignCriterionsResponse = await(AddCampaignCriterionsAsync( campaignCriterions, CampaignCriterionType.ProductScope) ); #endregion ManageCampaign #region ManageAdGroup // Create the ad group that will have the product partitions. var adGroups = new[] { new AdGroup { Name = "Product Categories", AdDistribution = AdDistribution.Search, BiddingModel = BiddingModel.Keyword, PricingModel = PricingModel.Cpc, StartDate = null, EndDate = new Microsoft.BingAds.V10.CampaignManagement.Date { Month = 12, Day = 31, Year = DateTime.UtcNow.Year + 1 }, Language = "English" } }; AddAdGroupsResponse addAdGroupsResponse = await AddAdGroupsAsync((long)campaignId, adGroups); long?[] adGroupIds = addAdGroupsResponse.AdGroupIds.ToArray(); BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray(); OutputAdGroupsWithPartialErrors(adGroups, adGroupIds, adGroupErrors); long adGroupId = (long)adGroupIds[0]; #region BidAllProducts var helper = new PartitionActionHelper(adGroupId); var root = helper.AddUnit( null, new ProductCondition { Operand = "All", Attribute = null }, 0.35, false ); OutputStatusMessage("Applying only the root as a Unit with a bid . . . \n"); var applyProductPartitionActionsResponse = await ApplyProductPartitionActionsAsync(helper.PartitionActions); var adGroupCriterions = await GetAdGroupCriterionsByIdsAsync( adGroupId, null, CriterionType.ProductPartition ); OutputStatusMessage("The ad group's product partition only has a tree root node: \n"); OutputProductPartitions(adGroupCriterions); /* * Let's update the bid of the root Unit we just added. */ BiddableAdGroupCriterion updatedRoot = new BiddableAdGroupCriterion { Id = applyProductPartitionActionsResponse.AdGroupCriterionIds[0], CriterionBid = new FixedBid { Bid = new Bid { Amount = 0.45 } } }; helper = new PartitionActionHelper(adGroupId); helper.UpdatePartition(updatedRoot); OutputStatusMessage("Updating the bid for the tree root node . . . \n"); await ApplyProductPartitionActionsAsync(helper.PartitionActions); adGroupCriterions = await GetAdGroupCriterionsByIdsAsync( adGroupId, null, CriterionType.ProductPartition ); OutputStatusMessage("Updated the bid for the tree root node: \n"); OutputProductPartitions(adGroupCriterions); #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 5,000 nodes; however, * we will build it in steps to demonstrate how to use the results from ApplyProductPartitionActions 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 PartitionActionHelper(adGroupId); /* * Check whether a root node exists already. */ adGroupCriterions = await GetAdGroupCriterionsByIdsAsync( adGroupId, null, CriterionType.ProductPartition ); var existingRoot = GetRootNode(adGroupCriterions); if (existingRoot != null) { helper.DeletePartition(existingRoot); } root = helper.AddSubdivision( null, new ProductCondition { Operand = "All", Attribute = null } ); /* * 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" } ); /* * 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" } ); var brandA = helper.AddUnit( petSuppliesSubdivision, new ProductCondition { Operand = "Brand", Attribute = "Brand A" }, 0.35, false ); /* * 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 ); var otherBrands = helper.AddUnit( petSuppliesSubdivision, new ProductCondition { Operand = "Brand", Attribute = null }, 0.35, false ); var otherPetSupplies = helper.AddUnit( animalsSubdivision, new ProductCondition { Operand = "CategoryL2", Attribute = null }, 0.35, false ); var electronics = helper.AddUnit( root, new ProductCondition { Operand = "CategoryL1", Attribute = "Electronics" }, 0.35, false ); var otherCategoryL1 = helper.AddUnit( root, new ProductCondition { Operand = "CategoryL1", Attribute = null }, 0.35, false ); OutputStatusMessage("Applying product partitions to the ad group . . . \n"); applyProductPartitionActionsResponse = await ApplyProductPartitionActionsAsync(helper.PartitionActions); // To retrieve product partitions after they have been applied, call GetAdGroupCriterionsByIds. // The product partition with ParentCriterionId set to null is the root node. adGroupCriterions = await GetAdGroupCriterionsByIdsAsync( adGroupId, null, CriterionType.ProductPartition ); /* * 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(adGroupCriterions); #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 PartitionActionHelper(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), and was created at Index 1 of the previous ApplyProductPartitionActions call. * The node that we are replacing is Electronics (CategoryL1), and was created at Index 8. */ var rootId = applyProductPartitionActionsResponse.AdGroupCriterionIds[1]; electronics.Id = applyProductPartitionActionsResponse.AdGroupCriterionIds[8]; helper.DeletePartition(electronics); var parent = new BiddableAdGroupCriterion() { Id = rootId }; var electronicsSubdivision = helper.AddSubdivision( parent, new ProductCondition { Operand = "CategoryL1", Attribute = "Electronics" } ); var brandC = helper.AddUnit( electronicsSubdivision, new ProductCondition { Operand = "Brand", Attribute = "Brand C" }, 0.35, false ); var brandD = helper.AddUnit( electronicsSubdivision, new ProductCondition { Operand = "Brand", Attribute = "Brand D" }, 0.35, false ); var otherElectronicsBrands = helper.AddUnit( electronicsSubdivision, new ProductCondition { Operand = "Brand", Attribute = null }, 0.35, false ); OutputStatusMessage( "Updating the product partition group to refine Electronics (CategoryL1) with 3 child nodes . . . \n" ); applyProductPartitionActionsResponse = await ApplyProductPartitionActionsAsync(helper.PartitionActions); adGroupCriterions = await GetAdGroupCriterionsByIdsAsync( adGroupId, null, CriterionType.ProductPartition ); /* * 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(adGroupCriterions); #endregion UpdateTree #endregion ManageAdGroup #region ManageAds /* * 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 ads = new Ad[] { new ProductAd { PromotionalText = "Free shipping on $99 purchases." }, }; AddAdsResponse addAdsResponse = await AddAdsAsync((long)adGroupIds[0], ads); long?[] adIds = addAdsResponse.AdIds.ToArray(); BatchError[] adErrors = addAdsResponse.PartialErrors.ToArray(); OutputAdsWithPartialErrors(ads, adIds, adErrors); #endregion ManageAds #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. */ await DeleteCampaignsAsync(authorizationData.AccountId, new[] { (long)campaignId }); OutputStatusMessage(String.Format("Deleted CampaignId {0}\n", campaignId)); #endregion CleanUp } // 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.V10.CampaignManagement.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <Microsoft.BingAds.V10.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.V10.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 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 { Service = new ServiceClient <ICampaignManagementService>(authorizationData); // Specify one or more campaigns. var campaigns = new[] { new Campaign { Name = "Women's Shoes" + DateTime.UtcNow, Description = "Red shoes line.", BudgetType = BudgetLimitType.MonthlyBudgetSpendUntilDepleted, MonthlyBudget = 1000.00, TimeZone = "PacificTimeUSCanadaTijuana", DaylightSaving = true, // You can set your campaign bid strategy to Enhanced CPC (EnhancedCpcBiddingScheme) // and then, at any time, set an individual ad group or keyword bid strategy to // Manual CPC (ManualCpcBiddingScheme). // For campaigns you can use either of the EnhancedCpcBiddingScheme or ManualCpcBiddingScheme objects. // If you do not set this element, then ManualCpcBiddingScheme is used by default. BiddingScheme = new EnhancedCpcBiddingScheme { }, // Used with FinalUrls shown in the text ads that we will add below. TrackingUrlTemplate = "http://tracker.example.com/?season={_season}&promocode={_promocode}&u={lpurl}" }, }; // Specify one or more ad groups. var adGroups = new[] { new AdGroup { Name = "Women's Red Shoe Sale", AdDistribution = AdDistribution.Search, BiddingModel = BiddingModel.Keyword, PricingModel = PricingModel.Cpc, StartDate = null, EndDate = new Microsoft.BingAds.V10.CampaignManagement.Date { Month = 12, Day = 31, Year = DateTime.UtcNow.Year + 1 }, SearchBid = new Bid { Amount = 0.09 }, Language = "English", // For ad groups you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. // If you do not set this element, then InheritFromParentBiddingScheme is used by default. BiddingScheme = new ManualCpcBiddingScheme { }, // You could use a tracking template which would override the campaign level // tracking template. Tracking templates defined for lower level entities // override those set for higher level entities. // In this example we are using the campaign level tracking template. TrackingUrlTemplate = null, } }; // 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 keywords = new[] { 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", // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. // If you do not set this element, then InheritFromParentBiddingScheme is used by default. BiddingScheme = new InheritFromParentBiddingScheme { }, }, new Keyword { Bid = new Bid { Amount = 0.47 }, Param2 = "10% Off", MatchType = MatchType.Phrase, Text = "Brand-A Shoes", // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. // If you do not set this element, then InheritFromParentBiddingScheme is used by default. BiddingScheme = new InheritFromParentBiddingScheme { }, }, new Keyword { Bid = new Bid { Amount = 0.47 }, Param2 = "10% Off", MatchType = MatchType.Phrase, Text = "Brand-A Shoes", // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. // If you do not set this element, then InheritFromParentBiddingScheme is used by default. BiddingScheme = new InheritFromParentBiddingScheme { }, } }; // 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 ads = new Ad[] { new TextAd { Title = "Women's Shoe Sale", Text = "Huge Savings on red shoes.", DisplayUrl = "Contoso.com", // If you are currently using Destination URLs, you must replace them with Final URLs. // Here is an example of a DestinationUrl you might have used previously. // DestinationUrl = "http://www.contoso.com/womenshoesale/?season=spring&promocode=PROMO123", // To migrate from DestinationUrl to FinalUrls for existing ads, you can set DestinationUrl // to an empty string when updating the ad. If you are removing DestinationUrl, // then FinalUrls is required. // DestinationUrl = "", // With FinalUrls you can separate the tracking template, custom parameters, and // landing page URLs. FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, // Final Mobile URLs can also be used if you want to direct the user to a different page // for mobile devices. FinalMobileUrls = new[] { "http://mobile.contoso.com/womenshoesale" }, // You could use a tracking template which would override the campaign level // tracking template. Tracking templates defined for lower level entities // override those set for higher level entities. // In this example we are using the campaign level tracking template. TrackingUrlTemplate = null, // Set custom parameters that are specific to this ad, // and can be used by the ad, ad group, campaign, or account level tracking template. // In this example we are using the campaign level tracking template. UrlCustomParameters = new CustomParameters { Parameters = new[] { new CustomParameter() { Key = "promoCode", Value = "PROMO1" }, new CustomParameter() { Key = "season", Value = "summer" }, } } }, new TextAd { Title = "Women's Super Shoe Sale", Text = "Huge Savings on red shoes.", DisplayUrl = "Contoso.com", // If you are currently using Destination URLs, you must replace them with Final URLs. // Here is an example of a DestinationUrl you might have used previously. // DestinationUrl = "http://www.contoso.com/womenshoesale/?season=spring&promocode=PROMO123", // To migrate from DestinationUrl to FinalUrls for existing ads, you can set DestinationUrl // to an empty string when updating the ad. If you are removing DestinationUrl, // then FinalUrls is required. // DestinationUrl = "", // With FinalUrls you can separate the tracking template, custom parameters, and // landing page URLs. FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, // Final Mobile URLs can also be used if you want to direct the user to a different page // for mobile devices. FinalMobileUrls = new[] { "http://mobile.contoso.com/womenshoesale" }, // You could use a tracking template which would override the campaign level // tracking template. Tracking templates defined for lower level entities // override those set for higher level entities. // In this example we are using the campaign level tracking template. TrackingUrlTemplate = null, // Set custom parameters that are specific to this ad, // and can be used by the ad, ad group, campaign, or account level tracking template. // In this example we are using the campaign level tracking template. UrlCustomParameters = new CustomParameters { Parameters = new[] { new CustomParameter() { Key = "promoCode", Value = "PROMO2" }, new CustomParameter() { Key = "season", Value = "summer" }, } }, }, new TextAd { Title = "Women's Red Shoe Sale", Text = "Huge Savings on red shoes.", DisplayUrl = "Contoso.com", // If you are currently using Destination URLs, you must replace them with Final URLs. // Here is an example of a DestinationUrl you might have used previously. // DestinationUrl = "http://www.contoso.com/womenshoesale/?season=spring&promocode=PROMO123", // To migrate from DestinationUrl to FinalUrls for existing ads, you can set DestinationUrl // to an empty string when updating the ad. If you are removing DestinationUrl, // then FinalUrls is required. // DestinationUrl = "", // With FinalUrls you can separate the tracking template, custom parameters, and // landing page URLs. FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, // Final Mobile URLs can also be used if you want to direct the user to a different page // for mobile devices. FinalMobileUrls = new[] { "http://mobile.contoso.com/womenshoesale" }, // You could use a tracking template which would override the campaign level // tracking template. Tracking templates defined for lower level entities // override those set for higher level entities. // In this example we are using the campaign level tracking template. TrackingUrlTemplate = null, // Set custom parameters that are specific to this ad, // and can be used by the ad, ad group, campaign, or account level tracking template. // In this example we are using the campaign level tracking template. UrlCustomParameters = new CustomParameters { Parameters = new[] { new CustomParameter() { Key = "promoCode", Value = "PROMO3" }, new CustomParameter() { Key = "season", Value = "summer" }, } }, }, new TextAd { Title = "", Text = "Huge Savings on red shoes.", DisplayUrl = "Contoso.com", // If you are currently using Destination URLs, you must replace them with Final URLs. // Here is an example of a DestinationUrl you might have used previously. // DestinationUrl = "http://www.contoso.com/womenshoesale/?season=spring&promocode=PROMO123", // To migrate from DestinationUrl to FinalUrls for existing ads, you can set DestinationUrl // to an empty string when updating the ad. If you are removing DestinationUrl, // then FinalUrls is required. // DestinationUrl = "", // With FinalUrls you can separate the tracking template, custom parameters, and // landing page URLs. FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, // Final Mobile URLs can also be used if you want to direct the user to a different page // for mobile devices. FinalMobileUrls = new[] { "http://mobile.contoso.com/womenshoesale" }, // You could use a tracking template which would override the campaign level // tracking template. Tracking templates defined for lower level entities // override those set for higher level entities. // In this example we are using the campaign level tracking template. TrackingUrlTemplate = null, // Set custom parameters that are specific to this ad, // and can be used by the ad, ad group, campaign, or account level tracking template. // In this example we are using the campaign level tracking template. UrlCustomParameters = new CustomParameters { Parameters = new[] { new CustomParameter() { Key = "promoCode", Value = "PROMO4" }, new CustomParameter() { Key = "season", Value = "summer" }, } }, }, new TextAd { Title = "Women's Super Shoe Sale", Text = "Huge Savings on red shoes.", DisplayUrl = "Contoso.com", // If you are currently using Destination URLs, you must replace them with Final URLs. // Here is an example of a DestinationUrl you might have used previously. // DestinationUrl = "http://www.contoso.com/womenshoesale/?season=spring&promocode=PROMO123", // To migrate from DestinationUrl to FinalUrls for existing ads, you can set DestinationUrl // to an empty string when updating the ad. If you are removing DestinationUrl, // then FinalUrls is required. // DestinationUrl = "", // With FinalUrls you can separate the tracking template, custom parameters, and // landing page URLs. FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, // Final Mobile URLs can also be used if you want to direct the user to a different page // for mobile devices. FinalMobileUrls = new[] { "http://mobile.contoso.com/womenshoesale" }, // You could use a tracking template which would override the campaign level // tracking template. Tracking templates defined for lower level entities // override those set for higher level entities. // In this example we are using the campaign level tracking template. TrackingUrlTemplate = null, // Set custom parameters that are specific to this ad, // and can be used by the ad, ad group, campaign, or account level tracking template. // In this example we are using the campaign level tracking template. UrlCustomParameters = new CustomParameters { Parameters = new[] { new CustomParameter() { Key = "promoCode", Value = "PROMO5" }, new CustomParameter() { Key = "season", Value = "summer" }, } }, }, }; // Add the campaign, ad group, keywords, and ads AddCampaignsResponse addCampaignsResponse = await AddCampaignsAsync(authorizationData.AccountId, campaigns); long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray(); BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); AddAdGroupsResponse addAdGroupsResponse = await AddAdGroupsAsync((long)campaignIds[0], adGroups); long?[] adGroupIds = addAdGroupsResponse.AdGroupIds.ToArray(); BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray(); AddKeywordsResponse addKeywordsResponse = await AddKeywordsAsync((long)adGroupIds[0], keywords); long?[] keywordIds = addKeywordsResponse.KeywordIds.ToArray(); BatchError[] keywordErrors = addKeywordsResponse.PartialErrors.ToArray(); AddAdsResponse addAdsResponse = await AddAdsAsync((long)adGroupIds[0], ads); long?[] adIds = addAdsResponse.AdIds.ToArray(); BatchError[] adErrors = addAdsResponse.PartialErrors.ToArray(); // Output the new assigned entity identifiers, as well as any partial errors OutputCampaignsWithPartialErrors(campaigns, campaignIds, campaignErrors); OutputAdGroupsWithPartialErrors(adGroups, adGroupIds, adGroupErrors); OutputKeywordsWithPartialErrors(keywords, keywordIds, keywordErrors); OutputAdsWithPartialErrors(ads, adIds, adErrors); // Here is a simple example that updates the campaign budget. var updateCampaign = new Campaign { Id = campaignIds[0], MonthlyBudget = 500, }; // As an exercise you can step through using the debugger and view the results. await GetCampaignsByIdsAsync( authorizationData.AccountId, new [] { (long)campaignIds[0] }, CampaignType.SearchAndContent | CampaignType.Shopping, CampaignAdditionalField.BiddingScheme ); await UpdateCampaignsAsync(authorizationData.AccountId, new[] { updateCampaign }); await GetCampaignsByIdsAsync( authorizationData.AccountId, new[] { (long)campaignIds[0] }, CampaignType.SearchAndContent | CampaignType.Shopping, CampaignAdditionalField.BiddingScheme ); // Update the Text for the 3 successfully created ads, and update some UrlCustomParameters. var updateAds = new Ad[] { new TextAd { Id = adIds[0], Text = "Huge Savings on All Red Shoes.", // Set the UrlCustomParameters element to null or empty to retain any // existing custom parameters. UrlCustomParameters = null, }, new TextAd { Id = adIds[1], Text = "Huge Savings on All Red Shoes.", // To remove all custom parameters, set the Parameters element of the // CustomParameters object to null or empty. UrlCustomParameters = new CustomParameters { Parameters = null, }, }, new TextAd { Id = adIds[2], Text = "Huge Savings on All Red Shoes.", // To remove a subset of custom parameters, specify the custom parameters that // you want to keep in the Parameters element of the CustomParameters object. UrlCustomParameters = new CustomParameters { Parameters = new[] { new CustomParameter() { Key = "promoCode", Value = "updatedpromo" }, } } }, }; // As an exercise you can step through using the debugger and view the results. await GetAdsByAdGroupIdAsync((long)adGroupIds[0]); var updateAdsResponse = await UpdateAdsAsync((long)adGroupIds[0], updateAds); await GetAdsByAdGroupIdAsync((long)adGroupIds[0]); // Here is a simple example that updates the keyword bid to use the ad group bid. var updateKeyword = new Keyword { // Set Bid.Amount null (new empty Bid) to use the ad group bid. // If the Bid property is null, your keyword bid will not be updated. Bid = new Bid(), Id = keywordIds[1], }; // As an exercise you can step through using the debugger and view the results. await GetKeywordsByAdGroupIdAsync((long)adGroupIds[0], KeywordAdditionalField.BiddingScheme); await UpdateKeywordsAsync((long)adGroupIds[0], new[] { updateKeyword }); await GetKeywordsByAdGroupIdAsync((long)adGroupIds[0], KeywordAdditionalField.BiddingScheme); // Delete the campaign, ad group, keyword, and ad that were previously added. // You should remove this line if you want to view the added entities in the // Bing Ads web application or another tool. await DeleteCampaignsAsync(authorizationData.AccountId, new[] { (long)campaignIds[0] }); OutputStatusMessage(String.Format("Deleted CampaignId {0}\n", 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.V10.CampaignManagement.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <Microsoft.BingAds.V10.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.V10.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 an ad group in a campaign. Later we will create labels for them. // Although not included in this example you can also create labels for ads and keywords. var campaigns = new[] { new Campaign { BudgetType = BudgetLimitType.DailyBudgetStandard, DailyBudget = 50, CampaignType = CampaignType.Search, 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); 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 }, } }; 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 labels and associate them with the campaign and ad group. var random = new Random(); var labels = new List <Label>(); for (var labelIndex = 0; labelIndex < 5; labelIndex++) { var color = string.Format("#{0:X6}", random.Next(0x100000)); labels.Add(new Label { ColorCode = color, Description = "Label Description", Name = "Label Name " + color + " " + DateTime.UtcNow }); } OutputStatusMessage("-----\nAddLabels:"); AddLabelsResponse addLabelsResponse = await CampaignManagementExampleHelper.AddLabelsAsync(labels); long?[] nullableLabelIds = addLabelsResponse.LabelIds.ToArray(); BatchError[] labelErrors = addLabelsResponse.PartialErrors.ToArray(); OutputStatusMessage("LabelIds:"); CampaignManagementExampleHelper.OutputArrayOfLong(nullableLabelIds); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(labelErrors); var labelIds = GetNonNullableIds(nullableLabelIds); OutputStatusMessage("-----\nGetLabelsByIds:"); var getLabelsByIdsResponse = await CampaignManagementExampleHelper.GetLabelsByIdsAsync( labelIds : labelIds, pageInfo : new Paging { Index = 0, Size = MaxGetLabelsByIds } ); var getLabels = getLabelsByIdsResponse.Labels; labelErrors = getLabelsByIdsResponse.PartialErrors.ToArray(); OutputStatusMessage("Labels:"); CampaignManagementExampleHelper.OutputArrayOfLabel(getLabels); OutputStatusMessage("PartialErrors:"); CampaignManagementExampleHelper.OutputArrayOfBatchError(labelErrors); var campaignLabelAssociations = CreateExampleLabelAssociationsByEntityId((long)campaignIds[0], labelIds); OutputStatusMessage("-----\nAssociating all of the labels with a campaign..."); CampaignManagementExampleHelper.OutputArrayOfLabelAssociation(campaignLabelAssociations); var setLabelAssociationsResponse = await CampaignManagementExampleHelper.SetLabelAssociationsAsync( entityType : EntityType.Campaign, labelAssociations : campaignLabelAssociations); var adGroupLabelAssociations = CreateExampleLabelAssociationsByEntityId((long)adGroupIds[0], labelIds); OutputStatusMessage("-----\nAssociating all of the labels with an ad group..."); CampaignManagementExampleHelper.OutputArrayOfLabelAssociation(adGroupLabelAssociations); setLabelAssociationsResponse = await CampaignManagementExampleHelper.SetLabelAssociationsAsync( entityType : EntityType.AdGroup, labelAssociations : adGroupLabelAssociations); OutputStatusMessage("-----\nUse paging to get all campaign label associations..."); var getLabelAssociationsByLabelIds = await GetLabelAssociationsByLabelIdsHelperAsync( CampaignManagementExampleHelper, entityType : EntityType.Campaign, labelIds : labelIds); CampaignManagementExampleHelper.OutputArrayOfLabelAssociation(getLabelAssociationsByLabelIds); OutputStatusMessage("-----\nUse paging to get all ad group label associations..."); getLabelAssociationsByLabelIds = await GetLabelAssociationsByLabelIdsHelperAsync( CampaignManagementExampleHelper : CampaignManagementExampleHelper, entityType : EntityType.AdGroup, labelIds : labelIds); CampaignManagementExampleHelper.OutputArrayOfLabelAssociation(getLabelAssociationsByLabelIds); OutputStatusMessage("-----\nGet label associations for the campaigns..."); var getLabelAssociationsByEntityIds = await GetLabelAssociationsByEntityIdsHelperAsync( CampaignManagementExampleHelper : CampaignManagementExampleHelper, entityType : EntityType.Campaign, entityIds : GetNonNullableIds(campaignIds) ); CampaignManagementExampleHelper.OutputArrayOfLabelAssociation(getLabelAssociationsByEntityIds); OutputStatusMessage("-----\nGet label associations for the ad groups..."); getLabelAssociationsByEntityIds = await GetLabelAssociationsByEntityIdsHelperAsync( CampaignManagementExampleHelper : CampaignManagementExampleHelper, entityType : EntityType.AdGroup, entityIds : GetNonNullableIds(adGroupIds) ); CampaignManagementExampleHelper.OutputArrayOfLabelAssociation(getLabelAssociationsByEntityIds); OutputStatusMessage("-----\nDelete all label associations that we set above..."); // Deleting the associations is not necessary if you are deleting the corresponding campaign(s), as the // contained ad groups, ads, and associations would also be deleted. var deleteLabelAssociationsResponse = await CampaignManagementExampleHelper.DeleteLabelAssociationsAsync( entityType : EntityType.Campaign, labelAssociations : campaignLabelAssociations); deleteLabelAssociationsResponse = await CampaignManagementExampleHelper.DeleteLabelAssociationsAsync( entityType : EntityType.AdGroup, labelAssociations : adGroupLabelAssociations); // Delete the account's labels. OutputStatusMessage("-----\nDeleteLabels:"); var deleteLabelsResponse = await CampaignManagementExampleHelper.DeleteLabelsAsync( labelIds : labelIds); foreach (var id in labelIds) { OutputStatusMessage(string.Format("Deleted Label 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); } }
private async Task <IList <long> > GetExampleCampaignIdsAsync( CampaignManagementExampleHelper CampaignManagementExampleHelper, AuthorizationData authorizationData) { var campaigns = new[] { new Campaign { Name = "Campaign One " + DateTime.UtcNow, Description = "Red shoes line.", DailyBudget = 20, BudgetType = BudgetLimitType.DailyBudgetStandard, TimeZone = "PacificTimeUSCanadaTijuana", }, }; var adGroups = new[] { new AdGroup { Name = "Women's Shoe Sale One " + DateTime.UtcNow, CpcBid = new Bid { Amount = 0.09 }, Language = "English", }, new AdGroup { Name = "Women's Shoe Sale Two " + DateTime.UtcNow, CpcBid = new Bid { Amount = 0.09 }, Language = "English", }, new AdGroup { Name = "Women's Shoe Sale Three " + DateTime.UtcNow, CpcBid = new Bid { Amount = 0.09 }, Language = "English", }, }; // Add the campaigns and ad groups OutputStatusMessage("Add campaigns:\n"); AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync( authorizationData.AccountId, campaigns, false); long?[] nillableCampaignIds = addCampaignsResponse.CampaignIds.ToArray(); BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); CampaignManagementExampleHelper.OutputArrayOfLong(nillableCampaignIds); CampaignManagementExampleHelper.OutputArrayOfBatchError(campaignErrors); OutputStatusMessage("Add ad groups:\n"); AddAdGroupsResponse addAdGroupsResponse = await CampaignManagementExampleHelper.AddAdGroupsAsync((long)nillableCampaignIds[0], adGroups, null); long?[] nillableAdGroupIds = addAdGroupsResponse.AdGroupIds.ToArray(); BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray(); CampaignManagementExampleHelper.OutputArrayOfLong(nillableAdGroupIds); CampaignManagementExampleHelper.OutputArrayOfBatchError(adGroupErrors); List <long> campaignIds = new List <long>(); foreach (var campaignId in nillableCampaignIds) { campaignIds.Add((long)campaignId); } return(campaignIds); }
public async override Task RunAsync(AuthorizationData authorizationData) { try { CampaignService = new ServiceClient <ICampaignManagementService>(authorizationData); var budgetIds = new List <long?>(); var budgets = new List <Budget>(); budgets.Add(new Budget { Amount = 50, BudgetType = BudgetLimitType.DailyBudgetStandard, Name = "My Shared Budget " + DateTime.UtcNow, }); budgetIds = (await AddBudgetsAsync(budgets)).BudgetIds.ToList(); // Specify one or more campaigns. var campaigns = new[] { new Campaign { Name = "Women's Shoes " + DateTime.UtcNow, Description = "Red shoes line.", // You must choose to set either the shared budget ID or daily amount. // You can set one or the other, but you may not set both. BudgetId = budgetIds.Count > 0 ? budgetIds[0] : null, DailyBudget = budgetIds.Count > 0 ? 0 : 50, BudgetType = BudgetLimitType.DailyBudgetStandard, // You can set your campaign bid strategy to Enhanced CPC (EnhancedCpcBiddingScheme) // and then, at any time, set an individual ad group or keyword bid strategy to // Manual CPC (ManualCpcBiddingScheme). // For campaigns you can use either of the EnhancedCpcBiddingScheme or ManualCpcBiddingScheme objects. // If you do not set this element, then ManualCpcBiddingScheme is used by default. BiddingScheme = new EnhancedCpcBiddingScheme { }, TimeZone = "PacificTimeUSCanadaTijuana", DaylightSaving = true, // Used with FinalUrls shown in the text ads that we will add below. TrackingUrlTemplate = "http://tracker.example.com/?season={_season}&promocode={_promocode}&u={lpurl}" }, }; // Specify one or more ad groups. var adGroups = new[] { new AdGroup { Name = "Women's Red Shoe Sale", AdDistribution = AdDistribution.Search, BiddingModel = BiddingModel.Keyword, PricingModel = PricingModel.Cpc, StartDate = null, EndDate = new Microsoft.BingAds.V10.CampaignManagement.Date { Month = 12, Day = 31, Year = DateTime.UtcNow.Year + 1 }, SearchBid = new Bid { Amount = 0.09 }, Language = "English", // For ad groups you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. // If you do not set this element, then InheritFromParentBiddingScheme is used by default. BiddingScheme = new ManualCpcBiddingScheme { }, // You could use a tracking template which would override the campaign level // tracking template. Tracking templates defined for lower level entities // override those set for higher level entities. // In this example we are using the campaign level tracking template. TrackingUrlTemplate = null, } }; // 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 keywords = new[] { 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", // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. // If you do not set this element, then InheritFromParentBiddingScheme is used by default. BiddingScheme = new InheritFromParentBiddingScheme { }, }, new Keyword { Bid = new Bid { Amount = 0.47 }, Param2 = "10% Off", MatchType = MatchType.Phrase, Text = "Brand-A Shoes", // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. // If you do not set this element, then InheritFromParentBiddingScheme is used by default. BiddingScheme = new InheritFromParentBiddingScheme { }, }, new Keyword { Bid = new Bid { Amount = 0.47 }, Param2 = "10% Off", MatchType = MatchType.Phrase, Text = "Brand-A Shoes", // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. // If you do not set this element, then InheritFromParentBiddingScheme is used by default. BiddingScheme = new InheritFromParentBiddingScheme { }, } }; // In this example only the first 3 ads should succeed. // The TitlePart2 of the fourth ad is empty and not valid, // and the fifth ad is a duplicate of the second ad. var ads = new Ad[] { new ExpandedTextAd { TitlePart1 = "Contoso", TitlePart2 = "Fast & Easy Setup", Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.", Path1 = "seattle", Path2 = "shoe sale", // With FinalUrls you can separate the tracking template, custom parameters, and // landing page URLs. FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, // Final Mobile URLs can also be used if you want to direct the user to a different page // for mobile devices. FinalMobileUrls = new[] { "http://mobile.contoso.com/womenshoesale" }, // You could use a tracking template which would override the campaign level // tracking template. Tracking templates defined for lower level entities // override those set for higher level entities. // In this example we are using the campaign level tracking template. TrackingUrlTemplate = null, // Set custom parameters that are specific to this ad, // and can be used by the ad, ad group, campaign, or account level tracking template. // In this example we are using the campaign level tracking template. UrlCustomParameters = new CustomParameters { Parameters = new[] { new CustomParameter() { Key = "promoCode", Value = "PROMO1" }, new CustomParameter() { Key = "season", Value = "summer" }, } } }, new ExpandedTextAd { TitlePart1 = "Contoso", TitlePart2 = "Quick & Easy Setup", Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.", Path1 = "seattle", Path2 = "shoe sale", // With FinalUrls you can separate the tracking template, custom parameters, and // landing page URLs. FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, // Final Mobile URLs can also be used if you want to direct the user to a different page // for mobile devices. FinalMobileUrls = new[] { "http://mobile.contoso.com/womenshoesale" }, // You could use a tracking template which would override the campaign level // tracking template. Tracking templates defined for lower level entities // override those set for higher level entities. // In this example we are using the campaign level tracking template. TrackingUrlTemplate = null, // Set custom parameters that are specific to this ad, // and can be used by the ad, ad group, campaign, or account level tracking template. // In this example we are using the campaign level tracking template. UrlCustomParameters = new CustomParameters { Parameters = new[] { new CustomParameter() { Key = "promoCode", Value = "PROMO2" }, new CustomParameter() { Key = "season", Value = "summer" }, } }, }, new ExpandedTextAd { TitlePart1 = "Contoso", TitlePart2 = "Fast & Simple Setup", Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.", Path1 = "seattle", Path2 = "shoe sale", // With FinalUrls you can separate the tracking template, custom parameters, and // landing page URLs. FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, // Final Mobile URLs can also be used if you want to direct the user to a different page // for mobile devices. FinalMobileUrls = new[] { "http://mobile.contoso.com/womenshoesale" }, // You could use a tracking template which would override the campaign level // tracking template. Tracking templates defined for lower level entities // override those set for higher level entities. // In this example we are using the campaign level tracking template. TrackingUrlTemplate = null, // Set custom parameters that are specific to this ad, // and can be used by the ad, ad group, campaign, or account level tracking template. // In this example we are using the campaign level tracking template. UrlCustomParameters = new CustomParameters { Parameters = new[] { new CustomParameter() { Key = "promoCode", Value = "PROMO3" }, new CustomParameter() { Key = "season", Value = "summer" }, } }, }, new ExpandedTextAd { TitlePart1 = "Contoso", TitlePart2 = "", Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.", Path1 = "seattle", Path2 = "shoe sale", // With FinalUrls you can separate the tracking template, custom parameters, and // landing page URLs. FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, // Final Mobile URLs can also be used if you want to direct the user to a different page // for mobile devices. FinalMobileUrls = new[] { "http://mobile.contoso.com/womenshoesale" }, // You could use a tracking template which would override the campaign level // tracking template. Tracking templates defined for lower level entities // override those set for higher level entities. // In this example we are using the campaign level tracking template. TrackingUrlTemplate = null, // Set custom parameters that are specific to this ad, // and can be used by the ad, ad group, campaign, or account level tracking template. // In this example we are using the campaign level tracking template. UrlCustomParameters = new CustomParameters { Parameters = new[] { new CustomParameter() { Key = "promoCode", Value = "PROMO4" }, new CustomParameter() { Key = "season", Value = "summer" }, } }, }, new ExpandedTextAd { TitlePart1 = "Contoso", TitlePart2 = "Quick & Easy Setup", Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.", Path1 = "seattle", Path2 = "shoe sale", // With FinalUrls you can separate the tracking template, custom parameters, and // landing page URLs. FinalUrls = new[] { "http://www.contoso.com/womenshoesale" }, // Final Mobile URLs can also be used if you want to direct the user to a different page // for mobile devices. FinalMobileUrls = new[] { "http://mobile.contoso.com/womenshoesale" }, // You could use a tracking template which would override the campaign level // tracking template. Tracking templates defined for lower level entities // override those set for higher level entities. // In this example we are using the campaign level tracking template. TrackingUrlTemplate = null, // Set custom parameters that are specific to this ad, // and can be used by the ad, ad group, campaign, or account level tracking template. // In this example we are using the campaign level tracking template. UrlCustomParameters = new CustomParameters { Parameters = new[] { new CustomParameter() { Key = "promoCode", Value = "PROMO5" }, new CustomParameter() { Key = "season", Value = "summer" }, } }, }, }; // Add the campaign, ad group, keywords, and ads AddCampaignsResponse addCampaignsResponse = await AddCampaignsAsync(authorizationData.AccountId, campaigns); long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray(); BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); AddAdGroupsResponse addAdGroupsResponse = await AddAdGroupsAsync((long)campaignIds[0], adGroups); long?[] adGroupIds = addAdGroupsResponse.AdGroupIds.ToArray(); BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray(); AddKeywordsResponse addKeywordsResponse = await AddKeywordsAsync((long)adGroupIds[0], keywords); long?[] keywordIds = addKeywordsResponse.KeywordIds.ToArray(); BatchError[] keywordErrors = addKeywordsResponse.PartialErrors.ToArray(); AddAdsResponse addAdsResponse = await AddAdsAsync((long)adGroupIds[0], ads); long?[] adIds = addAdsResponse.AdIds.ToArray(); BatchError[] adErrors = addAdsResponse.PartialErrors.ToArray(); // Output the new assigned entity identifiers, as well as any partial errors OutputCampaignsWithPartialErrors(campaigns, campaignIds, campaignErrors); OutputAdGroupsWithPartialErrors(adGroups, adGroupIds, adGroupErrors); OutputKeywordsWithPartialErrors(keywords, keywordIds, keywordErrors); OutputAdsWithPartialErrors(ads, adIds, adErrors); // Here is a simple example that updates the campaign budget. // If the campaign has a shared budget you cannot update the Campaign budget amount, // and you must instead update the amount in the Budget object. If you try to update // the budget amount of a campaign that has a shared budget, the service will return // the CampaignServiceCannotUpdateSharedBudget error code. var getCampaigns = (await GetCampaignsByAccountIdAsync( authorizationData.AccountId, CampaignType.SearchAndContent | CampaignType.Shopping, CampaignAdditionalField.BiddingScheme | CampaignAdditionalField.BudgetId )).Campaigns; var updateCampaigns = new List <Campaign>(); var updateBudgets = new List <Budget>(); var getCampaignIds = new List <long>(); var getBudgetIds = new List <long>(); // Increase existing budgets by 20% foreach (var campaign in getCampaigns) { // If the campaign has a shared budget, let's add the budget ID to the list we will update later. if (campaign != null && campaign.BudgetId > 0) { getBudgetIds.Add((long)campaign.BudgetId); } // If the campaign has its own budget, let's add it to the list of campaigns to update later. else if (campaign != null) { var updateCampaign = new Campaign { Id = campaign.Id, }; // Monthly budgets are deprecated and there will be a forced migration to daily budgets in calendar year 2017. // Shared budgets do not support the monthly budget type, so this is only applicable to unshared budgets. // During the migration all campaign level unshared budgets will be rationalized as daily. // The formula that will be used to convert monthly to daily budgets is: Monthly budget amount / 30.4. // Moving campaign monthly budget to daily budget is encouraged before monthly budgets are migrated. if (campaign.BudgetType == BudgetLimitType.MonthlyBudgetSpendUntilDepleted) { // Increase budget by 20 % updateCampaign.BudgetType = BudgetLimitType.DailyBudgetStandard; updateCampaign.DailyBudget = (campaign.MonthlyBudget / 30.4) * 1.2; } else { // Increase budget by 20 % updateCampaign.DailyBudget = campaign.DailyBudget * 1.2; } updateCampaigns.Add(updateCampaign); } } // Update shared budgets in Budget objects. if (getBudgetIds.Count > 0) { // The UpdateBudgets operation only accepts 100 Budget objects per call. // To simply the example we will update the first 100. getBudgetIds = getBudgetIds.Distinct().Take(100).ToList(); var getBudgets = (await GetBudgetsByIdsAsync(getBudgetIds)).Budgets; OutputStatusMessage("List of shared budgets BEFORE update:\n"); foreach (var budget in getBudgets) { OutputStatusMessage("Budget:"); OutputBudget(budget); } OutputStatusMessage("List of campaigns that share each budget:\n"); var getCampaignIdCollection = (await GetCampaignIdsByBudgetIdsAsync(getBudgetIds)).CampaignIdCollection; for (int index = 0; index < getCampaignIdCollection.Count; index++) { OutputStatusMessage(string.Format("BudgetId: {0}", getBudgetIds[index])); OutputStatusMessage("Campaign Ids:"); if (getCampaignIdCollection[index] != null) { foreach (var id in getCampaignIdCollection[index].Ids) { OutputStatusMessage(string.Format("\t{0}", id)); } } } foreach (var budget in getBudgets) { if (budget != null) { // Increase budget by 20 % budget.Amount *= 1.2m; updateBudgets.Add(budget); } } await UpdateBudgetsAsync(updateBudgets); getBudgets = (await GetBudgetsByIdsAsync(getBudgetIds)).Budgets; OutputStatusMessage("List of shared budgets AFTER update:\n"); foreach (var budget in getBudgets) { OutputStatusMessage("Budget:"); OutputBudget(budget); } } // Update unshared budgets in Campaign objects. if (updateCampaigns.Count > 0) { // The UpdateCampaigns operation only accepts 100 Campaign objects per call. // To simply the example we will update the first 100. updateCampaigns = updateCampaigns.Take(100).ToList(); foreach (var campaign in updateCampaigns) { getCampaignIds.Add((long)campaign.Id); } await UpdateCampaignsAsync(authorizationData.AccountId, updateCampaigns); getCampaigns = (await GetCampaignsByIdsAsync( authorizationData.AccountId, getCampaignIds, CampaignType.SearchAndContent | CampaignType.Shopping, CampaignAdditionalField.BiddingScheme | CampaignAdditionalField.BudgetId )).Campaigns; OutputStatusMessage("List of campaigns with unshared budget AFTER budget update:\n"); foreach (var campaign in getCampaigns) { OutputStatusMessage("Campaign:"); OutputCampaign(campaign); } } // Update the Text for the 3 successfully created ads, and update some UrlCustomParameters. var updateAds = new Ad[] { new ExpandedTextAd { Id = adIds[0], Text = "Huge Savings on All Red Shoes.", // Set the UrlCustomParameters element to null or empty to retain any // existing custom parameters. UrlCustomParameters = null, }, new ExpandedTextAd { Id = adIds[1], Text = "Huge Savings on All Red Shoes.", // To remove all custom parameters, set the Parameters element of the // CustomParameters object to null or empty. UrlCustomParameters = new CustomParameters { Parameters = null, }, }, new ExpandedTextAd { Id = adIds[2], Text = "Huge Savings on All Red Shoes.", // To remove a subset of custom parameters, specify the custom parameters that // you want to keep in the Parameters element of the CustomParameters object. UrlCustomParameters = new CustomParameters { Parameters = new[] { new CustomParameter() { Key = "promoCode", Value = "updatedpromo" }, } } }, }; // As an exercise you can step through using the debugger and view the results. var getAdsByAdGroupIdResponse = await GetAdsByAdGroupIdAsync((long)adGroupIds[0]); var updateAdsResponse = await UpdateAdsAsync((long)adGroupIds[0], updateAds); getAdsByAdGroupIdResponse = await GetAdsByAdGroupIdAsync((long)adGroupIds[0]); // Here is a simple example that updates the keyword bid to use the ad group bid. var updateKeyword = new Keyword { // Set Bid.Amount null (new empty Bid) to use the ad group bid. // If the Bid property is null, your keyword bid will not be updated. Bid = new Bid(), Id = keywordIds[1], }; // As an exercise you can step through using the debugger and view the results. var getKeywordsByAdGroupIdResponse = await GetKeywordsByAdGroupIdAsync((long)adGroupIds[0], KeywordAdditionalField.BiddingScheme); var updateKeywordsResponse = await UpdateKeywordsAsync((long)adGroupIds[0], new[] { updateKeyword }); getKeywordsByAdGroupIdResponse = await GetKeywordsByAdGroupIdAsync((long)adGroupIds[0], KeywordAdditionalField.BiddingScheme); // Delete the campaign, ad group, keyword, and ad that were previously added. // You should remove this line if you want to view the added entities in the // Bing Ads web application or another tool. await DeleteCampaignsAsync(authorizationData.AccountId, new[] { (long)campaignIds[0] }); OutputStatusMessage(string.Format("\nDeleted Campaign Id {0}\n", campaignIds[0])); // This sample will attempt to delete the budget that was created above. if (budgetIds.Count > 0) { await DeleteBudgetsAsync(new[] { (long)budgetIds[0] }); OutputStatusMessage(string.Format("\nDeleted Budget Id {0}\n", budgetIds[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.V10.CampaignManagement.AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException <Microsoft.BingAds.V10.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.V10.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); } }
private async Task <IList <long> > GetExampleCampaignIdsAsync(AuthorizationData authorizationData) { var campaigns = new[] { new Campaign { Name = "Campaign One " + DateTime.UtcNow, Description = "Red shoes line.", DailyBudget = 20, BudgetType = BudgetLimitType.DailyBudgetStandard, TimeZone = "PacificTimeUSCanadaTijuana", }, }; var adGroups = new[] { new AdGroup { Name = "Women's Shoe Sale One " + DateTime.UtcNow, AdDistribution = AdDistribution.Search, SearchBid = new Bid { Amount = 0.09 }, Language = "English", }, new AdGroup { Name = "Women's Shoe Sale Two " + DateTime.UtcNow, AdDistribution = AdDistribution.Search, SearchBid = new Bid { Amount = 0.09 }, Language = "English", }, new AdGroup { Name = "Women's Shoe Sale Three " + DateTime.UtcNow, AdDistribution = AdDistribution.Search, SearchBid = new Bid { Amount = 0.09 }, Language = "English", }, }; // Add the campaigns and ad groups OutputStatusMessage("Add campaigns:\n"); AddCampaignsResponse addCampaignsResponse = await AddCampaignsAsync(authorizationData.AccountId, campaigns); long?[] nillableCampaignIds = addCampaignsResponse.CampaignIds.ToArray(); BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray(); OutputIds(nillableCampaignIds); OutputPartialErrors(campaignErrors); OutputStatusMessage("Add ad groups:\n"); AddAdGroupsResponse addAdGroupsResponse = await AddAdGroupsAsync((long)nillableCampaignIds[0], adGroups); long?[] nillableAdGroupIds = addAdGroupsResponse.AdGroupIds.ToArray(); BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray(); OutputIds(nillableAdGroupIds); OutputPartialErrors(adGroupErrors); // This example uses the deprecated version 10 shared target library in order to later demonstrate // the inline migration from shared target criterions to unshared target criterions. List <long> adGroupIds = new List <long>(); foreach (var adGroupId in nillableAdGroupIds) { adGroupIds.Add((long)adGroupId); } // The shared target ID is output within the ShareDeprecatedTargetsAsync method. // We won't do anything further with it in this example. var sharedTargetId = await ShareDeprecatedTargetsAsync(authorizationData, adGroupIds); List <long> campaignIds = new List <long>(); foreach (var campaignId in nillableCampaignIds) { campaignIds.Add((long)campaignId); } return(campaignIds); }