Dynamic Search Ads Code Example

This example uses the Campaign Management API to setup a Dynamic Search Ads (DSA) campaign.

Note

You can no longer add, update, or retrieve campaigns that only support dynamic search ads. The campaign type of your existing campaigns has been updated from "DynamicSearchAds" to "Search". The ad groups are now considered "dynamic" ad groups, but there are no structural changes i.e., they contain the same auto targets and dynamic search ads as before.

Tip

Use the language selector in the documentation header to choose C#, Java, Php, or Python.

To get access and refresh tokens for your Microsoft Advertising user and make your first service call using the Bing Ads API, see the Quick Start guide. You'll want to review the Get Started guide and walkthroughs for your preferred language e.g., C#, Java, Php, and Python.

Supporting files for C#, Java, Php, and Python examples are available at GitHub. You can clone each repository or repurpose snippets as needed.

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Threading.Tasks;
using Microsoft.BingAds.V13.CampaignManagement;
using Microsoft.BingAds.V13.AdInsight;
using Microsoft.BingAds;

namespace BingAdsExamplesLibrary.V13
{
    /// <summary>
    /// How to setup Dynamic Search Ads (DSA) in a Search campaign with the Campaign Management service.
    /// </summary>
    public class DynamicSearchAds : ExampleBase
    {
        public const string DOMAIN_NAME = "contoso.com";
        public const string LANGUAGE = "EN";
        
        public override string Description
        {
            get { return "Dynamic Search Ads (DSA) Campaigns | Campaign Management V13"; }
        }

        public async override Task RunAsync(AuthorizationData authorizationData)
        {
            try
            {
                ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;

                AdInsightExampleHelper AdInsightExampleHelper = new AdInsightExampleHelper(
                    OutputStatusMessageDefault: this.OutputStatusMessage);
                AdInsightExampleHelper.AdInsightService = new ServiceClient<IAdInsightService>(
                    authorizationData: authorizationData,
                    environment: environment);

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

                // To get started with dynamic search ads, first you'll need to add a new Search campaign 
                // Include a DynamicSearchAdsSetting that specifies the target website domain and language.

                var campaigns = new[]{
                    new Campaign
                    {
                        BudgetType = Microsoft.BingAds.V13.CampaignManagement.BudgetLimitType.DailyBudgetStandard,
                        DailyBudget = 50,
                        CampaignType = CampaignType.Search,
                        Languages = new string[] { "All" },
                        Name = "Everyone's Shoes " + DateTime.UtcNow,
                        TimeZone = "PacificTimeUSCanadaTijuana",
                        Settings = new [] {
                            new DynamicSearchAdsSetting
                            {
                                DomainName = "contoso.com",
                                Language = "English"
                            }
                        },
                    },
                };

                OutputStatusMessage("-----\nAddCampaigns:");
                AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync(
                    accountId: authorizationData.AccountId,
                    campaigns: campaigns);
                long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray();
                Microsoft.BingAds.V13.CampaignManagement.BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray();
                OutputStatusMessage("CampaignIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(campaignIds);
                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(campaignErrors);

                // Create a new ad group with type set to "SearchDynamic"

                var adGroups = new[] {
                    new AdGroup
                    {
                        AdGroupType = "SearchDynamic",
                        Name = "Everyone's Red Shoe Sale",
                        StartDate = null,
                        EndDate = new Date {
                            Month = 12,
                            Day = 31,
                            Year = DateTime.UtcNow.Year + 1
                        },
                        CpcBid = new Bid { Amount = 0.09 },
                    }
                };

                OutputStatusMessage("-----\nAddAdGroups:");
                AddAdGroupsResponse addAdGroupsResponse = await CampaignManagementExampleHelper.AddAdGroupsAsync(
                    campaignId: (long)campaignIds[0],
                    adGroups: adGroups,
                    returnInheritedBidStrategyTypes: false);
                long?[] adGroupIds = addAdGroupsResponse.AdGroupIds.ToArray();
                Microsoft.BingAds.V13.CampaignManagement.BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray();
                OutputStatusMessage("AdGroupIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(adGroupIds);
                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(adGroupErrors);

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

                var adGroupCriterions = new List<AdGroupCriterion>();

                var adGroupWebpagePositivePageContent = new BiddableAdGroupCriterion
                {
                    AdGroupId = (long)adGroupIds[0],
                    CriterionBid = new FixedBid
                    {
                        Amount = 0.50
                    },
                    Criterion = new Webpage
                    {
                        Parameter = new WebpageParameter
                        {
                            Conditions = new[]
                            {
                                new WebpageCondition
                                {
                                    Argument = "flowers",
                                    Operand = WebpageConditionOperand.PageContent,
                                }
                            },
                            CriterionName = "Ad Group Webpage Positive Page Content Criterion"
                        },
                    },
                };
                adGroupCriterions.Add(adGroupWebpagePositivePageContent);

                // To discover the categories that you can use for Webpage criteria (positive or negative), 
                // use the GetDomainCategories operation with the Ad Insight service.

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

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

                if (categories.Count > 0)
                {
                    var adGroupWebpagePositiveCategory = new BiddableAdGroupCriterion
                    {
                        AdGroupId = (long)adGroupIds[0],
                        CriterionBid = new FixedBid
                        {
                            Amount = 0.50
                        },
                        Criterion = new Webpage
                        {
                            Parameter = new WebpageParameter
                            {
                                Conditions = new[]
                                {
                                    new WebpageCondition
                                    {
                                        Argument = categories[0].CategoryName,
                                        Operand = WebpageConditionOperand.Category,
                                    }
                                },
                                CriterionName = "Ad Group Webpage Positive Category Criterion"
                            },
                        }
                    };
                    adGroupCriterions.Add(adGroupWebpagePositiveCategory);
                }

                // If you want to exclude certain portions of your website, you can add negative Webpage 
                // criterion at the campaign and ad group level. 

                var adGroupWebpageNegativeUrl = new NegativeAdGroupCriterion
                {
                    AdGroupId = (long)adGroupIds[0],
                    Criterion = new Webpage
                    {
                        Parameter = new WebpageParameter
                        {
                            // You can choose whether you want the criterion argument to match partial URLs, 
                            // page content, page title, or categories that Bing thinks applies to your website.
                            Conditions = new[]
                            {
                                new WebpageCondition
                                {
                                    Argument = DOMAIN_NAME,
                                    Operand = WebpageConditionOperand.Url,
                                }
                            },
                            // If you do not specify any name, then it will be set to a concatenated list of conditions. 
                            CriterionName = null
                        }
                    },
                };
                adGroupCriterions.Add(adGroupWebpageNegativeUrl);

                OutputStatusMessage("-----\nAddAdGroupCriterions:");
                CampaignManagementExampleHelper.OutputArrayOfAdGroupCriterion(adGroupCriterions);
                AddAdGroupCriterionsResponse addAdGroupCriterionsResponse = await CampaignManagementExampleHelper.AddAdGroupCriterionsAsync(
                    adGroupCriterions: adGroupCriterions, 
                    criterionType: AdGroupCriterionType.Webpage);
                long?[] adGroupCriterionIds = addAdGroupCriterionsResponse.AdGroupCriterionIds.ToArray();
                OutputStatusMessage("AdGroupCriterionIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(adGroupCriterionIds);
                BatchErrorCollection[] adGroupCriterionErrors =
                    addAdGroupCriterionsResponse.NestedPartialErrors.ToArray();
                OutputStatusMessage("NestedPartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(adGroupCriterionErrors);

                // The negative Webpage criterion at the campaign level applies to all ad groups 
                // within the campaign; however, if you define ad group level negative Webpage criterion, 
                // the campaign criterion is ignored for that ad group.

                var campaignCriterions = new List<CampaignCriterion>();
                var campaignWebpageNegative = new NegativeCampaignCriterion
                {
                    CampaignId = (long)campaignIds[0],
                    Criterion = new Webpage
                    {
                        Parameter = new WebpageParameter
                        {
                            Conditions = new[]
                            {
                                new WebpageCondition
                                {
                                    Argument = DOMAIN_NAME + "\\seattle",
                                    Operand = WebpageConditionOperand.Url,
                                }
                            },
                            CriterionName = "Campaign Negative Webpage Url Criterion"
                        }
                    }
                };
                campaignCriterions.Add(campaignWebpageNegative);

                OutputStatusMessage("-----\nAddCampaignCriterions:");
                CampaignManagementExampleHelper.OutputArrayOfCampaignCriterion(campaignCriterions);
                AddCampaignCriterionsResponse addCampaignCriterionsResponse = await CampaignManagementExampleHelper.AddCampaignCriterionsAsync(
                        campaignCriterions: campaignCriterions, 
                        criterionType: CampaignCriterionType.Webpage);
                long?[] campaignCriterionIds = addCampaignCriterionsResponse.CampaignCriterionIds.ToArray();
                OutputStatusMessage("CampaignCriterionIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(campaignCriterionIds);
                BatchErrorCollection[] campaignCriterionErrors =
                    addCampaignCriterionsResponse.NestedPartialErrors.ToArray();
                OutputStatusMessage("NestedPartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(campaignCriterionErrors);

                // Finally you must add at least one DynamicSearchAd into the ad group. The ad title and display URL 
                // are generated automatically based on the website domain and language that you want to target.

                var ads = new Ad[] {
                    new DynamicSearchAd
                    {
                        Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                        Path1 = "seattle",
                        Path2 = "shoe sale",
                        // You cannot set FinalUrls for dynamic search ads. 
                        // The Final URL will be a dynamically selected landing page.
                        // The final URL is distinct from the path that customers will see and click on in your ad.
                        FinalUrls = null,                        
                    },
                };
                
                OutputStatusMessage("-----\nAddAds:");
                AddAdsResponse addAdsResponse = await CampaignManagementExampleHelper.AddAdsAsync(
                    adGroupId: (long)adGroupIds[0],
                    ads: ads);
                long?[] adIds = addAdsResponse.AdIds.ToArray();
                Microsoft.BingAds.V13.CampaignManagement.BatchError[] adErrors = addAdsResponse.PartialErrors.ToArray();
                OutputStatusMessage("AdIds:");
                CampaignManagementExampleHelper.OutputArrayOfLong(adIds);
                OutputStatusMessage("PartialErrors:");
                CampaignManagementExampleHelper.OutputArrayOfBatchError(adErrors);
                
                // Delete the campaign and everything it contains e.g., ad groups and ads.

                OutputStatusMessage("-----\nDeleteCampaigns:");
                await CampaignManagementExampleHelper.DeleteCampaignsAsync(
                    accountId: authorizationData.AccountId,
                    campaignIds: new[] { (long)campaignIds[0] });
                OutputStatusMessage(string.Format("Deleted Campaign Id {0}", campaignIds[0]));
            }
            // Catch authentication exceptions
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Campaign Management service exceptions
            catch (FaultException<Microsoft.BingAds.V13.CampaignManagement.AdApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException<Microsoft.BingAds.V13.CampaignManagement.ApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (FaultException<Microsoft.BingAds.V13.CampaignManagement.EditorialApiFaultDetail> ex)
            {
                OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
                OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
            }
            catch (Exception ex)
            {
                OutputStatusMessage(ex.Message);
            }
        }        
    }
}
package com.microsoft.bingads.examples.v13;

import com.microsoft.bingads.*;
import com.microsoft.bingads.v13.adinsight.ArrayOfDomainCategory;
import com.microsoft.bingads.v13.adinsight.GetDomainCategoriesResponse;
import com.microsoft.bingads.v13.campaignmanagement.*;
import com.microsoft.bingads.v13.campaignmanagement.ArrayOfBatchError;
import com.microsoft.bingads.v13.campaignmanagement.ArrayOflong;
import com.microsoft.bingads.v13.campaignmanagement.BudgetLimitType;
import com.microsoft.bingads.v13.adinsight.*;

import java.util.List;
import java.util.ArrayList;
import java.util.Calendar;

public class DynamicSearchAds extends ExampleBase {
    
    public final static String DOMAIN_NAME = "contoso.com";
    public final static String LANGUAGE = "EN";
    
    public static void main(String[] args) {

        try
        {      
            authorizationData = getAuthorizationData(); 
        
            AdInsightExampleHelper.AdInsightService = new ServiceClient<IAdInsightService>(
                            authorizationData, 
                            API_ENVIRONMENT,
                            IAdInsightService.class);    

            CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient<ICampaignManagementService>(
                            authorizationData, 
                            API_ENVIRONMENT,
                            ICampaignManagementService.class);
        
            // To get started with dynamic search ads, first you'll need to add a new Search campaign 
            // Include a DynamicSearchAdsSetting that specifies the target website domain and language.

            ArrayOfCampaign campaigns = new ArrayOfCampaign();
            Campaign campaign = new Campaign();
            campaign.setBudgetType(BudgetLimitType.DAILY_BUDGET_STANDARD);
            List<CampaignType> campaignTypes = new ArrayList<CampaignType>();
            campaignTypes.add(CampaignType.SEARCH);
            campaign.setCampaignType(campaignTypes);
            campaign.setDailyBudget(50.00);
            com.microsoft.bingads.v13.campaignmanagement.ArrayOfstring languages = 
                    new com.microsoft.bingads.v13.campaignmanagement.ArrayOfstring();
            languages.getStrings().add("All");
            campaign.setLanguages(languages);
            campaign.setName("Everyone's Shoes " + System.currentTimeMillis());
            DynamicSearchAdsSetting dynamicSearchAdsSetting = new DynamicSearchAdsSetting();
            dynamicSearchAdsSetting.setDomainName("contoso.com");
            dynamicSearchAdsSetting.setLanguage("English");
            dynamicSearchAdsSetting.setSource(DynamicSearchAdsSource.ALL);
            ArrayOfSetting arrayOfSetting = new ArrayOfSetting();
            arrayOfSetting.getSettings().add(dynamicSearchAdsSetting);
            campaign.setSettings(arrayOfSetting);
            campaign.setTimeZone("PacificTimeUSCanadaTijuana");
            campaigns.getCampaigns().add(campaign);

            outputStatusMessage("-----\nAddCampaigns:");
            AddCampaignsResponse addCampaignsResponse = CampaignManagementExampleHelper.addCampaigns(
                    authorizationData.getAccountId(), 
                    campaigns);            
            ArrayOfNullableOflong campaignIds = addCampaignsResponse.getCampaignIds();
            ArrayOfBatchError campaignErrors = addCampaignsResponse.getPartialErrors();
            outputStatusMessage("CampaignIds:");
            CampaignManagementExampleHelper.outputArrayOfNullableOflong(campaignIds);
            outputStatusMessage("PartialErrors:");
            CampaignManagementExampleHelper.outputArrayOfBatchError(campaignErrors);

            // Create a new ad group with type set to "SearchDynamic"
            
            ArrayOfAdGroup adGroups = new ArrayOfAdGroup();
            AdGroup adGroup = new AdGroup();
            adGroup.setAdGroupType("SearchDynamic");
            adGroup.setName("Everyone's Red Shoe Sale");
            adGroup.setStartDate(null);
            Calendar calendar = Calendar.getInstance();
            adGroup.setEndDate(new com.microsoft.bingads.v13.campaignmanagement.Date());
            adGroup.getEndDate().setDay(31);
            adGroup.getEndDate().setMonth(12);
            adGroup.getEndDate().setYear(calendar.get(Calendar.YEAR));
            Bid CpcBid = new Bid();
            CpcBid.setAmount(0.09);
            adGroup.setCpcBid(CpcBid);
            adGroups.getAdGroups().add(adGroup);
            
            outputStatusMessage("-----\nAddAdGroups:");
            AddAdGroupsResponse addAdGroupsResponse = CampaignManagementExampleHelper.addAdGroups(
                    campaignIds.getLongs().get(0), 
                    adGroups, 
                    false);
            ArrayOfNullableOflong adGroupIds = addAdGroupsResponse.getAdGroupIds();
            ArrayOfBatchError adGroupErrors = addAdGroupsResponse.getPartialErrors();
            outputStatusMessage("CampaignIds:");
            CampaignManagementExampleHelper.outputArrayOfNullableOflong(adGroupIds);
            outputStatusMessage("PartialErrors:");
            CampaignManagementExampleHelper.outputArrayOfBatchError(adGroupErrors); 

            // You can add one or more Webpage criteria to each ad group that helps determine 
            // whether or not to serve dynamic search ads.
            
            ArrayOfAdGroupCriterion adGroupCriterions = new ArrayOfAdGroupCriterion();	        
            BiddableAdGroupCriterion adGroupWebpagePositivePageContent = getExampleAdGroupWebpagePositivePageContent(adGroupIds.getLongs().get(0));	        
            adGroupCriterions.getAdGroupCriterions().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:");
            GetDomainCategoriesResponse getDomainCategoriesResponse = AdInsightExampleHelper.getDomainCategories(
                    null, 
                    DOMAIN_NAME, 
                    LANGUAGE);
            ArrayOfDomainCategory categories = getDomainCategoriesResponse.getCategories();
            outputStatusMessage("Categories:");
            AdInsightExampleHelper.outputArrayOfDomainCategory(categories);

            // If any categories are available let's use one as a condition.
            if(categories.getDomainCategories().size() > 0)
            {
                BiddableAdGroupCriterion adGroupWebpagePositiveCategory = getExampleAdGroupWebpagePositiveCategory(adGroupIds.getLongs().get(0), categories);
                adGroupCriterions.getAdGroupCriterions().add(adGroupWebpagePositiveCategory);
            }
            
            // If you want to exclude certain portions of your web site, you can add negative Webpage 
            // criterion at the campaign and ad group level.
            NegativeAdGroupCriterion adGroupWebpageNegativeUrl = getExampleAdGroupWebpageNegativeUrl(adGroupIds.getLongs().get(0));
            adGroupCriterions.getAdGroupCriterions().add(adGroupWebpageNegativeUrl);
            
            ArrayList<AdGroupCriterionType> adGroupCriterionTypes = new ArrayList<AdGroupCriterionType>();
            adGroupCriterionTypes.add(AdGroupCriterionType.WEBPAGE);
            
            outputStatusMessage("-----\nAddAdGroupCriterions:");
            AddAdGroupCriterionsResponse addAdGroupCriterionsResponse = CampaignManagementExampleHelper.addAdGroupCriterions(
                    adGroupCriterions, 
                    adGroupCriterionTypes);
            outputStatusMessage("AdGroupCriterionIds:");
            CampaignManagementExampleHelper.outputArrayOfNullableOflong(addAdGroupCriterionsResponse.getAdGroupCriterionIds());
            ArrayOfBatchErrorCollection adGroupCriterionErrors = addAdGroupCriterionsResponse.getNestedPartialErrors();
            outputStatusMessage("NestedPartialErrors:");
            CampaignManagementExampleHelper.outputArrayOfBatchErrorCollection(adGroupCriterionErrors);
            
            // The negative Webpage criterion at the campaign level applies to all ad groups 
            // within the campaign; however, if you define ad group level negative Webpage criterion, 
            // the campaign criterion is ignored for that ad group.
            
            ArrayOfCampaignCriterion campaignCriterions = new ArrayOfCampaignCriterion();
            NegativeCampaignCriterion negativeCampaignCriterion = getExampleCampaignWebpageNegativeUrl(campaignIds.getLongs().get(0));
            campaignCriterions.getCampaignCriterions().add(negativeCampaignCriterion);
            
            ArrayList<CampaignCriterionType> campaignCriterionTypes = new ArrayList<CampaignCriterionType>();
            campaignCriterionTypes.add(CampaignCriterionType.WEBPAGE);
            
            outputStatusMessage("-----\nAddCampaignCriterions:");
            AddCampaignCriterionsResponse addCampaignCriterionsResponse = CampaignManagementExampleHelper.addCampaignCriterions(
                    campaignCriterions, 
                    campaignCriterionTypes);
            outputStatusMessage("CampaignCriterionIds:");
            CampaignManagementExampleHelper.outputArrayOfNullableOflong(addCampaignCriterionsResponse.getCampaignCriterionIds());
            ArrayOfBatchErrorCollection campaignCriterionErrors = addCampaignCriterionsResponse.getNestedPartialErrors();
            outputStatusMessage("NestedPartialErrors:");
            CampaignManagementExampleHelper.outputArrayOfBatchErrorCollection(campaignCriterionErrors);
            
            // Finally you must add at least one DynamicSearchAd into the ad group. The ad title and display URL 
            // are generated automatically based on the website domain and language that you want to target.
            
            ArrayOfAd ads = new ArrayOfAd();
            DynamicSearchAd dynamicSearchAd  = new DynamicSearchAd();
            dynamicSearchAd.setText("Find New Customers & Increase Sales!");
            dynamicSearchAd.setTextPart2("Start Advertising on Contoso Today.");
            dynamicSearchAd.setPath1("seattle");
            dynamicSearchAd.setPath2("shoe sale");
            // You cannot set FinalUrls. The Final URL will be a dynamically selected landing page.
            // The final URL is distinct from the path that customers will see and click on in your ad.
            dynamicSearchAd.setFinalUrls(null);            
            ads.getAds().add(dynamicSearchAd);
            
            outputStatusMessage("-----\nAddAds:");
            AddAdsResponse addAdsResponse = CampaignManagementExampleHelper.addAds(
                    adGroupIds.getLongs().get(0), 
                    ads);
            ArrayOfNullableOflong adIds = addAdsResponse.getAdIds();
            ArrayOfBatchError adErrors = addAdsResponse.getPartialErrors();
            outputStatusMessage("AdIds:");
            CampaignManagementExampleHelper.outputArrayOfNullableOflong(adIds);
            outputStatusMessage("PartialErrors:");
            CampaignManagementExampleHelper.outputArrayOfBatchError(adErrors);
            
            // Delete the campaign and everything it contains e.g., ad groups and ads.

            outputStatusMessage("-----\nDeleteCampaigns:");
            ArrayOflong deleteCampaignIds = new ArrayOflong();
            deleteCampaignIds.getLongs().add(campaignIds.getLongs().get(0));
            CampaignManagementExampleHelper.deleteCampaigns(
                    authorizationData.getAccountId(), 
                    deleteCampaignIds);
            outputStatusMessage(String.format("Deleted CampaignId %d", deleteCampaignIds.getLongs().get(0))); 
        } 
        catch (Exception ex) {
            String faultXml = ExampleExceptionHelper.getBingAdsExceptionFaultXml(ex, System.out);
            outputStatusMessage(faultXml);
            String message = ExampleExceptionHelper.handleBingAdsSDKException(ex, System.out);
            outputStatusMessage(message);
        }
    }    

    protected static BiddableAdGroupCriterion getExampleAdGroupWebpagePositivePageContent(long adGroupId)
    {
        BiddableAdGroupCriterion adGroupWebpagePositivePageContent = new BiddableAdGroupCriterion();
        adGroupWebpagePositivePageContent.setAdGroupId(adGroupId);
        FixedBid criterionBid = new FixedBid();
        criterionBid.setAmount(0.50);
        adGroupWebpagePositivePageContent.setCriterionBid(criterionBid);
        WebpageCondition condition = new WebpageCondition();
        condition.setOperand(WebpageConditionOperand.PAGE_CONTENT);
        condition.setArgument("flowers");
        ArrayOfWebpageCondition conditions = new ArrayOfWebpageCondition();
        conditions.getWebpageConditions().add(condition);
        WebpageParameter webpageParameter = new WebpageParameter();
        webpageParameter.setConditions(conditions);
        webpageParameter.setCriterionName("Ad Group Webpage Positive Page Content Criterion");
        Webpage criterion = new Webpage();
        criterion.setParameter(webpageParameter);
        adGroupWebpagePositivePageContent.setCriterion(criterion);

        return adGroupWebpagePositivePageContent;
    }

    protected static BiddableAdGroupCriterion getExampleAdGroupWebpagePositiveCategory(long adGroupId, ArrayOfDomainCategory categories)
    {
        BiddableAdGroupCriterion adGroupWebpagePositiveCategory = new BiddableAdGroupCriterion();

        adGroupWebpagePositiveCategory.setAdGroupId(adGroupId);
        FixedBid criterionBid = new FixedBid();
        criterionBid.setAmount(0.50);
        adGroupWebpagePositiveCategory.setCriterionBid(criterionBid);
        WebpageCondition webpageCondition = new WebpageCondition();
        webpageCondition.setArgument(categories.getDomainCategories().get(0).getCategoryName());
        webpageCondition.setOperand(WebpageConditionOperand.CATEGORY);
        ArrayOfWebpageCondition conditions = new ArrayOfWebpageCondition();
        conditions.getWebpageConditions().add(webpageCondition);
        WebpageParameter webpageParameter = new WebpageParameter();
        webpageParameter.setConditions(conditions);
        webpageParameter.setCriterionName("Ad Group Webpage Positive Category Criterion");
        Webpage criterion = new Webpage();
        criterion.setParameter(webpageParameter);
        adGroupWebpagePositiveCategory.setCriterion(criterion);

        return adGroupWebpagePositiveCategory;
    }

    protected static NegativeAdGroupCriterion getExampleAdGroupWebpageNegativeUrl(long adGroupId)
    {
        NegativeAdGroupCriterion adGroupWebpageNegativeUrl = new NegativeAdGroupCriterion();
        adGroupWebpageNegativeUrl.setAdGroupId(adGroupId);
        // 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.
        WebpageCondition webpageCondition = new WebpageCondition();
        webpageCondition.setArgument(DOMAIN_NAME);
        webpageCondition.setOperand(WebpageConditionOperand.URL);
        ArrayOfWebpageCondition conditions = new ArrayOfWebpageCondition();
        conditions.getWebpageConditions().add(webpageCondition);
        WebpageParameter webpageParameter = new WebpageParameter();
        webpageParameter.setConditions(conditions);
        // If you do not specify any name, then it will be set to a concatenated list of conditions. 
        webpageParameter.setCriterionName(null);
        Webpage criterion = new Webpage();
        criterion.setParameter(webpageParameter);
        adGroupWebpageNegativeUrl.setCriterion(criterion);

        return adGroupWebpageNegativeUrl;
    }

    protected static NegativeCampaignCriterion getExampleCampaignWebpageNegativeUrl(long campaignId)
    {
        NegativeCampaignCriterion campaignWebpageNegativeUrl  = new NegativeCampaignCriterion();
        campaignWebpageNegativeUrl.setCampaignId(campaignId);
        WebpageCondition webpageCondition = new WebpageCondition();
        webpageCondition.setArgument(DOMAIN_NAME + "\\seattle");
        webpageCondition.setOperand(WebpageConditionOperand.URL);
        WebpageParameter webpageParameter = new WebpageParameter();
        ArrayOfWebpageCondition conditions = new ArrayOfWebpageCondition();
        conditions.getWebpageConditions().add(webpageCondition);
        webpageParameter.setConditions(conditions);
        webpageParameter.setCriterionName("Campaign Negative Webpage Url Criterion");
        Webpage webpage = new Webpage();
        webpage.setParameter(webpageParameter);
        campaignWebpageNegativeUrl.setCriterion(webpage);

        return campaignWebpageNegativeUrl;
    }
}
<?php

namespace Microsoft\BingAds\Samples\V13;

// For more information about installing and using the Bing Ads PHP SDK, 
// see https://go.microsoft.com/fwlink/?linkid=838593.

require_once __DIR__ . "/../vendor/autoload.php";

include __DIR__ . "/AuthHelper.php";
include __DIR__ . "/AdInsightExampleHelper.php";
include __DIR__ . "/CampaignManagementExampleHelper.php";

use SoapVar;
use SoapFault;
use Exception;

//Specify the Microsoft\BingAds\V13\CampaignManagement classes that will be used.
use Microsoft\BingAds\V13\CampaignManagement\Campaign;
use Microsoft\BingAds\V13\CampaignManagement\AdGroup;
use Microsoft\BingAds\V13\CampaignManagement\BiddableAdGroupCriterion;
use Microsoft\BingAds\V13\CampaignManagement\NegativeAdGroupCriterion;
use Microsoft\BingAds\V13\CampaignManagement\DeviceCriterion;
use Microsoft\BingAds\V13\CampaignManagement\BidMultiplier;
use Microsoft\BingAds\V13\CampaignManagement\AdGroupCriterion;
use Microsoft\BingAds\V13\CampaignManagement\AdGroupCriterionType;
use Microsoft\BingAds\V13\CampaignManagement\AdGroupCriterionStatus;
use Microsoft\BingAds\V13\CampaignManagement\NegativeCampaignCriterion;
use Microsoft\BingAds\V13\CampaignManagement\CampaignCriterion;
use Microsoft\BingAds\V13\CampaignManagement\CampaignCriterionType;
use Microsoft\BingAds\V13\CampaignManagement\CampaignCriterionStatus;
use Microsoft\BingAds\V13\CampaignManagement\BudgetLimitType;
use Microsoft\BingAds\V13\CampaignManagement\Bid;
use Microsoft\BingAds\V13\CampaignManagement\Date;
use Microsoft\BingAds\V13\CampaignManagement\DynamicSearchAd;
use Microsoft\BingAds\V13\CampaignManagement\DynamicSearchAdsSetting;
use Microsoft\BingAds\V13\CampaignManagement\WebpageConditionOperand;
use Microsoft\BingAds\V13\CampaignManagement\WebpageCondition;
use Microsoft\BingAds\V13\CampaignManagement\WebpageParameter;
use Microsoft\BingAds\V13\CampaignManagement\Webpage;
use Microsoft\BingAds\V13\CampaignManagement\FixedBid;
use Microsoft\BingAds\V13\CampaignManagement\CustomParameter;
use Microsoft\BingAds\V13\CampaignManagement\CustomParameters;
use Microsoft\BingAds\V13\CampaignManagement\CampaignType;
use Microsoft\BingAds\V13\CampaignManagement\BatchErrorCollection;

// Specify the Microsoft\BingAds\Auth classes that will be used.
use Microsoft\BingAds\Auth\ServiceClient;
use Microsoft\BingAds\Auth\ServiceClientType;

// Specify the Microsoft\BingAds\Samples classes that will be used.
use Microsoft\BingAds\Samples\V13\AuthHelper;
use Microsoft\BingAds\Samples\V13\AdInsightExampleHelper;
use Microsoft\BingAds\Samples\V13\CampaignManagementExampleHelper;

const DomainName = "contoso.com";
const Language = "EN";

try
{
    // Authenticate user credentials and set the account ID for the sample.  
    AuthHelper::Authenticate();

    // To get started with dynamic search ads, first you'll need to add a new Search campaign 
    // Include a DynamicSearchAdsSetting that specifies the target website domain and language.
        
    $campaigns = array();   
    $campaign = new Campaign();
    $campaign->Name = "Women's Shoes " . $_SERVER['REQUEST_TIME'];
    $campaign->BudgetType = BudgetLimitType::DailyBudgetStandard;
    $campaign->CampaignType = CampaignType::Search;
    $campaign->DailyBudget = 50.00;
    $campaign->Languages = array("All");    
    $campaign->TimeZone = "PacificTimeUSCanadaTijuana";
    $settings = array();
    $dynamicSearchSetting = new DynamicSearchAdsSetting();
    $dynamicSearchSetting->DomainName = "contoso.com";
    $dynamicSearchSetting->Language = "English";
    $encodedSetting = new SoapVar(
        $dynamicSearchSetting, 
        SOAP_ENC_OBJECT, 
        'DynamicSearchAdsSetting', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace()
    );
    $settings[] = $encodedSetting;
    $campaign->Settings = $settings;
    $campaigns[] = $campaign;
    
    print("-----\r\nAddCampaigns:\r\n");
    $addCampaignsResponse = CampaignManagementExampleHelper::AddCampaigns(
        $GLOBALS['AuthorizationData']->AccountId, 
        $campaigns
    );
    $campaignIds = $addCampaignsResponse->CampaignIds;
    print("CampaignIds:\r\n");
    CampaignManagementExampleHelper::OutputArrayOfLong($campaignIds);
    print("PartialErrors:\r\n");
    CampaignManagementExampleHelper::OutputArrayOfBatchError($addCampaignsResponse->PartialErrors);
    
    // Create a new ad group with type set to "SearchDynamic"

    $adGroups = array();
    $adGroup = new AdGroup();
    $adGroup->AdGroupType = "SearchDynamic";    
    $adGroup->CpcBid = new Bid();
    $adGroup->CpcBid->Amount = 0.09;
    date_default_timezone_set('UTC');
    $endDate = new Date();
    $endDate->Day = 31;
    $endDate->Month = 12;
    $endDate->Year = date("Y");
    $adGroup->EndDate = $endDate;
    $adGroup->Name = "Women's Red Shoe Sale";    
    $adGroup->StartDate = null;    
    $adGroups[] = $adGroup;
 
    print("-----\r\nAddAdGroups:\r\n");
    $addAdGroupsResponse = CampaignManagementExampleHelper::AddAdGroups(
        $campaignIds->long[0], 
        $adGroups,
        null
    );
    $adGroupIds = $addAdGroupsResponse->AdGroupIds;
    print("AdGroupIds:\r\n");
    CampaignManagementExampleHelper::OutputArrayOfLong($adGroupIds);
    print("PartialErrors:\r\n");
    CampaignManagementExampleHelper::OutputArrayOfBatchError($addAdGroupsResponse->PartialErrors);

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

    $adGroupCriterions = array();

    $adGroupWebpagePositivePageContent = new BiddableAdGroupCriterion();
    $adGroupWebpagePositivePageContent->Type = "BiddableAdGroupCriterion";
    $adGroupWebpagePositivePageContent->AdGroupId = $adGroupIds->long[0];
    $webpageConditionsAGWPPC = array();
    $conditionAGWPPC = new WebpageCondition();
    $conditionAGWPPC->Argument = "flowers";
    $conditionAGWPPC->Operand = WebpageConditionOperand::PageContent;
    $webpageConditionsAGWPPC[] = $conditionAGWPPC;
    $webpageParameterAGWPPC = new WebpageParameter();
    $webpageParameterAGWPPC->Conditions = $webpageConditionsAGWPPC;
    $webpageParameterAGWPPC->CriterionName = "Ad Group Webpage Positive Page Content Criterion";                
    $criterionAGWPPC = new Webpage();
    $criterionAGWPPC->Type = "Webpage";
    $criterionAGWPPC->Parameter = $webpageParameterAGWPPC;
    $adGroupWebpagePositivePageContent->Criterion = new SoapVar(
        $criterionAGWPPC, 
        SOAP_ENC_OBJECT, 
        'Webpage', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace()
    );    
    $criterionBidAGWPPC = new FixedBid();
    $criterionBidAGWPPC->Amount = 0.50;
    $adGroupWebpagePositivePageContent->CriterionBid = new SoapVar(
        $criterionBidAGWPPC, 
        SOAP_ENC_OBJECT, 
        'FixedBid', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace()
    );
    
    $adGroupCriterions[] = new SoapVar(
        $adGroupWebpagePositivePageContent, 
        SOAP_ENC_OBJECT, 
        'BiddableAdGroupCriterion', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace()
    );

    // To discover the categories that you can use for Webpage criteria (positive or negative), 
    // use the GetDomainCategories operation with the Ad Insight service.
    
    print("-----\r\nGetDomainCategories:\r\n");
    $getDomainCategoriesResponse = AdInsightExampleHelper::GetDomainCategories(
        null, 
        DomainName, 
        Language
    );
    $categories = $getDomainCategoriesResponse->Categories;
    print("Categories:\r\n");
    AdInsightExampleHelper::OutputArrayOfDomainCategory($categories);

    // If any categories are available let's use one as a condition.
    if (!empty($categories) && count((array)$categories) > 0)
    {
        $adGroupWebpagePositiveCategory = new BiddableAdGroupCriterion();
        $adGroupWebpagePositiveCategory->Type = "BiddableAdGroupCriterion";
        $adGroupWebpagePositiveCategory->AdGroupId = $adGroupIds->long[0];
        $webpageConditionsAGWPC = array();
        $conditionAGWPC = new WebpageCondition();
        $conditionAGWPC->Argument = $categories->DomainCategory[0]->CategoryName;
        $conditionAGWPC->Operand = WebpageConditionOperand::Category;
        $webpageConditionsAGWPC[] = $conditionAGWPC;
        $webpageParameterAGWPC = new WebpageParameter();
        $webpageParameterAGWPC->Conditions = $webpageConditionsAGWPC;
        $webpageParameterAGWPC->CriterionName = "Ad Group Webpage Positive Category Criterion";                    
        $criterionAGWPC = new Webpage();
        $criterionAGWPC->Type = "Webpage";
        $criterionAGWPC->Parameter = $webpageParameterAGWPC;
        $adGroupWebpagePositiveCategory->Criterion = new SoapVar(
            $criterionAGWPC, 
            SOAP_ENC_OBJECT, 
            'Webpage', 
            $GLOBALS['CampaignManagementProxy']->GetNamespace()
        );    
        $criterionBidAGWPC = new FixedBid();
        $criterionBidAGWPC->Amount = 0.50;
        $adGroupWebpagePositiveCategory->CriterionBid = new SoapVar(
            $criterionBidAGWPC, 
            SOAP_ENC_OBJECT, 
            'FixedBid', 
            $GLOBALS['CampaignManagementProxy']->GetNamespace()
        );
        
        $adGroupCriterions[] = new SoapVar(
            $adGroupWebpagePositiveCategory, 
            SOAP_ENC_OBJECT, 
            'BiddableAdGroupCriterion', 
            $GLOBALS['CampaignManagementProxy']->GetNamespace()
        );
    }

    // If you want to exclude certain portions of your website, you can add negative Webpage 
    // criterion at the campaign and ad group level. 

    $adGroupWebpageNegativeUrl = new NegativeAdGroupCriterion();
    $adGroupWebpageNegativeUrl->Type = "NegativeAdGroupCriterion";
    $adGroupWebpageNegativeUrl->AdGroupId = $adGroupIds->long[0];
    // 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.
    $webpageConditionsAGWNU = array();
    $conditionAGWNU = new WebpageCondition();
    $conditionAGWNU->Argument = DomainName;
    $conditionAGWNU->Operand = WebpageConditionOperand::Url;
    $webpageConditionsAGWNU[] = $conditionAGWNU;
    $webpageParameterAGWNU = new WebpageParameter();
    $webpageParameterAGWNU->Conditions = $webpageConditionsAGWNU;
    // If you do not specify any name, then it will be set to a concatenated list of conditions. 
    $webpageParameterAGWNU->CriterionName = null;                
    $criterionAGWNU = new Webpage();
    $criterionAGWNU->Type = "Webpage";
    $criterionAGWNU->Parameter = $webpageParameterAGWNU;
    $adGroupWebpageNegativeUrl->Criterion = new SoapVar(
        $criterionAGWNU, SOAP_ENC_OBJECT, 
        'Webpage', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace()
    );
    
    $adGroupCriterions[] = new SoapVar(
        $adGroupWebpageNegativeUrl, 
        SOAP_ENC_OBJECT, 
        'BiddableAdGroupCriterion', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace()
    );

    print("-----\r\nAddAdGroupCriterions:\r\n");
    $addAdGroupCriterionsResponse = CampaignManagementExampleHelper::AddAdGroupCriterions(
        $adGroupCriterions, 
        AdGroupCriterionType::Webpage
    );
    print("AdGroupCriterionIds:\r\n");
    CampaignManagementExampleHelper::OutputArrayOfLong($addAdGroupCriterionsResponse->AdGroupCriterionIds);
    print("NestedPartialErrors:\r\n");
    CampaignManagementExampleHelper::OutputArrayOfBatchErrorCollection($addAdGroupCriterionsResponse->NestedPartialErrors);

    // 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.

    $campaignCriterions = array();

    $campaignWebpageNegativeUrl = new NegativeCampaignCriterion();
    $campaignWebpageNegativeUrl->Type = "NegativeCampaignCriterion";
    $campaignWebpageNegativeUrl->CampaignId = $campaignIds->long[0];
    $webpageConditionsCWNU = array();
    $conditionCWNU = new WebpageCondition();
    $conditionCWNU->Argument = DomainName . "\\seattle";
    $conditionCWNU->Operand = WebpageConditionOperand::Url;
    $webpageConditionsCWNU[] = $conditionCWNU;
    $webpageParameterCWNU = new WebpageParameter();
    $webpageParameterCWNU->Conditions = $webpageConditionsCWNU;
    $webpageParameterCWNU->CriterionName = "Campaign Negative Webpage Url Criterion";                
    $criterionCWNU = new Webpage();
    $criterionCWNU->Type = "Webpage";
    $criterionCWNU->Parameter = $webpageParameterCWNU;
    $campaignWebpageNegativeUrl->Criterion = new SoapVar(
        $criterionCWNU, 
        SOAP_ENC_OBJECT, 
        'Webpage', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace()
    );

    $campaignCriterions[] = new SoapVar(
        $campaignWebpageNegativeUrl, 
        SOAP_ENC_OBJECT, 
        'NegativeCampaignCriterion', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace());
    
    print("-----\r\nAddCampaignCriterions:\r\n");
    $addCampaignCriterionsResponse = CampaignManagementExampleHelper::AddCampaignCriterions(
        $campaignCriterions, 
        CampaignCriterionType::Webpage
    );
    print("CampaignCriterionIds:\r\n");
    CampaignManagementExampleHelper::OutputArrayOfLong($addCampaignCriterionsResponse->CampaignCriterionIds);
    print("NestedPartialErrors:\r\n");
    CampaignManagementExampleHelper::OutputArrayOfBatchErrorCollection($addCampaignCriterionsResponse->NestedPartialErrors);

    // 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.

    $ads = array();
    $ad = new DynamicSearchAd();
    $ad->Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.";
    $ad->Path1 = "seattle";
    $ad->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.
    $ad->FinalUrls = null;
    $encodedAd = new SoapVar(
        $ad, 
        SOAP_ENC_OBJECT, 
        'DynamicSearchAd', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace()
    );
    $ads[] = $encodedAd;
    
    print("-----\r\nAddAds:\r\n");
    $addAdsResponse = CampaignManagementExampleHelper::AddAds(
        $adGroupIds->long[0], 
        $ads
    );
    print("AdIds:\r\n");
    CampaignManagementExampleHelper::OutputArrayOfLong($addAdsResponse->AdIds);
    print("PartialErrors:\r\n");
    CampaignManagementExampleHelper::OutputArrayOfBatchError($addAdsResponse->PartialErrors);

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

    print("-----\r\nDeleteCampaigns:\r\n");
    CampaignManagementExampleHelper::DeleteCampaigns(
        $GLOBALS['AuthorizationData']->AccountId, 
        array($campaignIds->long[0])
    );
    printf("Deleted Campaign Id %s\r\n", $campaignIds->long[0]);
}
catch (SoapFault $e)
{
    printf("-----\r\nFault Code: %s\r\nFault String: %s\r\nFault Detail: \r\n", $e->faultcode, $e->faultstring);
    var_dump($e->detail);
    print "-----\r\nLast SOAP request/response:\r\n";
    print $GLOBALS['Proxy']->GetWsdl() . "\r\n";
    print $GLOBALS['Proxy']->GetService()->__getLastRequest()."\r\n";
    print $GLOBALS['Proxy']->GetService()->__getLastResponse()."\r\n";
}
catch (Exception $e)
{
    // Ignore fault exceptions that we already caught.
    if ($e->getPrevious())
    { ; }
    else
    {
        print $e->getCode()." ".$e->getMessage()."\n\n";
        print $e->getTraceAsString()."\n\n";
    }
}
from auth_helper import *
from adinsight_example_helper import *
from campaignmanagement_example_helper import *

# You must provide credentials in auth_helper.py.

DOMAIN_NAME="contoso.com"
LANGUAGE="EN"

def get_ad_group_webpage_positive_page_content_example(ad_group_id):
    biddable_ad_group_criterion=set_elements_to_none(campaign_service.factory.create('BiddableAdGroupCriterion'))
    biddable_ad_group_criterion.Type='BiddableAdGroupCriterion'
    biddable_ad_group_criterion.AdGroupId=ad_group_id
    fixed_bid=set_elements_to_none(campaign_service.factory.create('FixedBid'))
    fixed_bid.Amount=0.45
    biddable_ad_group_criterion.CriterionBid=fixed_bid
    conditions=campaign_service.factory.create('ArrayOfWebpageCondition')
    condition=set_elements_to_none(campaign_service.factory.create('WebpageCondition'))
    condition.Operand='PageContent'
    condition.Argument='flowers'
    conditions.WebpageCondition.append(condition)
    webpage_parameter=set_elements_to_none(campaign_service.factory.create('WebpageParameter'))
    webpage_parameter.Conditions=conditions
    webpage_parameter.CriterionName='Ad Group Webpage Positive Page Content Criterion'
    webpage=set_elements_to_none(campaign_service.factory.create('Webpage'))
    webpage.Type='Webpage'
    webpage.Parameter=webpage_parameter
    biddable_ad_group_criterion.Criterion=webpage

    return biddable_ad_group_criterion

def get_ad_group_webpage_positive_category_example(ad_group_id, category_name):
    biddable_ad_group_criterion=set_elements_to_none(campaign_service.factory.create('BiddableAdGroupCriterion'))
    biddable_ad_group_criterion.Type='BiddableAdGroupCriterion'
    biddable_ad_group_criterion.AdGroupId=ad_group_id
    fixed_bid=set_elements_to_none(campaign_service.factory.create('FixedBid'))
    fixed_bid.Amount=0.50
    biddable_ad_group_criterion.CriterionBid=fixed_bid
    conditions=campaign_service.factory.create('ArrayOfWebpageCondition')
    condition=set_elements_to_none(campaign_service.factory.create('WebpageCondition'))
    condition.Argument=category_name
    condition.Operand='Category'
    conditions.WebpageCondition.append(condition)
    webpage_parameter=set_elements_to_none(campaign_service.factory.create('WebpageParameter'))
    webpage_parameter.Conditions=conditions
    webpage_parameter.CriterionName='Ad Group Webpage Positive Category Criterion'
    webpage=set_elements_to_none(campaign_service.factory.create('Webpage'))
    webpage.Type='Webpage'
    webpage.Parameter=webpage_parameter
    biddable_ad_group_criterion.Criterion=webpage

    return biddable_ad_group_criterion

def get_ad_group_webpage_negative_url_example(ad_group_id):
    negative_ad_group_criterion=set_elements_to_none(campaign_service.factory.create('NegativeAdGroupCriterion'))
    negative_ad_group_criterion.Type='NegativeAdGroupCriterion'
    negative_ad_group_criterion.AdGroupId=ad_group_id    
    # 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=campaign_service.factory.create('ArrayOfWebpageCondition')
    condition=set_elements_to_none(campaign_service.factory.create('WebpageCondition'))
    condition.Operand='Url'
    condition.Argument=DOMAIN_NAME
    conditions.WebpageCondition.append(condition)
    webpage_parameter=set_elements_to_none(campaign_service.factory.create('WebpageParameter'))
    webpage_parameter.Conditions=conditions
    # If you do not specify any name, then it will be set to a concatenated list of conditions. 
    webpage_parameter.CriterionName=None
    webpage=set_elements_to_none(campaign_service.factory.create('Webpage'))
    webpage.Type='Webpage'
    webpage.Parameter=webpage_parameter
    negative_ad_group_criterion.Criterion=webpage

    return negative_ad_group_criterion

def get_campaign_webpage_negative_url_example(campaign_id):
    negative_campaign_criterion=set_elements_to_none(campaign_service.factory.create('NegativeCampaignCriterion'))
    negative_campaign_criterion.Type='NegativeCampaignCriterion'
    negative_campaign_criterion.CampaignId=campaign_id
    
    conditions=campaign_service.factory.create('ArrayOfWebpageCondition')
    condition=set_elements_to_none(campaign_service.factory.create('WebpageCondition'))
    condition.Argument=DOMAIN_NAME + "\\seattle"
    condition.Operand='Url'
    conditions.WebpageCondition.append(condition)

    webpage_parameter=set_elements_to_none(campaign_service.factory.create('WebpageParameter'))
    webpage_parameter.Conditions=conditions
    webpage_parameter.CriterionName='Campaign Negative Webpage Url Criterion'

    webpage=set_elements_to_none(campaign_service.factory.create('Webpage'))
    webpage.Type='Webpage'
    webpage.Parameter=webpage_parameter
    negative_campaign_criterion.Criterion=webpage

    return negative_campaign_criterion

def main(authorization_data):

    try:
        # To get started with dynamic search ads, first you'll need to add a new Search campaign 
        # Include a DynamicSearchAdsSetting that specifies the target website domain and language.

        campaigns=campaign_service.factory.create('ArrayOfCampaign')
        campaign=set_elements_to_none(campaign_service.factory.create('Campaign'))
        campaign.BudgetType='DailyBudgetStandard'
        campaign.CampaignType=['DynamicSearchAds']
        campaign.DailyBudget=50
        languages=campaign_service.factory.create('ns3:ArrayOfstring')
        languages.string.append('All')
        campaign.Languages=languages
        campaign.Name="Women's Shoes " + strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
        settings=campaign_service.factory.create('ArrayOfSetting')
        setting=set_elements_to_none(campaign_service.factory.create('DynamicSearchAdsSetting'))
        setting.DomainName=DOMAIN_NAME
        setting.Language=LANGUAGE
        settings.Setting.append(setting)
        campaign.Settings=settings
        campaign.TimeZone='PacificTimeUSCanadaTijuana'
        campaigns.Campaign.append(campaign)

        output_status_message("-----\nAddCampaigns:")
        add_campaigns_response=campaign_service.AddCampaigns(
            AccountId=authorization_data.account_id,
            Campaigns=campaigns
        )
        campaign_ids={
            'long': add_campaigns_response.CampaignIds['long'] if add_campaigns_response.CampaignIds['long'] else None
        }
        output_status_message("CampaignIds:")
        output_array_of_long(campaign_ids)
        output_status_message("PartialErrors:")
        output_array_of_batcherror(add_campaigns_response.PartialErrors)

        # Create a new ad group with type set to "SearchDynamic"

        ad_groups=campaign_service.factory.create('ArrayOfAdGroup')
        ad_group=set_elements_to_none(campaign_service.factory.create('AdGroup'))
        ad_group.AdGroupType='SearchDynamic'
        ad_group.Name="Women's Red Shoe Sale"
        end_date=campaign_service.factory.create('Date')
        end_date.Day=31
        end_date.Month=12
        current_time=gmtime()
        end_date.Year=current_time.tm_year + 1
        ad_group.EndDate=end_date
        cpc_bid=campaign_service.factory.create('Bid')
        cpc_bid.Amount=0.09
        ad_group.CpcBid=cpc_bid
        ad_groups.AdGroup.append(ad_group)

        output_status_message("-----\nAddAdGroups:")
        add_ad_groups_response=campaign_service.AddAdGroups(
            CampaignId=campaign_ids['long'][0],
            AdGroups=ad_groups,
            ReturnInheritedBidStrategyTypes=False
        )
        ad_group_ids={
            'long': add_ad_groups_response.AdGroupIds['long'] if add_ad_groups_response.AdGroupIds['long'] else None
        }
        output_status_message("AdGroupIds:")
        output_array_of_long(ad_group_ids)
        output_status_message("PartialErrors:")
        output_array_of_batcherror(add_ad_groups_response.PartialErrors)

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

        ad_group_criterions=campaign_service.factory.create('ArrayOfAdGroupCriterion')
        ad_group_webpage_positive_page_content=get_ad_group_webpage_positive_page_content_example(ad_group_ids['long'][0])
        ad_group_criterions.AdGroupCriterion.append(ad_group_webpage_positive_page_content)

        # To discover the categories that you can use for Webpage criterion (positive or negative), 
        # use the GetDomainCategories operation with the Ad Insight service.

        output_status_message("-----\nGetDomainCategories:")
        categories=adinsight_service.GetDomainCategories(
            CategoryName=None,
            DomainName=DOMAIN_NAME,
            Language=LANGUAGE
        )
        output_status_message("DomainCategories:")
        output_array_of_domaincategory(categories)

        # If any categories are available let's use one as a condition.
        if(categories is not None and len(categories) > 0):
            ad_group_webpage_positive_category=get_ad_group_webpage_positive_category_example(
                ad_group_ids['long'][0], 
                categories['DomainCategory'][0].CategoryName
                )
            ad_group_criterions.AdGroupCriterion.append(ad_group_webpage_positive_category)

        # If you want to exclude certain portions of your website, you can add negative Webpage 
        # criterion at the campaign and ad group level. 

        ad_group_webpage_negative_url=get_ad_group_webpage_negative_url_example(ad_group_ids['long'][0])
        ad_group_criterions.AdGroupCriterion.append(ad_group_webpage_negative_url)
        
        output_status_message("-----\nAddAdGroupCriterions:")
        add_ad_group_criterions_response = campaign_service.AddAdGroupCriterions(
            AdGroupCriterions=ad_group_criterions,
            CriterionType='Webpage'
        )
        ad_group_criterion_ids={
            'long': add_ad_group_criterions_response.AdGroupCriterionIds['long'] 
            if add_ad_group_criterions_response.AdGroupCriterionIds['long'] else None
        }
        output_status_message("AdGroupCriterionIds:")
        output_array_of_long(ad_group_criterion_ids)
        output_status_message("NestedPartialErrors:")
        output_array_of_batcherrorcollection(add_ad_group_criterions_response.NestedPartialErrors) 
        
        # 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.

        campaign_criterions=campaign_service.factory.create('ArrayOfCampaignCriterion')
        campaign_webpage_negative_url = get_campaign_webpage_negative_url_example(campaign_ids['long'][0])
        campaign_criterions.CampaignCriterion.append(campaign_webpage_negative_url)

        output_status_message("-----\nAddCampaignCriterions:")
        add_campaign_criterions_response = campaign_service.AddCampaignCriterions(
            CampaignCriterions=campaign_criterions,
            CriterionType='Webpage'
        )
        campaign_criterion_ids={
            'long': add_campaign_criterions_response.CampaignCriterionIds['long'] 
            if add_campaign_criterions_response.CampaignCriterionIds['long'] else None
        }
        output_status_message("CampaignCriterionIds:")
        output_array_of_long(campaign_criterion_ids)
        output_status_message("NestedPartialErrors:")
        output_array_of_batcherrorcollection(add_campaign_criterions_response.NestedPartialErrors) 

        # 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.

        ads=campaign_service.factory.create('ArrayOfAd')
        dynamic_search_ad=set_elements_to_none(campaign_service.factory.create('DynamicSearchAd'))
        dynamic_search_ad.Text='Find New Customers & Increase Sales!'
        dynamic_search_ad.TextPart2='Start Advertising on Contoso Today.'
        dynamic_search_ad.Path1='seattle'
        dynamic_search_ad.Path2='shoe sale'
        dynamic_search_ad.Type='DynamicSearch'
        # 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.
        dynamic_search_ad.FinalUrls=None
        ads.Ad.append(dynamic_search_ad)
                
        output_status_message("-----\nAddAds:")
        add_ads_response=campaign_service.AddAds(
            AdGroupId=ad_group_ids['long'][0],
            Ads=ads
        )
        ad_ids={
            'long': add_ads_response.AdIds['long'] if add_ads_response.AdIds['long'] else None
        }
        output_status_message("AdIds:")
        output_array_of_long(ad_ids)
        output_status_message("PartialErrors:")
        output_array_of_batcherror(add_ads_response.PartialErrors)
        
        # Delete the campaign and everything it contains e.g., ad groups and ads.

        output_status_message("-----\nDeleteCampaigns:")
        campaign_service.DeleteCampaigns(
            AccountId=authorization_data.account_id,
            CampaignIds=campaign_ids
        )
        output_status_message("Deleted Campaign Id {0}".format(campaign_ids['long'][0]))

    except WebFault as ex:
        output_webfault_errors(ex)
    except Exception as ex:
        output_status_message(ex)

# Main execution

if __name__ == '__main__':

    print("Loading the web service client proxies...")

    authorization_data=AuthorizationData(
        account_id=None,
        customer_id=None,
        developer_token=DEVELOPER_TOKEN,
        authentication=None,
    )

    campaign_service=ServiceClient(
        service='CampaignManagementService', 
        version=13,
        authorization_data=authorization_data, 
        environment=ENVIRONMENT,
    )
    
    adinsight_service=ServiceClient(
        service='AdInsightService', 
        version=13,
        authorization_data=authorization_data, 
        environment=ENVIRONMENT,
    )     

    authenticate(authorization_data)       

    main(authorization_data)

See Also

Get Started with the Bing Ads API