コード例 #1
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                AdInsightExampleHelper AdInsightExampleHelper = new AdInsightExampleHelper(this.OutputStatusMessage);
                AdInsightExampleHelper.AdInsightService = new ServiceClient <IAdInsightService>(authorizationData);

                CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage);
                CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>(authorizationData);

                var campaigns = (await CampaignManagementExampleHelper.GetCampaignsByAccountIdAsync(
                                     authorizationData.AccountId,
                                     AllCampaignTypes,
                                     false)).Campaigns;

                IList <BudgetOpportunity> opportunities = null;

                // Get the budget opportunities for each campaign in the current authenticated account.

                foreach (var campaign in campaigns)
                {
                    if (campaign.Id != null)
                    {
                        opportunities = (await AdInsightExampleHelper.GetBudgetOpportunitiesAsync((long)campaign.Id)).Opportunities;
                        AdInsightExampleHelper.OutputArrayOfBudgetOpportunity(opportunities);
                    }
                }
            }
            // 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 AdInsight service exceptions
            catch (FaultException <Microsoft.BingAds.V11.AdInsight.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V11.AdInsight.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 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 (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }
コード例 #2
0
        private async Task <List <LabelAssociation> > GetLabelAssociationsByLabelIdsHelperAsync(
            CampaignManagementExampleHelper CampaignManagementExampleHelper,
            EntityType entityType,
            IList <long> labelIds
            )
        {
            var labelAssociations = new List <LabelAssociation>();
            var labelIdsPageIndex = 0;

            while (labelIdsPageIndex * MaxLabelIdsForGetLabelAssociations < labelIds.Count)
            {
                var getLabelIds =
                    labelIds.Skip(labelIdsPageIndex++ *MaxLabelIdsForGetLabelAssociations).Take(MaxLabelIdsForGetLabelAssociations).ToList();

                var labelAssociationsPageIndex = 0;
                var foundLastPage = false;

                while (!foundLastPage)
                {
                    var getLabelAssociationsByLabelIds = await CampaignManagementExampleHelper.GetLabelAssociationsByLabelIdsAsync(
                        entityType : entityType,
                        labelIds : getLabelIds,
                        pageInfo : new Paging
                    {
                        Index = labelAssociationsPageIndex++,
                        Size  = MaxPagingSize
                    }
                        ).ConfigureAwait(continueOnCapturedContext: false);

                    labelAssociations.AddRange(getLabelAssociationsByLabelIds.LabelAssociations);
                    foundLastPage = MaxPagingSize > getLabelAssociationsByLabelIds.LabelAssociations.Count;
                }
            }

            return(labelAssociations);
        }
コード例 #3
0
        private async Task <List <LabelAssociation> > GetLabelAssociationsByEntityIdsHelperAsync(
            CampaignManagementExampleHelper CampaignManagementExampleHelper,
            EntityType entityType,
            IList <long> entityIds
            )
        {
            var labelAssociations  = new List <LabelAssociation>();
            var entityIdsPageIndex = 0;

            while (entityIdsPageIndex * MaxEntityIdsForGetLabelAssociations < entityIds.Count)
            {
                var getEntityIds =
                    entityIds.Skip(entityIdsPageIndex++ *MaxEntityIdsForGetLabelAssociations).Take(MaxEntityIdsForGetLabelAssociations).ToList();

                var getLabelAssociationsByEntityIds = await CampaignManagementExampleHelper.GetLabelAssociationsByEntityIdsAsync(
                    entityIds : getEntityIds,
                    entityType : entityType
                    ).ConfigureAwait(continueOnCapturedContext: false);

                labelAssociations.AddRange(getLabelAssociationsByEntityIds.LabelAssociations);
            }

            return(labelAssociations);
        }
コード例 #4
0
        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);

                // Add a campaign that will later be associated with negative keywords.

                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",
                    }
                };

                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];

                // You may choose to associate an exclusive set of negative keywords to an individual campaign
                // or ad group. An exclusive set of negative keywords cannot be shared with other campaigns
                // or ad groups. This example only associates negative keywords with a campaign.

                var entityNegativeKeywords = new[]
                {
                    new EntityNegativeKeyword
                    {
                        EntityId         = campaignId,
                        EntityType       = "Campaign",
                        NegativeKeywords = new[]
                        {
                            new NegativeKeyword
                            {
                                MatchType = MatchType.Phrase,
                                Text      = "auto"
                            },
                            new NegativeKeyword
                            {
                                MatchType = MatchType.Phrase,
                                Text      = "auto"
                            },
                        }
                    }
                };

                AddNegativeKeywordsToEntitiesResponse addNegativeKeywordsToEntitiesResponse =
                    await CampaignManagementExampleHelper.AddNegativeKeywordsToEntitiesAsync(entityNegativeKeywords);

                CampaignManagementExampleHelper.OutputArrayOfIdCollection(addNegativeKeywordsToEntitiesResponse.NegativeKeywordIds);
                CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(addNegativeKeywordsToEntitiesResponse.NestedPartialErrors);
                if (addNegativeKeywordsToEntitiesResponse.NestedPartialErrors == null ||
                    addNegativeKeywordsToEntitiesResponse.NestedPartialErrors.Count == 0)
                {
                    OutputStatusMessage("Added an exclusive set of negative keywords to the Campaign.\n");
                    CampaignManagementExampleHelper.OutputArrayOfIdCollection(addNegativeKeywordsToEntitiesResponse.NegativeKeywordIds);
                }
                else
                {
                    CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(addNegativeKeywordsToEntitiesResponse.NestedPartialErrors);
                }

                GetNegativeKeywordsByEntityIdsResponse getNegativeKeywordsByEntityIdsResponse =
                    await CampaignManagementExampleHelper.GetNegativeKeywordsByEntityIdsAsync(new[] { campaignId }, "Campaign", authorizationData.AccountId);

                CampaignManagementExampleHelper.OutputArrayOfEntityNegativeKeyword(getNegativeKeywordsByEntityIdsResponse.EntityNegativeKeywords);
                CampaignManagementExampleHelper.OutputArrayOfBatchError(getNegativeKeywordsByEntityIdsResponse.PartialErrors);
                if (getNegativeKeywordsByEntityIdsResponse.PartialErrors == null ||
                    getNegativeKeywordsByEntityIdsResponse.PartialErrors.Count == 0)
                {
                    OutputStatusMessage("Retrieved an exclusive set of negative keywords for the Campaign.\n");
                    CampaignManagementExampleHelper.OutputArrayOfEntityNegativeKeyword(getNegativeKeywordsByEntityIdsResponse.EntityNegativeKeywords);
                }
                else
                {
                    CampaignManagementExampleHelper.OutputArrayOfBatchError(getNegativeKeywordsByEntityIdsResponse.PartialErrors);
                }

                // If you attempt to delete a negative keyword without an identifier the operation will
                // succeed but will return partial errors corresponding to the index of the negative keyword
                // that was not deleted.
                var nestedPartialErrors = (BatchErrorCollection[])(await CampaignManagementExampleHelper.DeleteNegativeKeywordsFromEntitiesAsync(entityNegativeKeywords)).NestedPartialErrors;
                if (nestedPartialErrors == null || nestedPartialErrors.Length == 0)
                {
                    OutputStatusMessage("Deleted an exclusive set of negative keywords from the Campaign.\n");
                }
                else
                {
                    OutputStatusMessage("Attempt to DeleteNegativeKeywordsFromEntities without NegativeKeyword identifier partially fails by design.");
                    CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(nestedPartialErrors);
                }

                // Delete the negative keywords with identifiers that were returned above.
                nestedPartialErrors = (BatchErrorCollection[])(await CampaignManagementExampleHelper.DeleteNegativeKeywordsFromEntitiesAsync(
                                                                   getNegativeKeywordsByEntityIdsResponse.EntityNegativeKeywords)).NestedPartialErrors;
                if (nestedPartialErrors == null || nestedPartialErrors.Length == 0)
                {
                    OutputStatusMessage("Deleted an exclusive set of negative keywords from the Campaign.\n");
                }
                else
                {
                    CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(nestedPartialErrors);
                }

                // Negative keywords can also be added and deleted from a shared negative keyword list.
                // The negative keyword list can be shared or associated with multiple campaigns.
                // NegativeKeywordList inherits from SharedList which inherits from SharedEntity.

                var negativeKeywordList = new NegativeKeywordList
                {
                    Name = "My Negative Keyword List" + DateTime.UtcNow,
                    Type = "NegativeKeywordList"
                };

                SharedListItem[] negativeKeywords =
                {
                    new NegativeKeyword
                    {
                        Text      = "car",
                        Type      = "NegativeKeyword",
                        MatchType = MatchType.Exact
                    },
                    new NegativeKeyword
                    {
                        Text      = "car",
                        Type      = "NegativeKeyword",
                        MatchType = MatchType.Phrase
                    }
                };

                // You can create a new list for negative keywords with or without negative keywords.

                var addSharedEntityResponse = await CampaignManagementExampleHelper.AddSharedEntityAsync(negativeKeywordList, negativeKeywords);

                var    sharedEntityId = addSharedEntityResponse.SharedEntityId;
                long[] listItemIds    = addSharedEntityResponse.ListItemIds.ToArray();

                OutputStatusMessage(string.Format("NegativeKeywordList successfully added to account library and assigned identifer {0}\n", sharedEntityId));

                negativeKeywordList.Id = addSharedEntityResponse.SharedEntityId;
                CampaignManagementExampleHelper.OutputSharedEntity(negativeKeywordList);
                CampaignManagementExampleHelper.OutputArrayOfSharedListItem(negativeKeywords.ToList());
                CampaignManagementExampleHelper.OutputArrayOfBatchError(addSharedEntityResponse.PartialErrors);

                OutputStatusMessage("Negative keywords currently in NegativeKeywordList:");
                negativeKeywords = (SharedListItem[])(await CampaignManagementExampleHelper.GetListItemsBySharedListAsync(new NegativeKeywordList {
                    Id = sharedEntityId
                })).ListItems;
                if (negativeKeywords == null || negativeKeywords.Length == 0)
                {
                    OutputStatusMessage("None\n");
                }
                else
                {
                    CampaignManagementExampleHelper.OutputArrayOfNegativeKeyword(negativeKeywords.Cast <NegativeKeyword>().ToList());
                }

                // To update the list of negative keywords, you must either add or remove from the list
                // using the respective AddListItemsToSharedList or DeleteListItemsFromSharedList operations.
                // To remove the negative keywords from the list pass the negative keyword identifers
                // and negative keyword list (SharedEntity) identifer.

                var partialErrors = (await CampaignManagementExampleHelper.DeleteListItemsFromSharedListAsync(listItemIds, new NegativeKeywordList {
                    Id = sharedEntityId
                }))?.PartialErrors;
                if (partialErrors == null || !partialErrors.Any())
                {
                    OutputStatusMessage("Deleted most recently added negative keywords from negative keyword list.\n");
                }
                else
                {
                    CampaignManagementExampleHelper.OutputArrayOfBatchError(partialErrors);
                }

                OutputStatusMessage("Negative keywords currently in NegativeKeywordList:");
                negativeKeywords = (SharedListItem[])(await CampaignManagementExampleHelper.GetListItemsBySharedListAsync(new NegativeKeywordList {
                    Id = sharedEntityId
                })).ListItems;
                if (negativeKeywords == null || negativeKeywords.Length == 0)
                {
                    OutputStatusMessage("None\n");
                }
                else
                {
                    CampaignManagementExampleHelper.OutputArrayOfNegativeKeyword(negativeKeywords.Cast <NegativeKeyword>().ToList());
                }

                // Whether you created the list with or without negative keywords, more can be added
                // using the AddListItemsToSharedList operation.

                negativeKeywords = new SharedListItem[]
                {
                    new NegativeKeyword
                    {
                        Text      = "auto",
                        Type      = "NegativeKeyword",
                        MatchType = MatchType.Exact
                    },
                    new NegativeKeyword
                    {
                        Text      = "auto",
                        Type      = "NegativeKeyword",
                        MatchType = MatchType.Phrase
                    }
                };

                var addListItemsToSharedListResponse = await CampaignManagementExampleHelper.AddListItemsToSharedListAsync(
                    negativeKeywords,
                    new NegativeKeywordList { Id = sharedEntityId });

                listItemIds = addListItemsToSharedListResponse.ListItemIds.ToArray();

                CampaignManagementExampleHelper.OutputArrayOfSharedListItem(negativeKeywords.ToList());
                CampaignManagementExampleHelper.OutputArrayOfBatchError(addListItemsToSharedListResponse.PartialErrors);

                OutputStatusMessage("Negative keywords currently in NegativeKeywordList:");
                negativeKeywords = (SharedListItem[])(await CampaignManagementExampleHelper.GetListItemsBySharedListAsync(new NegativeKeywordList {
                    Id = sharedEntityId
                })).ListItems;
                if (negativeKeywords == null || negativeKeywords.Length == 0)
                {
                    OutputStatusMessage("None\n");
                }
                else
                {
                    CampaignManagementExampleHelper.OutputArrayOfNegativeKeyword(negativeKeywords.Cast <NegativeKeyword>().ToList());
                }

                // You can update the name of the negative keyword list.

                negativeKeywordList = new NegativeKeywordList
                {
                    Id   = sharedEntityId,
                    Name = "My Updated Negative Keyword List",
                    Type = "NegativeKeywordList"
                };

                partialErrors = (await CampaignManagementExampleHelper.UpdateSharedEntitiesAsync(new SharedEntity[] { negativeKeywordList })).PartialErrors;
                if (partialErrors == null || !partialErrors.Any())
                {
                    OutputStatusMessage(string.Format("Updated Negative Keyword List Name to {0}.\n", negativeKeywordList.Name));
                }
                else
                {
                    CampaignManagementExampleHelper.OutputArrayOfBatchError(partialErrors);
                }

                // Get and output the negative keyword lists and store the list of identifiers.

                const string sharedEntityType = "NegativeKeywordList";
                var          sharedEntities   = (await CampaignManagementExampleHelper.GetSharedEntitiesByAccountIdAsync(sharedEntityType)).SharedEntities;
                CampaignManagementExampleHelper.OutputArrayOfSharedEntity(sharedEntities);
                var sharedEntityIds = new long[sharedEntities.Count];
                for (int index = 0; index < sharedEntities.Count; index++)
                {
                    if (sharedEntities[index].Id != null)
                    {
                        sharedEntityIds[index] = (long)sharedEntities[index].Id;
                    }
                }

                // Negative keywords were added to the negative keyword list above. You can associate the
                // shared list of negative keywords with a campaign with or without negative keywords.
                // Shared negative keyword lists cannot be associated with an ad group. An ad group can only
                // be assigned an exclusive set of negative keywords.

                var associations = new[]
                {
                    new SharedEntityAssociation
                    {
                        EntityId         = campaignId,
                        EntityType       = "Campaign",
                        SharedEntityId   = sharedEntityId,
                        SharedEntityType = "NegativeKeywordList"
                    }
                };

                partialErrors = (await CampaignManagementExampleHelper.SetSharedEntityAssociationsAsync(associations)).PartialErrors;
                if (partialErrors == null || !partialErrors.Any())
                {
                    OutputStatusMessage(string.Format("Associated CampaignId {0} with Negative Keyword List Id {1}.\n",
                                                      campaignId, sharedEntityId));
                }
                else
                {
                    CampaignManagementExampleHelper.OutputArrayOfBatchError(partialErrors);
                }

                // Get and output the associations either by Campaign or NegativeKeywordList identifier.
                GetSharedEntityAssociationsByEntityIdsResponse getSharedEntityAssociationsByEntityIdsResponse =
                    await CampaignManagementExampleHelper.GetSharedEntityAssociationsByEntityIdsAsync(new[] { campaignId }, "Campaign", "NegativeKeywordList");

                CampaignManagementExampleHelper.OutputArrayOfSharedEntityAssociation(getSharedEntityAssociationsByEntityIdsResponse.Associations);
                CampaignManagementExampleHelper.OutputArrayOfBatchError(getSharedEntityAssociationsByEntityIdsResponse.PartialErrors);

                // Currently the GetSharedEntityAssociationsBySharedEntityIds operation accepts only one shared entity identifier in the list.
                GetSharedEntityAssociationsBySharedEntityIdsResponse getSharedEntityAssociationsBySharedEntityIdsResponse =
                    await CampaignManagementExampleHelper.GetSharedEntityAssociationsBySharedEntityIdsAsync("Campaign", new[] { sharedEntityIds[sharedEntityIds.Length - 1] }, "NegativeKeywordList");

                CampaignManagementExampleHelper.OutputArrayOfSharedEntityAssociation(getSharedEntityAssociationsBySharedEntityIdsResponse.Associations);
                CampaignManagementExampleHelper.OutputArrayOfBatchError(getSharedEntityAssociationsBySharedEntityIdsResponse.PartialErrors);

                // Explicitly delete the association between the campaign and the negative keyword list.

                partialErrors = (await CampaignManagementExampleHelper.DeleteSharedEntityAssociationsAsync(associations)).PartialErrors;
                if (partialErrors == null || !partialErrors.Any())
                {
                    OutputStatusMessage("Deleted NegativeKeywordList associations\n");
                }
                else
                {
                    CampaignManagementExampleHelper.OutputArrayOfBatchError(partialErrors);
                }

                // Delete the campaign and any remaining assocations.

                await CampaignManagementExampleHelper.DeleteCampaignsAsync(authorizationData.AccountId, new[] { campaignId });

                OutputStatusMessage(string.Format("Deleted Campaign Id {0}\n", campaignId));

                // DeleteCampaigns does not delete the negative keyword list from the account's library.
                // Call the DeleteSharedEntities operation to delete the shared entities.

                partialErrors = (await CampaignManagementExampleHelper.DeleteSharedEntitiesAsync(new SharedEntity[] { new NegativeKeywordList {
                                                                                                                          Id = sharedEntityId
                                                                                                                      } }))?.PartialErrors;
                if (partialErrors == null || !partialErrors.Any())
                {
                    OutputStatusMessage(string.Format("Deleted Negative Keyword List (SharedEntity) Id {0}\n", sharedEntityId));
                }
                else
                {
                    CampaignManagementExampleHelper.OutputArrayOfBatchError(partialErrors);
                }
            }
            // 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);
            }
        }
コード例 #5
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);
            }
        }
コード例 #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);

                // A conversion goal cannot be deleted, so even if this is a test
                // please choose an appropriate name accordingly.
                var offlineConversionGoalName = "My Offline Conversion Goal";

                var conversionGoals = new ConversionGoal[]
                {
                    new OfflineConversionGoal
                    {
                        // Determines how long after a click that you want to count offline conversions.
                        ConversionWindowInMinutes = 43200,

                        // If the count type is 'Unique' then only the first offline conversion will be counted.
                        // By setting the count type to 'All', then all offline conversions for the same
                        // MicrosoftClickId with different conversion times will be added cumulatively.
                        CountType = ConversionGoalCountType.All,

                        Name = offlineConversionGoalName,

                        // The default conversion currency code and value. Each offline conversion can override it.
                        Revenue = new ConversionGoalRevenue
                        {
                            CurrencyCode = null,
                            Type         = ConversionGoalRevenueType.FixedValue,
                            Value        = 5.00m,
                        },
                        Scope  = EntityScope.Account,
                        Status = ConversionGoalStatus.Active,
                        TagId  = null
                    },
                };

                OutputStatusMessage("-----\nAddConversionGoals:");
                var addConversionGoalsResponse = await CampaignManagementExampleHelper.AddConversionGoalsAsync(
                    conversionGoals : conversionGoals);

                var          conversionGoalIds    = addConversionGoalsResponse.ConversionGoalIds.ToArray();
                BatchError[] conversionGoalErrors = addConversionGoalsResponse.PartialErrors.ToArray();
                OutputStatusMessage("ConversionGoalIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(conversionGoalIds);
                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(conversionGoalErrors);

                List <long> goalIds = GetNonNullableIds(conversionGoalIds);

                var conversionGoalTypes = ConversionGoalType.OfflineConversion;

                OutputStatusMessage("-----\nGetConversionGoalsByIds:");
                var getConversionGoalsResponse = (await CampaignManagementExampleHelper.GetConversionGoalsByIdsAsync(
                                                      conversionGoalIds: goalIds,
                                                      conversionGoalTypes: conversionGoalTypes));
                var getConversionGoals = getConversionGoalsResponse.ConversionGoals;
                conversionGoalErrors = getConversionGoalsResponse.PartialErrors.ToArray();
                OutputStatusMessage("ConversionGoals:");
                CampaignManagementExampleHelper.OutputArrayOfConversionGoal(getConversionGoals);
                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(conversionGoalErrors);

                // Every time you create a new OfflineConversionGoal via either the Bing Ads web application or Campaign Management API,
                // the MSCLKIDAutoTaggingEnabled value of the corresponding AccountProperty is set to 'true' automatically.
                // We can confirm the setting now.

                var accountPropertyNames = new List <AccountPropertyName>();
                accountPropertyNames.Add(AccountPropertyName.MSCLKIDAutoTaggingEnabled);

                OutputStatusMessage("-----\nGetAccountProperties:");
                var getAccountPropertiesResponse = await CampaignManagementExampleHelper.GetAccountPropertiesAsync(
                    accountPropertyNames : accountPropertyNames);

                var          accountProperties       = getAccountPropertiesResponse.AccountProperties;
                BatchError[] accountPropertiesErrors = getAccountPropertiesResponse.PartialErrors.ToArray();
                OutputStatusMessage("AccountProperties:");
                CampaignManagementExampleHelper.OutputArrayOfAccountProperty(accountProperties);
                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(accountPropertiesErrors);

                var offlineConversions = new[]
                {
                    new OfflineConversion
                    {
                        // If you do not specify an offline conversion currency code,
                        // then the 'CurrencyCode' element of the goal's 'ConversionGoalRevenue' is used.
                        ConversionCurrencyCode = "USD",

                        // The conversion name must match the 'Name' of the 'OfflineConversionGoal'.
                        // If it does not match you won't observe any error, although the offline
                        // conversion will not be counted.
                        ConversionName = offlineConversionGoalName,

                        // The date and time must be in UTC, should align to the date and time of the
                        // recorded click (MicrosoftClickId), and cannot be in the future.
                        ConversionTime = DateTime.UtcNow,

                        // If you do not specify an offline conversion value,
                        // then the 'Value' element of the goal's 'ConversionGoalRevenue' is used.
                        ConversionValue = 10,

                        MicrosoftClickId = "f894f652ea334e739002f7167ab8f8e3"
                    }
                };

                // After the OfflineConversionGoal is set up, wait two hours before submitting the offline conversions.
                // This example would not succeed in production because we created the goal very recently i.e.,
                // please see above call to AddConversionGoalsAsync.

                OutputStatusMessage("-----\nApplyOfflineConversions:");
                var applyOfflineConversionsResponse = await CampaignManagementExampleHelper.ApplyOfflineConversionsAsync(
                    offlineConversions : offlineConversions);

                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(applyOfflineConversionsResponse.PartialErrors);
            }
            // 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);
            }
        }
コード例 #7
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                // You will need to use the Campaign Management service to get the Bing Merchant Center Store Id.
                // This will be used when creating a new Bing Shopping Campaign.
                // For other operations such as adding product conditions,
                // you can manage Bing Shopping Campaigns solely with the Bulk Service.

                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage);
                CampaignManagementExampleHelper.CampaignManagementService =
                    new ServiceClient <ICampaignManagementService>(authorizationData, environment);

                BulkServiceManager = new BulkServiceManager(authorizationData, environment);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                #region CampaignThroughAdGroupSetup

                // 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;
                }

                var uploadEntities = new List <BulkEntity>();

                /* Add a new Bing Shopping campaign that will be associated with a ProductScope criterion.
                 *  - Set the CampaignType element of the Campaign to Shopping.
                 *  - Create a ShoppingSetting instance and set its Priority (0, 1, or 2), SalesCountryCode, and StoreId elements.
                 *    Add this shopping setting to the Settings list of the Campaign.
                 */

                var bulkCampaign = new BulkCampaign
                {
                    // ClientId may be used to associate records in the bulk upload file with records in the results file. The value of this field
                    // is not used or stored by the server; it is simply copied from the uploaded record to the corresponding result record.
                    // Note: This bulk file Client Id is not related to an application Client Id for OAuth.
                    ClientId = "YourClientIdGoesHere",
                    Campaign = new Campaign
                    {
                        // When using the Campaign Management service, the Id cannot be set. In the context of a BulkCampaign, the Id is optional
                        // and may be used as a negative reference key during bulk upload. For example the same negative value set for the campaign Id
                        // will be used when associating this new campaign with a new campaign product scope in the BulkCampaignProductScope object below.
                        Id           = campaignIdKey,
                        CampaignType = CampaignType.Shopping,
                        Settings     = new[] {
                            new ShoppingSetting()
                            {
                                Priority         = 0,
                                SalesCountryCode = "US",
                                StoreId          = (int)stores[0].Id
                            }
                        },
                        Name        = "Bing Shopping Campaign " + DateTime.UtcNow,
                        Description = "Bing Shopping Campaign Example.",

                        // 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}"
                    }
                };

                /* Optionally, you can create a ProductScope criterion that will be associated with your Bing Shopping campaign.
                 * Use the product scope criterion to include a subset of your product catalog, for example a specific brand,
                 * category, or product type. A campaign can only be associated with one ProductScope, which contains a list
                 * of up to 7 ProductCondition. You'll also be able to specify more specific product conditions for each ad group.
                 */

                var bulkCampaignProductScope = new BulkCampaignProductScope
                {
                    BiddableCampaignCriterion = new BiddableCampaignCriterion()
                    {
                        CampaignId   = campaignIdKey,
                        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 = Status.Active,
                };

                // Specify one or more ad groups.

                var bulkAdGroup = new BulkAdGroup
                {
                    CampaignId = campaignIdKey,
                    AdGroup    = new AdGroup
                    {
                        Id        = adGroupIdKey,
                        Name      = "Product Categories",
                        StartDate = null,
                        EndDate   = new Microsoft.BingAds.V12.CampaignManagement.Date
                        {
                            Month = 12,
                            Day   = 31,
                            Year  = DateTime.UtcNow.Year + 1
                        },
                        Language = "English",
                        Status   = AdGroupStatus.Active
                    },
                };

                /*
                 * 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 bulkProductAd = new BulkProductAd
                {
                    AdGroupId = adGroupIdKey,
                    ProductAd = new ProductAd {
                    }
                };

                uploadEntities.Add(bulkCampaign);
                uploadEntities.Add(bulkAdGroup);
                uploadEntities.Add(bulkCampaignProductScope);
                uploadEntities.Add(bulkProductAd);

                // Upload and write the output

                var Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                var downloadEntities = Reader.ReadEntities().ToList();

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var adGroupResults = downloadEntities.OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(adGroupResults);

                var productAdResults = downloadEntities.OfType <BulkProductAd>().ToList();
                OutputBulkProductAds(productAdResults);

                var campaignProductScopeResults = downloadEntities.OfType <BulkCampaignProductScope>().ToList();
                OutputBulkCampaignProductScopes(campaignProductScopeResults);

                Reader.Dispose();

                #endregion CampaignThroughAdGroupSetup

                #region BidAllProducts

                var adGroupId = (long)adGroupResults[0].AdGroup.Id;

                var helper = new ProductPartitionHelper(adGroupId);

                var root = helper.AddUnit(
                    null,
                    new ProductCondition {
                    Operand = "All", Attribute = null
                },
                    0.35,
                    false,
                    "root"
                    );

                OutputStatusMessage("Applying only the root as a Unit with a bid . . . \n");
                var applyBulkProductPartitionActionsResults =
                    await ApplyBulkProductPartitionActions(helper.PartitionActions);

                var productPartitions = await GetBulkAdGroupProductPartitionTree(adGroupId);

                OutputStatusMessage("The ad group's product partition only has a tree root node: \n");
                OutputProductPartitions(productPartitions);

                /*
                 * Let's update the bid of the root Unit we just added.
                 */

                var updatedRoot = GetNodeByClientId(applyBulkProductPartitionActionsResults, "root");
                var bid         = new FixedBid
                {
                    Amount = 0.45
                };
                ((BiddableAdGroupCriterion)(updatedRoot.AdGroupCriterion)).CriterionBid = bid;

                helper = new ProductPartitionHelper(adGroupId);
                helper.UpdatePartition(updatedRoot);

                OutputStatusMessage("Updating the bid for the tree root node . . . \n");
                await ApplyBulkProductPartitionActions(helper.PartitionActions);

                productPartitions = await GetBulkAdGroupProductPartitionTree(adGroupId);

                OutputStatusMessage("Updated the bid for the tree root node: \n");
                OutputProductPartitions(productPartitions);

                #endregion BidAllProducts

                #region InitializeTree

                /*
                 * Now we will overwrite any existing tree root, and build a product partition group tree structure in multiple steps.
                 * You could build the entire tree in a single call since there are less than 20,000 nodes; however,
                 * we will build it in steps to demonstrate how to use the results from bulk upload to update the tree.
                 *
                 * For a list of validation rules, see the Product Ads technical guide:
                 * https://docs.microsoft.com/en-us/bingads/guides/product-ads
                 */

                helper = new ProductPartitionHelper(adGroupId);

                /*
                 * Check whether a root node exists already.
                 */

                var existingRoot = GetNodeByClientId(applyBulkProductPartitionActionsResults, "root");
                if (existingRoot != null)
                {
                    existingRoot.ClientId = "deletedroot";
                    helper.DeletePartition(existingRoot);
                }

                root = helper.AddSubdivision(
                    null,
                    new ProductCondition {
                    Operand = "All", Attribute = null
                },
                    "root"
                    );

                /*
                 * The direct children of any node must have the same Operand.
                 * For this example we will use CategoryL1 nodes as children of the root.
                 * For a list of valid CategoryL1 through CategoryL5 values, see the Bing Category Taxonomy:
                 * http://go.microsoft.com/fwlink?LinkId=507666
                 */
                var animalsSubdivision = helper.AddSubdivision(
                    root,
                    new ProductCondition {
                    Operand = "CategoryL1", Attribute = "Animals & Pet Supplies"
                },
                    "animalsSubdivision"
                    );

                /*
                 * If you use a CategoryL2 node, it must be a descendant (child or later) of a CategoryL1 node.
                 * In other words you cannot have a CategoryL2 node as parent of a CategoryL1 node.
                 * For this example we will a CategoryL2 node as child of the CategoryL1 Animals & Pet Supplies node.
                 */
                var petSuppliesSubdivision = helper.AddSubdivision(
                    animalsSubdivision,
                    new ProductCondition {
                    Operand = "CategoryL2", Attribute = "Pet Supplies"
                },
                    "petSuppliesSubdivision"
                    );

                var brandA = helper.AddUnit(
                    petSuppliesSubdivision,
                    new ProductCondition {
                    Operand = "Brand", Attribute = "Brand A"
                },
                    0.35,
                    false,
                    "brandA"
                    );

                /*
                 * If you won't bid on Brand B, set the helper method's bidAmount to '0' and isNegative to true.
                 * The helper method will create a NegativeAdGroupCriterion and apply the condition.
                 */
                var brandB = helper.AddUnit(
                    petSuppliesSubdivision,
                    new ProductCondition {
                    Operand = "Brand", Attribute = "Brand B"
                },
                    0,
                    true,
                    "brandB"
                    );

                var otherBrands = helper.AddUnit(
                    petSuppliesSubdivision,
                    new ProductCondition {
                    Operand = "Brand", Attribute = null
                },
                    0.35,
                    false,
                    "otherBrands"
                    );

                var otherPetSupplies = helper.AddUnit(
                    animalsSubdivision,
                    new ProductCondition {
                    Operand = "CategoryL2", Attribute = null
                },
                    0.35,
                    false,
                    "otherPetSupplies"
                    );

                var electronics = helper.AddUnit(
                    root,
                    new ProductCondition {
                    Operand = "CategoryL1", Attribute = "Electronics"
                },
                    0.35,
                    false,
                    "electronics"
                    );

                var otherCategoryL1 = helper.AddUnit(
                    root,
                    new ProductCondition {
                    Operand = "CategoryL1", Attribute = null
                },
                    0.35,
                    false,
                    "otherCategoryL1"
                    );

                OutputStatusMessage("Applying product partitions to the ad group . . . \n");
                applyBulkProductPartitionActionsResults =
                    await ApplyBulkProductPartitionActions(helper.PartitionActions);

                productPartitions = await GetBulkAdGroupProductPartitionTree(adGroupId);

                /*
                 * The product partition group tree now has 9 nodes.
                 *
                 * All other (Root Node)
                 |
                 +-- Animals & Pet Supplies (CategoryL1)
                 |    |
                 |    +-- Pet Supplies (CategoryL2)
                 |    |    |
                 |    |    +-- Brand A
                 |    |    |
                 |    |    +-- Brand B
                 |    |    |
                 |    |    +-- All other (Brand)
                 |    |
                 |    +-- All other (CategoryL2)
                 |
                 +-- Electronics (CategoryL1)
                 |
                 +-- All other (CategoryL1)
                 |
                 */

                OutputStatusMessage("The product partition group tree now has 9 nodes: \n");
                OutputProductPartitions(productPartitions);

                #endregion InitializeTree

                #region UpdateTree

                /*
                 * Let's replace the Electronics (CategoryL1) node created above with an Electronics (CategoryL1) node that
                 * has children i.e. Brand C (Brand), Brand D (Brand), and All other (Brand) as follows:
                 *
                 *  Electronics (CategoryL1)
                 |
                 +-- Brand C (Brand)
                 |
                 +-- Brand D (Brand)
                 |
                 +-- All other (Brand)
                 |
                 */

                helper = new ProductPartitionHelper(adGroupId);

                /*
                 * To replace a node we must know its Id and its ParentCriterionId. In this case the parent of the node
                 * we are replacing is All other (Root Node). The node that we are replacing is Electronics (CategoryL1).
                 */
                var rootId = GetNodeByClientId(applyBulkProductPartitionActionsResults, "root").AdGroupCriterion.Id;
                electronics.AdGroupCriterion.Id = GetNodeByClientId(applyBulkProductPartitionActionsResults, "electronics").AdGroupCriterion.Id;
                helper.DeletePartition(electronics);

                var parent = new BulkAdGroupProductPartition
                {
                    AdGroupCriterion = new BiddableAdGroupCriterion()
                    {
                        Id = rootId
                    }
                };

                var electronicsSubdivision = helper.AddSubdivision(
                    parent,
                    new ProductCondition {
                    Operand = "CategoryL1", Attribute = "Electronics"
                },
                    "electronicsSubdivision"
                    );

                var brandC = helper.AddUnit(
                    electronicsSubdivision,
                    new ProductCondition {
                    Operand = "Brand", Attribute = "Brand C"
                },
                    0.35,
                    false,
                    "brandC"
                    );

                var brandD = helper.AddUnit(
                    electronicsSubdivision,
                    new ProductCondition {
                    Operand = "Brand", Attribute = "Brand D"
                },
                    0.35,
                    false,
                    "brandD"
                    );

                var otherElectronicsBrands = helper.AddUnit(
                    electronicsSubdivision,
                    new ProductCondition {
                    Operand = "Brand", Attribute = null
                },
                    0.35,
                    false,
                    "otherElectronicsBrands"
                    );

                OutputStatusMessage(
                    "Updating the product partition group to refine Electronics (CategoryL1) with 3 child nodes . . . \n"
                    );
                applyBulkProductPartitionActionsResults =
                    await ApplyBulkProductPartitionActions(helper.PartitionActions);

                productPartitions = await GetBulkAdGroupProductPartitionTree(adGroupId);

                /*
                 * The product partition group tree now has 12 nodes, including the children of Electronics (CategoryL1):
                 *
                 * All other (Root Node)
                 |
                 +-- Animals & Pet Supplies (CategoryL1)
                 |    |
                 |    +-- Pet Supplies (CategoryL2)
                 |    |    |
                 |    |    +-- Brand A
                 |    |    |
                 |    |    +-- Brand B
                 |    |    |
                 |    |    +-- All other (Brand)
                 |    |
                 |    +-- All other (CategoryL2)
                 |
                 +-- Electronics (CategoryL1)
                 |    |
                 |    +-- Brand C (Brand)
                 |    |
                 |    +-- Brand D (Brand)
                 |    |
                 |    +-- All other (Brand)
                 |
                 +-- All other (CategoryL1)
                 |
                 */

                OutputStatusMessage(
                    "The product partition group tree now has 12 nodes, including the children of Electronics (CategoryL1): \n"
                    );
                OutputProductPartitions(productPartitions);

                #endregion UpdateTree

                #region CleanUp

                //Delete the campaign, ad group, criterion, and ad that were previously added.
                //You should remove this region if you want to view the added entities in the
                //Bing Ads web application or another tool.

                //You must set the Id field to the corresponding entity identifier, and the Status field to Deleted.

                //When you delete a BulkCampaign, the dependent entities such as BulkAdGroup and BulkAdGroupProductPartition
                //are deleted without being specified explicitly.

                uploadEntities = new List <BulkEntity>();

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                // Upload and write the output

                OutputStatusMessage(
                    "Deleting the campaign, product conditions, ad group, product partitions, and product ad... \n"
                    );

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();
                OutputBulkCampaigns(downloadEntities.OfType <BulkCampaign>().ToList());

                Reader.Dispose();

                #endregion Cleanup
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V12.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V12.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            // Catch 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 (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
コード例 #8
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                // Used to output the Campaign Management objects within Bulk entities.
                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(
                    authorizationData: authorizationData,
                    apiEnvironment: environment);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                var tokenSource = new CancellationTokenSource();
                tokenSource.CancelAfter(TimeoutInMilliseconds);

                // In this example we will download all ad groups in the account.

                var downloadParameters = new DownloadParameters
                {
                    DataScope           = DataScope.EntityData,
                    DownloadEntities    = new[] { DownloadEntity.AdGroups },
                    FileType            = FileType,
                    LastSyncTimeInUTC   = null,
                    ResultFileDirectory = FileDirectory,
                    ResultFileName      = DownloadFileName,
                    OverwriteResultFile = true
                };

                OutputStatusMessage("-----\nDownloading all ad groups in the account.");

                var bulkFilePath = await BulkServiceManager.DownloadFileAsync(
                    parameters : downloadParameters,
                    progress : progress,
                    cancellationToken : tokenSource.Token);

                OutputStatusMessage("Download results:");

                Reader = new BulkFileReader(
                    filePath: bulkFilePath,
                    resultFileType: ResultFileType.FullDownload,
                    fileFormat: FileType);

                var bulkAdGroups = Reader.ReadEntities().ToList().OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(bulkAdGroups);

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                // We will activate ad groups for one month starting from today as an example.

                var nextMonth = DateTime.UtcNow.AddMonths(1);

                // Within the downloaded records, find all ad groups that you want to update.

                foreach (var bulkAdGroup in bulkAdGroups)
                {
                    var adGroup = bulkAdGroup.AdGroup;
                    if (adGroup != null && bulkAdGroup.AdGroup.Status.ToString().CompareTo("Active") != 0)
                    {
                        // For best performance, only upload the properties that you want to update.

                        Writer.WriteEntity(new BulkAdGroup
                        {
                            CampaignId = bulkAdGroup.CampaignId,
                            AdGroup    = new AdGroup
                            {
                                Id      = adGroup.Id,
                                EndDate = new Microsoft.BingAds.V13.CampaignManagement.Date
                                {
                                    Month = nextMonth.Month,
                                    Day   = nextMonth.Day,
                                    Year  = nextMonth.Year
                                },
                                Status = AdGroupStatus.Active,
                            }
                        });
                    }
                }

                Reader.Dispose();
                Writer.Dispose();

                // Upload the local file that we already prepared

                var fileUploadParameters = new FileUploadParameters
                {
                    ResultFileDirectory = FileDirectory,
                    CompressUploadFile  = true,
                    ResultFileName      = ResultFileName,
                    OverwriteResultFile = true,
                    UploadFilePath      = FileDirectory + UploadFileName,
                    ResponseMode        = ResponseMode.ErrorsAndResults
                };

                OutputStatusMessage("-----\nActivating the ad groups...");

                var resultFilePath = await BulkServiceManager.UploadFileAsync(
                    parameters : fileUploadParameters,
                    progress : progress,
                    cancellationToken : tokenSource.Token);

                Reader = new BulkFileReader(
                    filePath: resultFilePath,
                    resultFileType: ResultFileType.Upload,
                    fileFormat: FileType);

                OutputStatusMessage("Upload results:");

                bulkAdGroups = Reader.ReadEntities().ToList().OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(bulkAdGroups);

                Reader.Dispose();
            }
            // 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 Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V13.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V13.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }
コード例 #9
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);
            }
        }
コード例 #10
0
        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);

                // Used to output the Campaign Management objects within Bulk entities.
                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(
                    authorizationData: authorizationData,
                    apiEnvironment: environment);


                var uploadEntities = new List <BulkEntity>();

                // Setup a page feed that can be associated with one or more campaigns.

                var bulkPageFeed = new BulkFeed
                {
                    CustomAttributes = new[]
                    {
                        new FeedCustomAttributeContract
                        {
                            FeedAttributeType = "Url",
                            Name = "Page Url"
                        },
                        new FeedCustomAttributeContract
                        {
                            FeedAttributeType = "StringList",
                            Name = "Custom Label"
                        }
                    },
                    Id      = feedIdKey,
                    Name    = "My PageFeed " + DateTime.UtcNow,
                    Status  = Status.Active,
                    SubType = "PageFeed"
                };

                uploadEntities.Add(bulkPageFeed);

                var pageFeedItemCustomAttributes = new Dictionary <string, object>();
                pageFeedItemCustomAttributes.Add(
                    "Page Url",
                    "https://" + DOMAIN_NAME + "/3001");
                pageFeedItemCustomAttributes.Add(
                    "Custom Label", new string[] {
                    "Label_1_3001",
                    "Label_1_3002"
                });

                var serializerSettings = new JsonSerializerSettings();
                serializerSettings.NullValueHandling = NullValueHandling.Ignore;
                var pageFeedItemCustomAttributesJson = JsonConvert.SerializeObject(
                    pageFeedItemCustomAttributes, serializerSettings);

                var bulkPageFeedItem = new BulkFeedItem
                {
                    FeedId           = feedIdKey,
                    CustomAttributes = pageFeedItemCustomAttributesJson,
                    Status           = Status.Active
                };

                uploadEntities.Add(bulkPageFeedItem);

                // 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.
                // Page feeds can be associated at the campaign level via 'Source' and 'Page Feed Ids'.

                var bulkCampaign = new BulkCampaign
                {
                    Campaign = new Campaign
                    {
                        Id           = campaignIdKey,
                        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[] {
                            // Set the target website domain and language.
                            // Be sure to set the Source to AdvertiserSuppliedUrls or All,
                            // otherwise the PageFeedIds will be ignored.
                            new DynamicSearchAdsSetting
                            {
                                DomainName  = DOMAIN_NAME,
                                Language    = LANGUAGE,
                                Source      = DynamicSearchAdsSource.All,
                                PageFeedIds = new [] { feedIdKey }
                            }
                        },
                    },
                };

                uploadEntities.Add(bulkCampaign);

                // Create a new ad group within the dynamic search ads campaign.

                var bulkAdGroup = new BulkAdGroup
                {
                    CampaignId = campaignIdKey,
                    AdGroup    = new AdGroup
                    {
                        Id        = adGroupIdKey,
                        Name      = "Women's Red Shoe Sale",
                        StartDate = null,
                        EndDate   = new Microsoft.BingAds.V13.CampaignManagement.Date
                        {
                            Month = 12,
                            Day   = 31,
                            Year  = DateTime.UtcNow.Year + 1
                        },
                        CpcBid = new Bid {
                            Amount = 0.09
                        },
                    },
                };

                uploadEntities.Add(bulkAdGroup);

                // Create an auto target based on the custom label feed items created above e.g., "Label_1_3001".

                var adGroupWebpagePositiveCustomLabel = new BulkAdGroupDynamicSearchAdTarget
                {
                    BiddableAdGroupCriterion = new BiddableAdGroupCriterion
                    {
                        AdGroupId    = adGroupIdKey,
                        CriterionBid = new FixedBid
                        {
                            Amount = 0.50
                        },
                        Criterion = new Webpage
                        {
                            Parameter = new WebpageParameter
                            {
                                Conditions = new[]
                                {
                                    new WebpageCondition
                                    {
                                        Argument = "Label_1_3001",
                                        Operand  = WebpageConditionOperand.CustomLabel,
                                    },
                                },
                                CriterionName = "Ad Group Webpage Positive Custom Label Criterion"
                            },
                        },
                    }
                };
                uploadEntities.Add(adGroupWebpagePositiveCustomLabel);

                // To discover the categories that you can use for Webpage criterion (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;
                AdInsightExampleHelper.OutputArrayOfDomainCategory(categories);

                // If any categories are available let's use one as a condition.

                if (categories.Count > 0)
                {
                    var adGroupWebpagePositiveCategory = new BulkAdGroupDynamicSearchAdTarget
                    {
                        BiddableAdGroupCriterion = new BiddableAdGroupCriterion
                        {
                            AdGroupId    = adGroupIdKey,
                            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"
                                },
                            }
                        }
                    };
                    uploadEntities.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 BulkAdGroupNegativeDynamicSearchAdTarget
                {
                    NegativeAdGroupCriterion = new NegativeAdGroupCriterion
                    {
                        AdGroupId = adGroupIdKey,
                        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 = "https://" + DOMAIN_NAME + "/3001",
                                        Operand  = WebpageConditionOperand.Url,
                                    }
                                },
                                // If you do not specify any name, then it will be set to a concatenated list of conditions.
                                CriterionName = null
                            }
                        }
                    }
                };
                uploadEntities.Add(adGroupWebpageNegativeUrl);

                // Finally you must add at least one Dynamic Search Ad 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 bulkDynamicSearchAd = new BulkDynamicSearchAd
                {
                    AdGroupId       = adGroupIdKey,
                    DynamicSearchAd = new DynamicSearchAd
                    {
                        Text      = "Find New Customers & Increase Sales!",
                        TextPart2 = "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
                    },
                };

                uploadEntities.Add(bulkDynamicSearchAd);

                // Upload and write the output

                OutputStatusMessage("-----\nAdding page feed, campaign, ad group, criterions, and ads...");

                var Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                var downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                var feedResults = downloadEntities.OfType <BulkFeed>().ToList();
                OutputBulkFeeds(feedResults);

                var feedItemResults = downloadEntities.OfType <BulkFeedItem>().ToList();
                OutputBulkFeedItems(feedItemResults);

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var adGroupResults = downloadEntities.OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(adGroupResults);

                var adGroupDynamicSearchAdTargetResults = downloadEntities.OfType <BulkAdGroupDynamicSearchAdTarget>().ToList();
                OutputBulkAdGroupDynamicSearchAdTargets(adGroupDynamicSearchAdTargetResults);

                var adGroupNegativeDynamicSearchAdTargetResults = downloadEntities.OfType <BulkAdGroupNegativeDynamicSearchAdTarget>().ToList();
                OutputBulkAdGroupNegativeDynamicSearchAdTargets(adGroupNegativeDynamicSearchAdTargetResults);

                var dynamicSearchAdResults = downloadEntities.OfType <BulkDynamicSearchAd>().ToList();
                OutputBulkDynamicSearchAds(dynamicSearchAdResults);

                Reader.Dispose();

                // Delete the campaign and everything it contains e.g., ad groups and ads.

                uploadEntities = new List <BulkEntity>();

                foreach (var feedResult in feedResults)
                {
                    feedResult.Status = Status.Deleted;
                    uploadEntities.Add(feedResult);
                }

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                OutputStatusMessage("-----\nDeleting page feed, DSA campaign, and all contained entities...");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                feedResults = downloadEntities.OfType <BulkFeed>().ToList();
                OutputBulkFeeds(feedResults);

                campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                Reader.Dispose();
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V13.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V13.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
コード例 #11
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                // Used to output the Campaign Management objects within Bulk entities.
                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(
                    authorizationData: authorizationData,
                    apiEnvironment: environment);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                var uploadEntities = new List <BulkEntity>();

                // Define a campaign

                var bulkCampaign = new BulkCampaign
                {
                    ClientId = "YourClientIdGoesHere",
                    Campaign = new Campaign
                    {
                        Id           = campaignIdKey,
                        BudgetType   = BudgetLimitType.DailyBudgetStandard,
                        DailyBudget  = 50,
                        CampaignType = CampaignType.Search,
                        Languages    = new string[] { "All" },
                        Name         = "Women's Shoes " + DateTime.UtcNow,
                        TimeZone     = "PacificTimeUSCanadaTijuana",
                    }
                };

                uploadEntities.Add(bulkCampaign);

                // Define a set of negative sites that can be applied to the campaign.
                // You can set one negative site via the BulkCampaignNegativeSite (singular) bulk entity,
                // or multiple negative sites via the BulkCampaignNegativeSites (plural) bulk entity.
                //
                // If you upload a BulkCampaignNegativeSites bulk entity, then you are effectively replacing any existing
                // negative sites assigned to the campaign.
                //
                // When the SDK writes a BulkCampaignNegativeSites entity to the bulk upload file,
                // an extra Campaign Negative Site record is included where the Status is Deleted and the
                // Website field is empty. (This is the record that deletes any existing campaign negative sites.)
                //
                // If you include additional BulkCampaignNegativeSite or BulkCampaignNegativeSites in the same upload,
                // they will also be included in the set of negative sites applied to the campaign.

                var bulkCampaignNegativeSite = new BulkCampaignNegativeSite[] {
                    new BulkCampaignNegativeSite {
                        CampaignId = campaignIdKey,
                        Website    = "contoso.com/negativesite1"
                    },
                    new BulkCampaignNegativeSite {
                        CampaignId = campaignIdKey,
                        Website    = "contoso.com/negativesite2"
                    },
                };

                foreach (var campaignNegativeSite in bulkCampaignNegativeSite)
                {
                    uploadEntities.Add(campaignNegativeSite);
                }

                var bulkCampaignNegativeSites = new BulkCampaignNegativeSites {
                    CampaignNegativeSites = new CampaignNegativeSites
                    {
                        CampaignId    = campaignIdKey,
                        NegativeSites = new string[]
                        {
                            "contoso.com/negativesite3",
                            "contoso.com/negativesite4",
                        }
                    }
                };

                uploadEntities.Add(bulkCampaignNegativeSites);

                // Upload and write the output

                OutputStatusMessage("-----\nApplying negative sites to a new campaign...");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                var downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                // If the upload result file contains a Campaign Negative Site record where the Status is Deleted
                // and the Website field is empty, the SDK represents all negative sites for the campaign
                // via a BulkCampaignNegativeSites (plural) object. Otherwise the SDK represents negative sites
                // for the campaign via one or more BulkCampaignNegativeSite (singlular) objects.

                var campaignNegativeSiteResults = downloadEntities.OfType <BulkCampaignNegativeSite>().ToList();
                OutputBulkCampaignNegativeSite(campaignNegativeSiteResults);

                var campaignNegativeSitesResults = downloadEntities.OfType <BulkCampaignNegativeSites>().ToList();
                OutputBulkCampaignNegativeSites(campaignNegativeSitesResults);

                Reader.Dispose();

                // Delete the campaign and everything it contains e.g., ad groups and ads.

                uploadEntities = new List <BulkEntity>();

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                // Upload and write the output

                OutputStatusMessage("-----\nDeleting the campaign and everything it contains e.g., ad groups and ads...");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                OutputBulkCampaigns(downloadEntities.OfType <BulkCampaign>().ToList());
                OutputBulkNegativeKeywordLists(downloadEntities.OfType <BulkNegativeKeywordList>().ToList());

                Reader.Dispose();
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V13.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V13.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
コード例 #12
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage);
                CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>(authorizationData);

                // Add a campaign that will later be associated with ad extensions.

                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",

                        // Used with FinalUrls shown in the sitelinks that we will add below.
                        TrackingUrlTemplate =
                            "http://tracker.example.com/?season={_season}&promocode={_promocode}&u={lpurl}"
                    }
                };

                AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync(authorizationData.AccountId, campaigns);

                long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray();
                CampaignManagementExampleHelper.OutputArrayOfLong(campaignIds);
                CampaignManagementExampleHelper.OutputArrayOfBatchError(addCampaignsResponse?.PartialErrors);

                // Specify the extensions.

                var adExtensions = new AdExtension[] {
                    //new AppAdExtension
                    //{
                    //    AppPlatform = "Windows",
                    //    AppStoreId = "AppStoreIdGoesHere",
                    //    DestinationUrl = "DestinationUrlGoesHere",
                    //    DisplayText = "Contoso",
                    //},
                    new CallAdExtension {
                        CountryCode = "US",
                        PhoneNumber = "2065550100",
                        IsCallOnly  = false,
                        Scheduling  = new Schedule {
                            // For this example assume the call center is open Monday - Friday from 9am - 9pm
                            // in the account's time zone.

                            UseSearcherTimeZone = false,
                            DayTimeRanges       = new[]
                            {
                                new DayTime
                                {
                                    Day         = Day.Monday,
                                    StartHour   = 9,
                                    StartMinute = Minute.Zero,
                                    EndHour     = 21,
                                    EndMinute   = Minute.Zero,
                                },
                                new DayTime
                                {
                                    Day         = Day.Tuesday,
                                    StartHour   = 9,
                                    StartMinute = Minute.Zero,
                                    EndHour     = 21,
                                    EndMinute   = Minute.Zero,
                                },
                                new DayTime
                                {
                                    Day         = Day.Wednesday,
                                    StartHour   = 9,
                                    StartMinute = Minute.Zero,
                                    EndHour     = 21,
                                    EndMinute   = Minute.Zero,
                                },
                                new DayTime
                                {
                                    Day         = Day.Thursday,
                                    StartHour   = 9,
                                    StartMinute = Minute.Zero,
                                    EndHour     = 21,
                                    EndMinute   = Minute.Zero,
                                },
                                new DayTime
                                {
                                    Day         = Day.Friday,
                                    StartHour   = 9,
                                    StartMinute = Minute.Zero,
                                    EndHour     = 21,
                                    EndMinute   = Minute.Zero,
                                },
                            },
                            StartDate = null,
                            EndDate   = new Microsoft.BingAds.V11.CampaignManagement.Date {
                                Month = 12,
                                Day   = 31,
                                Year  = DateTime.UtcNow.Year + 1
                            },
                        }
                    },
                    new CalloutAdExtension
                    {
                        Text = "Callout Text"
                    },
                    new LocationAdExtension {
                        PhoneNumber = "206-555-0100",
                        CompanyName = "Contoso Shoes",
                        Address     = new Microsoft.BingAds.V11.CampaignManagement.Address {
                            StreetAddress  = "1234 Washington Place",
                            StreetAddress2 = "Suite 1210",
                            CityName       = "Woodinville",
                            ProvinceName   = "WA",
                            CountryCode    = "US",
                            PostalCode     = "98608"
                        },
                        Scheduling = new Schedule {
                            // For this example assume you want to drive traffic every Saturday morning
                            // in the search user's time zone.

                            UseSearcherTimeZone = true,
                            DayTimeRanges       = new[]
                            {
                                new DayTime
                                {
                                    Day         = Day.Saturday,
                                    StartHour   = 9,
                                    StartMinute = Minute.Zero,
                                    EndHour     = 12,
                                    EndMinute   = Minute.Zero,
                                },
                            },
                            StartDate = null,
                            EndDate   = new Microsoft.BingAds.V11.CampaignManagement.Date {
                                Month = 12,
                                Day   = 31,
                                Year  = DateTime.UtcNow.Year + 1
                            },
                        }
                    },
                    new PriceAdExtension
                    {
                        Language  = "English",
                        TableRows = new PriceTableRow[]
                        {
                            new PriceTableRow
                            {
                                CurrencyCode = "USD",
                                Description  = "Come to the event",
                                FinalUrls    = new string[]
                                {
                                    "https://contoso.com"
                                },
                                Header         = "New Event",
                                Price          = 9.99,
                                PriceQualifier = PriceQualifier.From,
                                PriceUnit      = PriceUnit.PerDay,
                            },
                            new PriceTableRow
                            {
                                CurrencyCode = "USD",
                                Description  = "Come to the next event",
                                FinalUrls    = new string[]
                                {
                                    "https://contoso.com"
                                },
                                Header         = "Next Event",
                                Price          = 9.99,
                                PriceQualifier = PriceQualifier.From,
                                PriceUnit      = PriceUnit.PerDay,
                            },
                            new PriceTableRow
                            {
                                CurrencyCode = "USD",
                                Description  = "Come to the final event",
                                FinalUrls    = new string[]
                                {
                                    "https://contoso.com"
                                },
                                Header         = "Final Event",
                                Price          = 9.99,
                                PriceQualifier = PriceQualifier.From,
                                PriceUnit      = PriceUnit.PerDay,
                            },
                        },
                        PriceExtensionType  = PriceExtensionType.Events,
                        TrackingUrlTemplate = "http://tracker.com?url={lpurl}&matchtype={matchtype}",
                        UrlCustomParameters = new CustomParameters
                        {
                            // Each custom parameter is delimited by a semicolon (;) in the Bulk file
                            Parameters = new[] {
                                new CustomParameter()
                                {
                                    Key   = "promoCode",
                                    Value = "PROMO1"
                                },
                                new CustomParameter()
                                {
                                    Key   = "season",
                                    Value = "summer"
                                },
                            }
                        },
                    },
                    new ReviewAdExtension
                    {
                        IsExact = true,
                        Source  = "Review Source Name",
                        Text    = "Review Text",
                        Url     = "http://review.contoso.com" // The Url of the third-party review. This is not your business Url.
                    },
                    new StructuredSnippetAdExtension
                    {
                        Header = "Brands",
                        Values = new [] { "Windows", "Xbox", "Skype" }
                    }
                };

                // Get
                adExtensions = adExtensions.Concat(GetSampleSitelink2AdExtensions()).ToArray();


                // Add all extensions to the account's ad extension library
                var addAdExtensionsResponse = (await CampaignManagementExampleHelper.AddAdExtensionsAsync(
                                                   authorizationData.AccountId,
                                                   adExtensions
                                                   ));
                var adExtensionIdentities = addAdExtensionsResponse?.AdExtensionIdentities;
                CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(addAdExtensionsResponse?.NestedPartialErrors);

                OutputStatusMessage("Added ad extensions.\n");

                // DeleteAdExtensionsAssociations, SetAdExtensionsAssociations, and GetAdExtensionsEditorialReasons
                // operations each require a list of type AdExtensionIdToEntityIdAssociation.
                var adExtensionIdToEntityIdAssociations = new List <AdExtensionIdToEntityIdAssociation>();

                // GetAdExtensionsByIds requires a list of type long.
                var adExtensionIds = new List <long>();

                // Loop through the list of extension IDs and build any required data structures
                // for subsequent operations.

                foreach (var adExtensionIdentity in adExtensionIdentities)
                {
                    if (adExtensionIdentity != null)
                    {
                        adExtensionIdToEntityIdAssociations.Add(new AdExtensionIdToEntityIdAssociation
                        {
                            AdExtensionId = adExtensionIdentity.Id,
                            EntityId      = (long)campaignIds[0]
                        });

                        adExtensionIds.Add(adExtensionIdentity.Id);
                    }
                }

                // Associate the specified ad extensions with the respective campaigns or ad groups.
                await CampaignManagementExampleHelper.SetAdExtensionsAssociationsAsync(
                    authorizationData.AccountId,
                    adExtensionIdToEntityIdAssociations,
                    AssociationType.Campaign
                    );

                OutputStatusMessage("Set ad extension associations.\n");

                // Get editorial rejection reasons for the respective ad extension and entity associations.
                var getAdExtensionsEditorialReasonsResponse =
                    (await CampaignManagementExampleHelper.GetAdExtensionsEditorialReasonsAsync(
                         authorizationData.AccountId,
                         adExtensionIdToEntityIdAssociations,
                         AssociationType.Campaign
                         ));
                var adExtensionEditorialReasonCollection =
                    (AdExtensionEditorialReasonCollection[])getAdExtensionsEditorialReasonsResponse?.EditorialReasons;
                CampaignManagementExampleHelper.OutputArrayOfBatchError(getAdExtensionsEditorialReasonsResponse?.PartialErrors);

                AdExtensionsTypeFilter adExtensionsTypeFilter =
                    AdExtensionsTypeFilter.AppAdExtension |
                    AdExtensionsTypeFilter.CallAdExtension |
                    AdExtensionsTypeFilter.CalloutAdExtension |
                    AdExtensionsTypeFilter.ImageAdExtension |
                    AdExtensionsTypeFilter.LocationAdExtension |
                    AdExtensionsTypeFilter.Sitelink2AdExtension |
                    // You should remove this flag if your customer is not enabled for price ad extensions.
                    AdExtensionsTypeFilter.PriceAdExtension |
                    AdExtensionsTypeFilter.ReviewAdExtension |
                    AdExtensionsTypeFilter.StructuredSnippetAdExtension;

                // Get all ad extensions added above.
                var getAdExtensionsByIdsResponse = (await CampaignManagementExampleHelper.GetAdExtensionsByIdsAsync(
                                                        authorizationData.AccountId,
                                                        adExtensionIds,
                                                        adExtensionsTypeFilter
                                                        ));
                adExtensions = getAdExtensionsByIdsResponse?.AdExtensions.ToArray();
                CampaignManagementExampleHelper.OutputArrayOfBatchError(getAdExtensionsByIdsResponse?.PartialErrors);

                OutputStatusMessage("List of ad extensions that were added above:\n");
                CampaignManagementExampleHelper.OutputArrayOfAdExtension(adExtensions);

                // Get only the location extensions and remove scheduling.

                adExtensionsTypeFilter = AdExtensionsTypeFilter.LocationAdExtension;

                getAdExtensionsByIdsResponse = (await CampaignManagementExampleHelper.GetAdExtensionsByIdsAsync(
                                                    authorizationData.AccountId,
                                                    adExtensionIds,
                                                    adExtensionsTypeFilter
                                                    ));
                adExtensions = getAdExtensionsByIdsResponse?.AdExtensions.ToArray();

                // In this example partial errors will be returned for indices where the ad extensions
                // are not location ad extensions because we only requested AdExtensionsTypeFilter.LocationAdExtension.
                // This is an example, and ideally you would only send the required ad extension IDs.

                CampaignManagementExampleHelper.OutputArrayOfBatchError(getAdExtensionsByIdsResponse?.PartialErrors);

                var updateExtensions   = new List <AdExtension>();
                var updateExtensionIds = new List <long>();

                foreach (var extension in adExtensions)
                {
                    // GetAdExtensionsByIds will return a nil element if the request filters / conditions were not met.
                    if (extension != null && extension.Id != null)
                    {
                        // Remove read-only elements that would otherwise cause the update operation to fail.
                        var updateExtension = SetReadOnlyAdExtensionElementsToNull(extension);

                        // If you set the Scheduling element null, any existing scheduling set for the ad extension will remain unchanged.
                        // If you set this to any non-null Schedule object, you are effectively replacing existing scheduling
                        // for the ad extension. In this example, we will remove any existing scheduling by setting this element
                        // to an empty Schedule object.
                        updateExtension.Scheduling = new Schedule {
                        };

                        updateExtensions.Add(updateExtension);
                        updateExtensionIds.Add((long)updateExtension.Id);
                    }
                }

                OutputStatusMessage("Removing scheduling from the location ad extensions..\n");
                await CampaignManagementExampleHelper.UpdateAdExtensionsAsync(authorizationData.AccountId, updateExtensions);

                // Get only the location extensions to output the result.

                getAdExtensionsByIdsResponse = (await CampaignManagementExampleHelper.GetAdExtensionsByIdsAsync(
                                                    authorizationData.AccountId,
                                                    updateExtensionIds,
                                                    adExtensionsTypeFilter
                                                    ));
                adExtensions = getAdExtensionsByIdsResponse?.AdExtensions.ToArray();
                CampaignManagementExampleHelper.OutputArrayOfBatchError(getAdExtensionsByIdsResponse?.PartialErrors);

                OutputStatusMessage("List of ad extensions that were updated above:\n");
                CampaignManagementExampleHelper.OutputArrayOfAdExtension(adExtensions);

                // Delete the ad extension associations, ad extensions, and campaign, that were previously added.
                // At this point the ad extensions are still available in the account's ad extensions library.

                await CampaignManagementExampleHelper.DeleteAdExtensionsAssociationsAsync(
                    authorizationData.AccountId,
                    adExtensionIdToEntityIdAssociations,
                    AssociationType.Campaign
                    );

                OutputStatusMessage("Deleted ad extension associations.\n");

                // Delete the ad extensions from the account’s ad extension library.

                await CampaignManagementExampleHelper.DeleteAdExtensionsAsync(
                    authorizationData.AccountId,
                    adExtensionIds
                    );

                OutputStatusMessage("Deleted ad extensions.\n");

                await CampaignManagementExampleHelper.DeleteCampaignsAsync(authorizationData.AccountId, new[] { (long)campaignIds[0] });

                OutputStatusMessage(string.Format("Deleted Campaign Id {0}\n", (long)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.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 Customer Management service exceptions
            catch (FaultException <Microsoft.BingAds.V11.CustomerManagement.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V11.CustomerManagement.ApiFault> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }
コード例 #13
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            Stream     responseStream = null;
            FileStream fileStream     = null;

            var fileInfo = new FileInfo(LocalFile);

            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);
                CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>(
                    authorizationData: authorizationData,
                    environment: environment);

                OutputStatusMessage("-----\nGetGeoLocationsFileUrl:");
                var getGeoLocationsFileUrlResponse = await CampaignManagementExampleHelper.GetGeoLocationsFileUrlAsync(
                    version : Version,
                    languageLocale : LanguageLocale);

                // Going forward you should track the date and time of the previous download,
                // and compare it with the last modified time provided by the service.
                var previousSyncTimeUtc = new DateTime(2017, 8, 10, 0, 0, 0, DateTimeKind.Utc);

                var fileUrl = getGeoLocationsFileUrlResponse.FileUrl;
                var fileUrlExpiryTimeUtc = getGeoLocationsFileUrlResponse.FileUrlExpiryTimeUtc;
                var lastModifiedTimeUtc  = getGeoLocationsFileUrlResponse.LastModifiedTimeUtc;

                OutputStatusMessage(string.Format("FileUrl: {0}", fileUrl));
                OutputStatusMessage(string.Format("FileUrlExpiryTimeUtc: {0}", fileUrlExpiryTimeUtc));
                OutputStatusMessage(string.Format("LastModifiedTimeUtc: {0}", lastModifiedTimeUtc));

                // Download the file if it was modified since the previous download.
                if (DateTime.Compare(previousSyncTimeUtc, lastModifiedTimeUtc) < 0)
                {
                    DownloadFile(fileUrl, LocalFile);
                }
            }
            // 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);
            }
            finally
            {
                if (fileStream != null)
                {
                    fileStream.Close();
                }
                if (responseStream != null)
                {
                    responseStream.Close();
                }
            }
        }
コード例 #14
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                // Used to output the Campaign Management objects within Bulk entities.
                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(
                    authorizationData: authorizationData,
                    apiEnvironment: environment);

                var uploadEntities = new List <BulkEntity>();

                // Add a new campaign and associate it with ad extensions.

                uploadEntities.Add(GetBulkCampaign());

                uploadEntities.Add(GetBulkActionAdExtension());
                uploadEntities.Add(GetBulkAppAdExtension());
                uploadEntities.Add(GetBulkCallAdExtension());
                uploadEntities.Add(GetBulkCalloutAdExtension());
                uploadEntities.Add(GetBulkLocationAdExtension());
                uploadEntities.Add(GetBulkPriceAdExtension());
                uploadEntities.Add(GetBulkReviewAdExtension());
                uploadEntities.Add(GetBulkSitelinkAdExtension());
                uploadEntities.Add(GetBulkStructuredSnippetAdExtension());

                uploadEntities.Add(GetBulkCampaignActionAdExtension());
                uploadEntities.Add(GetBulkCampaignAppAdExtension());
                uploadEntities.Add(GetBulkCampaignCallAdExtension());
                uploadEntities.Add(GetBulkCampaignCalloutAdExtension());
                uploadEntities.Add(GetBulkCampaignLocationAdExtension());
                uploadEntities.Add(GetBulkCampaignPriceAdExtension());
                uploadEntities.Add(GetBulkCampaignReviewAdExtension());
                uploadEntities.Add(GetBulkCampaignSitelinkAdExtension());
                uploadEntities.Add(GetBulkCampaignStructuredSnippetAdExtension());

                OutputStatusMessage("-----\nAdding campaign, ad extensions, and associations...");

                var Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                var downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var actionAdExtensionResults = downloadEntities.OfType <BulkActionAdExtension>().ToList();
                OutputBulkActionAdExtensions(actionAdExtensionResults);

                var appAdExtensionResults = downloadEntities.OfType <BulkAppAdExtension>().ToList();
                OutputBulkAppAdExtensions(appAdExtensionResults);

                var callAdExtensionResults = downloadEntities.OfType <BulkCallAdExtension>().ToList();
                OutputBulkCallAdExtensions(callAdExtensionResults);

                var calloutAdExtensionResults = downloadEntities.OfType <BulkCalloutAdExtension>().ToList();
                OutputBulkCalloutAdExtensions(calloutAdExtensionResults);

                var imageAdExtensionResults = downloadEntities.OfType <BulkImageAdExtension>().ToList();
                OutputBulkImageAdExtensions(imageAdExtensionResults);

                var locationAdExtensionResults = downloadEntities.OfType <BulkLocationAdExtension>().ToList();
                OutputBulkLocationAdExtensions(locationAdExtensionResults);

                var priceAdExtensionResults = downloadEntities.OfType <BulkPriceAdExtension>().ToList();
                OutputBulkPriceAdExtensions(priceAdExtensionResults);

                var reviewAdExtensionResults = downloadEntities.OfType <BulkReviewAdExtension>().ToList();
                OutputBulkReviewAdExtensions(reviewAdExtensionResults);

                var structuredSnippetAdExtensionResults = downloadEntities.OfType <BulkStructuredSnippetAdExtension>().ToList();
                OutputBulkStructuredSnippetAdExtensions(structuredSnippetAdExtensionResults);

                var sitelinkAdExtensionResults = downloadEntities.OfType <BulkSitelinkAdExtension>().ToList();
                OutputBulkSitelinkAdExtensions(sitelinkAdExtensionResults);

                OutputBulkCampaignAdExtensionAssociations(downloadEntities.OfType <BulkCampaignAdExtensionAssociation>().ToList());

                Reader.Dispose();


                // Delete the campaign and ad extensions that were previously added.

                uploadEntities = new List <BulkEntity>();

                foreach (var campaignResult in campaignResults)
                {
                    if (campaignResult.Campaign != null)
                    {
                        campaignResult.Campaign.Status = CampaignStatus.Deleted;
                        uploadEntities.Add(campaignResult);
                    }
                }

                foreach (var actionAdExtensionResult in actionAdExtensionResults)
                {
                    if (actionAdExtensionResult.ActionAdExtension.Id > 0)
                    {
                        actionAdExtensionResult.ActionAdExtension.Status = AdExtensionStatus.Deleted;
                        uploadEntities.Add(actionAdExtensionResult);
                    }
                }

                foreach (var appAdExtensionResult in appAdExtensionResults)
                {
                    //By default the sample does not successfully create any app ad extensions,
                    //because you need to provide details above such as the AppStoreId.
                    if (appAdExtensionResult.AppAdExtension.Id > 0)
                    {
                        appAdExtensionResult.AppAdExtension.Status = AdExtensionStatus.Deleted;
                        uploadEntities.Add(appAdExtensionResult);
                    }
                }

                foreach (var callAdExtensionResult in callAdExtensionResults)
                {
                    if (callAdExtensionResult.CallAdExtension.Id > 0)
                    {
                        callAdExtensionResult.CallAdExtension.Status = AdExtensionStatus.Deleted;
                        uploadEntities.Add(callAdExtensionResult);
                    }
                }

                foreach (var calloutAdExtensionResult in calloutAdExtensionResults)
                {
                    if (calloutAdExtensionResult.CalloutAdExtension.Id > 0)
                    {
                        calloutAdExtensionResult.CalloutAdExtension.Status = AdExtensionStatus.Deleted;
                        uploadEntities.Add(calloutAdExtensionResult);
                    }
                }

                foreach (var imageAdExtensionResult in imageAdExtensionResults)
                {
                    if (imageAdExtensionResult.ImageAdExtension.Id > 0)
                    {
                        imageAdExtensionResult.ImageAdExtension.Status = AdExtensionStatus.Deleted;
                        uploadEntities.Add(imageAdExtensionResult);
                    }
                }

                foreach (var locationAdExtensionResult in locationAdExtensionResults)
                {
                    if (locationAdExtensionResult.LocationAdExtension.Id > 0)
                    {
                        locationAdExtensionResult.LocationAdExtension.Status = AdExtensionStatus.Deleted;
                        uploadEntities.Add(locationAdExtensionResult);
                    }
                }

                foreach (var priceAdExtensionResult in priceAdExtensionResults)
                {
                    if (priceAdExtensionResult.PriceAdExtension.Id > 0)
                    {
                        priceAdExtensionResult.PriceAdExtension.Status = AdExtensionStatus.Deleted;
                        uploadEntities.Add(priceAdExtensionResult);
                    }
                }

                foreach (var reviewAdExtensionResult in reviewAdExtensionResults)
                {
                    if (reviewAdExtensionResult.ReviewAdExtension.Id > 0)
                    {
                        reviewAdExtensionResult.ReviewAdExtension.Status = AdExtensionStatus.Deleted;
                        uploadEntities.Add(reviewAdExtensionResult);
                    }
                }

                foreach (var sitelinkAdExtensionResult in sitelinkAdExtensionResults)
                {
                    if (sitelinkAdExtensionResult.SitelinkAdExtension.Id > 0)
                    {
                        sitelinkAdExtensionResult.SitelinkAdExtension.Status = AdExtensionStatus.Deleted;
                        uploadEntities.Add(sitelinkAdExtensionResult);
                    }
                }

                foreach (var structuredSnippetAdExtensionResult in structuredSnippetAdExtensionResults)
                {
                    if (structuredSnippetAdExtensionResult.StructuredSnippetAdExtension.Id > 0)
                    {
                        structuredSnippetAdExtensionResult.StructuredSnippetAdExtension.Status = AdExtensionStatus.Deleted;
                        uploadEntities.Add(structuredSnippetAdExtensionResult);
                    }
                }

                // Upload and write the output

                OutputStatusMessage("-----\nDeleting campaign and ad extensions...");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                OutputBulkCampaigns(downloadEntities.OfType <BulkCampaign>().ToList());
                OutputBulkActionAdExtensions(downloadEntities.OfType <BulkActionAdExtension>().ToList());
                OutputBulkAppAdExtensions(downloadEntities.OfType <BulkAppAdExtension>().ToList());
                OutputBulkCallAdExtensions(downloadEntities.OfType <BulkCallAdExtension>().ToList());
                OutputBulkCalloutAdExtensions(downloadEntities.OfType <BulkCalloutAdExtension>().ToList());
                OutputBulkImageAdExtensions(downloadEntities.OfType <BulkImageAdExtension>().ToList());
                OutputBulkLocationAdExtensions(downloadEntities.OfType <BulkLocationAdExtension>().ToList());
                OutputBulkPriceAdExtensions(downloadEntities.OfType <BulkPriceAdExtension>().ToList());
                OutputBulkReviewAdExtensions(downloadEntities.OfType <BulkReviewAdExtension>().ToList());
                OutputBulkSitelinkAdExtensions(downloadEntities.OfType <BulkSitelinkAdExtension>().ToList());
                OutputBulkStructuredSnippetAdExtensions(downloadEntities.OfType <BulkStructuredSnippetAdExtension>().ToList());

                Reader.Dispose();
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V13.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V13.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
コード例 #15
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(authorizationData, environment);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                OutputStatusMessage("Add and Update Criterions . . .\n");
                await AddUpdateDeleteCriterions().ConfigureAwait(continueOnCapturedContext: false);
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch 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 Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V12.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V12.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
コード例 #16
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                // The Bing Merchant Center Store Id cannot be retrieved via the Bulk service,
                // so we'll use the Campaign Management service i.e., the GetBMCStoresByCustomerId service operation below.

                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);
                CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>(
                    authorizationData: authorizationData,
                    environment: environment);

                BulkServiceManager = new BulkServiceManager(
                    authorizationData: authorizationData,
                    apiEnvironment: environment);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                // 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)
                {
                    OutputStatusMessage(
                        string.Format("You do not have any BMC stores registered for CustomerId {0}.", authorizationData.CustomerId)
                        );
                    return;
                }

                var uploadEntities = new List <BulkEntity>();

                // Create a Shopping campaign with product conditions.

                var bulkCampaign = new BulkCampaign
                {
                    Campaign = new Campaign
                    {
                        Id           = campaignIdKey,
                        CampaignType = CampaignType.Shopping,
                        Languages    = new string[] { "All" },
                        Name         = "Women's Shoes " + DateTime.UtcNow,
                        DailyBudget  = 50,
                        BudgetType   = BudgetLimitType.DailyBudgetStandard,
                        Settings     = new[] {
                            new ShoppingSetting()
                            {
                                Priority         = 0,
                                SalesCountryCode = "US",
                                StoreId          = (int)stores[0].Id
                            }
                        },
                        TimeZone = "PacificTimeUSCanadaTijuana",
                    }
                };
                uploadEntities.Add(bulkCampaign);

                // 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 bulkCampaignProductScope = new BulkCampaignProductScope
                {
                    BiddableCampaignCriterion = new BiddableCampaignCriterion()
                    {
                        CampaignId   = campaignIdKey,
                        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
                    },
                };
                uploadEntities.Add(bulkCampaignProductScope);

                // Create the ad group that will have the product partitions.

                var bulkAdGroup = new BulkAdGroup
                {
                    CampaignId = campaignIdKey,
                    AdGroup    = new AdGroup
                    {
                        Id        = adGroupIdKey,
                        Name      = "Women's Red Shoe Sale",
                        StartDate = null,
                        EndDate   = new Microsoft.BingAds.V13.CampaignManagement.Date
                        {
                            Month = 12,
                            Day   = 31,
                            Year  = DateTime.UtcNow.Year + 1
                        },
                        CpcBid = new Bid {
                            Amount = 0.09
                        },
                    },
                };
                uploadEntities.Add(bulkAdGroup);

                // 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 bulkProductAd = new BulkProductAd
                {
                    AdGroupId = adGroupIdKey,
                    ProductAd = new ProductAd {
                    }
                };
                uploadEntities.Add(bulkProductAd);

                // Upload and write the output

                OutputStatusMessage("-----\nAdding the campaign, product scope, ad group, and ad...");

                var Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                var downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var adGroupResults = downloadEntities.OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(adGroupResults);

                var campaignProductScopeResults = downloadEntities.OfType <BulkCampaignProductScope>().ToList();
                OutputBulkCampaignProductScopes(campaignProductScopeResults);

                var productAdResults = downloadEntities.OfType <BulkProductAd>().ToList();
                OutputBulkProductAds(productAdResults);

                Reader.Dispose();

                // Bid all products

                var adGroupId = (long)adGroupResults[0].AdGroup.Id;

                var helper = new ProductPartitionHelper(adGroupId);

                var root = helper.AddUnit(
                    null,
                    new ProductCondition {
                    Operand = "All", Attribute = null
                },
                    0.35,
                    false,
                    "root"
                    );

                OutputStatusMessage("-----\nApplying only the root as a Unit with a bid...");
                var applyBulkProductPartitionActionsResults =
                    await ApplyBulkProductPartitionActions(helper.PartitionActions);

                var productPartitions = await GetBulkAdGroupProductPartitionTree(adGroupId);

                OutputStatusMessage("The ad group's product partition only has a tree root node:");
                OutputProductPartitions(productPartitions);

                // Let's update the bid of the root Unit we just added.

                var updatedRoot = GetNodeByClientId(applyBulkProductPartitionActionsResults, "root");
                var bid         = new FixedBid
                {
                    Amount = 0.45
                };
                ((BiddableAdGroupCriterion)(updatedRoot.AdGroupCriterion)).CriterionBid = bid;

                helper = new ProductPartitionHelper(adGroupId);
                helper.UpdatePartition(updatedRoot);

                OutputStatusMessage("Updating the bid for the tree root node...");
                await ApplyBulkProductPartitionActions(helper.PartitionActions);

                productPartitions = await GetBulkAdGroupProductPartitionTree(adGroupId);

                OutputStatusMessage("Updated the bid for the tree root node:");
                OutputProductPartitions(productPartitions);

                // 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 20,000 nodes; however,
                // we will build it in steps to demonstrate how to use the results from bulk upload to update the tree.

                helper = new ProductPartitionHelper(adGroupId);

                // Check whether a root node exists already.

                var existingRoot = GetNodeByClientId(applyBulkProductPartitionActionsResults, "root");
                if (existingRoot != null)
                {
                    existingRoot.ClientId = "deletedroot";
                    helper.DeletePartition(existingRoot);
                }

                root = helper.AddSubdivision(
                    null,
                    new ProductCondition {
                    Operand = "All", Attribute = null
                },
                    "root"
                    );

                // The direct children of any node must have the same Operand.
                // For this example we will use CategoryL1 nodes as children of the root.
                // For a list of valid CategoryL1 through CategoryL5 values, see the Bing Category Taxonomy:
                // http://go.microsoft.com/fwlink?LinkId=507666

                var animalsSubdivision = helper.AddSubdivision(
                    root,
                    new ProductCondition {
                    Operand = "CategoryL1", Attribute = "Animals & Pet Supplies"
                },
                    "animalsSubdivision"
                    );

                // If you use a CategoryL2 node, it must be a descendant (child or later) of a CategoryL1 node.
                // In other words you cannot have a CategoryL2 node as parent of a CategoryL1 node.
                // For this example we will a CategoryL2 node as child of the CategoryL1 Animals & Pet Supplies node.

                var petSuppliesSubdivision = helper.AddSubdivision(
                    animalsSubdivision,
                    new ProductCondition {
                    Operand = "CategoryL2", Attribute = "Pet Supplies"
                },
                    "petSuppliesSubdivision"
                    );

                var brandA = helper.AddUnit(
                    petSuppliesSubdivision,
                    new ProductCondition {
                    Operand = "Brand", Attribute = "Brand A"
                },
                    0.35,
                    false,
                    "brandA"
                    );

                // If you won't bid on Brand B, set the helper method's bidAmount to '0' and isNegative to true.
                // The helper method will create a NegativeAdGroupCriterion and apply the condition.

                var brandB = helper.AddUnit(
                    petSuppliesSubdivision,
                    new ProductCondition {
                    Operand = "Brand", Attribute = "Brand B"
                },
                    0,
                    true,
                    "brandB"
                    );

                var otherBrands = helper.AddUnit(
                    petSuppliesSubdivision,
                    new ProductCondition {
                    Operand = "Brand", Attribute = null
                },
                    0.35,
                    false,
                    "otherBrands"
                    );

                var otherPetSupplies = helper.AddUnit(
                    animalsSubdivision,
                    new ProductCondition {
                    Operand = "CategoryL2", Attribute = null
                },
                    0.35,
                    false,
                    "otherPetSupplies"
                    );

                var electronics = helper.AddUnit(
                    root,
                    new ProductCondition {
                    Operand = "CategoryL1", Attribute = "Electronics"
                },
                    0.35,
                    false,
                    "electronics"
                    );

                var otherCategoryL1 = helper.AddUnit(
                    root,
                    new ProductCondition {
                    Operand = "CategoryL1", Attribute = null
                },
                    0.35,
                    false,
                    "otherCategoryL1"
                    );

                OutputStatusMessage("-----\nApplying product partitions to the ad group...");
                applyBulkProductPartitionActionsResults =
                    await ApplyBulkProductPartitionActions(helper.PartitionActions);

                productPartitions = await GetBulkAdGroupProductPartitionTree(adGroupId);

                // The product partition group tree now has 9 nodes.

                //All other (Root Node)
                // |
                // +-- Animals & Pet Supplies (CategoryL1)
                // |    |
                // |    +-- Pet Supplies (CategoryL2)
                // |    |    |
                // |    |    +-- Brand A
                // |    |    |
                // |    |    +-- Brand B
                // |    |    |
                // |    |    +-- All other (Brand)
                // |    |
                // |    +-- All other (CategoryL2)
                // |
                // +-- Electronics (CategoryL1)
                // |
                // +-- All other (CategoryL1)

                OutputStatusMessage("The product partition group tree now has 9 nodes:");
                OutputProductPartitions(productPartitions);

                // Let's replace the Electronics (CategoryL1) node created above with an Electronics (CategoryL1) node that
                // has children i.e. Brand C (Brand), Brand D (Brand), and All other (Brand) as follows:

                //Electronics (CategoryL1)
                //|
                //+-- Brand C (Brand)
                //|
                //+-- Brand D (Brand)
                //|
                //+-- All other (Brand)

                helper = new ProductPartitionHelper(adGroupId);

                // To replace a node we must know its Id and its ParentCriterionId. In this case the parent of the node
                // we are replacing is All other (Root Node). The node that we are replacing is Electronics (CategoryL1).

                var rootId = GetNodeByClientId(applyBulkProductPartitionActionsResults, "root").AdGroupCriterion.Id;
                electronics.AdGroupCriterion.Id = GetNodeByClientId(applyBulkProductPartitionActionsResults, "electronics").AdGroupCriterion.Id;
                helper.DeletePartition(electronics);

                var parent = new BulkAdGroupProductPartition
                {
                    AdGroupCriterion = new BiddableAdGroupCriterion()
                    {
                        Id = rootId
                    }
                };

                var electronicsSubdivision = helper.AddSubdivision(
                    parent,
                    new ProductCondition {
                    Operand = "CategoryL1", Attribute = "Electronics"
                },
                    "electronicsSubdivision"
                    );

                var brandC = helper.AddUnit(
                    electronicsSubdivision,
                    new ProductCondition {
                    Operand = "Brand", Attribute = "Brand C"
                },
                    0.35,
                    false,
                    "brandC"
                    );

                var brandD = helper.AddUnit(
                    electronicsSubdivision,
                    new ProductCondition {
                    Operand = "Brand", Attribute = "Brand D"
                },
                    0.35,
                    false,
                    "brandD"
                    );

                var otherElectronicsBrands = helper.AddUnit(
                    electronicsSubdivision,
                    new ProductCondition {
                    Operand = "Brand", Attribute = null
                },
                    0.35,
                    false,
                    "otherElectronicsBrands"
                    );

                OutputStatusMessage(
                    "Updating the product partition group to refine Electronics (CategoryL1) with 3 child nodes . . . \n"
                    );
                applyBulkProductPartitionActionsResults =
                    await ApplyBulkProductPartitionActions(helper.PartitionActions);

                productPartitions = await GetBulkAdGroupProductPartitionTree(adGroupId);

                // The product partition group tree now has 12 nodes, including the children of Electronics (CategoryL1):

                //All other (Root Node)
                // |
                // +-- Animals & Pet Supplies (CategoryL1)
                // |    |
                // |    +-- Pet Supplies (CategoryL2)
                // |    |    |
                // |    |    +-- Brand A
                // |    |    |
                // |    |    +-- Brand B
                // |    |    |
                // |    |    +-- All other (Brand)
                // |    |
                // |    +-- All other (CategoryL2)
                // |
                // +-- Electronics (CategoryL1)
                // |    |
                // |    +-- Brand C (Brand)
                // |    |
                // |    +-- Brand D (Brand)
                // |    |
                // |    +-- All other (Brand)
                // |
                // +-- All other (CategoryL1)

                OutputStatusMessage(
                    "The product partition group tree now has 12 nodes, including the children of Electronics (CategoryL1): \n"
                    );
                OutputProductPartitions(productPartitions);

                // Delete the campaign and everything it contains e.g., ad groups and ads.

                uploadEntities = new List <BulkEntity>();

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                // Upload and write the output

                OutputStatusMessage("-----\nDeleting the campaign and everything it contains e.g., ad groups and ads...");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                Reader.Dispose();
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V13.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V13.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            // Catch 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 (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
コード例 #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 a budget that can be shared by campaigns in the same account.

                var budgets = new[]
                {
                    new Budget
                    {
                        Amount     = 50,
                        BudgetType = BudgetLimitType.DailyBudgetStandard,
                        Name       = "My Shared Budget " + DateTime.UtcNow,
                    }
                };

                OutputStatusMessage("-----\nAddBudgets:");
                AddBudgetsResponse addBudgetsResponse = await CampaignManagementExampleHelper.AddBudgetsAsync(
                    budgets : budgets);

                long?[]      budgetIds    = addBudgetsResponse.BudgetIds.ToArray();
                BatchError[] budgetErrors = addBudgetsResponse.PartialErrors.ToArray();
                OutputStatusMessage("BudgetIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(budgetIds);
                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(budgetErrors);

                // Add one or more campaigns.

                var campaigns = new[] {
                    new Campaign
                    {
                        // We'll use the shared budget instead of defining a daily amount for this campaign.
                        BudgetId    = budgetIds[0],
                        DailyBudget = null,
                        BudgetType  = null,
                        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);

                // 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 account's shared budget.

                OutputStatusMessage("-----\nDeleteBudgets:");
                await CampaignManagementExampleHelper.DeleteBudgetsAsync(
                    budgetIds : new[] { (long)budgetIds[0] });

                OutputStatusMessage(string.Format("Deleted Budget Id {0}", 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 <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);
            }
        }
コード例 #18
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);
            }
        }
コード例 #19
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);
            }
        }
コード例 #20
0
        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);

                OutputStatusMessage("-----\nGetCampaignsByAccountId:");
                var campaigns = (await CampaignManagementExampleHelper.GetCampaignsByAccountIdAsync(
                                     accountId: authorizationData.AccountId,
                                     campaignType: AllCampaignTypes,
                                     returnAdditionalFields: CampaignAdditionalField.AdScheduleUseSearcherTimeZone)).Campaigns;
                OutputStatusMessage("Campaigns:");
                CampaignManagementExampleHelper.OutputArrayOfCampaign(campaigns);

                IList <BudgetOpportunity> opportunities = null;

                // Get the budget opportunities for each campaign in the current account.

                foreach (var campaign in campaigns)
                {
                    if (campaign.Id != null)
                    {
                        OutputStatusMessage("-----\nGetBudgetOpportunities:");
                        opportunities = (await AdInsightExampleHelper.GetBudgetOpportunitiesAsync(
                                             campaignId: (long)campaign.Id)).Opportunities;
                        OutputStatusMessage("Opportunities:");
                        AdInsightExampleHelper.OutputArrayOfBudgetOpportunity(opportunities);
                    }
                }
            }
            // 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 AdInsight service exceptions
            catch (FaultException <Microsoft.BingAds.V13.AdInsight.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V13.AdInsight.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 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 (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }
コード例 #21
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                // Used to output the Campaign Management objects within Bulk entities.
                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(
                    authorizationData: authorizationData,
                    apiEnvironment: environment);

                var progress = new Progress<BulkOperationProgressInfo>(x =>
                    OutputStatusMessage(string.Format("{0} % Complete",
                        x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                var uploadEntities = new List<BulkEntity>();

                // Add a search campaign.
                
                var bulkCampaign = new BulkCampaign
                {
                    Campaign = new Campaign
                    {
                        BudgetType = BudgetLimitType.DailyBudgetStandard,
                        DailyBudget = 50,
                        CampaignType = CampaignType.Search,
                        Id = campaignIdKey,
                        Languages = new string[] { "All" },
                        Name = "Women's Shoes " + DateTime.UtcNow,
                        TimeZone = "PacificTimeUSCanadaTijuana",
                    },
                };
                uploadEntities.Add(bulkCampaign);

                // Add an ad group within the campaign.

                var bulkAdGroup = new BulkAdGroup
                {
                    CampaignId = campaignIdKey,
                    AdGroup = new AdGroup
                    {
                        Id = adGroupIdKey,
                        Name = "Women's Red Shoe Sale",
                        StartDate = null,
                        EndDate = new Microsoft.BingAds.V12.CampaignManagement.Date
                        {
                            Month = 12,
                            Day = 31,
                            Year = DateTime.UtcNow.Year + 1
                        },
                        CpcBid = new Bid { Amount = 0.09 },
                    },
                };
                uploadEntities.Add(bulkAdGroup);

                // Add keywords and ads within the ad group.

                var bulkKeyword = new BulkKeyword{
                    AdGroupId = adGroupIdKey,
                    Keyword = new Keyword
                    {
                        Bid = new Bid { Amount = 0.47 },
                        Param2 = "10% Off",
                        MatchType = MatchType.Phrase,
                        Text = "Brand-A Shoes",
                    },                    
                };
                uploadEntities.Add(bulkKeyword);

                var bulkExpandedTextAd = new BulkExpandedTextAd
                {
                    AdGroupId = adGroupIdKey,
                    ExpandedTextAd = 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"
                        },
                    },
                };
                uploadEntities.Add(bulkExpandedTextAd);

                // Upload and write the output

                OutputStatusMessage("-----\nAdding campaign, ad group, keyword, and ad...");

                var Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);
                var downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                var campaignResults = downloadEntities.OfType<BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var adGroupResults = downloadEntities.OfType<BulkAdGroup>().ToList();
                OutputBulkAdGroups(adGroupResults);

                var keywordResults = downloadEntities.OfType<BulkKeyword>().ToList();
                OutputBulkKeywords(keywordResults);

                var expandedTextAdResults = downloadEntities.OfType<BulkExpandedTextAd>().ToList();
                OutputBulkExpandedTextAds(expandedTextAdResults);

                Reader.Dispose();
                
                // Delete the campaign and everything it contains e.g., ad groups and ads.

                uploadEntities = new List<BulkEntity>();
                
                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }
                
                // Upload and write the output

                OutputStatusMessage("-----\nDeleting the campaign and everything it contains e.g., ad groups and ads...");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);
                downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                campaignResults = downloadEntities.OfType<BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                Reader.Dispose();
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException<Microsoft.BingAds.V12.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException<Microsoft.BingAds.V12.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException<DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException<UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null) { Reader.Dispose(); }
                if (Writer != null) { Writer.Dispose(); }
            }
        }
コード例 #22
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                // Used to output the Campaign Management objects within Bulk entities.
                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(
                    authorizationData: authorizationData,
                    apiEnvironment: environment);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                var uploadEntities = new List <BulkEntity>();

                // Setup an ad customizer feed that can be referenced later in the ad copy.

                var bulkAdCustomizerFeed = new BulkFeed
                {
                    CustomAttributes = new[]
                    {
                        new FeedCustomAttributeContract
                        {
                            FeedAttributeType = "String",
                            Name = "Product"
                        },
                        new FeedCustomAttributeContract
                        {
                            FeedAttributeType = "String",
                            Name = "Materials_Lightweight"
                        },
                        new FeedCustomAttributeContract
                        {
                            FeedAttributeType = "String",
                            Name = "Description_Lightweight"
                        },
                        new FeedCustomAttributeContract
                        {
                            FeedAttributeType = "Int64",
                            Name = "Finishes"
                        },
                        new FeedCustomAttributeContract
                        {
                            FeedAttributeType = "Price",
                            Name = "StartPrice"
                        },
                    },
                    Id      = feedIdKey,
                    Name    = "My AdCustomizerFeed " + DateTime.UtcNow,
                    Status  = Status.Active,
                    SubType = "AdCustomizerFeed",
                };

                uploadEntities.Add(bulkAdCustomizerFeed);

                var adCustomizerFeedItemCustomAttributes = new Dictionary <string, object>();
                adCustomizerFeedItemCustomAttributes.Add("Product", "Contoso 900");
                adCustomizerFeedItemCustomAttributes.Add("Materials_Lightweight", "titanium or acetate");
                adCustomizerFeedItemCustomAttributes.Add("Description_Lightweight", "Stylish, lightweight shades");
                adCustomizerFeedItemCustomAttributes.Add("Finishes", 8);
                adCustomizerFeedItemCustomAttributes.Add("StartPrice", "$24.99");

                var serializerSettings = new JsonSerializerSettings();
                serializerSettings.NullValueHandling = NullValueHandling.Ignore;
                var adCustomizerFeedItemCustomAttributesJson = JsonConvert.SerializeObject(
                    adCustomizerFeedItemCustomAttributes, serializerSettings);

                var bulkAdCustomizerFeedItem = new BulkFeedItem
                {
                    FeedId           = feedIdKey,
                    CustomAttributes = adCustomizerFeedItemCustomAttributesJson,
                    Id            = null,
                    AdGroupName   = null,
                    AudienceId    = null,
                    CampaignName  = null,
                    DayTimeRanges = new[]
                    {
                        new DayTime
                        {
                            Day         = Day.Monday,
                            StartHour   = 9,
                            StartMinute = Minute.Zero,
                            EndHour     = 21,
                            EndMinute   = Minute.Zero,
                        },
                    },
                    EndDate          = null,
                    StartDate        = DateTime.UtcNow,
                    IntentOption     = IntentOption.PeopleIn,
                    Keyword          = "lightweight sunglasses",
                    LocationId       = 190,
                    MatchType        = MatchType.Broad,
                    DevicePreference = null,
                    Status           = Status.Active
                };

                uploadEntities.Add(bulkAdCustomizerFeedItem);

                // Add a search campaign.

                var bulkCampaign = new BulkCampaign
                {
                    Campaign = new Campaign
                    {
                        BudgetType   = BudgetLimitType.DailyBudgetStandard,
                        DailyBudget  = 50,
                        CampaignType = CampaignType.Search,
                        Id           = campaignIdKey,
                        Languages    = new string[] { "All" },
                        Name         = "Summer Sunglasses " + DateTime.UtcNow,
                        TimeZone     = "PacificTimeUSCanadaTijuana",
                    },
                };
                uploadEntities.Add(bulkCampaign);

                // Add an ad group within the campaign.

                var bulkAdGroup = new BulkAdGroup
                {
                    CampaignId = campaignIdKey,
                    AdGroup    = new AdGroup
                    {
                        Id        = adGroupIdKey,
                        Name      = "Sunglasses Sale",
                        StartDate = null,
                        EndDate   = new Microsoft.BingAds.V13.CampaignManagement.Date
                        {
                            Month = 12,
                            Day   = 31,
                            Year  = DateTime.UtcNow.Year + 1
                        },
                        CpcBid = new Bid {
                            Amount = 0.09
                        },
                    },
                };
                uploadEntities.Add(bulkAdGroup);

                // Add keywords and ads within the ad group.

                var bulkKeyword = new BulkKeyword {
                    AdGroupId = adGroupIdKey,
                    Keyword   = new Keyword
                    {
                        Bid = new Bid {
                            Amount = 0.47
                        },
                        Param2    = "10% Off",
                        MatchType = MatchType.Phrase,
                        Text      = "Brand-A Sunglasses",
                    },
                };
                uploadEntities.Add(bulkKeyword);

                var bulkExpandedTextAd = new BulkExpandedTextAd
                {
                    AdGroupId      = adGroupIdKey,
                    ExpandedTextAd = new ExpandedTextAd
                    {
                        TitlePart1 = "The latest {=Sunglasses.Product}s",
                        TitlePart2 = "In {=Sunglasses.Materials_Lightweight}",
                        TitlePart3 = null,
                        Text       = "{=Sunglasses.Description_Lightweight} in {=Sunglasses.Finishes} finishes.",
                        TextPart2  = "Starting at only {=Sunglasses.StartPrice}!",
                        Path1      = "deals",
                        Path2      = null,
                        FinalUrls  = new[] {
                            "https://www.contoso.com"
                        },
                    },
                };
                uploadEntities.Add(bulkExpandedTextAd);

                // Upload and write the output

                OutputStatusMessage("-----\nAdding the ad customizer feed, campaign, ad group, keyword, and ad...");

                var Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                var downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                var feedResults = downloadEntities.OfType <BulkFeed>().ToList();
                OutputBulkFeeds(feedResults);

                var feedItemResults = downloadEntities.OfType <BulkFeedItem>().ToList();
                OutputBulkFeedItems(feedItemResults);

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var adGroupResults = downloadEntities.OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(adGroupResults);

                var keywordResults = downloadEntities.OfType <BulkKeyword>().ToList();
                OutputBulkKeywords(keywordResults);

                var expandedTextAdResults = downloadEntities.OfType <BulkExpandedTextAd>().ToList();
                OutputBulkExpandedTextAds(expandedTextAdResults);

                Reader.Dispose();

                // Delete the feed and campaign and everything it contains e.g., ad groups and ads.

                uploadEntities = new List <BulkEntity>();

                foreach (var feedResult in feedResults)
                {
                    feedResult.Status = Status.Deleted;
                    uploadEntities.Add(feedResult);
                }

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                // Upload and write the output

                OutputStatusMessage("-----\nDeleting the feed and campaign and everything it contains e.g., ad groups and ads...");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                Reader.Dispose();
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V13.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V13.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
コード例 #23
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                CampaignManagementExampleHelper CampaignManagementExampleHelper =
                    new CampaignManagementExampleHelper(this.OutputStatusMessage);
                CampaignManagementExampleHelper.CampaignManagementService =
                    new ServiceClient <ICampaignManagementService>(authorizationData, environment);

                #region MediaRepresentations

                var landscapeImageMedia = GetImageMedia(
                    "Image191x100",
                    MediaFilePath + LandscapeImageMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var landscapeLogoMedia = GetImageMedia(
                    "Image4x1",
                    MediaFilePath + LandscapeLogoMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var squareImageMedia = GetImageMedia(
                    "Image1x1",
                    MediaFilePath + SquareImageMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var squareLogoMedia = GetImageMedia(
                    "Image1x1",
                    MediaFilePath + SquareLogoMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var imageAdExtensionMedia = GetImageMedia(
                    "Image15x10",
                    MediaFilePath + ImageAdExtensionMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var addMedia = new Media[]
                {
                    landscapeImageMedia,
                    landscapeLogoMedia,
                    squareImageMedia,
                    squareLogoMedia,
                    imageAdExtensionMedia
                };
                CampaignManagementExampleHelper.OutputArrayOfMedia(addMedia);

                var imageMediaIds = (await CampaignManagementExampleHelper.AddMediaAsync(
                                         authorizationData.AccountId,
                                         addMedia)).MediaIds;

                // The index of returned IDs is consistent with the order you submitted them in the request;
                // however, the sequence of the IDs themselves is not guaranteed. For example you might observe:
                // - Landscape Image Media Id == imageMediaIds[0] == 1
                // - Landscape Logo Media Id == imageMediaIds[1] == 4
                // - Square Image Media Id == imageMediaIds[2] == 3
                // - Square Logo Media Id == imageMediaIds[3] == 2
                // - Image Ad Extension Media Id == imageMediaIds[4] == 0

                // You can use the first four Media Ids when you add or update a Responsive Ad
                // in an Audience campaign e.g., see AudienceCampaigns.cs.

                var adMediaIds = new List <long> {
                    imageMediaIds[0], imageMediaIds[1], imageMediaIds[2], imageMediaIds[3]
                };
                OutputStatusMessage("Media Ids for Responsive Ad:");
                CampaignManagementExampleHelper.OutputArrayOfLong(adMediaIds);

                // You can use the fifth Media Id when you add or update an Image Ad Extension
                // in a Search campaign e.g., see AdExtensions.cs.

                var extensionMediaIds = new List <long> {
                    imageMediaIds[4]
                };
                OutputStatusMessage("Media Ids for Image Ad Extension:");
                CampaignManagementExampleHelper.OutputArrayOfLong(extensionMediaIds);

                // Get the media representations to confirm the stored dimensions
                // and get the Url where you can later view or download the media.

                var getResponsiveAdMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByAccountIdAsync(
                                                        MediaEnabledEntityFilter.ResponsiveAd)).MediaMetaData;
                CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getResponsiveAdMediaMetaData);

                var getImageAdExtensionMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByAccountIdAsync(
                                                            MediaEnabledEntityFilter.ImageAdExtension)).MediaMetaData;
                CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getImageAdExtensionMediaMetaData);

                var getMediaMetaData = (await CampaignManagementExampleHelper.GetMediaMetaDataByIdsAsync(imageMediaIds)).MediaMetaData;
                CampaignManagementExampleHelper.OutputArrayOfMediaMetaData(getMediaMetaData);

                #endregion MediaRepresentations

                #region Delete

                // Comment out (disable) the delete operation if you want to use the media IDs
                // in another example e.g., AudienceCampaigns.cs.

                var deleteMediaResponse = (await CampaignManagementExampleHelper.DeleteMediaAsync(
                                               authorizationData.AccountId,
                                               imageMediaIds));

                foreach (var id in imageMediaIds)
                {
                    OutputStatusMessage(string.Format("Deleted Media Id {0}\n", id));
                }

                #endregion Delete
            }
            // Catch authentication exceptions
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Campaign Management service exceptions
            catch (FaultException <Microsoft.BingAds.V12.CampaignManagement.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V12.CampaignManagement.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V12.CampaignManagement.EditorialApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }
コード例 #24
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                // Media cannot be added via the Bulk service, so we'll use the Campaign Management service
                // i.e., the AddMedia service operation below.

                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);
                CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient <ICampaignManagementService>(
                    authorizationData: authorizationData,
                    environment: environment);

                BulkServiceManager = new BulkServiceManager(
                    authorizationData: authorizationData,
                    apiEnvironment: environment);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                // Add an image to your media library.
                // The image asset is needed later to create the responsive ad.
                var landscapeImageMedia = GetImageMedia(
                    "Image191x100",
                    MediaFilePath + ResponsiveAdMediaFileName,
                    System.Drawing.Imaging.ImageFormat.Png);

                var media = new Media[]
                {
                    landscapeImageMedia,
                };

                OutputStatusMessage("-----\nAddMedia:");
                AddMediaResponse addMediaResponse = await CampaignManagementExampleHelper.AddMediaAsync(
                    accountId : authorizationData.AccountId,
                    media : media);

                long[] mediaIds = addMediaResponse.MediaIds.ToArray();
                OutputStatusMessage("MediaIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(mediaIds);

                var uploadEntities = new List <BulkEntity>();

                // Create an Audience campaign with one ad group and a responsive ad.

                var bulkCampaign = new BulkCampaign
                {
                    Campaign = new Campaign
                    {
                        Id = campaignIdKey,
                        // CampaignType must be set for Audience campaigns
                        CampaignType = CampaignType.Audience,
                        // Languages must be set for Audience campaigns
                        Languages   = new string[] { "All" },
                        Name        = "Women's Shoes " + DateTime.UtcNow,
                        DailyBudget = 50,
                        BudgetType  = BudgetLimitType.DailyBudgetStandard,
                        Settings    = null,
                        TimeZone    = "PacificTimeUSCanadaTijuana",
                    }
                };
                uploadEntities.Add(bulkCampaign);

                // Specify one or more ad groups.

                var bulkAdGroup = new BulkAdGroup
                {
                    CampaignId = campaignIdKey,
                    AdGroup    = new AdGroup
                    {
                        Id        = adGroupIdKey,
                        Name      = "Women's Red Shoe Sale",
                        StartDate = null,
                        EndDate   = new Microsoft.BingAds.V13.CampaignManagement.Date
                        {
                            Month = 12,
                            Day   = 31,
                            Year  = DateTime.UtcNow.Year + 1
                        },
                        CpcBid = new Bid {
                            Amount = 0.09
                        },
                        // Language cannot be set for ad groups in Audience campaigns
                        Language = null,
                        // Network cannot be set for ad groups in Audience campaigns
                        Network = null,
                    },
                };
                uploadEntities.Add(bulkAdGroup);

                var bulkResponsiveAd = new BulkResponsiveAd
                {
                    AdGroupId    = adGroupIdKey,
                    ResponsiveAd = new ResponsiveAd
                    {
                        Id           = responsiveAdIdKey,
                        BusinessName = "Contoso",
                        CallToAction = CallToAction.AddToCart,
                        FinalUrls    = new[] {
                            "https://www.contoso.com/womenshoesale"
                        },
                        ForwardCompatibilityMap = null,
                        Headline = "Fast & Easy Setup",
                        Images   = new[]
                        {
                            // You are only required to provide a landscape image asset.
                            // Optionally you can include additional asset links, i.e., one image asset for each supported sub type.
                            // For any image asset sub types that you do not explicitly set,
                            // the service will automatically create image asset links by cropping the LandscapeImageMedia.
                            new AssetLink
                            {
                                Asset = new ImageAsset
                                {
                                    CropHeight = null,
                                    CropWidth  = null,
                                    CropX      = null,
                                    CropY      = null,
                                    Id         = mediaIds[0],
                                    Name       = "My LandscapeImageMedia",
                                    SubType    = "LandscapeImageMedia",
                                    Type       = null
                                },
                            },
                        },
                        LongHeadlineString = "Find New Customers & Increase Sales!",
                        Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                    },
                };
                uploadEntities.Add(bulkResponsiveAd);

                // Upload and write the output

                OutputStatusMessage("-----\nAdding campaign, ad group, and ad...");

                var Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                var downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var adGroupResults = downloadEntities.OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(adGroupResults);

                var responsiveAdResults = downloadEntities.OfType <BulkResponsiveAd>().ToList();
                OutputBulkResponsiveAds(responsiveAdResults);

                Reader.Dispose();

                // Delete the campaign and everything it contains e.g., ad groups and ads.

                uploadEntities = new List <BulkEntity>();

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                OutputStatusMessage("-----\nDeleting campaign, ad group, and ad...");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                Reader.Dispose();
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V13.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V13.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
コード例 #25
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);
            }
        }
コード例 #26
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(authorizationData);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                var downloadParameters = new DownloadParameters
                {
                    DownloadEntities    = new[] { DownloadEntity.RemarketingLists },
                    ResultFileDirectory = FileDirectory,
                    ResultFileName      = DownloadFileName,
                    OverwriteResultFile = true,
                    LastSyncTimeInUTC   = null
                };

                var bulkFilePath = await BulkServiceManager.DownloadFileAsync(downloadParameters);

                OutputStatusMessage("Downloaded all remarketing lists that the current user can associate with ad groups.\n");
                Reader = new BulkFileReader(bulkFilePath, ResultFileType.FullDownload, FileType);
                var downloadEntities = Reader.ReadEntities().ToList();

                var remarketingListResults = downloadEntities.OfType <BulkRemarketingList>().ToList();
                OutputBulkRemarketingLists(remarketingListResults);

                Reader.Dispose();

                // You must already have at least one remarketing list.
                if (remarketingListResults.Count < 1)
                {
                    OutputStatusMessage("You do not have any remarketing lists that the current user can associate with ad groups.\n");
                    return;
                }

                var uploadEntities = new List <BulkEntity>();

                #region Add

                // Prepare the bulk entities that you want to upload.

                var bulkCampaign = new BulkCampaign
                {
                    Campaign = new Campaign
                    {
                        Id          = campaignIdKey,
                        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",

                        TrackingUrlTemplate = null
                    }
                };

                // Specify one or more ad groups.

                var bulkAdGroup = new BulkAdGroup
                {
                    // ClientId may be used to associate records in the bulk upload file with records in the results file. The value of this field
                    // is not used or stored by the server; it is simply copied from the uploaded record to the corresponding result record.
                    // Note: This bulk file Client Id is not related to an application Client Id for OAuth.
                    ClientId   = "YourClientIdGoesHere",
                    CampaignId = campaignIdKey,
                    AdGroup    = new AdGroup
                    {
                        // When using the Campaign Management service, the Id cannot be set. In the context of a BulkAdGroup, the Id is optional
                        // and may be used as a negative reference key during bulk upload. For example the same negative value set for the
                        // ad group Id will be used when associating this new ad group with a new ad group remarketing list association
                        // in the BulkAdGroupRemarketingListAssociation object below.
                        Id             = adGroupIdKey,
                        Name           = "Women's Red Shoe Sale",
                        AdDistribution = AdDistribution.Search,
                        BiddingScheme  = new InheritFromParentBiddingScheme(),
                        PricingModel   = PricingModel.Cpc,
                        StartDate      = null,
                        EndDate        = new Microsoft.BingAds.V11.CampaignManagement.Date
                        {
                            Month = 12,
                            Day   = 31,
                            Year  = DateTime.UtcNow.Year + 1
                        },
                        Language            = "English",
                        Status              = AdGroupStatus.Active,
                        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,
                    },
                };

                uploadEntities.Add(bulkCampaign);
                uploadEntities.Add(bulkAdGroup);

                // This example associates all of the remarketing lists with the new ad group.

                foreach (var remarketingList in remarketingListResults)
                {
                    if (remarketingList.RemarketingList != null && remarketingList.RemarketingList.Id != null)
                    {
                        var bulkAdGroupRemarketingListAssociation = new BulkAdGroupRemarketingListAssociation
                        {
                            ClientId = "MyBulkAdGroupRemarketingListAssociation " + remarketingList.RemarketingList.Id,
                            BiddableAdGroupCriterion = new BiddableAdGroupCriterion
                            {
                                AdGroupId = adGroupIdKey,
                                Criterion = new AudienceCriterion
                                {
                                    AudienceId   = (long)remarketingList.RemarketingList.Id,
                                    AudienceType = AudienceType.RemarketingList,
                                },
                                CriterionBid = new BidMultiplier
                                {
                                    Multiplier = 20.00,
                                },
                                Status = AdGroupCriterionStatus.Paused,
                            },
                            // Read-only properties
                            AdGroupName         = null,
                            CampaignName        = null,
                            RemarketingListName = null,
                        };

                        uploadEntities.Add(bulkAdGroupRemarketingListAssociation);
                    }
                }

                // Upload and write the output

                OutputStatusMessage("\nAdding campaign, ad group, and ad group remarketing list associations...\n");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var adGroupResults = downloadEntities.OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(adGroupResults);

                var adGroupRemarketingListResults = downloadEntities.OfType <BulkAdGroupRemarketingListAssociation>().ToList();
                OutputBulkAdGroupRemarketingListAssociations(adGroupRemarketingListResults);

                Reader.Dispose();

                #endregion Add

                #region CleanUp

                // 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 region if you want to view the added entities in the
                // Bing Ads web application or another tool.

                // You must set the Id field to the corresponding entity identifier, and the Status field to Deleted.

                // When you delete a BulkCampaign, the dependent entities such as BulkAdGroup and BulkAdGroupRemarketingListAssociation
                // are deleted without being specified explicitly.

                uploadEntities = new List <BulkEntity>();

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                // Upload and write the output

                OutputStatusMessage("\nDeleting campaign, ad group, and ad group remarketing list associations . . .\n");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();
                OutputBulkCampaigns(downloadEntities.OfType <BulkCampaign>().ToList());

                Reader.Dispose();

                #endregion Cleanup
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V11.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V11.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
コード例 #27
0
        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);

                // Used to output the Campaign Management objects within Bulk entities.
                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(
                    authorizationData: authorizationData,
                    apiEnvironment: environment);

                var uploadEntities = new List <BulkEntity>();

                // 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 bulkCampaign = new BulkCampaign
                {
                    ClientId = "YourClientIdGoesHere",
                    Campaign = new Campaign
                    {
                        Id           = campaignIdKey,
                        BudgetType   = Microsoft.BingAds.V12.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"
                            }
                        },
                    },
                };

                uploadEntities.Add(bulkCampaign);

                // Create a new ad group within the dynamic search ads campaign.

                var bulkAdGroup = new BulkAdGroup
                {
                    CampaignId = campaignIdKey,
                    AdGroup    = new AdGroup
                    {
                        Id        = adGroupIdKey,
                        Name      = "Women's Red Shoe Sale",
                        StartDate = null,
                        EndDate   = new Microsoft.BingAds.V12.CampaignManagement.Date
                        {
                            Month = 12,
                            Day   = 31,
                            Year  = DateTime.UtcNow.Year + 1
                        },
                        CpcBid = new Bid {
                            Amount = 0.09
                        },
                    },
                };

                uploadEntities.Add(bulkAdGroup);

                // You can add one or more Webpage criteria to each ad group that helps determine
                // whether or not to serve dynamic search ads.

                var adGroupWebpagePositivePageContent = new BulkAdGroupDynamicSearchAdTarget
                {
                    BiddableAdGroupCriterion = new BiddableAdGroupCriterion
                    {
                        AdGroupId    = adGroupIdKey,
                        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"
                            },
                        },
                    }
                };
                uploadEntities.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.

                OutputStatusMessage("-----\nGetDomainCategories:");
                var getDomainCategoriesResponse = await AdInsightExampleHelper.GetDomainCategoriesAsync(
                    categoryName : null,
                    domainName : DOMAIN_NAME,
                    language : LANGUAGE);

                var categories = getDomainCategoriesResponse.Categories;
                AdInsightExampleHelper.OutputArrayOfDomainCategory(categories);

                // If any categories are available let's use one as a condition.

                if (categories.Count > 0)
                {
                    var adGroupWebpagePositiveCategory = new BulkAdGroupDynamicSearchAdTarget
                    {
                        BiddableAdGroupCriterion = new BiddableAdGroupCriterion
                        {
                            AdGroupId    = adGroupIdKey,
                            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"
                                },
                            }
                        }
                    };
                    uploadEntities.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 BulkAdGroupNegativeDynamicSearchAdTarget
                {
                    NegativeAdGroupCriterion = new NegativeAdGroupCriterion
                    {
                        AdGroupId = adGroupIdKey,
                        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
                            }
                        }
                    }
                };
                uploadEntities.Add(adGroupWebpageNegativeUrl);

                // 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 campaignWebpageNegative = new BulkCampaignNegativeDynamicSearchAdTarget
                {
                    NegativeCampaignCriterion = new NegativeCampaignCriterion
                    {
                        CampaignId = campaignIdKey,
                        Criterion  = new Webpage
                        {
                            Parameter = new WebpageParameter
                            {
                                Conditions = new[]
                                {
                                    new WebpageCondition
                                    {
                                        Argument = DOMAIN_NAME + "\\seattle",
                                        Operand  = WebpageConditionOperand.Url,
                                    }
                                },
                                CriterionName = "Campaign Negative Webpage Url Criterion"
                            }
                        }
                    }
                };
                uploadEntities.Add(campaignWebpageNegative);


                // 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 bulkDynamicSearchAd = new BulkDynamicSearchAd
                {
                    ClientId        = "here",
                    AdGroupId       = adGroupIdKey,
                    DynamicSearchAd = 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,
                    },
                };

                uploadEntities.Add(bulkDynamicSearchAd);

                // Upload and write the output

                OutputStatusMessage("-----\nAdding campaign, ad group, criterions, and ads...");

                var Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                var downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var adGroupResults = downloadEntities.OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(adGroupResults);

                var campaignNegativeDynamicSearchAdTargetResults = downloadEntities.OfType <BulkCampaignNegativeDynamicSearchAdTarget>().ToList();
                OutputBulkCampaignNegativeDynamicSearchAdTargets(campaignNegativeDynamicSearchAdTargetResults);

                var adGroupDynamicSearchAdTargetResults = downloadEntities.OfType <BulkAdGroupDynamicSearchAdTarget>().ToList();
                OutputBulkAdGroupDynamicSearchAdTargets(adGroupDynamicSearchAdTargetResults);

                var adGroupNegativeDynamicSearchAdTargetResults = downloadEntities.OfType <BulkAdGroupNegativeDynamicSearchAdTarget>().ToList();
                OutputBulkAdGroupNegativeDynamicSearchAdTargets(adGroupNegativeDynamicSearchAdTargetResults);

                var dynamicSearchAdResults = downloadEntities.OfType <BulkDynamicSearchAd>().ToList();
                OutputBulkDynamicSearchAds(dynamicSearchAdResults);

                Reader.Dispose();

                // Delete the campaign and everything it contains e.g., ad groups and ads.

                uploadEntities = new List <BulkEntity>();

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                OutputStatusMessage("-----\nDeleting DSA campaign, criterions, and ad...");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();

                OutputStatusMessage("Upload results:");

                campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                Reader.Dispose();
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V12.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V12.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
コード例 #28
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(authorizationData);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                #region Add

                // Prepare the bulk entities that you want to upload. Each bulk entity contains the corresponding campaign management object,
                // and additional elements needed to read from and write to a bulk file.

                var bulkCampaign = new BulkCampaign
                {
                    // ClientId may be used to associate records in the bulk upload file with records in the results file. The value of this field
                    // is not used or stored by the server; it is simply copied from the uploaded record to the corresponding result record.
                    // Note: This bulk file Client Id is not related to an application Client Id for OAuth.
                    ClientId = "YourClientIdGoesHere",
                    Campaign = new Campaign
                    {
                        // When using the Campaign Management service, the Id cannot be set. In the context of a BulkCampaign, the Id is optional
                        // and may be used as a negative reference key during bulk upload. For example the same negative value set for the campaign Id
                        // will be used when associating this new campaign with a new call ad extension in the BulkCampaignCallAdExtension object below.
                        Id          = campaignIdKey,
                        Name        = "Women's Shoes " + DateTime.UtcNow,
                        Description = "Red shoes line.",

                        // 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",
                    }
                };

                // You can specify one negative site per BulkCampaignNegativeSite (singular), or multiple negative sites
                // in a BulkCampaignNegativeSites (plural) object.

                var bulkCampaignNegativeSite = new BulkCampaignNegativeSite[] {
                    new BulkCampaignNegativeSite {
                        // CampaignName will be ignored if you specify CampaignId.
                        CampaignName = null,
                        CampaignId   = campaignIdKey,
                        Website      = "contoso.com/negativesite1"
                    },
                    new BulkCampaignNegativeSite {
                        CampaignId = campaignIdKey,
                        Website    = "contoso.com/negativesite2"
                    },
                };

                // If you upload a BulkCampaignNegativeSites bulk entity, then you are effectively replacing any existing
                // negative sites assigned to the campaign. Thus, when a BulkCampaignNegativeSites entity is written to the
                // upload file, an extra Campaign Negative Site record is included where the Status is Deleted and the
                // Website field is empty.
                // That said, if you include additional BulkCampaignNegativeSite or BulkCampaignNegativeSites in the same upload,
                // they will be included in the new set of negative sites.
                var bulkCampaignNegativeSites = new BulkCampaignNegativeSites[] {
                    new BulkCampaignNegativeSites {
                        // CampaignName will be ignored if you specify CampaignId.
                        CampaignName          = null,
                        CampaignNegativeSites = new CampaignNegativeSites
                        {
                            CampaignId    = campaignIdKey,
                            NegativeSites = new string[]
                            {
                                "contoso.com/negativesite3",
                                "contoso.com/negativesite4",
                            }
                        }
                    },
                };

                var uploadEntities = new List <BulkEntity>();
                uploadEntities.Add(bulkCampaign);

                foreach (var campaignNegativeSite in bulkCampaignNegativeSite)
                {
                    uploadEntities.Add(campaignNegativeSite);
                }

                foreach (var campaignNegativeSites in bulkCampaignNegativeSites)
                {
                    uploadEntities.Add(campaignNegativeSites);
                }

                // Upload and write the output

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                var downloadEntities = Reader.ReadEntities().ToList();

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                // If you modify the sample to upload only BulkCampaignNegativeSite entities for a campaign, the SDK will abstract
                // the results file contents as one or more BulkCampaignNegativeSite. If you upload both BulkCampaignNegativeSite
                // and BulkCampaignNegativeSites as shown above, then the SDK will abstract the results file contents as a
                // BulkCampaignNegativeSites object containing all of the negative sites for the campaign,
                // including those uploaded as a BulkCampaignNegativeSite.

                // Whether you use the SDK to upload the entities, or only use the SDK to read an upload results file,
                // the SDK will abstract the results file as follows:
                // If the file contains an extra Campaign Negative Site record where the Status is Deleted and the
                // Website field is empty, the SDK returns a BulkCampaignNegativeSites (plural) object.
                // Otherwise the SDK returns one or more BulkCampaignNegativeSite (singlular) objects.

                var campaignNegativeSiteResults = downloadEntities.OfType <BulkCampaignNegativeSite>().ToList();
                OutputBulkCampaignNegativeSite(campaignNegativeSiteResults);

                var campaignNegativeSitesResults = downloadEntities.OfType <BulkCampaignNegativeSites>().ToList();
                OutputBulkCampaignNegativeSites(campaignNegativeSitesResults);

                Reader.Dispose();

                #endregion Add

                #region CleanUp

                //Delete the campaign and negative sites 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.

                //You must set the Id field to the corresponding entity identifier, and the Status field to Deleted.

                //When you delete a BulkCampaign, the dependent entities such as BulkCampaignNegativeSite
                //are deleted without being specified explicitly.

                uploadEntities = new List <BulkEntity>();

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                // Upload and write the output

                OutputStatusMessage("\nDeleting campaign and negative sites . . .\n");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();
                OutputBulkCampaigns(downloadEntities.OfType <BulkCampaign>().ToList());
                Reader.Dispose();

                #endregion Cleanup
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V11.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V11.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }
コード例 #29
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(authorizationData, environment);
                BulkServiceManager.StatusPollIntervalInMilliseconds = 5000;

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                #region Download

                // In this example we will download all ad groups in the account.

                var entities = new[] {
                    DownloadEntity.AdGroups,
                };

                // You can limit by specific campaign IDs and request performance data.

                var downloadParameters = new DownloadParameters
                {
                    CampaignIds = null,
                    DataScope   = DataScope.EntityData,
                    PerformanceStatsDateRange = null,
                    DownloadEntities          = entities,
                    FileType            = FileType,
                    LastSyncTimeInUTC   = null,
                    ResultFileDirectory = FileDirectory,
                    ResultFileName      = DownloadFileName,
                    OverwriteResultFile = true
                };

                // You can submit a download or upload request and the BulkServiceManager will automatically
                // return results. The BulkServiceManager abstracts the details of checking for result file
                // completion, and you don't have to write any code for results polling.

                var bulkFilePath = await BulkServiceManager.DownloadFileAsync(downloadParameters);

                OutputStatusMessage("Downloaded all ad groups in the account.\n");

                #endregion Download

                #region Parse

                Reader = new BulkFileReader(bulkFilePath, ResultFileType.FullDownload, FileType);
                var bulkAdGroups = Reader.ReadEntities().ToList().OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(bulkAdGroups);

                Writer = new BulkFileWriter(FileDirectory + UploadFileName);

                // We will activate ad groups for one month starting from today as an example.

                var nextMonth = DateTime.UtcNow.AddMonths(1);

                // Within the downloaded records, find all ad groups that you want to update.

                foreach (var bulkAdGroup in bulkAdGroups)
                {
                    var adGroup = bulkAdGroup.AdGroup;
                    if (adGroup != null && bulkAdGroup.IsExpired)
                    {
                        // For best performance, only upload the properties that you want to update.

                        Writer.WriteEntity(new BulkAdGroup
                        {
                            CampaignId = bulkAdGroup.CampaignId,
                            AdGroup    = new AdGroup
                            {
                                Id      = adGroup.Id,
                                EndDate = new Microsoft.BingAds.V12.CampaignManagement.Date
                                {
                                    Month = nextMonth.Month,
                                    Day   = nextMonth.Day,
                                    Year  = nextMonth.Year
                                },
                                Status = AdGroupStatus.Active,
                            }
                        });
                    }
                }

                Reader.Dispose();
                Writer.Dispose();

                #endregion Parse

                #region Upload

                // Upload the local file that we already prepared

                var fileUploadParameters = new FileUploadParameters
                {
                    ResultFileDirectory = FileDirectory,
                    CompressUploadFile  = true,
                    ResultFileName      = ResultFileName,
                    OverwriteResultFile = true,
                    UploadFilePath      = FileDirectory + UploadFileName,
                    ResponseMode        = ResponseMode.ErrorsAndResults
                };

                var resultFilePath = await BulkServiceManager.UploadFileAsync(fileUploadParameters, progress, CancellationToken.None);

                OutputStatusMessage("Updated ad groups.\n");

                Reader       = new BulkFileReader(resultFilePath, ResultFileType.Upload, FileType);
                bulkAdGroups = Reader.ReadEntities().ToList().OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(bulkAdGroups);
                Reader.Dispose();

                #endregion Upload


                #region Entities

                // We can make the same update without explicitly reading or writing a local file.
                // When working with entities a file is downloaded to the temp directory,
                // although you don't need to manage it.

                var downloadEntities = await BulkServiceManager.DownloadEntitiesAsync(downloadParameters);

                OutputStatusMessage("Downloaded all ad groups in the account.\n");
                bulkAdGroups = downloadEntities.ToList().OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(bulkAdGroups);

                var uploadEntities = new List <BulkEntity>();

                foreach (var bulkAdGroup in bulkAdGroups)
                {
                    var adGroup = bulkAdGroup.AdGroup;
                    if (adGroup != null && bulkAdGroup.IsExpired)
                    {
                        // Instead of Writer.WriteEntity, we will add to the in-memory list

                        uploadEntities.Add(new BulkAdGroup
                        {
                            CampaignId = bulkAdGroup.CampaignId,
                            AdGroup    = new AdGroup
                            {
                                Id      = adGroup.Id,
                                EndDate = new Microsoft.BingAds.V12.CampaignManagement.Date
                                {
                                    Month = nextMonth.Month,
                                    Day   = nextMonth.Day,
                                    Year  = nextMonth.Year
                                },
                                Status = AdGroupStatus.Active,
                            }
                        });
                    }
                }

                var entityUploadParameters = new EntityUploadParameters
                {
                    Entities     = uploadEntities,
                    ResponseMode = ResponseMode.ErrorsAndResults,
                };

                var resultEntities = await BulkServiceManager.UploadEntitiesAsync(entityUploadParameters, progress, CancellationToken.None);

                OutputStatusMessage("Updated ad groups.\n");

                bulkAdGroups = resultEntities.ToList().OfType <BulkAdGroup>().ToList();
                OutputBulkAdGroups(bulkAdGroups);

                #endregion Entities
            }
            // 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 Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V12.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V12.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }
コード例 #30
0
        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                CampaignManagementExampleHelper = new CampaignManagementExampleHelper(this.OutputStatusMessage);

                BulkServiceManager = new BulkServiceManager(authorizationData, environment);

                var progress = new Progress <BulkOperationProgressInfo>(x =>
                                                                        OutputStatusMessage(string.Format("{0} % Complete",
                                                                                                          x.PercentComplete.ToString(CultureInfo.InvariantCulture))));

                #region Add

                // Prepare the bulk entities that you want to upload. Each bulk entity contains the corresponding campaign management object,
                // and additional elements needed to read from and write to a bulk file.

                var bulkCampaign = new BulkCampaign
                {
                    // ClientId may be used to associate records in the bulk upload file with records in the results file. The value of this field
                    // is not used or stored by the server; it is simply copied from the uploaded record to the corresponding result record.
                    // Note: This bulk file Client Id is not related to an application Client Id for OAuth.
                    ClientId = "YourClientIdGoesHere",
                    Campaign = new Campaign
                    {
                        // When using the Campaign Management service, the Id cannot be set. In the context of a BulkCampaign, the Id is optional
                        // and may be used as a negative reference key during bulk upload. For example the same negative value set for the campaign Id
                        // will be used when associating this new campaign with a new negative keyword in the BulkCampaignNegativeKeyword object below.
                        Id          = campaignIdKey,
                        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 bulkCampaignNegativeKeywords = new BulkCampaignNegativeKeyword[] {
                    new BulkCampaignNegativeKeyword {
                        CampaignId      = campaignIdKey,
                        NegativeKeyword = new NegativeKeyword
                        {
                            MatchType = MatchType.Phrase,
                            Text      = "auto",
                        }
                    },
                    new BulkCampaignNegativeKeyword {
                        CampaignId      = campaignIdKey,
                        NegativeKeyword = new NegativeKeyword
                        {
                            MatchType = MatchType.Exact,
                            Text      = "auto",
                        }
                    },
                    new BulkCampaignNegativeKeyword {
                        CampaignId      = campaignIdKey,
                        NegativeKeyword = new NegativeKeyword
                        {
                            MatchType = MatchType.Phrase,
                            Text      = "car",
                        }
                    },
                    new BulkCampaignNegativeKeyword {
                        CampaignId      = campaignIdKey,
                        NegativeKeyword = new NegativeKeyword
                        {
                            MatchType = MatchType.Exact,
                            Text      = "car",
                        }
                    },
                };

                // Negative keywords can be added and deleted from a shared negative keyword list. The negative keyword list can be shared or associated with multiple campaigns.
                // You can create up to 20 negative keyword lists per account and share or associate them with any campaign in the same account.
                // To create a negative keyword list, upload a BulkNegativeKeywordList (Negative Keyword List record type).
                // For each negative keyword that you want to add to the list, upload a BulkSharedNegativeKeyword (Shared Negative Keyword record type).
                // To associate the negative keyword list with a campaign, also upload a BulkCampaignNegativeKeywordList (Campaign Negative Keyword List Association record type).

                var bulkNegativeKeywordList = new BulkNegativeKeywordList
                {
                    NegativeKeywordList = new NegativeKeywordList
                    {
                        // Since we are adding the list and the negative keywords during the same upload,
                        // we will use a reference key to the negative keyword list identifier.
                        Id   = negativeKeywordListIdKey,
                        Name = "My NKW List",
                    },
                };

                var bulkSharedNegativeKeywords = new BulkSharedNegativeKeyword[] {
                    new BulkSharedNegativeKeyword {
                        NegativeKeyword = new NegativeKeyword
                        {
                            MatchType = MatchType.Phrase,
                            Text      = "mobile",
                        },
                        NegativeKeywordListId = negativeKeywordListIdKey,
                    },
                    new BulkSharedNegativeKeyword {
                        NegativeKeyword = new NegativeKeyword
                        {
                            MatchType = MatchType.Exact,
                            Text      = "mobile",
                        },
                        NegativeKeywordListId = negativeKeywordListIdKey,
                    },
                };

                var bulkCampaignNegativeKeywordList = new BulkCampaignNegativeKeywordList
                {
                    SharedEntityAssociation = new SharedEntityAssociation
                    {
                        EntityId         = campaignIdKey,
                        EntityType       = "Campaign",
                        SharedEntityId   = negativeKeywordListIdKey,
                        SharedEntityType = "NegativeKeywordList",
                    }
                };

                var uploadEntities = new List <BulkEntity>();
                uploadEntities.Add(bulkCampaign);

                foreach (var bulkCampaignNegativeKeyword in bulkCampaignNegativeKeywords)
                {
                    uploadEntities.Add(bulkCampaignNegativeKeyword);
                }

                uploadEntities.Add(bulkNegativeKeywordList);
                foreach (var bulkSharedNegativeKeyword in bulkSharedNegativeKeywords)
                {
                    uploadEntities.Add(bulkSharedNegativeKeyword);
                }
                uploadEntities.Add(bulkCampaignNegativeKeywordList);

                // Upload and write the output

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                var downloadEntities = Reader.ReadEntities().ToList();

                var campaignResults = downloadEntities.OfType <BulkCampaign>().ToList();
                OutputBulkCampaigns(campaignResults);

                var campaignNegativeKeywordResults = downloadEntities.OfType <BulkCampaignNegativeKeyword>().ToList();
                OutputBulkCampaignNegativeKeywords(campaignNegativeKeywordResults);

                var negativeKeywordListResults = downloadEntities.OfType <BulkNegativeKeywordList>().ToList();
                OutputBulkNegativeKeywordLists(negativeKeywordListResults);

                var sharedNegativeKeywordListResults = downloadEntities.OfType <BulkSharedNegativeKeyword>().ToList();
                OutputBulkSharedNegativeKeywords(sharedNegativeKeywordListResults);

                var campaignNegativeKeywordListResults = downloadEntities.OfType <BulkCampaignNegativeKeywordList>().ToList();
                OutputBulkCampaignNegativeKeywordLists(campaignNegativeKeywordListResults);

                Reader.Dispose();

                #endregion Add

                #region CleanUp

                //Delete the campaign and negative keywords 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.

                //You must set the Id field to the corresponding entity identifier, and the Status field to Deleted.

                //When you delete a BulkCampaign, the dependent entities such as BulkCampaignNegativeKeyword
                //are deleted without being specified explicitly.
                //When you delete a BulkNegativeKeywordList, the dependent entities such as BulkSharedNegativeKeyword
                //are deleted without being specified explicitly.

                uploadEntities = new List <BulkEntity>();

                foreach (var campaignResult in campaignResults)
                {
                    campaignResult.Campaign.Status = CampaignStatus.Deleted;
                    uploadEntities.Add(campaignResult);
                }

                foreach (var negativeKeywordListResult in negativeKeywordListResults)
                {
                    negativeKeywordListResult.Status = Status.Deleted;
                    uploadEntities.Add(negativeKeywordListResult);
                }

                // Upload and write the output

                OutputStatusMessage("\nDeleting campaign and negative keywords . . .\n");

                Reader = await WriteEntitiesAndUploadFileAsync(uploadEntities);

                downloadEntities = Reader.ReadEntities().ToList();
                OutputBulkCampaigns(downloadEntities.OfType <BulkCampaign>().ToList());
                OutputBulkNegativeKeywordLists(downloadEntities.OfType <BulkNegativeKeywordList>().ToList());
                Reader.Dispose();

                #endregion Cleanup
            }
            // Catch Microsoft Account authorization exceptions.
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Bulk service exceptions
            catch (FaultException <Microsoft.BingAds.V12.Bulk.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException <Microsoft.BingAds.V12.Bulk.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationInProgressException ex)
            {
                OutputStatusMessage("The result file for the bulk operation is not yet available for download.");
                OutputStatusMessage(ex.Message);
            }
            catch (BulkOperationCouldNotBeCompletedException <DownloadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (BulkOperationCouldNotBeCompletedException <UploadStatus> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                }
                if (Writer != null)
                {
                    Writer.Dispose();
                }
            }
        }