Keywords and Ads Code Example

This example demonstrates how to setup ads and keywords for a search advertising campaign.

Tip

To get access and refresh tokens for your Bing Ads user and make your first service call using the Bing Ads API, see the Quick Start sample. 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.V12.CampaignManagement;
using Microsoft.BingAds;

namespace BingAdsExamplesLibrary.V12
{
    /// <summary>
    /// This example demonstrates how to add ads and keywords to a new ad group, 
    /// and handle partial errors when some ads or keywords are not successfully created.
    /// </summary>
    public class KeywordsAds : ExampleBase
    {
        public override string Description
        {
            get { return "Keywords and Ads | Campaign Management V12"; }
        }

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

                var budgetIds = new List<long?>();
                var budgets = new List<Budget>();
                budgets.Add(new Budget
                {
                    Amount = 50,
                    BudgetType = BudgetLimitType.DailyBudgetStandard,
                    Name = "My Shared Budget " + DateTime.UtcNow,
                });

                budgetIds = (await CampaignManagementExampleHelper.AddBudgetsAsync(budgets)).BudgetIds.ToList();

                // Specify one or more campaigns.

                var campaigns = new[]{
                    new Campaign
                    {
                        Name = "Women's Shoes " + DateTime.UtcNow,
                        Description = "Red shoes line.",

                        // You must choose to set either the shared  budget ID or daily amount.
                        // You can set one or the other, but you may not set both.
                        BudgetId = budgetIds.Count > 0 ? budgetIds[0] : null,
                        DailyBudget = budgetIds.Count > 0 ? 0 : 50,
                        BudgetType = BudgetLimitType.DailyBudgetStandard,
                        
                        // You can set your campaign bid strategy to Enhanced CPC (EnhancedCpcBiddingScheme) 
                        // and then, at any time, set an individual ad group or keyword bid strategy to 
                        // Manual CPC (ManualCpcBiddingScheme).
                        // For campaigns you can use either of the EnhancedCpcBiddingScheme or ManualCpcBiddingScheme objects. 
                        // If you do not set this element, then EnhancedCpcBiddingScheme is used by default.
                        BiddingScheme = new EnhancedCpcBiddingScheme { },
                        
                        TimeZone = "PacificTimeUSCanadaTijuana",
                                                
                        // Used with FinalUrls shown in the text ads that we will add below.
                        TrackingUrlTemplate = 
                            "http://tracker.example.com/?season={_season}&promocode={_promocode}&u={lpurl}"
                    },
                };

                // Specify one or more ad groups.

                var adGroups = new[] {
                    new AdGroup
                    {
                        Name = "Women's Red Shoe Sale",
                        StartDate = null,
                        EndDate = new Microsoft.BingAds.V12.CampaignManagement.Date {
                            Month = 12,
                            Day = 31,
                            Year = DateTime.UtcNow.Year + 1
                        },
                        CpcBid = new Bid { Amount = 0.09 },
                        Language = "English",
                        
                        // For ad groups you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
                        // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
                        BiddingScheme = new ManualCpcBiddingScheme { },

                        Settings = new[]
                        {
                            new TargetSetting
                            {
                                Details = new []
                                {
                                    new TargetSettingDetail
                                    {
                                        CriterionTypeGroup = CriterionTypeGroup.Audience,
                                        TargetAndBid = true
                                    }
                                }
                            }
                        },
                    }
                };

                // In this example only the second keyword should succeed. The Text of the first keyword exceeds the limit.

                var keywords = new[] {
                    new Keyword
                    {
                        Bid = new Bid { Amount = 0.47 },
                        Param2 = "10% Off",
                        MatchType = MatchType.Broad,
                        Text = "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes " +
                               "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes " +
                               "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes",
                        // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
                        // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
                        BiddingScheme = new InheritFromParentBiddingScheme { },
                    },
                    new Keyword
                    {
                        Bid = new Bid { Amount = 0.47 },
                        Param2 = "10% Off",
                        MatchType = MatchType.Phrase,
                        Text = "Brand-A Shoes",
                        // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
                        // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
                        BiddingScheme = new InheritFromParentBiddingScheme { },
                    },
                };

                // In this example only the first 3 ads should succeed. 
                // The TitlePart2 of the fourth ad is empty and not valid.

                var ads = new Ad[] {
                    new ExpandedTextAd 
                    {
                        TitlePart1 = "Contoso",
                        TitlePart2 = "Fast & Easy Setup",
                        Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                        Path1 = "seattle",
                        Path2 = "shoe sale",

                        // With FinalUrls you can separate the tracking template, custom parameters, and 
                        // landing page URLs. 
                        FinalUrls = new[] {
                            "http://www.contoso.com/womenshoesale"
                        },
                        // Final Mobile URLs can also be used if you want to direct the user to a different page 
                        // for mobile devices.
                        FinalMobileUrls = new[] {
                            "http://mobile.contoso.com/womenshoesale"
                        }, 
                        // You could use a tracking template which would override the campaign level
                        // tracking template. Tracking templates defined for lower level entities 
                        // override those set for higher level entities.
                        // In this example we are using the campaign level tracking template.
                        TrackingUrlTemplate = null,

                        // Set custom parameters that are specific to this ad, 
                        // and can be used by the ad, ad group, campaign, or account level tracking template. 
                        // In this example we are using the campaign level tracking template.
                        UrlCustomParameters = new CustomParameters {
                            Parameters = new[] {
                                new CustomParameter(){
                                    Key = "promoCode",
                                    Value = "PROMO1"
                                },
                                new CustomParameter(){
                                    Key = "season",
                                    Value = "summer"
                                },
                            }
                        }
                    },
                    new ExpandedTextAd {
                        TitlePart1 = "Contoso",
                        TitlePart2 = "Quick & Easy Setup",
                        Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                        Path1 = "seattle",
                        Path2 = "shoe sale",      

                        // With FinalUrls you can separate the tracking template, custom parameters, and 
                        // landing page URLs. 
                        FinalUrls = new[] {
                            "http://www.contoso.com/womenshoesale"
                        },
                        // Final Mobile URLs can also be used if you want to direct the user to a different page 
                        // for mobile devices.
                        FinalMobileUrls = new[] {
                            "http://mobile.contoso.com/womenshoesale"
                        }, 
                        // You could use a tracking template which would override the campaign level
                        // tracking template. Tracking templates defined for lower level entities 
                        // override those set for higher level entities.
                        // In this example we are using the campaign level tracking template.
                        TrackingUrlTemplate = null,

                        // Set custom parameters that are specific to this ad, 
                        // and can be used by the ad, ad group, campaign, or account level tracking template. 
                        // In this example we are using the campaign level tracking template.
                        UrlCustomParameters = new CustomParameters {
                            Parameters = new[] {
                                new CustomParameter(){
                                    Key = "promoCode",
                                    Value = "PROMO2"
                                },
                                new CustomParameter(){
                                    Key = "season",
                                    Value = "summer"
                                },
                            }
                        },
                    },
                    new ExpandedTextAd {
                        TitlePart1 = "Contoso",
                        TitlePart2 = "Fast & Simple Setup",
                        Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                        Path1 = "seattle",
                        Path2 = "shoe sale",

                        // With FinalUrls you can separate the tracking template, custom parameters, and 
                        // landing page URLs. 
                        FinalUrls = new[] {
                            "http://www.contoso.com/womenshoesale"
                        },
                        // Final Mobile URLs can also be used if you want to direct the user to a different page 
                        // for mobile devices.
                        FinalMobileUrls = new[] {
                            "http://mobile.contoso.com/womenshoesale"
                        }, 
                        // You could use a tracking template which would override the campaign level
                        // tracking template. Tracking templates defined for lower level entities 
                        // override those set for higher level entities.
                        // In this example we are using the campaign level tracking template.
                        TrackingUrlTemplate = null,

                        // Set custom parameters that are specific to this ad, 
                        // and can be used by the ad, ad group, campaign, or account level tracking template. 
                        // In this example we are using the campaign level tracking template.
                        UrlCustomParameters = new CustomParameters {
                            Parameters = new[] {
                                new CustomParameter(){
                                    Key = "promoCode",
                                    Value = "PROMO3"
                                },
                                new CustomParameter(){
                                    Key = "season",
                                    Value = "summer"
                                },
                            }
                        },
                    },
                    new ExpandedTextAd {
                        TitlePart1 = "Contoso",
                        TitlePart2 = "",
                        Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.",
                        Path1 = "seattle",
                        Path2 = "shoe sale",    

                        // With FinalUrls you can separate the tracking template, custom parameters, and 
                        // landing page URLs. 
                        FinalUrls = new[] {
                            "http://www.contoso.com/womenshoesale"
                        },
                        // Final Mobile URLs can also be used if you want to direct the user to a different page 
                        // for mobile devices.
                        FinalMobileUrls = new[] {
                            "http://mobile.contoso.com/womenshoesale"
                        }, 
                        // You could use a tracking template which would override the campaign level
                        // tracking template. Tracking templates defined for lower level entities 
                        // override those set for higher level entities.
                        // In this example we are using the campaign level tracking template.
                        TrackingUrlTemplate = null,

                        // Set custom parameters that are specific to this ad, 
                        // and can be used by the ad, ad group, campaign, or account level tracking template. 
                        // In this example we are using the campaign level tracking template.
                        UrlCustomParameters = new CustomParameters {
                            Parameters = new[] {
                                new CustomParameter(){
                                    Key = "promoCode",
                                    Value = "PROMO4"
                                },
                                new CustomParameter(){
                                    Key = "season",
                                    Value = "summer"
                                },
                            }
                        },
                    },
                };

                // Add the campaign, ad group, keywords, and ads

                AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync(
                    authorizationData.AccountId, 
                    campaigns,
                    false);
                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, null);
                long?[] adGroupIds = addAdGroupsResponse.AdGroupIds.ToArray();
                BatchError[] adGroupErrors = addAdGroupsResponse.PartialErrors.ToArray();
                CampaignManagementExampleHelper.OutputArrayOfLong(adGroupIds);
                CampaignManagementExampleHelper.OutputArrayOfBatchError(adGroupErrors);

                AddKeywordsResponse addKeywordsResponse = await CampaignManagementExampleHelper.AddKeywordsAsync((long)adGroupIds[0], keywords, null);
                long?[] keywordIds = addKeywordsResponse.KeywordIds.ToArray();
                BatchError[] keywordErrors = addKeywordsResponse.PartialErrors.ToArray();
                CampaignManagementExampleHelper.OutputArrayOfLong(keywordIds);
                CampaignManagementExampleHelper.OutputArrayOfBatchError(keywordErrors);

                AddAdsResponse addAdsResponse = await CampaignManagementExampleHelper.AddAdsAsync((long)adGroupIds[0], ads);
                long?[] adIds = addAdsResponse.AdIds.ToArray();
                BatchError[] adErrors = addAdsResponse.PartialErrors.ToArray();
                CampaignManagementExampleHelper.OutputArrayOfLong(adIds);
                CampaignManagementExampleHelper.OutputArrayOfBatchError(adErrors);

                // Here is a simple example that updates the campaign budget.
                // If the campaign has a shared budget you cannot update the Campaign budget amount,
                // and you must instead update the amount in the Budget object. If you try to update 
                // the budget amount of a campaign that has a shared budget, the service will return 
                // the CampaignServiceCannotUpdateSharedBudget error code.
                
                var getCampaigns = (await CampaignManagementExampleHelper.GetCampaignsByAccountIdAsync(
                    authorizationData.AccountId,
                    AllCampaignTypes
                )).Campaigns;

                var updateCampaigns = new List<Campaign>();
                var updateBudgets = new List<Budget>();
                var getCampaignIds = new List<long>();
                var getBudgetIds = new List<long>();

                // Increase existing budgets by 20%
                foreach (var campaign in getCampaigns)
                {
                    // If the campaign has a shared budget, let's add the budget ID to the list we will update later.
                    if (campaign != null && campaign.BudgetId > 0)
                    {
                        getBudgetIds.Add((long)campaign.BudgetId);
                    }
                    // If the campaign has its own budget, let's add it to the list of campaigns to update later.
                    else if(campaign != null)
                    {
                        // Increase budget by 20 %
                        var updateCampaign = new Campaign
                        {
                            DailyBudget = campaign.DailyBudget * 1.2,
                            Id = campaign.Id,
                        };

                        updateCampaigns.Add(updateCampaign);
                    }
                }

                // Update shared budgets in Budget objects.
                if (getBudgetIds.Count > 0)
                {
                    // The UpdateBudgets operation only accepts 100 Budget objects per call. 
                    // To simply the example we will update the first 100.
                    getBudgetIds = getBudgetIds.Distinct().Take(100).ToList();
                    var getBudgets = (await CampaignManagementExampleHelper.GetBudgetsByIdsAsync(getBudgetIds)).Budgets;

                    OutputStatusMessage("List of shared budgets BEFORE update:\n");
                    foreach (var budget in getBudgets)
                    {
                        OutputStatusMessage("Budget:");
                        CampaignManagementExampleHelper.OutputBudget(budget);
                    }

                    OutputStatusMessage("List of campaigns that share each budget:\n");
                    var getCampaignIdCollection = (await CampaignManagementExampleHelper.GetCampaignIdsByBudgetIdsAsync(getBudgetIds)).CampaignIdCollection;
                    for(int index = 0; index < getCampaignIdCollection.Count; index++)
                    {
                        OutputStatusMessage(string.Format("BudgetId: {0}", getBudgetIds[index]));
                        OutputStatusMessage("Campaign Ids:");
                        if(getCampaignIdCollection[index] != null)
                        {
                            foreach (var id in getCampaignIdCollection[index].Ids)
                            {
                                OutputStatusMessage(string.Format("\t{0}", id));
                            }
                        }
                    }

                    foreach (var budget in getBudgets)
                    {
                        if (budget != null)
                        {
                            // Increase budget by 20 %
                            budget.Amount *= 1.2m;
                            updateBudgets.Add(budget);
                        }
                    }
                    await CampaignManagementExampleHelper.UpdateBudgetsAsync(updateBudgets);

                    getBudgets = (await CampaignManagementExampleHelper.GetBudgetsByIdsAsync(getBudgetIds)).Budgets;

                    OutputStatusMessage("List of shared budgets AFTER update:\n");
                    foreach (var budget in getBudgets)
                    {
                        OutputStatusMessage("Budget:");
                        CampaignManagementExampleHelper.OutputBudget(budget);
                    }
                }

                // Update unshared budgets in Campaign objects.
                if(updateCampaigns.Count > 0)
                {
                    // The UpdateCampaigns operation only accepts 100 Campaign objects per call. 
                    // To simply the example we will update the first 100.
                    updateCampaigns = updateCampaigns.Take(100).ToList();
                    
                    foreach (var campaign in updateCampaigns)
                    {
                        getCampaignIds.Add((long)campaign.Id);
                    }

                    await CampaignManagementExampleHelper.UpdateCampaignsAsync(
                        authorizationData.AccountId, 
                        updateCampaigns,
                        false);

                    getCampaigns = (await CampaignManagementExampleHelper.GetCampaignsByIdsAsync(
                        authorizationData.AccountId,
                        getCampaignIds,
                        CampaignType.Search | CampaignType.Shopping | CampaignType.DynamicSearchAds
                    )).Campaigns;

                    OutputStatusMessage("List of campaigns with unshared budget AFTER budget update:\n");
                    foreach (var campaign in getCampaigns)
                    {
                        OutputStatusMessage("Campaign:");
                        CampaignManagementExampleHelper.OutputCampaign(campaign);
                    }
                }
                
                // Update the Text for the 3 successfully created ads, and update some UrlCustomParameters.
                var updateAds = new Ad[] {
                    new ExpandedTextAd {
                        Id = adIds[0],
                        Text = "Huge Savings on All Red Shoes.",
                        // Set the UrlCustomParameters element to null or empty to retain any 
                        // existing custom parameters.
                        UrlCustomParameters = null,
                    },
                    new ExpandedTextAd {
                        Id = adIds[1],
                        Text = "Huge Savings on All Red Shoes.",
                        // To remove all custom parameters, set the Parameters element of the 
                        // CustomParameters object to null or empty.
                        UrlCustomParameters = new CustomParameters {
                            Parameters = null,
                        },
                    },
                    new ExpandedTextAd {
                        Id = adIds[2],
                        Text = "Huge Savings on All Red Shoes.",
                        // To remove a subset of custom parameters, specify the custom parameters that 
                        // you want to keep in the Parameters element of the CustomParameters object.
                        UrlCustomParameters = new CustomParameters {
                            Parameters = new[] {
                                new CustomParameter(){
                                    Key = "promoCode",
                                    Value = "updatedpromo"
                                },
                            }
                        }
                    },
                };

                // As an exercise you can step through using the debugger and view the results.

                var getAdsByAdGroupIdResponse = await CampaignManagementExampleHelper.GetAdsByAdGroupIdAsync(
                    (long)adGroupIds[0],
                    AllAdTypes,
                    null
                    );
                var updateAdsResponse = await CampaignManagementExampleHelper.UpdateAdsAsync((long)adGroupIds[0], updateAds);
                getAdsByAdGroupIdResponse = await CampaignManagementExampleHelper.GetAdsByAdGroupIdAsync(
                    (long)adGroupIds[0],
                    AllAdTypes,
                    null
                    );


                // Here is a simple example that updates the keyword bid to use the ad group bid.

                var updateKeyword = new Keyword
                {
                    // Set Bid.Amount null (new empty Bid) to use the ad group bid.
                    // If the Bid property is null, your keyword bid will not be updated.
                    Bid = new Bid(),
                    Id = keywordIds[1],
                };

                // As an exercise you can step through using the debugger and view the results.

                var getKeywordsByAdGroupIdResponse = 
                    await CampaignManagementExampleHelper.GetKeywordsByAdGroupIdAsync((long)adGroupIds[0]);
                var updateKeywordsResponse = 
                    await CampaignManagementExampleHelper.UpdateKeywordsAsync((long)adGroupIds[0], new[] { updateKeyword }, null);
                getKeywordsByAdGroupIdResponse = 
                    await CampaignManagementExampleHelper.GetKeywordsByAdGroupIdAsync((long)adGroupIds[0]);
                
                // Delete the campaign, ad group, keyword, and ad that were previously added. 
                // You should remove this line if you want to view the added entities in the 
                // Bing Ads web application or another tool.

                await CampaignManagementExampleHelper.DeleteCampaignsAsync(authorizationData.AccountId, new[] { (long)campaignIds[0] });
                OutputStatusMessage(string.Format("\nDeleted Campaign Id {0}\n", campaignIds[0]));

                // This sample will attempt to delete the budget that was created above.
                if (budgetIds.Count > 0)
                {
                    await CampaignManagementExampleHelper.DeleteBudgetsAsync(new[] { (long)budgetIds[0] });
                    OutputStatusMessage(string.Format("\nDeleted Budget Id {0}\n", budgetIds[0]));
                }
            }
            // Catch authentication exceptions
            catch (OAuthTokenRequestException ex)
            {
                OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
            }
            // Catch Campaign Management service exceptions
            catch (FaultException<Microsoft.BingAds.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);
            }
        }
    }
}
package com.microsoft.bingads.examples.v12;

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

import com.microsoft.bingads.*;
import com.microsoft.bingads.v12.campaignmanagement.*;
import java.util.HashSet;
import java.util.List;

public class KeywordsAds extends ExampleBase {
    
    public static void main(java.lang.String[] args) {
     
        try
        {
            authorizationData = getAuthorizationData(null,null); 
             
            CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient<ICampaignManagementService>(
                        authorizationData, 
                        API_ENVIRONMENT,
                        ICampaignManagementService.class);
                        
            // Let's create a new budget and share it with a new campaign.

            ArrayOfNullableOflong budgetIds = new ArrayOfNullableOflong();
                        
            ArrayOfBudget budgets = new ArrayOfBudget();
            Budget addBudget = new Budget();
            addBudget.setAmount(new java.math.BigDecimal(50));
            addBudget.setBudgetType(BudgetLimitType.DAILY_BUDGET_STANDARD);
            addBudget.setName("My Shared Budget " + System.currentTimeMillis());
            budgets.getBudgets().add(addBudget);

            budgetIds = CampaignManagementExampleHelper.addBudgets(budgets).getBudgetIds();
            

            // Specify a campaign. 

            ArrayOfCampaign campaigns = new ArrayOfCampaign();
            Campaign campaign = new Campaign();
            campaign.setName("Summer Shoes " + System.currentTimeMillis());
            campaign.setDescription("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.
            campaign.setBudgetId(budgetIds.getLongs().size() > 0 ? budgetIds.getLongs().get(0) : 0L);
            campaign.setDailyBudget(budgetIds.getLongs().size() > 0 ? 0.0 : 50.0);
            campaign.setBudgetType(BudgetLimitType.DAILY_BUDGET_STANDARD);
            campaign.setTimeZone("PacificTimeUSCanadaTijuana");
             
            // You can set your campaign bid strategy to Enhanced CPC (EnhancedCpcBiddingScheme) 
            // and then, at any time, set an individual ad group or keyword bid strategy to 
            // Manual CPC (ManualCpcBiddingScheme).
            // For campaigns you can use either of the EnhancedCpcBiddingScheme or ManualCpcBiddingScheme objects. 
            // If you do not set this element, then ManualCpcBiddingScheme is used by default.
            campaign.setBiddingScheme(new EnhancedCpcBiddingScheme());
             
            // Used with FinalUrls shown in the expanded text ads that we will add below.
            campaign.setTrackingUrlTemplate(
                "http://tracker.example.com/?season={_season}&promocode={_promocode}&u={lpurl}");

            campaigns.getCampaigns().add(campaign);

            // Specify an ad group. 

            ArrayOfAdGroup adGroups = new ArrayOfAdGroup();
            AdGroup adGroup = new AdGroup();
            adGroup.setName("Women's Red Shoes");
            adGroup.setStartDate(null);
            Calendar calendar = Calendar.getInstance();
            adGroup.setEndDate(new com.microsoft.bingads.v12.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);
            adGroup.setLanguage("English");
            
            // For ad groups you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
            // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
            adGroup.setBiddingScheme(new ManualCpcBiddingScheme());

            // Applicable for all audiences that are associated with this ad group. Set TargetAndBid to True 
            // if you want to show ads only to people included in the remarketing list, with the option to change
            // the bid amount. 
            ArrayOfSetting settings = new ArrayOfSetting();
            TargetSetting targetSetting = new TargetSetting();
            ArrayOfTargetSettingDetail targetSettingDetails = new ArrayOfTargetSettingDetail();
            TargetSettingDetail adGroupAudienceTargetSettingDetail = new TargetSettingDetail();
            adGroupAudienceTargetSettingDetail.setCriterionTypeGroup(CriterionTypeGroup.AUDIENCE);
            adGroupAudienceTargetSettingDetail.setTargetAndBid(Boolean.TRUE);
            targetSettingDetails.getTargetSettingDetails().add(adGroupAudienceTargetSettingDetail);
            targetSetting.setDetails(targetSettingDetails);
            settings.getSettings().add(targetSetting);
            adGroup.setSettings(settings);

            adGroups.getAdGroups().add(adGroup);

            // In this example only the second keyword should succeed. The Text of the first keyword exceeds the limit,
            // and the third keyword is a duplicate of the second keyword. 

            ArrayOfKeyword keywords = new ArrayOfKeyword();

            Keyword keyword1 = new Keyword();
            keyword1.setBid(new Bid());
            keyword1.getBid().setAmount(0.47);
            keyword1.setParam2("10% Off");
            keyword1.setMatchType(MatchType.BROAD);
            keyword1.setText("Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes " +
                             "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes " +
                             "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes");
            // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
            // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
            keyword1.setBiddingScheme(new InheritFromParentBiddingScheme());
            keywords.getKeywords().add(keyword1);

            Keyword keyword2 = new Keyword();
            keyword2.setBid(new Bid());
            keyword2.getBid().setAmount(0.47);
            keyword2.setParam2("10% Off");
            keyword2.setMatchType(MatchType.PHRASE);
            keyword2.setText("Brand-A Shoes");
            // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
            // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
            keyword2.setBiddingScheme(new InheritFromParentBiddingScheme());
            keywords.getKeywords().add(keyword2);

            Keyword keyword3 = new Keyword();
            keyword3.setBid(new Bid());
            keyword3.getBid().setAmount(0.47);
            keyword3.setParam2("10% Off");
            keyword3.setMatchType(MatchType.PHRASE);
            keyword3.setText("Brand-A Shoes");
            // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
            // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
            keyword3.setBiddingScheme(new InheritFromParentBiddingScheme());
            keywords.getKeywords().add(keyword3);


            // In this example only the first 3 ads should succeed. 
            // The TitlePart2 of the fourth ad is empty and not valid,
            // and the fifth ad is a duplicate of the second ad. 

            ArrayOfAd ads = new ArrayOfAd();

            for(int i=0; i < 5; i++){
                ExpandedTextAd expandedTextAd = new ExpandedTextAd();
                expandedTextAd.setTitlePart1("Contoso");
                expandedTextAd.setTitlePart2("Fast & Easy Setup");
                expandedTextAd.setText("Find New Customers & Increase Sales! Start Advertising on Contoso Today.");
                expandedTextAd.setPath1("seattle");
                expandedTextAd.setPath2("shoe sale");

                // With FinalUrls you can separate the tracking template, custom parameters, and 
                // landing page URLs. 
                com.microsoft.bingads.v12.campaignmanagement.ArrayOfstring finalUrls = new com.microsoft.bingads.v12.campaignmanagement.ArrayOfstring();
                finalUrls.getStrings().add("http://www.contoso.com/womenshoesale");
                expandedTextAd.setFinalUrls(finalUrls);

                // Final Mobile URLs can also be used if you want to direct the user to a different page 
                // for mobile devices.
                com.microsoft.bingads.v12.campaignmanagement.ArrayOfstring finalMobileUrls = new com.microsoft.bingads.v12.campaignmanagement.ArrayOfstring();
                finalMobileUrls.getStrings().add("http://mobile.contoso.com/womenshoesale");
                expandedTextAd.setFinalMobileUrls(finalMobileUrls);

                // You could use a tracking template which would override the campaign level
                // tracking template. Tracking templates defined for lower level entities 
                // override those set for higher level entities.
                // In this example we are using the campaign level tracking template.
                expandedTextAd.setTrackingUrlTemplate(null);

                // Set custom parameters that are specific to this ad, 
                // and can be used by the ad, ad group, campaign, or account level tracking template. 
                // In this example we are using the campaign level tracking template.
                CustomParameters urlCustomParameters = new CustomParameters();
                CustomParameter customParameter1 = new CustomParameter();
                customParameter1.setKey("promoCode");
                customParameter1.setValue("PROMO" + (i+1));
                ArrayOfCustomParameter customParameters = new ArrayOfCustomParameter();
                customParameters.getCustomParameters().add(customParameter1);
                CustomParameter customParameter2 = new CustomParameter();
                customParameter2.setKey("season");
                customParameter2.setValue("summer");
                customParameters.getCustomParameters().add(customParameter2);
                urlCustomParameters.setParameters(customParameters);
                expandedTextAd.setUrlCustomParameters(urlCustomParameters);

                ads.getAds().add(expandedTextAd);
            }

            ((ExpandedTextAd)(ads.getAds().get(1))).setTitlePart2("Quick & Easy Setup");
            ((ExpandedTextAd)(ads.getAds().get(2))).setTitlePart2("Fast & Simple Setup");
            ((ExpandedTextAd)(ads.getAds().get(3))).setTitlePart2("");
            ((ExpandedTextAd)(ads.getAds().get(4))).setTitlePart2("Quick & Easy Setup");


            // Add the campaign, ad group, keywords, and ads

            AddCampaignsResponse addCampaignsResponse = CampaignManagementExampleHelper.addCampaigns(
                    authorizationData.getAccountId(), 
                    campaigns,
                    false);
            ArrayOfNullableOflong nullableCampaignIds = addCampaignsResponse.getCampaignIds();
            ArrayOfBatchError campaignErrors = addCampaignsResponse.getPartialErrors();
            CampaignManagementExampleHelper.outputArrayOfNullableOflong(nullableCampaignIds);
            CampaignManagementExampleHelper.outputArrayOfBatchError(campaignErrors);

            AddAdGroupsResponse addAdGroupsResponse = CampaignManagementExampleHelper.addAdGroups(nullableCampaignIds.getLongs().get(0), adGroups, false);
            ArrayOfNullableOflong adGroupIds = addAdGroupsResponse.getAdGroupIds();
            ArrayOfBatchError adGroupErrors = addAdGroupsResponse.getPartialErrors();
            CampaignManagementExampleHelper.outputArrayOfNullableOflong(adGroupIds);
            CampaignManagementExampleHelper.outputArrayOfBatchError(adGroupErrors);

            AddKeywordsResponse addKeywordsResponse = CampaignManagementExampleHelper.addKeywords(adGroupIds.getLongs().get(0), keywords, false);
            ArrayOfNullableOflong keywordIds = addKeywordsResponse.getKeywordIds();
            ArrayOfBatchError keywordErrors = addKeywordsResponse.getPartialErrors();
            CampaignManagementExampleHelper.outputArrayOfNullableOflong(keywordIds);
            CampaignManagementExampleHelper.outputArrayOfBatchError(keywordErrors);

            AddAdsResponse addAdsResponse = CampaignManagementExampleHelper.addAds(adGroupIds.getLongs().get(0), ads);
            ArrayOfNullableOflong adIds = addAdsResponse.getAdIds();
            ArrayOfBatchError adErrors = addAdsResponse.getPartialErrors();
            CampaignManagementExampleHelper.outputArrayOfNullableOflong(adIds);
            CampaignManagementExampleHelper.outputArrayOfBatchError(adErrors);


            // Here is a simple example that updates the campaign budget.
            // If the campaign has a shared budget you cannot update the Campaign budget amount,
            // and you must instead update the amount in the Budget object. If you try to update 
            // the budget amount of a campaign that has a shared budget, the service will return 
            // the CampaignServiceCannotUpdateSharedBudget error code.
            
            ArrayList<CampaignType> campaignTypes = new ArrayList<CampaignType>();
            campaignTypes.add(CampaignType.DYNAMIC_SEARCH_ADS);
            campaignTypes.add(CampaignType.SHOPPING);
            campaignTypes.add(CampaignType.SEARCH);
                        
            ArrayOfCampaign getCampaigns = CampaignManagementExampleHelper.getCampaignsByAccountId(
                authorizationData.getAccountId(),
                campaignTypes).getCampaigns();

            ArrayOfCampaign updateCampaigns = new ArrayOfCampaign();
            ArrayOfBudget updateBudgets = new ArrayOfBudget();
            com.microsoft.bingads.v12.campaignmanagement.ArrayOflong campaignIds = new com.microsoft.bingads.v12.campaignmanagement.ArrayOflong();
            com.microsoft.bingads.v12.campaignmanagement.ArrayOflong getBudgetIds = new com.microsoft.bingads.v12.campaignmanagement.ArrayOflong();
            
            // Increase existing budgets by 20%
            for (Campaign getCampaign : getCampaigns.getCampaigns())
            {
                // If the campaign has a shared budget, let's add the budget ID to the list we will update later.
                if (getCampaign != null && getCampaign.getBudgetId() != null && getCampaign.getBudgetId() > 0)
                {
                    getBudgetIds.getLongs().add((long)getCampaign.getBudgetId());
                }
                // If the campaign has its own budget, let's add it to the list of campaigns to update later.
                else if(getCampaign != null)
                {
                    Campaign updateCampaign = new Campaign();
                    updateCampaign.setDailyBudget(getCampaign.getDailyBudget() * 1.2);
                    updateCampaign.setId(getCampaign.getId());
                    
                    updateCampaigns.getCampaigns().add(updateCampaign);
                }
            }

            // Update shared budgets in Budget objects.
            if (getBudgetIds.getLongs() != null && getBudgetIds.getLongs().size() > 0)
            {
                ArrayList<java.lang.Long> distinctBudgetIds = new ArrayList<java.lang.Long>(new HashSet<Long>(getBudgetIds.getLongs()));
                com.microsoft.bingads.v12.campaignmanagement.ArrayOflong getDistinctBudgetIds = new com.microsoft.bingads.v12.campaignmanagement.ArrayOflong();
                for(java.lang.Long id : distinctBudgetIds){
                    getDistinctBudgetIds.getLongs().add(id);
                }
                ArrayOfBudget getBudgets = CampaignManagementExampleHelper.getBudgetsByIds(getDistinctBudgetIds).getBudgets();

                outputStatusMessage("List of shared budgets BEFORE update:\n");
                for (Budget budget : getBudgets.getBudgets())
                {
                    outputStatusMessage("Budget:");
                    CampaignManagementExampleHelper.outputBudget(budget);
                }

                outputStatusMessage("List of campaigns that share each budget:\n");
                ArrayOfIdCollection getCampaignIdCollection = CampaignManagementExampleHelper.getCampaignIdsByBudgetIds(getDistinctBudgetIds).getCampaignIdCollection();
                for(int index = 0; index < getCampaignIdCollection.getIdCollections().size(); index++)
                {
                    outputStatusMessage(String.format("BudgetId: %s", getDistinctBudgetIds.getLongs().get(index)));
                    outputStatusMessage("Campaign Ids:");
                    if(getCampaignIdCollection.getIdCollections().get(index) != null)
                    {
                        for (java.lang.Long id : getCampaignIdCollection.getIdCollections().get(index).getIds().getLongs())
                        {
                            outputStatusMessage(String.format("\t%s", id));
                        }
                    }
                }

                for (Budget budget : getBudgets.getBudgets())
                {
                    if (budget != null)
                    {
                        // Increase budget by 20 %
                        budget.setAmount(new java.math.BigDecimal(budget.getAmount().doubleValue() * 1.2));
                        updateBudgets.getBudgets().add(budget);
                    }
                }
                CampaignManagementExampleHelper.updateBudgets(updateBudgets);

                getBudgets = CampaignManagementExampleHelper.getBudgetsByIds(getDistinctBudgetIds).getBudgets();

                outputStatusMessage("List of shared budgets AFTER update:\n");
                for (Budget budget : getBudgets.getBudgets())
                {
                    outputStatusMessage("Budget:");
                    CampaignManagementExampleHelper.outputBudget(budget);
                }
            }

            // Update unshared budgets in Campaign objects.
            if(updateCampaigns.getCampaigns() != null && updateCampaigns.getCampaigns().size() > 0)
            {
                // The UpdateCampaigns operation only accepts 100 Campaign objects per call. 
                // To simply the example we will update the first 100.
                int maxIndex = updateCampaigns.getCampaigns().size() < 100 ? updateCampaigns.getCampaigns().size() : 99;
                List<Campaign> campaignSubList = updateCampaigns.getCampaigns().subList(0, maxIndex);
                updateCampaigns = new ArrayOfCampaign();
                for (Campaign updateCampaign : campaignSubList){
                    updateCampaigns.getCampaigns().add(updateCampaign);
                    campaignIds.getLongs().add((long)updateCampaign.getId());
                }
                
                CampaignManagementExampleHelper.updateCampaigns(
                        authorizationData.getAccountId(), 
                        updateCampaigns,
                        false);
                                
                campaigns = CampaignManagementExampleHelper.getCampaignsByIds(authorizationData.getAccountId(),
                    campaignIds,
                    campaignTypes).getCampaigns();

                outputStatusMessage("List of campaigns with unshared budget AFTER budget update:\n");
                for (Campaign getCampaign : getCampaigns.getCampaigns())
                {
                    outputStatusMessage("Campaign:");
                    CampaignManagementExampleHelper.outputCampaign(getCampaign);
                }
            }

            // Update the Text for the 3 successfully created ads, and update some UrlCustomParameters.

            ArrayOfAd updateAds = new ArrayOfAd();

            ExpandedTextAd updateExpandedTextAd1 = new ExpandedTextAd();
            updateExpandedTextAd1.setId(adIds.getLongs().get(0));
            updateExpandedTextAd1.setText("Huge Savings on All Red Shoes.");
            // Set the UrlCustomParameters element to null or empty to retain any 
            // existing custom parameters.
            CustomParameters urlCustomParameters1 = null;
            updateExpandedTextAd1.setUrlCustomParameters(urlCustomParameters1);
            updateAds.getAds().add(updateExpandedTextAd1);

            ExpandedTextAd updateExpandedTextAd2 = new ExpandedTextAd();
            updateExpandedTextAd2.setId(adIds.getLongs().get(1));
            updateExpandedTextAd2.setText("Huge Savings on All Red Shoes.");
            // To remove all custom parameters, set the Parameters element of the 
            // CustomParameters object to null or empty.
            CustomParameters urlCustomParameters2 = new CustomParameters();
            ArrayOfCustomParameter customParameters2 = null;
            urlCustomParameters2.setParameters(customParameters2);
            updateExpandedTextAd2.setUrlCustomParameters(urlCustomParameters2);
            updateAds.getAds().add(updateExpandedTextAd2);

            ExpandedTextAd updateExpandedTextAd3 = new ExpandedTextAd();
            updateExpandedTextAd3.setId(adIds.getLongs().get(2));
            updateExpandedTextAd3.setText("Huge Savings on All Red Shoes.");
            // To remove a subset of custom parameters, specify the custom parameters that 
            // you want to keep in the Parameters element of the CustomParameters object.
            CustomParameters urlCustomParameters3 = new CustomParameters();
            CustomParameter customParameter3 = new CustomParameter();
            customParameter3.setKey("promoCode");
            customParameter3.setValue("updatedpromo");
            ArrayOfCustomParameter customParameters3 = new ArrayOfCustomParameter();
            customParameters3.getCustomParameters().add(customParameter3);
            urlCustomParameters3.setParameters(customParameters3);
            updateExpandedTextAd3.setUrlCustomParameters(urlCustomParameters3);
            updateAds.getAds().add(updateExpandedTextAd3);

            // As an exercise you can step through using the debugger and view the results.

            com.microsoft.bingads.v12.campaignmanagement.ArrayOflong updateAdGroupIds = new com.microsoft.bingads.v12.campaignmanagement.ArrayOflong();
            updateAdGroupIds.getLongs().add(adGroupIds.getLongs().get(0));

            ArrayOfAdType adTypes = new ArrayOfAdType();
            adTypes.getAdTypes().add(AdType.EXPANDED_TEXT);            
            GetAdsByAdGroupIdResponse getAdsByAdGroupIdResponse = CampaignManagementExampleHelper.getAdsByAdGroupId(
                    adGroupIds.getLongs().get(0), 
                    adTypes,
                    null);
            UpdateAdsResponse updateAdsResponse = CampaignManagementExampleHelper.updateAds(adGroupIds.getLongs().get(0), updateAds);
            getAdsByAdGroupIdResponse = CampaignManagementExampleHelper.getAdsByAdGroupId(
                    adGroupIds.getLongs().get(0), 
                    adTypes,
                    null);


            // Here is a simple example that updates the keyword bid to use the ad group bid.

            Keyword updateKeyword = new Keyword();
            updateKeyword.setId(keywordIds.getLongs().get(0));
            updateKeyword.setBid(new Bid());
            updateKeyword.getBid().setAmount(null);
            ArrayOfKeyword updateKeywords = new ArrayOfKeyword();
            updateKeywords.getKeywords().add(updateKeyword);

            // As an exercise you can step through using the debugger and view the results.

            com.microsoft.bingads.v12.campaignmanagement.ArrayOflong updateKeywordIds = new com.microsoft.bingads.v12.campaignmanagement.ArrayOflong();
            updateKeywordIds.getLongs().add(keywordIds.getLongs().get(0));
            
            GetKeywordsByAdGroupIdResponse getKeywordsByAdGroupIdResponse = CampaignManagementExampleHelper.getKeywordsByAdGroupId(adGroupIds.getLongs().get(0));
            UpdateKeywordsResponse updateKeywordsResponse = CampaignManagementExampleHelper.updateKeywords(adGroupIds.getLongs().get(0), updateKeywords, false);
            getKeywordsByAdGroupIdResponse = CampaignManagementExampleHelper.getKeywordsByAdGroupId(adGroupIds.getLongs().get(0));      


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

            campaignIds = new com.microsoft.bingads.v12.campaignmanagement.ArrayOflong();
            campaignIds.getLongs().add(nullableCampaignIds.getLongs().get(0));
            CampaignManagementExampleHelper.deleteCampaigns(authorizationData.getAccountId(), campaignIds);
            outputStatusMessage(String.format("Deleted CampaignId %d\n", nullableCampaignIds.getLongs().get(0)));
            
            // This sample will attempt to delete the budget that was created above.
            if(budgetIds.getLongs().size() > 0){
                com.microsoft.bingads.v12.campaignmanagement.ArrayOflong deleteBudgetIds = 
                        new com.microsoft.bingads.v12.campaignmanagement.ArrayOflong();
                deleteBudgetIds.getLongs().add(budgetIds.getLongs().get(0));
                CampaignManagementExampleHelper.deleteBudgets(deleteBudgetIds);
                outputStatusMessage(String.format("Deleted BudgetId %d\n", deleteBudgetIds.getLongs().get(0)));
            }
            
            outputStatusMessage("Program execution completed\n"); 

        } 
        catch (Exception ex) {
            String faultXml = BingAdsExceptionHelper.getBingAdsExceptionFaultXml(ex, System.out);
            String message = BingAdsExceptionHelper.handleBingAdsSDKException(ex, System.out);
            ex.printStackTrace();
        }
    }    
 }
<?php

namespace Microsoft\BingAds\Samples\V12;

// 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__ . "/CampaignManagementExampleHelper.php";

use SoapVar;
use SoapFault;
use Exception;

//Specify the Microsoft\BingAds\V12\CampaignManagement classes that will be used.
use Microsoft\BingAds\V12\CampaignManagement\Budget;
use Microsoft\BingAds\V12\CampaignManagement\Campaign;
use Microsoft\BingAds\V12\CampaignManagement\CampaignType;
use Microsoft\BingAds\V12\CampaignManagement\IdCollection;
use Microsoft\BingAds\V12\CampaignManagement\AdGroup;
use Microsoft\BingAds\V12\CampaignManagement\Keyword;
use Microsoft\BingAds\V12\CampaignManagement\Ad;
use Microsoft\BingAds\V12\CampaignManagement\AdType;
use Microsoft\BingAds\V12\CampaignManagement\AdAdditionalField;
use Microsoft\BingAds\V12\CampaignManagement\CampaignAdditionalField;
use Microsoft\BingAds\V12\CampaignManagement\ExpandedTextAd;
use Microsoft\BingAds\V12\CampaignManagement\Bid;
use Microsoft\BingAds\V12\CampaignManagement\BiddingScheme;
use Microsoft\BingAds\V12\CampaignManagement\MatchType;
use Microsoft\BingAds\V12\CampaignManagement\BudgetLimitType;
use Microsoft\BingAds\V12\CampaignManagement\Date;
use Microsoft\BingAds\V12\CampaignManagement\CustomParameters;
use Microsoft\BingAds\V12\CampaignManagement\CustomParameter;
use Microsoft\BingAds\V12\CampaignManagement\EnhancedCpcBiddingScheme;
use Microsoft\BingAds\V12\CampaignManagement\InheritFromParentBiddingScheme;
use Microsoft\BingAds\V12\CampaignManagement\ManualCpcBiddingScheme;
use Microsoft\BingAds\V12\CampaignManagement\Setting;
use Microsoft\BingAds\V12\CampaignManagement\TargetSettingDetail;
use Microsoft\BingAds\V12\CampaignManagement\TargetSetting;
use Microsoft\BingAds\V12\CampaignManagement\CriterionTypeGroup;

// 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\V12\AuthHelper;
use Microsoft\BingAds\Samples\V12\CampaignManagementExampleHelper;

$GLOBALS['AuthorizationData'] = null;
$GLOBALS['Proxy'] = null;
$GLOBALS['CampaignManagementProxy'] = null; 

// Disable WSDL caching.

ini_set("soap.wsdl_cache_enabled", "0");
ini_set("soap.wsdl_cache_ttl", "0");
    
try
{
    // Authenticate for Bing Ads services with a Microsoft Account.
    
    AuthHelper::Authenticate();

    $GLOBALS['CampaignManagementProxy'] = new ServiceClient(
        ServiceClientType::CampaignManagementVersion12, 
        $GLOBALS['AuthorizationData'], 
        AuthHelper::GetApiEnvironment());

    // Let's create a new budget and share it with a new campaign.

    $budgetIds = array();
    $budgets = array();
    $budget = new Budget();
    $budget->Amount = 50;
    $budget->BudgetType = BudgetLimitType::DailyBudgetStandard;
    $budget->Name = "My Shared Budget " . $_SERVER['REQUEST_TIME'];
    
    $budgets[] = $budget;
    $budgetIds = CampaignManagementExampleHelper::AddBudgets($budgets)->BudgetIds;
                
    // Specify one or more campaigns.
    
    $campaigns = array();
   
    $campaign = new Campaign();
    $campaign->Name = "Winter Clothing " . $_SERVER['REQUEST_TIME'];
    $campaign->Description = "Winter clothing 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.
    $campaign->BudgetId = count($budgetIds) > 0 ? $budgetIds->long[0] : null;
    $campaign->DailyBudget = count($budgetIds) > 0 ? 0 : 50;
    $campaign->BudgetType = BudgetLimitType::DailyBudgetStandard;
    $campaign->TimeZone = "PacificTimeUSCanadaTijuana";
    
    // You can set your campaign bid strategy to Enhanced CPC (EnhancedCpcBiddingScheme) 
    // and then, at any time, set an individual ad group or keyword bid strategy to 
    // Manual CPC (ManualCpcBiddingScheme).
    // For campaigns you can use either of the EnhancedCpcBiddingScheme or ManualCpcBiddingScheme objects. 
    // If you do not set this element, then ManualCpcBiddingScheme is used by default.
    $biddingScheme = new EnhancedCpcBiddingScheme();
    $campaign->BiddingScheme = new SoapVar(
        $biddingScheme, 
        SOAP_ENC_OBJECT, 
        'EnhancedCpcBiddingScheme', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace());
        
    // Used with FinalUrls shown in the ads that we will add below.
    $campaign->TrackingUrlTemplate = 
       "http://tracker.example.com/?season={_season}&promocode={_promocode}&u={lpurl}";

    $campaigns[] = $campaign;
    
    // Specify one or more ad groups.

    $adGroups = array();

    date_default_timezone_set('UTC');
    $endDate = new Date();
    $endDate->Day = 31;
    $endDate->Month = 12;
    $endDate->Year = date("Y");

    $adGroup = new AdGroup();
    $adGroup->Name = "Women's Heated Ski Glove Sale";
    $adGroup->StartDate = null;
    $adGroup->EndDate = $endDate;
    $adGroup->CpcBid = new Bid();
    $adGroup->CpcBid->Amount = 0.07;
    $adGroup->Language = "English";
    
    // For ad groups you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
    // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
    $biddingScheme = new ManualCpcBiddingScheme();
    $adGroup->BiddingScheme = new SoapVar(
        $biddingScheme, 
        SOAP_ENC_OBJECT, 
        'ManualCpcBiddingScheme', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace());
    
    // Applicable for all audiences that are associated with this ad group. Set TargetAndBid to True 
    // if you want to show ads only to people included in the remarketing list, with the option to change
    // the bid amount. 
    $adGroupSettings = array();
    $adGroupTargetSetting = new TargetSetting();
    $adGroupAudienceTargetSettingDetail = new TargetSettingDetail();
    $adGroupAudienceTargetSettingDetail->CriterionTypeGroup = CriterionTypeGroup::Audience;
    $adGroupAudienceTargetSettingDetail->TargetAndBid = True;
    $adGroupTargetSetting->Details = array();
    $adGroupTargetSetting->Details[] = $adGroupAudienceTargetSettingDetail;
    $encodedAdGroupTargetSetting = new SoapVar(
        $adGroupTargetSetting, 
        SOAP_ENC_OBJECT, 
        'TargetSetting', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace());
    $adGroupSettings[] = $encodedAdGroupTargetSetting;
    $adGroup->Settings=$adGroupSettings;
    
    $adGroups[] = $adGroup;

    // In this example only the second keyword should succeed. The Text of the first keyword exceeds the limit,
    // and the third keyword is a duplicate of the second keyword. 

    $keywords = array();

    $keyword = new Keyword();
    $keyword->Bid = new Bid();
    $keyword->Bid->Amount = 0.47;
    $keyword->Param2 = "10% Off";
    $keyword->MatchType = MatchType::Broad;
    $keyword->Text = "Brand-A Gloves Brand-A Gloves Brand-A Gloves Brand-A Gloves Brand-A Gloves " .
                     "Brand-A Gloves Brand-A Gloves Brand-A Gloves Brand-A Gloves Brand-A Gloves " .
                     "Brand-A Gloves Brand-A Gloves Brand-A Gloves Brand-A Gloves Brand-A Gloves";
    // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
    // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
    $biddingScheme = new InheritFromParentBiddingScheme();
    $keyword->BiddingScheme = new SoapVar(
        $biddingScheme, 
        SOAP_ENC_OBJECT, 
        'InheritFromParentBiddingScheme', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace());
    $keywords[] = $keyword;

    $keyword = new Keyword();
    $keyword->Bid = new Bid();
    $keyword->Bid->Amount = 0.47;
    $keyword->Param2 = "10% Off";
    $keyword->MatchType = MatchType::Phrase;
    $keyword->Text = "Brand-A Gloves";
    // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
    // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
    $biddingScheme = new InheritFromParentBiddingScheme();
    $keyword->BiddingScheme = new SoapVar(
        $biddingScheme, 
        SOAP_ENC_OBJECT, 
        'InheritFromParentBiddingScheme', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace());
    $keywords[] = $keyword;

    $keyword = new Keyword();
    $keyword->Bid = new Bid();
    $keyword->Bid->Amount = 0.47;
    $keyword->Param2 = "10% Off";
    $keyword->MatchType = MatchType::Phrase;
    $keyword->Text = "Brand-A Gloves";
    // For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
    // If you do not set this element, then InheritFromParentBiddingScheme is used by default.
    $biddingScheme = new InheritFromParentBiddingScheme();
    $keyword->BiddingScheme = new SoapVar(
        $biddingScheme, 
        SOAP_ENC_OBJECT, 
        'InheritFromParentBiddingScheme', 
        $GLOBALS['CampaignManagementProxy']->GetNamespace());
    $keywords[] = $keyword;

    // In this example only the first 3 ads should succeed. 
    // The TitlePart2 of the fourth ad is empty and not valid,
    // and the fifth ad is a duplicate of the second ad. 

    $ads = array();

    for ($index = 0; $index < 5; $index++)
    {
        $expandedTextAd = new ExpandedTextAd();
        $expandedTextAd->TitlePart1 = "Contoso";
        $expandedTextAd->TitlePart2 = "Fast & Easy Setup";
        $expandedTextAd->Text = "Find New Customers & Increase Sales! Start Advertising on Contoso Today.";
        $expandedTextAd->Path1 = "seattle";
        $expandedTextAd->Path2 = "shoe sale";

        // With FinalUrls you can separate the tracking template, custom parameters, and 
        // landing page URLs. 

        $expandedTextAd->FinalUrls = array();
        $expandedTextAd->FinalUrls[] = "http://www.contoso.com/womenshoesale";

        // Final Mobile URLs can also be used if you want to direct the user to a different page 
        // for mobile devices.
        $expandedTextAd->FinalMobileUrls = array();
        $expandedTextAd->FinalMobileUrls[] = "http://mobile.contoso.com/womenshoesale";

        // Set custom parameters that are specific to this ad.
        $expandedTextAd->UrlCustomParameters = new CustomParameters();
        $expandedTextAd->UrlCustomParameters->Parameters = array();
        $customParameter1 = new CustomParameter();
        $customParameter1->Key = "promoCode";
        $customParameter1->Value = "PROMO" . ($index+1);
        $expandedTextAd->UrlCustomParameters->Parameters[] = $customParameter1;
        $customParameter2 = new CustomParameter();
        $customParameter2->Key = "season";
        $customParameter2->Value = "summer";
        $expandedTextAd->UrlCustomParameters->Parameters[] = $customParameter2;   

        $ads[] = new SoapVar($expandedTextAd, SOAP_ENC_OBJECT, 'ExpandedTextAd', $GLOBALS['CampaignManagementProxy']->GetNamespace());
    }

    $ads[1]->enc_value->TitlePart2 = "Quick & Easy Setup";
    $ads[2]->enc_value->TitlePart2 = "Fast & Simple Setup";
    $ads[3]->enc_value->TitlePart2 = "";
    $ads[4]->enc_value->TitlePart2 = "Quick & Easy Setup";

    // Add the campaign, ad group, keywords, and ads
    
    print "AddCampaigns\n";
    $addCampaignsResponse = CampaignManagementExampleHelper::AddCampaigns(
        $GLOBALS['AuthorizationData']->AccountId, 
        $campaigns,
        false);
    $nillableCampaignIds = $addCampaignsResponse->CampaignIds;
    CampaignManagementExampleHelper::OutputArrayOfLong($nillableCampaignIds);
    if(isset($addCampaignsResponse->PartialErrors->BatchError)){
        CampaignManagementExampleHelper::OutputArrayOfBatchError($addCampaignsResponse->PartialErrors);
    }

    print "AddAdGroups\n";
    $addAdGroupsResponse = CampaignManagementExampleHelper::AddAdGroups(
        $nillableCampaignIds->long[0], 
        $adGroups,
        null);
    $nillableAdGroupIds = $addAdGroupsResponse->AdGroupIds;
    CampaignManagementExampleHelper::OutputArrayOfLong($nillableAdGroupIds);
    if(isset($addAdGroupsResponse->PartialErrors->BatchError)){
        CampaignManagementExampleHelper::OutputArrayOfBatchError($addAdGroupsResponse->PartialErrors);
    }

    print "AddKeywords\n";
    $addKeywordsResponse = CampaignManagementExampleHelper::AddKeywords(
        $nillableAdGroupIds->long[0], 
        $keywords,
        null);
    $nillableKeywordIds = $addKeywordsResponse->KeywordIds;
    CampaignManagementExampleHelper::OutputArrayOfLong($nillableKeywordIds);
    if(isset($addKeywordsResponse->PartialErrors->BatchError)){
        CampaignManagementExampleHelper::OutputArrayOfBatchError($addKeywordsResponse->PartialErrors);
    }

    print "AddAds\n";
    $addAdsResponse = CampaignManagementExampleHelper::AddAds($nillableAdGroupIds->long[0], $ads);
    $nillableAdIds = $addAdsResponse->AdIds;
    CampaignManagementExampleHelper::OutputArrayOfLong($nillableAdIds);
    if(isset($addAdsResponse->PartialErrors->BatchError)){
        CampaignManagementExampleHelper::OutputArrayOfBatchError($addAdsResponse->PartialErrors);
    }
          
    
    // Here is a simple example that updates the campaign budget.
    // If the campaign has a shared budget you cannot update the Campaign budget amount,
    // and you must instead update the amount in the Budget object. If you try to update 
    // the budget amount of a campaign that has a shared budget, the service will return 
    // the CampaignServiceCannotUpdateSharedBudget error code.

    $getCampaigns = CampaignManagementExampleHelper::GetCampaignsByAccountId(
            $GLOBALS['AuthorizationData']->AccountId, 
            AuthHelper::CampaignTypes,
            CampaignAdditionalField::ExperimentId
        )->Campaigns;

    $updateCampaigns = array();
    $updateBudgets = array();
    $getCampaignIds = array();
    $getBudgetIds = array();

    // Increase existing budgets by 20%
    foreach ($getCampaigns->Campaign as $campaign)
    {
        // If the campaign has a shared budget, let's add the budget ID to the list we will update later.
        if (!empty($campaign) && isset($campaign->BudgetId) && $campaign->BudgetId > 0)
        {
            $getBudgetIds[] = $campaign->BudgetId;
        }
    }

    // Update shared budgets in Budget objects.
    if (!empty($getBudgetIds))
    {
        // The UpdateBudgets operation only accepts 100 Budget objects per call. 
        // To simply the example we will update the first 100.
        $getUniqueBudgetIds = array_unique($getBudgetIds, SORT_REGULAR);
        $top100BudgetIds = array_slice($getUniqueBudgetIds, 0, 100);
        $getBudgets = CampaignManagementExampleHelper::GetBudgetsByIds($top100BudgetIds)->Budgets;

        print("List of shared budgets BEFORE update:\n\n");
        foreach ($getBudgets->Budget as $budget)
        {
            print("Budget:\n");
            CampaignManagementExampleHelper::OutputBudget($budget);
        }

        print("List of campaigns that share each budget:\n\n");
        $getCampaignIdCollection = CampaignManagementExampleHelper::GetCampaignIdsByBudgetIds($top100BudgetIds)->CampaignIdCollection;
        for($index = 0; $index < count($getCampaignIdCollection); $index++)
        {
            printf("BudgetId: %s\n", $top100BudgetIds[$index]);
            print("Campaign Ids:\n");
            if(!empty($getCampaignIdCollection->IdCollection[$index]))
            {
                foreach ($getCampaignIdCollection->IdCollection[$index]->Ids->long as $id)
                {
                    printf("\t%s\n", $id);
                }
            }
            print("\n");
        }

        foreach ($getBudgets->Budget as $budget)
        {
            if (!empty($budget))
            {
                // Increase budget by 20 %
                $budget->Amount *= 1.2;
                $updateBudgets[] = $budget;
            }
        }
        CampaignManagementExampleHelper::UpdateBudgets($updateBudgets);

        $getBudgets = CampaignManagementExampleHelper::GetBudgetsByIds($top100BudgetIds)->Budgets;

        print("List of shared budgets AFTER update:\n\n");
        foreach ($getBudgets->Budget as $budget)
        {
            print("Budget:\n");
            CampaignManagementExampleHelper::OutputBudget($budget);
        }
    }

    // Update unshared budgets in Campaign objects.
    if(!empty($getCampaigns))
    {
        print("List of 100 campaigns BEFORE update:\n");
        // The UpdateCampaigns operation only accepts 100 Campaign objects per call. 
        // To simply the example we will update the first 100.
        $index=0;
        while($index < 100 && $index < count($getCampaigns))
        {
            $campaign = $getCampaigns->Campaign[$index];
            print("Campaign:\n");
            CampaignManagementExampleHelper::OutputCampaign($campaign);

            $updateCampaign = new Campaign();
            $updateCampaign->Id = $campaign->Id;
                        
            // If the campaign has a shared budget, we can update other properties of the campaign, 
            // but cannot update the budget via Campaign object.
            if (isset($campaign->BudgetId) && $campaign->BudgetId > 0)
            {
                $updateCampaign->Name = $campaign->Name . $_SERVER['REQUEST_TIME'];
            }        
            else
            {
                // Increase budget by 20 %
                $updateCampaign->BudgetType = $campaign->BudgetType;
                $updateCampaign->DailyBudget = $campaign->DailyBudget * 1.2;
            }
            
            $getCampaignIds[] = $updateCampaign->Id;
            $updateCampaigns[] = $updateCampaign;
            $index++;
        }
        
        CampaignManagementExampleHelper::UpdateCampaigns(
            $GLOBALS['AuthorizationData']->AccountId, 
            $updateCampaigns,
            false);

        $getCampaigns = CampaignManagementExampleHelper::GetCampaignsByIds(
            $GLOBALS['AuthorizationData']->AccountId, 
            $getCampaignIds, 
            AuthHelper::CampaignTypes,
            CampaignAdditionalField::ExperimentId
        )->Campaigns;

        print("List of campaigns AFTER update:\n");
        foreach ($getCampaigns->Campaign as $campaign)
        {
            print("Campaign:\n");
            CampaignManagementExampleHelper::OutputCampaign($campaign);
        }
    }
    
    
    // Update the Text for the 3 successfully created ads, and update some UrlCustomParameters.

    $updateAds = array();

    $updateExpandedTextAd = new ExpandedTextAd();
    $updateExpandedTextAd->Id = $nillableAdIds->long[0];
    $updateExpandedTextAd->Text = "Huge Savings on All Red Shoes.";
    // Set the UrlCustomParameters element to null or empty to retain any 
    // existing custom parameters.
    $updateExpandedTextAd->UrlCustomParameters = null;
    $updateAds[] = new SoapVar($updateExpandedTextAd, SOAP_ENC_OBJECT, 'ExpandedTextAd', $GLOBALS['CampaignManagementProxy']->GetNamespace());

    $updateExpandedTextAd = new ExpandedTextAd();
    $updateExpandedTextAd->Id = $nillableAdIds->long[1];
    $updateExpandedTextAd->Text = "Huge Savings on All Red Shoes.";
    // To remove all custom parameters, set the Parameters element of the  
    // CustomParameters object to null or empty.
    $updateExpandedTextAd->UrlCustomParameters = new CustomParameters();
    $updateExpandedTextAd->UrlCustomParameters->Parameters = null;
    $updateAds[] = new SoapVar($updateExpandedTextAd, SOAP_ENC_OBJECT, 'ExpandedTextAd', $GLOBALS['CampaignManagementProxy']->GetNamespace());
 
    $updateExpandedTextAd = new ExpandedTextAd();
    $updateExpandedTextAd->Id = $nillableAdIds->long[2];
    $updateExpandedTextAd->Text = "Huge Savings on All Red Shoes.";
    // To remove a subset of custom parameters, specify the custom parameters that 
    // you want to keep in the Parameters element of the CustomParameters object.
    $updateExpandedTextAd->UrlCustomParameters = new CustomParameters();
    $updateExpandedTextAd->UrlCustomParameters->Parameters = array();
    $updateCustomParameter = new CustomParameter();
    $updateCustomParameter->Key = "promoCode";
    $updateCustomParameter->Value = "updatedpromo";
    $updateExpandedTextAd->UrlCustomParameters->Parameters[] = $updateCustomParameter;
    $updateAds[] = new SoapVar($updateExpandedTextAd, SOAP_ENC_OBJECT, 'ExpandedTextAd', $GLOBALS['CampaignManagementProxy']->GetNamespace());

    // As an exercise you can view the results before and after update.

    $adTypes = array(AdType::AppInstall, AdType::DynamicSearch, AdType::ExpandedText, AdType::Product, AdType::Text);
    $adAdditionalFields = array(AdAdditionalField::TextPart2, AdAdditionalField::TitlePart3);
    $ads = CampaignManagementExampleHelper::GetAdsByAdGroupId(
        $nillableAdGroupIds->long[0], 
        $adTypes,
        $adAdditionalFields);

    if(isset($ads->Ads)){
        CampaignManagementExampleHelper::OutputArrayOfAd($ads->Ads);
    }    

    $updateAdsResponse = CampaignManagementExampleHelper::UpdateAds($nillableAdGroupIds->long[0], $updateAds);
    $ads = CampaignManagementExampleHelper::GetAdsByAdGroupId(
        $nillableAdGroupIds->long[0], 
        $adTypes,
        $adAdditionalFields);
    if(isset($ads->Ads)){
        CampaignManagementExampleHelper::OutputArrayOfAd($ads->Ads);
    }  

    // Here is a simple example that updates the keyword bid to use the ad group bid

    $updateKeywords = array();
    $updateKeyword = new Keyword();
    $updateKeyword->Id = $nillableKeywordIds->long[1];
    // Set Bid.Amount null (new empty Bid) to use the ad group bid.
    // If the Bid property is null, your keyword bid will not be updated.
    $updateKeyword->Bid = new Bid();
    $updateKeywords[] = $updateKeyword;

    // As an exercise you can view the results before and after update.

    $keywords = CampaignManagementExampleHelper::GetKeywordsByAdGroupId($nillableAdGroupIds->long[0], null);
    if(isset($keywords->Keywords)){
        CampaignManagementExampleHelper::OutputArrayOfKeyword($keywords->Keywords);
    }  

    $updateKeywordsResponse = CampaignManagementExampleHelper::UpdateKeywords(
        $nillableAdGroupIds->long[0], 
        $updateKeywords,
        null);
    $keywords = CampaignManagementExampleHelper::GetKeywordsByAdGroupId($nillableAdGroupIds->long[0], null);
    if(isset($keywords->Keywords)){
        CampaignManagementExampleHelper::OutputArrayOfKeyword($keywords->Keywords);
    }  
        
    // As an exercise you can delete the keyword
    CampaignManagementExampleHelper::DeleteKeywords($nillableAdGroupIds->long[0], array($nillableKeywordIds->long[1]));

    // Delete the campaign, budget, ad group, keyword, and ad that were previously added. 
    // You should remove these lines if you want to view the added entities in the 
    // Bing Ads web application or another tool.
    
    CampaignManagementExampleHelper::DeleteBudgets(array($budgetIds->long[0]));
    printf("Deleted BudgetId %d\n\n", $budgetIds->long[0]);

    CampaignManagementExampleHelper::DeleteCampaigns($GLOBALS['AuthorizationData']->AccountId, array($nillableCampaignIds->long[0]));
    printf("Deleted CampaignId %d\n\n", $nillableCampaignIds->long[0]);
}
catch (SoapFault $e)
{
    print "\nLast SOAP request/response:\n";
    printf("Fault Code: %s\nFault String: %s\n", $e->faultcode, $e->faultstring);
    print $GLOBALS['Proxy']->GetWsdl() . "\n";
    print $GLOBALS['Proxy']->GetService()->__getLastRequest()."\n";
    print $GLOBALS['Proxy']->GetService()->__getLastResponse()."\n";
    
    if (isset($e->detail->AdApiFaultDetail))
    {
        CampaignManagementExampleHelper::OutputAdApiFaultDetail($e->detail->AdApiFaultDetail);
        
    }
    elseif (isset($e->detail->ApiFaultDetail))
    {
        CampaignManagementExampleHelper::OutputApiFaultDetail($e->detail->ApiFaultDetail);
    }
    elseif (isset($e->detail->EditorialApiFaultDetail))
    {
        CampaignManagementExampleHelper::OutputEditorialApiFaultDetail($e->detail->EditorialApiFaultDetail);
    }
}
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 campaignmanagement_example_helper import *

# You must provide credentials in auth_helper.py.

def main(authorization_data):

    try:
        # Let's create a new budget and share it with a new campaign.
                
        budgets = campaign_service.factory.create('ArrayOfBudget')
        budget=set_elements_to_none(campaign_service.factory.create('Budget'))
        budget.Amount = 50
        budget.BudgetType = 'DailyBudgetStandard'
        budget.Name = "My Shared Budget " + strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
        budgets.Budget.append(budget)
                    
        add_budgets_response = campaign_service.AddBudgets(budgets)
        budget_ids={
            'long': add_budgets_response.BudgetIds['long'] if add_budgets_response.BudgetIds['long'] else None
        }
        output_status_message("Budget Ids:")
        output_array_of_long(budget_ids)

        # Specify one or more campaigns.
        
        campaigns=campaign_service.factory.create('ArrayOfCampaign')
        campaign=set_elements_to_none(campaign_service.factory.create('Campaign'))
        campaign.Name="Summer Shoes " + strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
        campaign.Description="Summer 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.
        campaign.BudgetId = budget_ids['long'][0] if len(budget_ids['long']) > 0 else None
        campaign.DailyBudget = None if len(budget_ids['long']) > 0 else 50
        campaign.BudgetType = 'DailyBudgetStandard'

        campaign.TimeZone='PacificTimeUSCanadaTijuana'
        campaign.Status='Paused'

        # You can set your campaign bid strategy to Enhanced CPC (EnhancedCpcBiddingScheme) 
        # and then, at any time, set an individual ad group or keyword bid strategy to 
        # Manual CPC (ManualCpcBiddingScheme).
        # For campaigns you can use either of the EnhancedCpcBiddingScheme or ManualCpcBiddingScheme objects. 
        # If you do not set this element, then ManualCpcBiddingScheme is used by default.
        campaign_bidding_scheme=set_elements_to_none(campaign_service.factory.create('EnhancedCpcBiddingScheme'))
        campaign.BiddingScheme=campaign_bidding_scheme

        # Used with FinalUrls shown in the expanded text ads that we will add below.
        campaign.TrackingUrlTemplate="http://tracker.example.com/?season={_season}&promocode={_promocode}&u={lpurl}"
        
        campaigns.Campaign.append(campaign)

        ad_groups=campaign_service.factory.create('ArrayOfAdGroup')
        ad_group=set_elements_to_none(campaign_service.factory.create('AdGroup'))
        ad_group.Name="Women's Red Shoes"
        ad_group.Network='OwnedAndOperatedAndSyndicatedSearch'
        ad_group.Status='Paused'
        end_date=campaign_service.factory.create('Date')
        end_date.Day=31
        end_date.Month=12
        end_date.Year=strftime("%Y", gmtime())
        ad_group.EndDate=end_date
        cpc_bid=campaign_service.factory.create('Bid')
        cpc_bid.Amount=0.09
        ad_group.CpcBid=cpc_bid
        ad_group.Language='English'

        # Applicable for all audiences that are associated with this ad group. Set TargetAndBid to True 
        # if you want to show ads only to people included in the remarketing list, with the option to change
        # the bid amount. 
        ad_group_settings=campaign_service.factory.create('ArrayOfSetting')
        ad_group_target_setting=campaign_service.factory.create('TargetSetting')
        ad_group_audience_target_setting_detail=campaign_service.factory.create('TargetSettingDetail')
        ad_group_audience_target_setting_detail.CriterionTypeGroup='Audience'
        ad_group_audience_target_setting_detail.TargetAndBid=True
        ad_group_target_setting.Details.TargetSettingDetail.append(ad_group_audience_target_setting_detail)
        ad_group_settings.Setting.append(ad_group_target_setting)
        ad_group.Settings=ad_group_settings
        
        # For ad groups you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
        # If you do not set this element, then InheritFromParentBiddingScheme is used by default.
        ad_group_bidding_scheme=set_elements_to_none(campaign_service.factory.create('ManualCpcBiddingScheme'))
        ad_group.BiddingScheme=ad_group_bidding_scheme
        
        # You could use a tracking template which would override the campaign level
        # tracking template. Tracking templates defined for lower level entities 
        # override those set for higher level entities.
        # In this example we are using the campaign level tracking template.
        ad_group.TrackingUrlTemplate=None

        ad_groups.AdGroup.append(ad_group)

        # In this example only the first 3 ads should succeed. 
        # The TitlePart2 of the fourth ad is empty and not valid,
        # and the fifth ad is a duplicate of the second ad.
        
        ads=campaign_service.factory.create('ArrayOfAd')
        
        for index in range(5):
            expanded_text_ad=set_elements_to_none(campaign_service.factory.create('ExpandedTextAd'))
            expanded_text_ad.TitlePart1='Contoso'
            expanded_text_ad.TitlePart2='Fast & Easy Setup'
            expanded_text_ad.Text='Huge Savings on red shoes.'
            expanded_text_ad.Path1='seattle'
            expanded_text_ad.Path2='shoe sale'
            expanded_text_ad.Type='ExpandedText'
            
            # With FinalUrls you can separate the tracking template, custom parameters, and 
            # landing page URLs.
            final_urls=campaign_service.factory.create('ns3:ArrayOfstring')
            final_urls.string.append('http://www.contoso.com/womenshoesale')
            expanded_text_ad.FinalUrls=final_urls

            # Final Mobile URLs can also be used if you want to direct the user to a different page 
            # for mobile devices.
            final_mobile_urls=campaign_service.factory.create('ns3:ArrayOfstring')
            final_mobile_urls.string.append('http://mobile.contoso.com/womenshoesale')
            expanded_text_ad.FinalMobileUrls=final_mobile_urls

            # You could use a tracking template which would override the campaign level
            # tracking template. Tracking templates defined for lower level entities 
            # override those set for higher level entities.
            # In this example we are using the campaign level tracking template.
            expanded_text_ad.TrackingUrlTemplate=None,

            # Set custom parameters that are specific to this ad, 
            # and can be used by the ad, ad group, campaign, or account level tracking template. 
            # In this example we are using the campaign level tracking template.
            url_custom_parameters=campaign_service.factory.create('CustomParameters')
            parameters=campaign_service.factory.create('ArrayOfCustomParameter')
            custom_parameter1=campaign_service.factory.create('CustomParameter')
            custom_parameter1.Key='promoCode'
            custom_parameter1.Value='PROMO' + str(index)
            parameters.CustomParameter.append(custom_parameter1)
            custom_parameter2=campaign_service.factory.create('CustomParameter')
            custom_parameter2.Key='season'
            custom_parameter2.Value='summer'
            parameters.CustomParameter.append(custom_parameter2)
            url_custom_parameters.Parameters=parameters
            expanded_text_ad.UrlCustomParameters=url_custom_parameters
            ads.Ad.append(expanded_text_ad)
        
        ads.Ad[1].TitlePart2="Quick & Easy Setup"
        ads.Ad[2].TitlePart2="Fast & Simple Setup"
        ads.Ad[3].TitlePart2=''
        ads.Ad[4].TitlePart2="Quick & Easy Setup"

        # In this example only the second keyword should succeed. The Text of the first keyword exceeds the limit,
        # and the third keyword is a duplicate of the second keyword.  

        keywords=campaign_service.factory.create('ArrayOfKeyword')
        
        for index in range(3):
            keyword=set_elements_to_none(campaign_service.factory.create('Keyword'))
            keyword.Bid=campaign_service.factory.create('Bid')
            keyword.Bid.Amount=0.47
            keyword.Param2='10% Off'
            keyword.MatchType='Broad'
            keyword.Text='Brand-A Shoes'

            # For keywords you can use either of the InheritFromParentBiddingScheme or ManualCpcBiddingScheme objects. 
            # If you do not set this element, then InheritFromParentBiddingScheme is used by default.
            keyword_bidding_scheme=set_elements_to_none(campaign_service.factory.create('InheritFromParentBiddingScheme'))
            keyword.BiddingScheme=keyword_bidding_scheme

            keywords.Keyword.append(keyword)
        
        keywords.Keyword[0].Text=(
            "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes "
            "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes "
            "Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes Brand-A Shoes"
        )

        # Add the campaign, ad group, keywords, and ads
        
        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("Campaign Ids:")
        output_array_of_long(campaign_ids)
        
        add_ad_groups_response=campaign_service.AddAdGroups(
            CampaignId=campaign_ids['long'][0],
            AdGroups=ad_groups
        )
        ad_group_ids={
            'long': add_ad_groups_response.AdGroupIds['long'] if add_ad_groups_response.AdGroupIds['long'] else None
        }
        output_status_message("Ad Group Ids:")
        output_array_of_long(ad_group_ids)
        
        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
        }
        ad_errors={
            'BatchError': add_ads_response.PartialErrors['BatchError'] if add_ads_response.PartialErrors else None
        }    
        output_status_message("Ad Ids:")
        output_array_of_long(ad_ids)
        
        add_keywords_response=campaign_service.AddKeywords(
            AdGroupId=ad_group_ids['long'][0],
            Keywords=keywords
        )
        keyword_ids={
            'long': add_keywords_response.KeywordIds['long'] if add_keywords_response.KeywordIds else None
        }
        keyword_errors={
            'BatchError': add_keywords_response.PartialErrors['BatchError'] if add_keywords_response.PartialErrors else None
        } 
        output_status_message("Keyword Ids:")
        output_array_of_long(keyword_ids)
        
        # Here is a simple example that updates the campaign budget.
        # If the campaign has a shared budget you cannot update the Campaign budget amount,
        # and you must instead update the amount in the Budget object. If you try to update 
        # the budget amount of a campaign that has a shared budget, the service will return 
        # the CampaignServiceCannotUpdateSharedBudget error code.

        get_campaigns=campaign_service.GetCampaignsByAccountId(
            AccountId=authorization_data.account_id,
            CampaignType=ALL_CAMPAIGN_TYPES
        )
        
        update_campaigns = campaign_service.factory.create('ArrayOfCampaign')
        update_budgets = campaign_service.factory.create('ArrayOfBudget')
        get_campaign_ids = []
        get_budget_ids = []

        # Increase existing budgets by 20%
        for campaign in get_campaigns['Campaign']:

            # If the campaign has a shared budget, let's add the budget ID to the list we will update later.
            if campaign is not None and campaign.BudgetId is not None and campaign.BudgetId > 0:
                get_budget_ids.append(campaign.BudgetId)
            # If the campaign has its own budget, let's add it to the list of campaigns to update later.
            elif campaign is not None:
                update_campaigns.Campaign.append(campaign)
        
        # Update shared budgets in Budget objects.
        if get_budget_ids is not None and len(get_budget_ids) > 0:
            # The UpdateBudgets operation only accepts 100 Budget objects per call. 
            # To simply the example we will update the first 100.
            distinct_budget_ids = {'long': list(set(get_budget_ids))[:100]}
            get_budgets = campaign_service.GetBudgetsByIds(
                BudgetIds=distinct_budget_ids
            ).Budgets

            output_status_message("List of shared budgets BEFORE update:\n")
            for budget in get_budgets['Budget']:
                output_status_message("Budget:")
                output_budget(budget)

            output_status_message("List of campaigns that share each budget:\n")
            get_campaign_id_collection = campaign_service.GetCampaignIdsByBudgetIds(distinct_budget_ids).CampaignIdCollection

            index=0

            for index in range(len(get_campaign_id_collection['IdCollection'])):
                output_status_message("BudgetId: {0}".format(distinct_budget_ids['long'][index]))
                output_status_message("Campaign Ids:")
                if get_campaign_id_collection['IdCollection'][index] is not None:
                    for id in get_campaign_id_collection['IdCollection'][index].Ids['long']:
                        output_status_message("\t{0}".format(id))
                index=index+1

            for budget in get_budgets['Budget']:
                if budget is not None:
                    # Increase budget by 20 %
                    budget.Amount *= 1.2
                    update_budgets.Budget.append(budget)
            campaign_service.UpdateBudgets(Budgets=update_budgets)

            get_budgets = campaign_service.GetBudgetsByIds(
                BudgetIds=distinct_budget_ids
            ).Budgets

            output_status_message("List of shared budgets AFTER update:\n")
            for budget in get_budgets['Budget']:
                output_status_message("Budget:")
                output_budget(budget)

        # Update unshared budgets in Campaign objects.
        if update_campaigns is not None:

            # The UpdateCampaigns operation only accepts 100 Campaign objects per call. 
            # To simply the example we will update the first 100.
            update_100_campaigns = update_campaigns['Campaign'][:100]
            update_campaigns = campaign_service.factory.create('ArrayOfCampaign')
            for campaign in update_100_campaigns:
                update_campaigns.Campaign.append(campaign)

            output_status_message("List of campaigns with unshared budget BEFORE budget update:\n")
            for campaign in update_campaigns['Campaign']:
                output_status_message("Campaign:")
                output_campaign(campaign)
                set_read_only_campaign_elements_to_none(campaign)

                # Increase budget by 20 %
                campaign.DailyBudget *= 1.2

                get_campaign_ids.append(campaign.Id)
            
            campaign_service.UpdateCampaigns(
                AccountId=authorization_data.account_id,
                Campaigns=update_campaigns
            )

            get_campaigns=campaign_service.GetCampaignsByIds(
                AccountId=authorization_data.account_id,
                CampaignIds={'long': get_campaign_ids},
                CampaignType=ALL_CAMPAIGN_TYPES
            ).Campaigns
            
            output_status_message("List of campaigns with unshared budget AFTER budget update:\n")
            for campaign in get_campaigns['Campaign']:
                output_status_message("Campaign:")
                output_campaign(campaign)
        
        # Update the Text for the 3 successfully created ads, and update some UrlCustomParameters.
        update_ads=campaign_service.factory.create('ArrayOfAd')

        # Set the UrlCustomParameters element to null or empty to retain any 
        # existing custom parameters.
        expanded_text_ad_0=set_elements_to_none(campaign_service.factory.create('ExpandedTextAd'))
        expanded_text_ad_0.Id=ad_ids['long'][0]
        expanded_text_ad_0.Text='Huge Savings on All Red Shoes.'
        expanded_text_ad_0.UrlCustomParameters=None
        expanded_text_ad_0.Type='ExpandedText'
        update_ads.Ad.append(expanded_text_ad_0)

        # To remove all custom parameters, set the Parameters element of the 
        # CustomParameters object to null or empty.
        expanded_text_ad_1=set_elements_to_none(campaign_service.factory.create('ExpandedTextAd'))
        expanded_text_ad_1.Id=ad_ids['long'][1]
        expanded_text_ad_1.Text='Huge Savings on All Red Shoes.'
        url_custom_parameters_1=campaign_service.factory.create('CustomParameters')
        parameters_1=campaign_service.factory.create('ArrayOfCustomParameter')
        custom_parameter_1=campaign_service.factory.create('CustomParameter')
        # Set the CustomParameter to None or leave unspecified to have the same effect
        #custom_parameter_1=None
        parameters_1.CustomParameter.append(custom_parameter_1)
        url_custom_parameters_1.Parameters=parameters_1
        expanded_text_ad_1.UrlCustomParameters=url_custom_parameters_1
        expanded_text_ad_1.Type='ExpandedText'
        update_ads.Ad.append(expanded_text_ad_1)

        # To remove a subset of custom parameters, specify the custom parameters that 
        # you want to keep in the Parameters element of the CustomParameters object.
        expanded_text_ad_2=set_elements_to_none(campaign_service.factory.create('ExpandedTextAd'))
        expanded_text_ad_2.Id=ad_ids['long'][2]
        expanded_text_ad_2.Text='Huge Savings on All Red Shoes.'
        url_custom_parameters_2=campaign_service.factory.create('CustomParameters')
        parameters_2=campaign_service.factory.create('ArrayOfCustomParameter')
        custom_parameter_2=campaign_service.factory.create('CustomParameter')
        custom_parameter_2.Key='promoCode'
        custom_parameter_2.Value='updatedpromo'
        parameters_2.CustomParameter.append(custom_parameter_2)
        url_custom_parameters_2.Parameters=parameters_2
        expanded_text_ad_2.UrlCustomParameters=url_custom_parameters_2
        expanded_text_ad_2.Type='ExpandedText'
        update_ads.Ad.append(expanded_text_ad_2)

        # As an exercise you can step through using the debugger and view the results.

        campaign_service.GetAdsByAdGroupId(
            AdGroupId=ad_group_ids['long'][0],
            AdTypes=ALL_AD_TYPES
        )
        campaign_service.UpdateAds(
            AdGroupId=ad_group_ids['long'][0],
            Ads=update_ads
        )
        campaign_service.GetAdsByAdGroupId(
            AdGroupId=ad_group_ids['long'][0],
            AdTypes=ALL_AD_TYPES
        )

        update_keywords=campaign_service.factory.create('ArrayOfKeyword')
        update_keyword=set_elements_to_none(campaign_service.factory.create('Keyword'))
        update_keyword.Id=keyword_ids['long'][0]
        
        # You can set the Bid.Amount property to change the keyword level bid.
        update_keyword.Bid=campaign_service.factory.create('Bid')
        update_keyword.Bid.Amount=0.46
        
        # When using the Campaign Management service with the Bing Ads Python SDK,
        # if you want to inherit the ad group level bid, instead of using the keyword level bid,
        # the service expects that you would have set the Bid.Amount null (new empty Bid). However, 
        # it is important to note that SUDS (used by the Bing Ads Python SDK) does not allow the 
        # Bid.Amount property to be null, so you will need to delete the keyword and then add a new 
        # keyword without the Bid set, or with Bid set to None. 

        # We recommend that you use the BulkServiceManager for keyword updates, i.e. upload BulkKeyword entities.
        # With the BulkKeyword upload, you won't have to delete and add keywords to inherit from the ad group level bid,
        # and you also have the flexibility of updating millions of keywords across all campaigns in your account.
        # For examples of how to use the Bulk service for keyword updates, please see BulkKeywordsAds.py.
        
        # When using the Campaign Management service with the Bing Ads Python SDK,
        # if the Bid property is not specified or is null, your keyword bid will not be updated.
        #update_keyword.Bid=None
        
        update_keywords.Keyword.append(update_keyword)

        campaign_service.GetKeywordsByAdGroupId(
            AdGroupId=ad_group_ids['long'][0]
        )
        campaign_service.UpdateKeywords(
            AdGroupId=ad_group_ids['long'][0],
            Keywords=update_keywords
        )
        campaign_service.GetKeywordsByAdGroupId(
            AdGroupId=ad_group_ids['long'][0]
        )
        
        # Delete the campaign, ad group, keyword, and ad that were previously added. 
        # You should remove this line if you want to view the added entities in the 
        # Bing Ads web application or another tool.

        campaign_service.DeleteCampaigns(
            AccountId=authorization_data.account_id,
            CampaignIds=campaign_ids
        )
        for campaign_id in campaign_ids['long']:
            output_status_message("Deleted CampaignId {0}\n".format(campaign_id))
        
        # This sample will attempt to delete the budget that was created above.
        if len(budget_ids['long']) > 0:
            campaign_service.DeleteBudgets(
                BudgetIds=budget_ids
            )
            for budget_id in budget_ids['long']:
                output_status_message("Deleted BudgetId {0}\n".format(budget_id))

        output_status_message("Program execution completed")

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

# Main execution
if __name__ == '__main__':

    print("Python loads the web service proxies at runtime, so you will observe " \
          "a performance delay between program launch and main execution...\n")
    
    authorization_data=AuthorizationData(
        account_id=None,
        customer_id=None,
        developer_token=DEVELOPER_TOKEN,
        authentication=None,
    )

    campaign_service=ServiceClient(
        service='CampaignManagementService', 
        version=12,
        authorization_data=authorization_data, 
        environment=ENVIRONMENT,
    )

    # You should authenticate for Bing Ads production services with a Microsoft Account.
        
    authenticate(authorization_data)
        
    main(authorization_data)

See Also

Get Started with the Bing Ads API