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 { ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment; CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage); CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>(authorizationData, environment); // 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; // Optionally you can update the name and description of a UetTag with the UpdateUetTags operation. OutputStatusMessage("UET Tag BEFORE update:\n"); CampaignManagementExampleHelper.OutputUetTag(uetTags[0]); uetTags = new[] { new UetTag { Description = "Updated Uet Tag Description", Id = tagId, Name = "Updated Uet Tag Name " + DateTime.UtcNow, } }; await CampaignManagementExampleHelper.UpdateUetTagsAsync(uetTags); uetTags = (await CampaignManagementExampleHelper.GetUetTagsByIdsAsync(new[] { (long)tagId })).UetTags; OutputStatusMessage("UET Tag AFTER update:\n"); CampaignManagementExampleHelper.OutputUetTag(uetTags[0]); // Add conversion goals that depend on the UET Tag Id retreived above. // Please note that you cannot delete conversion goals. If you want to stop // tracking conversions for the goal, you can set the goal status to Paused. var conversionGoals = new ConversionGoal[] { new DurationGoal { ConversionWindowInMinutes = 30, CountType = ConversionGoalCountType.All, MinimumDurationInSeconds = 60, Name = "My Duration Goal " + DateTime.UtcNow, Revenue = new ConversionGoalRevenue { Type = ConversionGoalRevenueType.FixedValue, Value = 5.00m, CurrencyCode = null }, Scope = EntityScope.Account, Status = ConversionGoalStatus.Active, TagId = tagId, }, new EventGoal { // The type of user interaction you want to track. ActionExpression = "play", ActionOperator = ExpressionOperator.Contains, // The category of event you want to track. CategoryExpression = "video", CategoryOperator = ExpressionOperator.Contains, ConversionWindowInMinutes = 30, CountType = ConversionGoalCountType.All, // The name of the element that caused the action. LabelExpression = "trailer", LabelOperator = ExpressionOperator.Contains, Name = "My Event Goal " + DateTime.UtcNow, Revenue = new ConversionGoalRevenue { Type = ConversionGoalRevenueType.FixedValue, Value = 5.00m, CurrencyCode = null }, Scope = EntityScope.Account, Status = ConversionGoalStatus.Active, TagId = tagId, // A numerical value associated with that event. // Could be length of the video played etc. Value = 5.00m, ValueOperator = ValueOperator.Equals, }, new PagesViewedPerVisitGoal { ConversionWindowInMinutes = 30, CountType = ConversionGoalCountType.All, MinimumPagesViewed = 5, Name = "My Pages Viewed Per Visit Goal " + DateTime.UtcNow, Revenue = new ConversionGoalRevenue { Type = ConversionGoalRevenueType.FixedValue, Value = 5.00m, CurrencyCode = null }, Scope = EntityScope.Account, Status = ConversionGoalStatus.Active, TagId = tagId, }, new UrlGoal { ConversionWindowInMinutes = 30, CountType = ConversionGoalCountType.All, Name = "My Url Goal " + DateTime.UtcNow, Revenue = new ConversionGoalRevenue { Type = ConversionGoalRevenueType.FixedValue, Value = 5.00m, CurrencyCode = null }, Scope = EntityScope.Account, Status = ConversionGoalStatus.Active, TagId = tagId, UrlExpression = "contoso", UrlOperator = ExpressionOperator.Contains }, new AppInstallGoal { // You must provide a valid app platform and app store identifier, // otherwise this goal will not be added successfully. AppPlatform = "Windows", AppStoreId = "AppStoreIdGoesHere", ConversionWindowInMinutes = 30, CountType = ConversionGoalCountType.All, Name = "My App Install Goal " + DateTime.UtcNow, Revenue = new ConversionGoalRevenue { Type = ConversionGoalRevenueType.FixedValue, Value = 5.00m, CurrencyCode = null }, // Account scope is not supported for app install goals. You can // set scope to Customer or don't set it for the same result. Scope = EntityScope.Customer, Status = ConversionGoalStatus.Active, // The TagId is inherited from the ConversionGoal base class, // however, App Install goals do not use a UET tag. TagId = null, }, }; var addConversionGoalsResponse = await CampaignManagementExampleHelper.AddConversionGoalsAsync(conversionGoals); // Find the conversion goals that were added successfully. List <long> conversionGoalIds = GetNonNullableIds(addConversionGoalsResponse.ConversionGoalIds); OutputStatusMessage("List of errors returned from AddConversionGoals (if any):\n"); CampaignManagementExampleHelper.OutputArrayOfBatchError(addConversionGoalsResponse.PartialErrors); var conversionGoalTypes = ConversionGoalType.AppInstall | ConversionGoalType.Duration | ConversionGoalType.Event | ConversionGoalType.PagesViewedPerVisit | ConversionGoalType.Url; var getConversionGoals = (await CampaignManagementExampleHelper.GetConversionGoalsByIdsAsync(conversionGoalIds, conversionGoalTypes)).ConversionGoals; OutputStatusMessage("List of conversion goals BEFORE update:\n"); foreach (var conversionGoal in getConversionGoals) { CampaignManagementExampleHelper.OutputConversionGoal(conversionGoal); } var updateConversionGoals = new ConversionGoal[] { new DurationGoal { ConversionWindowInMinutes = 60, CountType = ConversionGoalCountType.Unique, // You can change the conversion goal type e.g. in this example an event goal // had been created above at index 1. Now we are using the returned identifier // at index 1 to update the type from EventGoal to DurationGoal. Id = conversionGoalIds[1], MinimumDurationInSeconds = 120, Name = "My Updated Duration Goal " + DateTime.UtcNow, Revenue = new ConversionGoalRevenue { Type = ConversionGoalRevenueType.FixedValue, Value = 10.00m, CurrencyCode = null }, // The Scope cannot be updated, even if you update the goal type. // You can either send the same value or leave Scope empty. Scope = EntityScope.Account, Status = ConversionGoalStatus.Paused, // 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 EventGoal { // For both add and update conversion goal operations, you must include one or more // of the following events: // ActionExpression, CategoryExpression, LabelExpression, or Value. // For example if you do not include ActionExpression during update, // any existing ActionOperator and ActionExpression settings will be deleted. ActionExpression = null, ActionOperator = null, CategoryExpression = "video", CategoryOperator = ExpressionOperator.Equals, Id = conversionGoalIds[0], // You cannot update the operator unless you also include the expression. // The following attempt to update LabelOperator will result in an error. LabelExpression = null, LabelOperator = ExpressionOperator.Equals, Name = "My Updated Event Goal " + DateTime.UtcNow, Revenue = new ConversionGoalRevenue { Type = ConversionGoalRevenueType.FixedValue, Value = 5.00m, CurrencyCode = null }, // You must specify the previous settings unless you want // them replaced during the update conversion goal operation. Value = 5.00m, ValueOperator = ValueOperator.Equals, }, new PagesViewedPerVisitGoal { Id = conversionGoalIds[2], Name = "My Updated Pages Viewed Per Visit Goal " + DateTime.UtcNow, // When updating a conversion goal, if the Revenue element is nil or empty then none // of the nested properties will be updated. However, if this element is not nil or empty // then you are effectively replacing any existing revenue properties. For example to delete // any previous revenue settings, set the Revenue element to an empty ConversionGoalRevenue object. Revenue = new ConversionGoalRevenue(), }, new UrlGoal { Id = conversionGoalIds[3], Name = "My Updated Url Goal" + DateTime.UtcNow, // If not specified during update, the previous Url settings are retained. UrlExpression = null, UrlOperator = ExpressionOperator.BeginsWith } }; var updateConversionGoalsResponse = await CampaignManagementExampleHelper.UpdateConversionGoalsAsync(updateConversionGoals); OutputStatusMessage("List of errors returned from UpdateConversionGoals (if any):\n"); CampaignManagementExampleHelper.OutputArrayOfBatchError(updateConversionGoalsResponse.PartialErrors); getConversionGoals = (await CampaignManagementExampleHelper.GetConversionGoalsByIdsAsync(conversionGoalIds, conversionGoalTypes)).ConversionGoals; OutputStatusMessage("List of conversion goals AFTER update:\n"); foreach (var conversionGoal in getConversionGoals) { CampaignManagementExampleHelper.OutputConversionGoal(conversionGoal); } } // 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 ConversionGoal 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); // 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://msdn.microsoft.com/library/bing-ads-universal-event-tracking-guide.aspx. // 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 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 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) { 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://msdn.microsoft.com/library/bing-ads-universal-event-tracking-guide.aspx. // We will use the same UET tag for the remainder of this example. var tagId = uetTags[0].Id; // Optionally you can update the name and description of a UetTag with the UpdateUetTags operation. OutputStatusMessage("UET Tag BEFORE update:\n"); OutputUetTag(uetTags[0]); uetTags = new[] { new UetTag { Description = "Updated Uet Tag Description", Id = tagId, Name = "Updated Uet Tag Name " + DateTime.UtcNow, } }; await UpdateUetTagsAsync(uetTags); uetTags = (await GetUetTagsByIdsAsync(new[] { (long)tagId })).UetTags; OutputStatusMessage("UET Tag AFTER update:\n"); OutputUetTag(uetTags[0]); // Add conversion goals that depend on the UET Tag Id retreived above. // Please note that you cannot delete conversion goals. If you want to stop // tracking conversions for the goal, you can set the goal status to Paused. var conversionGoals = new ConversionGoal[] { new DurationGoal { ConversionWindowInMinutes = 30, CountType = ConversionGoalCountType.All, MinimumDurationInSeconds = 60, Name = "My Duration Goal " + DateTime.UtcNow, Revenue = new ConversionGoalRevenue { Type = ConversionGoalRevenueType.FixedValue, Value = 5.00m, CurrencyCode = null }, Scope = EntityScope.Account, Status = ConversionGoalStatus.Active, TagId = tagId, }, new EventGoal { // The type of user interaction you want to track. ActionExpression = "play", ActionOperator = ExpressionOperator.Contains, // The category of event you want to track. CategoryExpression = "video", CategoryOperator = ExpressionOperator.Contains, ConversionWindowInMinutes = 30, CountType = ConversionGoalCountType.All, // The name of the element that caused the action. LabelExpression = "trailer", LabelOperator = ExpressionOperator.Contains, Name = "My Event Goal " + DateTime.UtcNow, Revenue = new ConversionGoalRevenue { Type = ConversionGoalRevenueType.FixedValue, Value = 5.00m, CurrencyCode = null }, Scope = EntityScope.Account, Status = ConversionGoalStatus.Active, TagId = tagId, // A numerical value associated with that event. // Could be length of the video played etc. Value = 5.00m, ValueOperator = ValueOperator.Equals, }, new PagesViewedPerVisitGoal { ConversionWindowInMinutes = 30, CountType = ConversionGoalCountType.All, MinimumPagesViewed = 5, Name = "My Pages Viewed Per Visit Goal " + DateTime.UtcNow, Revenue = new ConversionGoalRevenue { Type = ConversionGoalRevenueType.FixedValue, Value = 5.00m, CurrencyCode = null }, Scope = EntityScope.Account, Status = ConversionGoalStatus.Active, TagId = tagId, }, new UrlGoal { ConversionWindowInMinutes = 30, CountType = ConversionGoalCountType.All, Name = "My Url Goal " + DateTime.UtcNow, Revenue = new ConversionGoalRevenue { Type = ConversionGoalRevenueType.FixedValue, Value = 5.00m, CurrencyCode = null }, Scope = EntityScope.Account, Status = ConversionGoalStatus.Active, TagId = tagId, UrlExpression = "contoso", UrlOperator = ExpressionOperator.Contains }, new AppInstallGoal { // You must provide a valid app platform and app store identifier, // otherwise this goal will not be added successfully. AppPlatform = "Windows", AppStoreId = "AppStoreIdGoesHere", ConversionWindowInMinutes = 30, CountType = ConversionGoalCountType.All, Name = "My App Install Goal " + DateTime.UtcNow, Revenue = new ConversionGoalRevenue { Type = ConversionGoalRevenueType.FixedValue, Value = 5.00m, CurrencyCode = null }, // Account scope is not supported for app install goals. You can // set scope to Customer or don't set it for the same result. Scope = EntityScope.Customer, Status = ConversionGoalStatus.Active, // The TagId is inherited from the ConversionGoal base class, // however, App Install goals do not use a UET tag. TagId = null, }, }; var addConversionGoalsResponse = await AddConversionGoalsAsync(conversionGoals); // Find the conversion goals that were added successfully. List<long> conversionGoalIds = new List<long>(); foreach (var goalId in addConversionGoalsResponse.ConversionGoalIds) { if (goalId != null) { conversionGoalIds.Add((long)goalId); } } OutputStatusMessage("List of errors returned from AddConversionGoals (if any):\n"); OutputPartialErrors(addConversionGoalsResponse.PartialErrors); var conversionGoalTypes = ConversionGoalType.AppInstall | ConversionGoalType.Duration | ConversionGoalType.Event | ConversionGoalType.PagesViewedPerVisit | ConversionGoalType.Url; var getConversionGoals = (await GetConversionGoalsByIdsAsync(conversionGoalIds, conversionGoalTypes)).ConversionGoals; OutputStatusMessage("List of conversion goals BEFORE update:\n"); foreach (var conversionGoal in getConversionGoals) { OutputConversionGoal(conversionGoal); } var updateConversionGoals = new ConversionGoal[] { new DurationGoal { ConversionWindowInMinutes = 60, CountType = ConversionGoalCountType.Unique, // You can change the conversion goal type e.g. in this example an event goal // had been created above at index 1. Now we are using the returned identifier // at index 1 to update the type from EventGoal to DurationGoal. Id = conversionGoalIds[1], MinimumDurationInSeconds = 120, Name = "My Updated Duration Goal " + DateTime.UtcNow, Revenue = new ConversionGoalRevenue { Type = ConversionGoalRevenueType.FixedValue, Value = 10.00m, CurrencyCode = null }, // The Scope cannot be updated, even if you update the goal type. // You can either send the same value or leave Scope empty. Scope = EntityScope.Account, Status = ConversionGoalStatus.Paused, // 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 EventGoal { // For both add and update conversion goal operations, you must include one or more // of the following events: // ActionExpression, CategoryExpression, LabelExpression, or Value. // For example if you do not include ActionExpression during update, // any existing ActionOperator and ActionExpression settings will be deleted. ActionExpression = null, ActionOperator = null, CategoryExpression = "video", CategoryOperator = ExpressionOperator.Equals, Id = conversionGoalIds[0], // You cannot update the operator unless you also include the expression. // The following attempt to update LabelOperator will result in an error. LabelExpression = null, LabelOperator = ExpressionOperator.Equals, Name = "My Updated Event Goal " + DateTime.UtcNow, Revenue = new ConversionGoalRevenue { Type = ConversionGoalRevenueType.FixedValue, Value = 5.00m, CurrencyCode = null }, // You must specify the previous settings unless you want // them replaced during the update conversion goal operation. Value = 5.00m, ValueOperator = ValueOperator.Equals, }, new PagesViewedPerVisitGoal { Id = conversionGoalIds[2], Name = "My Updated Pages Viewed Per Visit Goal " + DateTime.UtcNow, // When updating a conversion goal, if the Revenue element is nil or empty then none // of the nested properties will be updated. However, if this element is not nil or empty // then you are effectively replacing any existing revenue properties. For example to delete // any previous revenue settings, set the Revenue element to an empty ConversionGoalRevenue object. Revenue = new ConversionGoalRevenue(), }, new UrlGoal { Id = conversionGoalIds[3], Name = "My Updated Url Goal" + DateTime.UtcNow, // If not specified during update, the previous Url settings are retained. UrlExpression = null, UrlOperator = ExpressionOperator.BeginsWith } }; var updateConversionGoalsResponse = await UpdateConversionGoalsAsync(updateConversionGoals); OutputStatusMessage("List of errors returned from UpdateConversionGoals (if any):\n"); OutputPartialErrors(updateConversionGoalsResponse.PartialErrors); getConversionGoals = (await GetConversionGoalsByIdsAsync(conversionGoalIds, conversionGoalTypes)).ConversionGoals; OutputStatusMessage("List of conversion goals AFTER update:\n"); foreach (var conversionGoal in getConversionGoals) { OutputConversionGoal(conversionGoal); } } // 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 ConversionGoal 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); // 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); } }