Example #1
0
        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);
            }
        }
Example #3
0
        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);
            }
        }
Example #4
0
        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);
            }
        }
Example #6
0
        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);
            }
        }
Example #8
0
        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);
            }
        }
Example #10
0
        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);
            }
        }
Example #15
0
        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);
            }
        }
Example #16
0
        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);
            }
        }
Example #17
0
        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);
            }
        }
Example #18
0
        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);
        }
Example #19
0
        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);
            }
        }
Example #20
0
        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);
        }