ภาษา
หมายเหตุ
การเข้าถึงหน้านี้ต้องได้รับการอนุญาต คุณสามารถลอง ลงชื่อเข้าใช้หรือเปลี่ยนไดเรกทอรีได้
การเข้าถึงหน้านี้ต้องได้รับการอนุญาต คุณสามารถลองเปลี่ยนไดเรกทอรีได้
ตัวอย่างนี้แสดงวิธีการเพิ่ม รับ และลบส่วนขยายสําหรับไลบรารีส่วนขยายโฆษณาของบัญชี ตั้งค่า รับ และลบการเชื่อมโยงส่วนขยายกับแคมเปญ และระบุสาเหตุที่ส่วนขยายล้มเหลวในการตรวจสอบบรรณาธิการ
เคล็ดลับ
ใช้ตัวเลือกภาษาในส่วนหัวของเอกสารประกอบเพื่อเลือก C#, Java, PHP หรือ Python
เมื่อต้องการรับการเข้าถึงและรีเฟรชโทเค็นสําหรับผู้ใช้ Microsoft Advertising ของคุณ และทําการเรียกใช้บริการครั้งแรกของคุณโดยใช้ Bing Ads API ให้ดูคู่มือเริ่มต้นใช้งานด่วน คุณจะต้องตรวจสอบคู่มือเริ่มต้นใช้งานและคําแนะนําสําหรับภาษาที่คุณต้องการ เช่น C#, Java, PHP และ Python
ไฟล์ที่สนับสนุนสําหรับตัวอย่าง C#, Java, PHP และ Python มีอยู่ที่ GitHub คุณสามารถโคลนแต่ละที่เก็บหรือนําส่วนย่อยไปใช้ใหม่ได้ตามต้องการ
using System;
using System.Drawing;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Threading.Tasks;
using Microsoft.BingAds.V13.CampaignManagement;
using Microsoft.BingAds;
namespace BingAdsExamplesLibrary.V13
{
/// <summary>
/// How to manage ad extensions for an account's ad extension library,
/// associate the extensions with a campaign, and determine why an extension failed
/// editorial review.
/// </summary>
public class AdExtensions : ExampleBase
{
// To run this example you'll need to provide your own image.
// For required aspect ratios and recommended dimensions please see
// Image remarks at https://go.microsoft.com/fwlink/?linkid=872754.
private const string MediaFilePath = "c:\\dev\\media\\";
private const string ImageAdExtensionMediaFileName = "imageadextension300x200.png";
public override string Description
{
get { return "Ad Extensions | Campaign Management V13"; }
}
public async override Task RunAsync(AuthorizationData authorizationData)
{
try
{
ApiEnvironment environment = ((OAuthDesktopMobileAuthCodeGrant)authorizationData.Authentication).Environment;
CampaignManagementExampleHelper CampaignManagementExampleHelper = new CampaignManagementExampleHelper(
OutputStatusMessageDefault: this.OutputStatusMessage);
CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient<ICampaignManagementService>(
authorizationData: authorizationData,
environment: environment);
// Add a campaign to associate with ad extensions.
var campaigns = new[] {
new Campaign
{
BudgetType = BudgetLimitType.DailyBudgetStandard,
DailyBudget = 50,
Languages = new string[] { "All" },
Name = "Everyone's Shoes " + DateTime.UtcNow,
TimeZone = "PacificTimeUSCanadaTijuana",
}
};
OutputStatusMessage("-----\nAddCampaigns:");
AddCampaignsResponse addCampaignsResponse = await CampaignManagementExampleHelper.AddCampaignsAsync(
accountId: authorizationData.AccountId,
campaigns: campaigns);
long?[] campaignIds = addCampaignsResponse.CampaignIds.ToArray();
BatchError[] campaignErrors = addCampaignsResponse.PartialErrors.ToArray();
OutputStatusMessage("CampaignIds:");
CampaignManagementExampleHelper.OutputArrayOfLong(campaignIds);
OutputStatusMessage("PartialErrors:");
CampaignManagementExampleHelper.OutputArrayOfBatchError(campaignErrors);
// Create media for the image ad extension that we'll add later.
var imageAdExtensionMedia = GetImageMedia(
"Image15x10",
MediaFilePath + ImageAdExtensionMediaFileName,
System.Drawing.Imaging.ImageFormat.Png);
var media = new Media[]
{
imageAdExtensionMedia
};
// Add the media to the account's library.
OutputStatusMessage("-----\nAddMedia:");
AddMediaResponse addMediaResponse = await CampaignManagementExampleHelper.AddMediaAsync(
accountId: authorizationData.AccountId,
media: media);
long[] mediaIds = addMediaResponse.MediaIds.ToArray();
OutputStatusMessage("MediaIds:");
CampaignManagementExampleHelper.OutputArrayOfLong(mediaIds);
// Add the extensions to the account's library.
var adExtensions = new AdExtension[] {
new ActionAdExtension
{
ActionType = ActionAdExtensionActionType.ActNow,
FinalUrls = new string[]
{
"https://www.contoso.com/womenshoesale"
},
Language = "English",
Status = AdExtensionStatus.Active,
},
//new AppAdExtension
//{
// AppPlatform = "Windows",
// AppStoreId = "AppStoreIdGoesHere",
// DestinationUrl = "DestinationUrlGoesHere",
// DisplayText = "Contoso",
//},
new CallAdExtension {
CountryCode = "US",
PhoneNumber = "2065550100",
IsCallOnly = false,
// Include the call extension Monday - Friday from 9am - 9pm
// in the account's time zone.
Scheduling = new Schedule {
UseSearcherTimeZone = false,
DayTimeRanges = new[]
{
new DayTime
{
Day = Day.Monday,
StartHour = 9,
StartMinute = Minute.Zero,
EndHour = 21,
EndMinute = Minute.Zero,
},
new DayTime
{
Day = Day.Tuesday,
StartHour = 9,
StartMinute = Minute.Zero,
EndHour = 21,
EndMinute = Minute.Zero,
},
new DayTime
{
Day = Day.Wednesday,
StartHour = 9,
StartMinute = Minute.Zero,
EndHour = 21,
EndMinute = Minute.Zero,
},
new DayTime
{
Day = Day.Thursday,
StartHour = 9,
StartMinute = Minute.Zero,
EndHour = 21,
EndMinute = Minute.Zero,
},
new DayTime
{
Day = Day.Friday,
StartHour = 9,
StartMinute = Minute.Zero,
EndHour = 21,
EndMinute = Minute.Zero,
},
},
StartDate = null,
EndDate = new Microsoft.BingAds.V13.CampaignManagement.Date {
Month = 12,
Day = 31,
Year = DateTime.UtcNow.Year + 1
},
}
},
new CalloutAdExtension
{
Text = "Callout Text"
},
new ImageAdExtension
{
AlternativeText = "Image Extension Alt Text",
ImageMediaIds = mediaIds,
Images = new AssetLink[]
{
new AssetLink
{
Asset = new ImageAsset
{
Id = 12345, // 1.91 aspect ratio image id. This type of image is required for Images
SubType = "LandscapeImageMedia",
}
}
}
},
new LocationAdExtension {
PhoneNumber = "206-555-0100",
CompanyName = "Contoso Shoes",
Address = new Microsoft.BingAds.V13.CampaignManagement.Address {
StreetAddress = "1234 Washington Place",
StreetAddress2 = "Suite 1210",
CityName = "Woodinville",
ProvinceName = "WA",
CountryCode = "US",
PostalCode = "98608"
},
// Include the location extension every Saturday morning
// in the search user's time zone.
Scheduling = new Schedule {
UseSearcherTimeZone = true,
DayTimeRanges = new[]
{
new DayTime
{
Day = Day.Saturday,
StartHour = 9,
StartMinute = Minute.Zero,
EndHour = 12,
EndMinute = Minute.Zero,
},
},
StartDate = null,
EndDate = new Microsoft.BingAds.V13.CampaignManagement.Date {
Month = 12,
Day = 31,
Year = DateTime.UtcNow.Year + 1
},
}
},
new PriceAdExtension
{
Language = "English",
PriceExtensionType = PriceExtensionType.Events,
TableRows = new PriceTableRow[]
{
new PriceTableRow
{
CurrencyCode = "USD",
Description = "Come to the event",
FinalUrls = new string[]
{
"https://contoso.com"
},
Header = "New Event",
Price = 9.99,
PriceQualifier = PriceQualifier.From,
PriceUnit = PriceUnit.PerDay,
},
new PriceTableRow
{
CurrencyCode = "USD",
Description = "Come to the next event",
FinalUrls = new string[]
{
"https://contoso.com"
},
Header = "Next Event",
Price = 9.99,
PriceQualifier = PriceQualifier.From,
PriceUnit = PriceUnit.PerDay,
},
new PriceTableRow
{
CurrencyCode = "USD",
Description = "Come to the final event",
FinalUrls = new string[]
{
"https://contoso.com"
},
Header = "Final Event",
Price = 9.99,
PriceQualifier = PriceQualifier.From,
PriceUnit = PriceUnit.PerDay,
},
},
},
new ReviewAdExtension
{
IsExact = true,
Source = "Review Source Name",
Text = "Review Text",
// The Url of the third-party review. This is not your business Url.
Url = "https://review.contoso.com"
},
new SitelinkAdExtension {
Description1 = "Simple & Transparent.",
Description2 = "No Upfront Cost.",
DisplayText = "Everyone's Shoe Sale",
FinalUrls = new[] {
"https://www.contoso.com/womenshoesale"
},
},
new StructuredSnippetAdExtension
{
Header = "Brands",
Values = new [] { "Windows", "Xbox", "Skype"}
}
};
OutputStatusMessage("-----\nAddAdExtensions:");
var addAdExtensionsResponse = await CampaignManagementExampleHelper.AddAdExtensionsAsync(
accountId: authorizationData.AccountId,
adExtensions: adExtensions);
OutputStatusMessage("AdExtensionIdentities:");
var adExtensionIdentities = addAdExtensionsResponse?.AdExtensionIdentities;
OutputStatusMessage("NestedPartialErrors:");
CampaignManagementExampleHelper.OutputArrayOfBatchErrorCollection(addAdExtensionsResponse?.NestedPartialErrors);
// DeleteAdExtensionsAssociations, SetAdExtensionsAssociations, and GetAdExtensionsEditorialReasons
// operations each require a list of type AdExtensionIdToEntityIdAssociation.
var adExtensionIdToEntityIdAssociations = new List<AdExtensionIdToEntityIdAssociation>();
// GetAdExtensionsByIds requires a list of type long.
var adExtensionIds = new List<long>();
// Loop through the list of extension IDs and build any required data structures
// for subsequent operations.
foreach (var adExtensionIdentity in adExtensionIdentities)
{
if (adExtensionIdentity != null)
{
adExtensionIdToEntityIdAssociations.Add(new AdExtensionIdToEntityIdAssociation
{
AdExtensionId = adExtensionIdentity.Id,
EntityId = (long)campaignIds[0]
});
adExtensionIds.Add(adExtensionIdentity.Id);
}
}
// Associate the ad extensions with the campaign.
OutputStatusMessage("-----\nSetAdExtensionsAssociations:");
var setAdExtensionsAssociationsResponse = await CampaignManagementExampleHelper.SetAdExtensionsAssociationsAsync(
accountId: authorizationData.AccountId,
adExtensionIdToEntityIdAssociations: adExtensionIdToEntityIdAssociations,
associationType: AssociationType.Campaign);
OutputStatusMessage("PartialErrors:");
CampaignManagementExampleHelper.OutputArrayOfBatchError(setAdExtensionsAssociationsResponse?.PartialErrors);
// Get editorial rejection reasons for the ad extension and entity associations.
OutputStatusMessage("-----\nGetAdExtensionsEditorialReasons:");
var getAdExtensionsEditorialReasonsResponse = await CampaignManagementExampleHelper.GetAdExtensionsEditorialReasonsAsync(
accountId: authorizationData.AccountId,
adExtensionIdToEntityIdAssociations: adExtensionIdToEntityIdAssociations,
associationType: AssociationType.Campaign);
OutputStatusMessage("EditorialReasons:");
var adExtensionEditorialReasonCollection =
(AdExtensionEditorialReasonCollection[])getAdExtensionsEditorialReasonsResponse?.EditorialReasons;
CampaignManagementExampleHelper.OutputArrayOfAdExtensionEditorialReasonCollection(adExtensionEditorialReasonCollection);
OutputStatusMessage("PartialErrors:");
CampaignManagementExampleHelper.OutputArrayOfBatchError(getAdExtensionsEditorialReasonsResponse?.PartialErrors);
// Get only the location ad extensions and then remove scheduling.
AdExtensionsTypeFilter adExtensionsTypeFilter = AdExtensionsTypeFilter.LocationAdExtension;
// In this example partial errors will be returned for indices where the ad extensions
// are not location ad extensions.
// This is an example, and ideally you would only send the required ad extension IDs.
OutputStatusMessage("-----\nGetAdExtensionsByIds:");
var getAdExtensionsByIdsResponse = (await CampaignManagementExampleHelper.GetAdExtensionsByIdsAsync(
accountId: authorizationData.AccountId,
adExtensionIds: adExtensionIds,
adExtensionType: adExtensionsTypeFilter,
returnAdditionalFields: AdExtensionAdditionalField.DisplayText | AdExtensionAdditionalField.Images));
adExtensions = getAdExtensionsByIdsResponse?.AdExtensions.ToArray();
BatchError[] getAdExtensionErrors = getAdExtensionsByIdsResponse?.PartialErrors.ToArray();
OutputStatusMessage("AdExtensions:");
CampaignManagementExampleHelper.OutputArrayOfAdExtension(adExtensions);
OutputStatusMessage("PartialErrors:");
CampaignManagementExampleHelper.OutputArrayOfBatchError(getAdExtensionErrors);
var updateExtensions = new List<AdExtension>();
var updateExtensionIds = new List<long>();
foreach (var extension in adExtensions)
{
// GetAdExtensionsByIds will return a nil element if the request conditions were not met.
if (extension != null && extension.Id != null)
{
// Remove read-only elements that would otherwise cause the update operation to fail.
var updateExtension = SetReadOnlyAdExtensionElementsToNull(extension);
// If you set the Scheduling element null, any existing scheduling set for the ad extension will remain unchanged.
// If you set this to any non-null Schedule object, you are effectively replacing existing scheduling
// for the ad extension. In this example, we will remove any existing scheduling by setting this element
// to an empty Schedule object.
updateExtension.Scheduling = new Schedule { };
updateExtensions.Add(updateExtension);
updateExtensionIds.Add((long)updateExtension.Id);
}
}
OutputStatusMessage("-----\nUpdateAdExtensions:");
await CampaignManagementExampleHelper.UpdateAdExtensionsAsync(
accountId: authorizationData.AccountId,
adExtensions: updateExtensions);
OutputStatusMessage("Removed scheduling from the location ad extensions.");
// Get only the location extensions to output the result.
OutputStatusMessage("-----\nGetAdExtensionsByIds:");
getAdExtensionsByIdsResponse = await CampaignManagementExampleHelper.GetAdExtensionsByIdsAsync(
accountId: authorizationData.AccountId,
adExtensionIds: updateExtensionIds,
adExtensionType: adExtensionsTypeFilter,
returnAdditionalFields: AdExtensionAdditionalField.DisplayText | AdExtensionAdditionalField.Images);
adExtensions = getAdExtensionsByIdsResponse?.AdExtensions.ToArray();
getAdExtensionErrors = getAdExtensionsByIdsResponse?.PartialErrors.ToArray();
OutputStatusMessage("AdExtensions:");
CampaignManagementExampleHelper.OutputArrayOfAdExtension(adExtensions);
OutputStatusMessage("PartialErrors:");
CampaignManagementExampleHelper.OutputArrayOfBatchError(getAdExtensionErrors);
// Delete the ad extension associations, ad extensions, and campaign, that were previously added.
// At this point the ad extensions are still available in the account's ad extensions library.
OutputStatusMessage("-----\nDeleteAdExtensionsAssociations:");
await CampaignManagementExampleHelper.DeleteAdExtensionsAssociationsAsync(
authorizationData.AccountId,
adExtensionIdToEntityIdAssociations,
AssociationType.Campaign);
OutputStatusMessage("Deleted ad extension associations.");
// Delete the ad extensions from the account's ad extension library.
OutputStatusMessage("-----\nDeleteAdExtensions:");
await CampaignManagementExampleHelper.DeleteAdExtensionsAsync(
authorizationData.AccountId,
adExtensionIds);
OutputStatusMessage("Deleted ad extensions.");
// Delete the account's media that was used for the image ad extension.
OutputStatusMessage("-----\nDeleteMedia:");
await CampaignManagementExampleHelper.DeleteMediaAsync(
accountId: authorizationData.AccountId,
mediaIds: mediaIds);
foreach (var id in mediaIds)
{
OutputStatusMessage(string.Format("Deleted Media Id {0}", id));
}
// Delete the campaign and everything it contains e.g., ad groups and ads.
OutputStatusMessage("-----\nDeleteCampaigns:");
await CampaignManagementExampleHelper.DeleteCampaignsAsync(
accountId: authorizationData.AccountId,
campaignIds: new[] { (long)campaignIds[0] });
OutputStatusMessage(string.Format("Deleted Campaign Id {0}", campaignIds[0]));
}
// Catch authentication exceptions
catch (OAuthTokenRequestException ex)
{
OutputStatusMessage(string.Format("Couldn't get OAuth tokens. Error: {0}. Description: {1}", ex.Details.Error, ex.Details.Description));
}
// Catch Campaign Management service exceptions
catch (FaultException<Microsoft.BingAds.V13.CampaignManagement.AdApiFaultDetail> ex)
{
OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
}
catch (FaultException<Microsoft.BingAds.V13.CampaignManagement.ApiFaultDetail> ex)
{
OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
}
catch (FaultException<Microsoft.BingAds.V13.CampaignManagement.EditorialApiFaultDetail> ex)
{
OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
OutputStatusMessage(string.Join("; ", ex.Detail.BatchErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
}
// Catch Customer Management service exceptions
catch (FaultException<Microsoft.BingAds.V13.CustomerManagement.AdApiFaultDetail> ex)
{
OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
}
catch (FaultException<Microsoft.BingAds.V13.CustomerManagement.ApiFault> ex)
{
OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message))));
}
catch (Exception ex)
{
OutputStatusMessage(ex.Message);
}
}
/// <summary>
/// Get image media that can be managed with the Campaign Management API.
/// </summary>
/// <param name="mediaType">The media type reflects the aspect ratio.</param>
/// <param name="imageFileName">The file name and path.</param>
/// <param name="imageFormat">For supported image formats see <see href="https://go.microsoft.com/fwlink/?linkid=872754">Image remarks</see>.</param>
/// <returns>A Campaign Management Image object.</returns>
private Microsoft.BingAds.V13.CampaignManagement.Image GetImageMedia(
string mediaType,
string imageFileName,
System.Drawing.Imaging.ImageFormat imageFormat)
{
var image = new Microsoft.BingAds.V13.CampaignManagement.Image();
image.Data = GetBmpBase64String(imageFileName, imageFormat);
image.MediaType = mediaType;
image.Type = "Image";
return image;
}
/// <summary>
/// Get the image media as base64 string.
/// </summary>
/// <param name="imageFileName">The file name and path.</param>
/// <param name="imageFormat">For supported image formats see <see href="https://go.microsoft.com/fwlink/?linkid=872754">Image remarks</see>.</param>
/// <returns></returns>
private string GetBmpBase64String(
string imageFileName,
System.Drawing.Imaging.ImageFormat imageFormat)
{
var bmp = new Bitmap(imageFileName);
using (MemoryStream ms = new MemoryStream())
{
bmp.Save(ms, imageFormat);
byte[] imageBytes = ms.ToArray();
string base64String = Convert.ToBase64String(imageBytes);
return base64String;
}
}
}
}
package com.microsoft.bingads.examples.v13;
import com.microsoft.bingads.*;
import com.microsoft.bingads.v13.campaignmanagement.*;
import java.util.ArrayList;
import java.util.Calendar;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.util.Base64;
public class AdExtensions extends ExampleBase {
public static void main(java.lang.String[] args) {
// To run this example you'll need to provide your own image.
// For required aspect ratios and recommended dimensions please see
// Image remarks at https://go.microsoft.com/fwlink/?linkid=872754.
java.lang.String MEDIA_FILE_PATH = "c:\\dev\\media\\";
java.lang.String IMAGE_AD_EXTENSION_MEDIA_FILE_NAME = "imageadextension300x200.png";
try
{
authorizationData = getAuthorizationData();
CampaignManagementExampleHelper.CampaignManagementService = new ServiceClient<ICampaignManagementService>(
authorizationData,
API_ENVIRONMENT,
ICampaignManagementService.class);
Calendar calendar = Calendar.getInstance();
// Add a campaign to associate with ad extensions.
ArrayOfCampaign campaigns = new ArrayOfCampaign();
Campaign campaign = new Campaign();
campaign.setBudgetType(BudgetLimitType.DAILY_BUDGET_STANDARD);
campaign.setDailyBudget(50.00);
ArrayOfstring languages = new ArrayOfstring();
languages.getStrings().add("All");
campaign.setLanguages(languages);
campaign.setName("Everyone's Shoes " + System.currentTimeMillis());
campaign.setTimeZone("PacificTimeUSCanadaTijuana");
campaigns.getCampaigns().add(campaign);
outputStatusMessage("-----\nAddCampaigns:");
AddCampaignsResponse addCampaignsResponse = CampaignManagementExampleHelper.addCampaigns(
authorizationData.getAccountId(),
campaigns
);
ArrayOfNullableOflong campaignIds = addCampaignsResponse.getCampaignIds();
ArrayOfBatchError campaignErrors = addCampaignsResponse.getPartialErrors();
outputStatusMessage("CampaignIds:");
CampaignManagementExampleHelper.outputArrayOfNullableOflong(campaignIds);
outputStatusMessage("PartialErrors:");
CampaignManagementExampleHelper.outputArrayOfBatchError(campaignErrors);
// Create media for the image ad extension that we'll add later.
Image imageAdExtensionMedia = getImageMedia(
"Image15x10",
MEDIA_FILE_PATH + IMAGE_AD_EXTENSION_MEDIA_FILE_NAME);
ArrayOfMedia addMedia = new ArrayOfMedia();
addMedia.getMedias().add(imageAdExtensionMedia);
CampaignManagementExampleHelper.outputArrayOfMedia(addMedia);
outputStatusMessage("-----\nAddMedia:");
ArrayOflong mediaIds = CampaignManagementExampleHelper.addMedia(
authorizationData.getAccountId(),
addMedia).getMediaIds();
outputStatusMessage("MediaIds:");
CampaignManagementExampleHelper.outputArrayOflong(mediaIds);
// Add the extensions to the account's library.
ArrayOfAdExtension adExtensions = new ArrayOfAdExtension();
ActionAdExtension actionAdExtension = new ActionAdExtension();
actionAdExtension.setActionType(ActionAdExtensionActionType.ACT_NOW);
com.microsoft.bingads.v13.campaignmanagement.ArrayOfstring finalUrls = new com.microsoft.bingads.v13.campaignmanagement.ArrayOfstring();
finalUrls.getStrings().add("https://www.contoso.com/womenshoesale");
actionAdExtension.setFinalUrls(finalUrls);
actionAdExtension.setLanguage("English");
actionAdExtension.setStatus(AdExtensionStatus.ACTIVE);
adExtensions.getAdExtensions().add(actionAdExtension);
AppAdExtension appAdExtension = new AppAdExtension();
appAdExtension.setAppPlatform("Windows");
appAdExtension.setAppStoreId("AppStoreIdGoesHere");
appAdExtension.setDestinationUrl("DestinationUrlGoesHere");
appAdExtension.setDisplayText("Contoso");
// If you supply the AppAdExtension properties above, then you can add this line.
//adExtensions.getAdExtensions().add(appAdExtension);
CallAdExtension callAdExtension = new CallAdExtension();
callAdExtension.setCountryCode("US");
callAdExtension.setPhoneNumber("2065550100");
callAdExtension.setIsCallOnly(false);
// Include the call extension Monday - Friday from 9am - 9pm
// in the account's time zone.
Schedule callScheduling = new Schedule();
ArrayOfDayTime callDayTimeRanges = new ArrayOfDayTime();
DayTime callMonday = new DayTime();
callMonday.setDay(Day.MONDAY);
callMonday.setStartHour(9);
callMonday.setStartMinute(Minute.ZERO);
callMonday.setEndHour(21);
callMonday.setEndMinute(Minute.ZERO);
callDayTimeRanges.getDayTimes().add(callMonday);
DayTime callTuesday = new DayTime();
callTuesday.setDay(Day.TUESDAY);
callTuesday.setStartHour(9);
callTuesday.setStartMinute(Minute.ZERO);
callTuesday.setEndHour(21);
callTuesday.setEndMinute(Minute.ZERO);
callDayTimeRanges.getDayTimes().add(callTuesday);
DayTime callWednesday = new DayTime();
callWednesday.setDay(Day.WEDNESDAY);
callWednesday.setStartHour(9);
callWednesday.setStartMinute(Minute.ZERO);
callWednesday.setEndHour(21);
callWednesday.setEndMinute(Minute.ZERO);
callDayTimeRanges.getDayTimes().add(callWednesday);
DayTime callThursday = new DayTime();
callThursday.setDay(Day.THURSDAY);
callThursday.setStartHour(9);
callThursday.setStartMinute(Minute.ZERO);
callThursday.setEndHour(21);
callThursday.setEndMinute(Minute.ZERO);
callDayTimeRanges.getDayTimes().add(callThursday);
DayTime callFriday = new DayTime();
callFriday.setDay(Day.FRIDAY);
callFriday.setStartHour(9);
callFriday.setStartMinute(Minute.ZERO);
callFriday.setEndHour(21);
callFriday.setEndMinute(Minute.ZERO);
callDayTimeRanges.getDayTimes().add(callFriday);
callScheduling.setDayTimeRanges(callDayTimeRanges);
callScheduling.setEndDate(new com.microsoft.bingads.v13.campaignmanagement.Date());
callScheduling.getEndDate().setDay(31);
callScheduling.getEndDate().setMonth(12);
callScheduling.getEndDate().setYear(calendar.get(Calendar.YEAR) + 1);
callScheduling.setStartDate(null);
callAdExtension.setScheduling(callScheduling);
adExtensions.getAdExtensions().add(callAdExtension);
CalloutAdExtension calloutAdExtension = new CalloutAdExtension();
calloutAdExtension.setText("Callout text");
adExtensions.getAdExtensions().add(calloutAdExtension);
LocationAdExtension locationAdExtension = new LocationAdExtension();
locationAdExtension.setPhoneNumber("206-555-0100");
locationAdExtension.setCompanyName("Contoso Shoes");
com.microsoft.bingads.v13.campaignmanagement.Address address =
new com.microsoft.bingads.v13.campaignmanagement.Address();
address.setStreetAddress("1234 Washington Place");
address.setStreetAddress2("Suite 1210");
address.setCityName("Woodinville");
address.setProvinceName("WA");
address.setCountryCode("US");
address.setPostalCode("98608");
locationAdExtension.setAddress(address);
// Include the location extension every Saturday morning
// in the search user's time zone.
Schedule locationScheduling = new Schedule();
ArrayOfDayTime locationDayTimeRanges = new ArrayOfDayTime();
DayTime locationDayTime = new DayTime();
locationDayTime.setDay(Day.SATURDAY);
locationDayTime.setStartHour(9);
locationDayTime.setStartMinute(Minute.ZERO);
locationDayTime.setEndHour(12);
locationDayTime.setEndMinute(Minute.ZERO);
locationDayTimeRanges.getDayTimes().add(locationDayTime);
locationScheduling.setDayTimeRanges(locationDayTimeRanges);
locationScheduling.setEndDate(new com.microsoft.bingads.v13.campaignmanagement.Date());
locationScheduling.getEndDate().setDay(31);
locationScheduling.getEndDate().setMonth(12);
locationScheduling.getEndDate().setYear(calendar.get(Calendar.YEAR) + 1);
locationScheduling.setStartDate(null);
locationAdExtension.setScheduling(locationScheduling);
adExtensions.getAdExtensions().add(locationAdExtension);
PriceAdExtension priceAdExtension = new PriceAdExtension();
priceAdExtension.setLanguage("English");
priceAdExtension.setPriceExtensionType(PriceExtensionType.EVENTS);
ArrayOfPriceTableRow tableRows = new ArrayOfPriceTableRow();
PriceTableRow tableRowA = new PriceTableRow();
tableRowA.setCurrencyCode("USD");
tableRowA.setDescription("Come to the event");
tableRowA.setFinalUrls(finalUrls);
tableRowA.setHeader("New Event");
tableRowA.setPrice(9.99D);
tableRowA.setPriceQualifier(PriceQualifier.FROM);
tableRowA.setPriceUnit(PriceUnit.PER_DAY);
tableRows.getPriceTableRows().add(tableRowA);
PriceTableRow tableRowB = new PriceTableRow();
tableRowB.setCurrencyCode("USD");
tableRowB.setDescription("Come to the next event");
tableRowB.setFinalUrls(finalUrls);
tableRowB.setHeader("Next Event");
tableRowB.setPrice(9.99D);
tableRowB.setPriceQualifier(PriceQualifier.FROM);
tableRowB.setPriceUnit(PriceUnit.PER_DAY);
tableRows.getPriceTableRows().add(tableRowB);
PriceTableRow tableRowC = new PriceTableRow();
tableRowC.setCurrencyCode("USD");
tableRowC.setDescription("Come to the final event");
tableRowC.setFinalUrls(finalUrls);
tableRowC.setHeader("Final Event");
tableRowC.setPrice(9.99D);
tableRowC.setPriceQualifier(PriceQualifier.FROM);
tableRowC.setPriceUnit(PriceUnit.PER_DAY);
tableRows.getPriceTableRows().add(tableRowC);
priceAdExtension.setTableRows(tableRows);
adExtensions.getAdExtensions().add(priceAdExtension);
ReviewAdExtension reviewAdExtension = new ReviewAdExtension();
reviewAdExtension.setIsExact(true);
reviewAdExtension.setSource("Review Source Name");
reviewAdExtension.setText("Review Text");
// The Url of the third-party review. This is not your business Url.
reviewAdExtension.setUrl("https://review.contoso.com");
adExtensions.getAdExtensions().add(reviewAdExtension);
SitelinkAdExtension sitelinkAdExtension = new SitelinkAdExtension();
sitelinkAdExtension.setDescription1("Simple & Transparent.");
sitelinkAdExtension.setDescription2("No Upfront Cost.");
sitelinkAdExtension.setDisplayText("Everyone's Shoe Sale");
sitelinkAdExtension.setFinalUrls(finalUrls);
adExtensions.getAdExtensions().add(sitelinkAdExtension);
StructuredSnippetAdExtension structuredSnippetAdExtension = new StructuredSnippetAdExtension();
structuredSnippetAdExtension.setHeader("Brands");
com.microsoft.bingads.v13.campaignmanagement.ArrayOfstring values = new com.microsoft.bingads.v13.campaignmanagement.ArrayOfstring();
values.getStrings().add("Windows");
values.getStrings().add("Xbox");
values.getStrings().add("Skype");
structuredSnippetAdExtension.setValues(values);
adExtensions.getAdExtensions().add(structuredSnippetAdExtension);
outputStatusMessage("-----\nAddAdExtensions:");
AddAdExtensionsResponse addAdExtensionsResponse = CampaignManagementExampleHelper.addAdExtensions(
authorizationData.getAccountId(),
adExtensions);
outputStatusMessage("AdExtensionIdentities:");
ArrayOfAdExtensionIdentity adExtensionIdentities = addAdExtensionsResponse.getAdExtensionIdentities();
outputStatusMessage("NestedPartialErrors:");
CampaignManagementExampleHelper.outputArrayOfBatchErrorCollection(addAdExtensionsResponse.getNestedPartialErrors());
// DeleteAdExtensionsAssociations, SetAdExtensionsAssociations, and GetAdExtensionsEditorialReasons
// operations each require a list of type AdExtensionIdToEntityIdAssociation.
ArrayOfAdExtensionIdToEntityIdAssociation adExtensionIdToEntityIdAssociations = new ArrayOfAdExtensionIdToEntityIdAssociation();
// GetAdExtensionsByIds requires a list of type long.
ArrayOflong adExtensionIds = new ArrayOflong();
// Loop through the list of extension IDs and build any required data structures
// for subsequent operations.
for (AdExtensionIdentity adExtensionIdentity : adExtensionIdentities.getAdExtensionIdentities()) {
AdExtensionIdToEntityIdAssociation adExtensionIdToEntityIdAssociation = new AdExtensionIdToEntityIdAssociation();
adExtensionIdToEntityIdAssociation.setAdExtensionId(adExtensionIdentity.getId());
adExtensionIdToEntityIdAssociation.setEntityId(campaignIds.getLongs().get(0));
adExtensionIdToEntityIdAssociations.getAdExtensionIdToEntityIdAssociations().add(adExtensionIdToEntityIdAssociation);
adExtensionIds.getLongs().add(adExtensionIdentity.getId());
}
// Associate the ad extensions with the campaign.
outputStatusMessage("-----\nSetAdExtensionsAssociations:");
SetAdExtensionsAssociationsResponse setAdExtensionsAssociationsResponse = CampaignManagementExampleHelper.setAdExtensionsAssociations(
authorizationData.getAccountId(),
adExtensionIdToEntityIdAssociations,
AssociationType.CAMPAIGN);
outputStatusMessage("PartialErrors:");
CampaignManagementExampleHelper.outputArrayOfBatchError(setAdExtensionsAssociationsResponse.getPartialErrors());
// Get editorial rejection reasons for the ad extension and entity associations.
outputStatusMessage("-----\nGetAdExtensionsEditorialReasons:");
GetAdExtensionsEditorialReasonsResponse getAdExtensionsEditorialReasonsResponse = CampaignManagementExampleHelper.getAdExtensionsEditorialReasons(
authorizationData.getAccountId(),
adExtensionIdToEntityIdAssociations,
AssociationType.CAMPAIGN);
outputStatusMessage("EditorialReasons:");
ArrayOfAdExtensionEditorialReasonCollection adExtensionEditorialReasonCollection = getAdExtensionsEditorialReasonsResponse.getEditorialReasons();
CampaignManagementExampleHelper.outputArrayOfAdExtensionEditorialReasonCollection(adExtensionEditorialReasonCollection);
outputStatusMessage("PartialErrors:");
CampaignManagementExampleHelper.outputArrayOfBatchError(getAdExtensionsEditorialReasonsResponse.getPartialErrors());
// Get only the location extensions and remove scheduling.
ArrayList<AdExtensionsTypeFilter> adExtensionsTypeFilter = new ArrayList<AdExtensionsTypeFilter>();
adExtensionsTypeFilter.add(AdExtensionsTypeFilter.LOCATION_AD_EXTENSION);
ArrayList<AdExtensionAdditionalField> returnAdditionalFields = new ArrayList<AdExtensionAdditionalField>();
returnAdditionalFields.add(AdExtensionAdditionalField.DISPLAY_TEXT);
returnAdditionalFields.add(AdExtensionAdditionalField.IMAGES);
// In this example partial errors will be returned for indices where the ad extensions
// are not location ad extensions.
// This is an example, and ideally you would only send the required ad extension IDs.
outputStatusMessage("-----\nGetAdExtensionsByIds:");
GetAdExtensionsByIdsResponse getAdExtensionsByIdsResponse = CampaignManagementExampleHelper.getAdExtensionsByIds(
authorizationData.getAccountId(),
adExtensionIds,
adExtensionsTypeFilter,
returnAdditionalFields);
adExtensions = getAdExtensionsByIdsResponse.getAdExtensions();
outputStatusMessage("AdExtensions:");
CampaignManagementExampleHelper.outputArrayOfAdExtension(adExtensions);
outputStatusMessage("PartialErrors:");
CampaignManagementExampleHelper.outputArrayOfBatchError(getAdExtensionsByIdsResponse.getPartialErrors());
ArrayOfAdExtension updateExtensions = new ArrayOfAdExtension();
ArrayOflong updateExtensionIds = new ArrayOflong();
for (AdExtension extension : adExtensions.getAdExtensions())
{
// GetAdExtensionsByIds will return a nil element if the request conditions were not met.
if(extension != null && extension.getId() != null)
{
// Remove read-only elements that would otherwise cause the update operation to fail.
AdExtension updateExtension = setReadOnlyAdExtensionElementsToNull(extension);
// If you set the Scheduling element null, any existing scheduling set for the ad extension will remain unchanged.
// If you set this to any non-null Schedule object, you are effectively replacing existing scheduling
// for the ad extension. In this example, we will remove any existing scheduling by setting this element
// to an empty Schedule object.
updateExtension.setScheduling(new Schedule());
updateExtensions.getAdExtensions().add(updateExtension);
updateExtensionIds.getLongs().add((long)updateExtension.getId());
}
}
outputStatusMessage("-----\nUpdateAdExtensions:");
CampaignManagementExampleHelper.updateAdExtensions(
authorizationData.getAccountId(),
updateExtensions);
outputStatusMessage("Removed scheduling from the location ad extensions.");
// Get only the location extension to output the result.
outputStatusMessage("-----\nGetAdExtensionsByIds:");
getAdExtensionsByIdsResponse = CampaignManagementExampleHelper.getAdExtensionsByIds(
authorizationData.getAccountId(),
adExtensionIds,
adExtensionsTypeFilter,
returnAdditionalFields);
adExtensions = getAdExtensionsByIdsResponse.getAdExtensions();
outputStatusMessage("AdExtensions:");
CampaignManagementExampleHelper.outputArrayOfAdExtension(adExtensions);
outputStatusMessage("PartialErrors:");
CampaignManagementExampleHelper.outputArrayOfBatchError(getAdExtensionsByIdsResponse.getPartialErrors());
// Delete the ad extension associations, ad extensions, and campaign, that were previously added.
// At this point the ad extensions are still available in the account's ad extensions library.
outputStatusMessage("-----\nDeleteAdExtensionsAssociations:");
CampaignManagementExampleHelper.deleteAdExtensionsAssociations(
authorizationData.getAccountId(),
adExtensionIdToEntityIdAssociations,
AssociationType.CAMPAIGN);
outputStatusMessage("Deleted ad extension associations.");
// Delete the ad extensions from the account’s ad extension library.
outputStatusMessage("-----\nDeleteAdExtensions:");
CampaignManagementExampleHelper.deleteAdExtensions(
authorizationData.getAccountId(),
adExtensionIds);
outputStatusMessage("Deleted ad extensions.");
// Delete the account's media that was used for the image ad extension.
outputStatusMessage("-----\nDeleteMedia:");
CampaignManagementExampleHelper.deleteMedia(
authorizationData.getAccountId(),
mediaIds);
for (java.lang.Long id : mediaIds.getLongs())
{
outputStatusMessage(String.format("Deleted Media Id %s", id));
}
// Delete the campaign and everything it contains e.g., ad groups and ads.
outputStatusMessage("-----\nDeleteCampaigns:");
ArrayOflong deleteCampaignIds = new ArrayOflong();
deleteCampaignIds.getLongs().add(campaignIds.getLongs().get(0));
CampaignManagementExampleHelper.deleteCampaigns(
authorizationData.getAccountId(),
deleteCampaignIds);
outputStatusMessage(String.format("Deleted CampaignId %d", deleteCampaignIds.getLongs().get(0)));
}
catch (Exception ex) {
String faultXml = ExampleExceptionHelper.getBingAdsExceptionFaultXml(ex, System.out);
outputStatusMessage(faultXml);
String message = ExampleExceptionHelper.handleBingAdsSDKException(ex, System.out);
outputStatusMessage(message);
}
}
// Get image media that can be managed with the Campaign Management API.
static Image getImageMedia(
java.lang.String mediaType,
java.lang.String imageFileName) throws UnsupportedEncodingException, IOException
{
Image image = new Image();
image.setData(getBmpBase64String(imageFileName));
image.setMediaType(mediaType);
image.setType("Image");
return image;
}
// Get the image media as base64 string.
static java.lang.String getBmpBase64String(
java.lang.String imageFileName) throws UnsupportedEncodingException, IOException
{
File fi = new File(imageFileName);
byte[] imageBytes = Files.readAllBytes(fi.toPath());
java.lang.String base64String = new java.lang.String(Base64.getEncoder().encode(imageBytes), "UTF-8");
return base64String;
}
}
<?php
use Microsoft\MsAds\Rest\ApiException;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\ActionAdExtension;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\ActionAdExtensionActionType;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\AddAdExtensionsRequest;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\AddMediaRequest;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\Address;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\AdExtensionIdToEntityIdAssociation;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\AdExtensionStatus;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\AdExtensionsTypeFilter;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\AppAdExtension;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\AssociationType;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\BudgetLimitType;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\CallAdExtension;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\CalloutAdExtension;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\Campaign;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\CampaignType;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\Date;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\Day;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\DayTime;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\DeleteAdExtensionsAssociationsRequest;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\DeleteAdExtensionsRequest;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\DeleteMediaRequest;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\GetAdExtensionsByIdsRequest;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\GetAdExtensionsEditorialReasonsRequest;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\GetCampaignsByIdsRequest;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\LocationAdExtension;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\Minute;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\PriceAdExtension;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\PriceTableRow;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\ReviewAdExtension;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\Schedule;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\SetAdExtensionsAssociationsRequest;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\SitelinkAdExtension;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\StructuredSnippetAdExtension;
use Microsoft\MsAds\Rest\Model\CampaignManagementService\UpdateAdExtensionsRequest;
use Microsoft\MsAds\Rest\Test\RestApiTestBase;
class AdExtensionsTest extends RestApiTestBase
{
// To run this example you'll need to provide your own image.
// For required aspect ratios and recommended dimensions please see
// Image remarks at https://go.microsoft.com/fwlink/?linkid=872754.
protected string $mediaFilePath = "c:\\dev\\media\\";
protected string $imageAdExtensionMediaFileName = "imageadextension300x200.png";
// Add a new search campaign.
/**
* @throws ApiException
*/
public function testAddCampaigns()
{
$budgetLimitType = BudgetLimitType::DAILY_BUDGET_STANDARD;
$campaignType = CampaignType::SEARCH;
$campaign = new Campaign();
$campaign->setName("Women's Shoes ".self::generateRandomAlphaNumeric());
$campaign->setBudgetType($budgetLimitType);
$campaign->setDailyBudget(50.00);
$campaign->setLanguages(array("All"));
$campaign->setTimeZone("PacificTimeUSCanadaTijuana");
$campaign->setCampaignType($campaignType);
print("-----\r\nGetAdExtensionsByIds:\r\n");
$request = new GetAdExtensionsByIdsRequest(
[
'AccountId' => self::CUSTOMER_ACCOUNT_ID,
'AdExtensionIds' => [1, 2, 3],
'AdExtensionType' => [
AdExtensionsTypeFilter::LOCATION_AD_EXTENSION,
AdExtensionsTypeFilter::CALL_AD_EXTENSION
],
'ReturnAdditionalFields' => null
]
);
$response = self::$campaignManagementServiceApi->getAdExtensionsByIds($request);
return self::addCampaignsRequest([$campaign]);
}
/**
* @depends testAddCampaigns
* @throws ApiException
*/
public function testGetCampaigns($campaignIds)
{
$budgetLimitType = BudgetLimitType::DAILY_BUDGET_STANDARD;
$campaignType = CampaignType::SEARCH;
$request = new GetCampaignsByIdsRequest(
[
'AccountId' => self::CUSTOMER_ACCOUNT_ID,
'CampaignIds' => $campaignIds
]
);
$getCampaignsResponse = self::$campaignManagementServiceApi->getCampaignsByIds($request);
print("GetCampaignsByIds:\r\n");
print_r($getCampaignsResponse->getCampaigns());
print("PartialErrors:\r\n");
print_r($getCampaignsResponse->getPartialErrors());
self::assertEmpty($getCampaignsResponse->getPartialErrors());
self::assertEquals($budgetLimitType, $getCampaignsResponse->getCampaigns()[0]->getBudgetType());
self::assertEquals($campaignType, $getCampaignsResponse->getCampaigns()[0]->getCampaignType());
return $campaignIds;
}
/**
* @depends testGetCampaigns
* @throws ApiException
*/
public function testAdExtensions($campaignIds)
{
$imageAdExtensionMedia = $this->GetImageMedia(
"Image15x10",
$this->mediaFilePath.$this->imageAdExtensionMediaFileName
);
$addMedia = array();
$addMedia[] = $imageAdExtensionMedia;
print("-----\r\nAddMedia:\r\n");
$request = new AddMediaRequest(
[
'AccountId' => self::CUSTOMER_ACCOUNT_ID,
'Media' => $addMedia
]
);
$response = self::$campaignManagementServiceApi->addMedia($request);
$mediaIds = $response->getMediaIds();
print("MediaIds:\r\n");
print_r($mediaIds);
// Add the extensions to the account's library.
$adExtensions = array();
$extension = new ActionAdExtension();
$extension->setActionType(ActionAdExtensionActionType::ACT_NOW);
$extension->setFinalUrls(array("http://www.contoso.com/womenshoesale"));
$extension->setLanguage("English");
$extension->setStatus(AdExtensionStatus::ACTIVE);
$adExtensions[] = $extension;
$extension = new AppAdExtension();
$extension->setAppPlatform("Windows");
$extension->setAppStoreId("AppStoreIdGoesHere");
$extension->setDisplayText("Contoso");
$extension->setDestinationUrl("DestinationUrlGoesHere");
// If you supply the AppAdExtension properties above, then you can add this line.
//$adExtensions[] = $encodedExtension;
$extension = new CallAdExtension();
$extension->setCountryCode("US");
$extension->setPhoneNumber("2065550100");
$extension->setIsCallOnly(false);
// Include the call extension Monday - Friday from 9am - 9pm
// in the account's time zone.
$callScheduling = new Schedule();
$callDayTimeRanges = array();
for ($index = 0; $index < 5; $index++) {
$dayTime = new DayTime();
$dayTime->setStartHour(9);
$dayTime->setStartMinute(Minute::ZERO);
$dayTime->setEndHour(21);
$dayTime->setEndMinute(Minute::ZERO);
$callDayTimeRanges[] = $dayTime;
}
$callDayTimeRanges[0]->setDay(Day::MONDAY);
$callDayTimeRanges[1]->setDay(Day::TUESDAY);
$callDayTimeRanges[2]->setDay(Day::WEDNESDAY);
$callDayTimeRanges[3]->setDay(Day::THURSDAY);
$callDayTimeRanges[4]->setDay(Day::FRIDAY);
$callScheduling->setDayTimeRanges($callDayTimeRanges);
$callScheduling->setUseSearcherTimeZone(false);
$callScheduling->setStartDate(null);
$callSchedulingEndDate = new Date();
$callSchedulingEndDate->setDay(31);
$callSchedulingEndDate->setMonth(12);
$callSchedulingEndDate->setYear(date("Y"));
$callScheduling->setEndDate($callSchedulingEndDate);
$extension->setScheduling($callScheduling);
$adExtensions[] = $extension;
$extension = new CalloutAdExtension();
$extension->setText("Callout Text");
$adExtensions[] = $extension;
$extension = new LocationAdExtension();
$extension->setPhoneNumber("206-555-0100");
$extension->setCompanyName("Alpine Ski House");
$address = new Address();
$address->setStreetAddress("1234 Washington Place");
$address->setStreetAddress2("Suite 1210");
$address->setCityName("Woodinville");
$address->setProvinceName("WA");
$address->setCountryCode("US");
$address->setPostalCode("98608");
$extension->setAddress($address);
// Include the location extension every Saturday morning
// in the search user's time zone.
$locationScheduling = new Schedule();
$locationDayTimeRanges = array();
$locationDayTime = new DayTime();
$locationDayTime->setDay(Day::SATURDAY);
$locationDayTime->setStartHour(9);
$locationDayTime->setStartMinute(Minute::ZERO);
$locationDayTime->setEndHour(12);
$locationDayTime->setEndMinute(Minute::ZERO);
$locationDayTimeRanges[] = $locationDayTime;
$locationScheduling->setDayTimeRanges($locationDayTimeRanges);
$locationScheduling->setUseSearcherTimeZone(false);
$locationScheduling->setStartDate(null);
$locationSchedulingEndDate = new Date();
$locationSchedulingEndDate->setDay(31);
$locationSchedulingEndDate->setMonth(12);
$locationSchedulingEndDate->setYear(date("Y"));
$locationScheduling->setEndDate($locationSchedulingEndDate);
$extension->setScheduling($locationScheduling);
$adExtensions[] = $extension;
$extension = new PriceAdExtension();
$extension->setLanguage("English");
$extension->setPriceExtensionType('Events');
$tableRows = array();
$tableRowA = new PriceTableRow();
$tableRowA->setCurrencyCode("USD");
$tableRowA->setDescription("Come to the event");
$tableRowA->setFinalUrls(array("http://www.contoso.com/womenshoesale"));
$tableRowA->setHeader("New Event");
$tableRowA->setPrice(9.99);
$tableRowA->setPriceQualifier('From');
$tableRowA->setPriceUnit('PerDay');
$tableRows[] = $tableRowA;
$tableRowB = new PriceTableRow();
$tableRowB->setCurrencyCode("USD");
$tableRowB->setDescription("Come to the next event");
$tableRowB->setFinalUrls(array("http://www.contoso.com/womenshoesale"));
$tableRowB->setHeader("Next Event");
$tableRowB->setPrice(9.99);
$tableRowB->setPriceQualifier('From');
$tableRowB->setPriceUnit('PerDay');
$tableRows[] = $tableRowB;
$tableRowC = new PriceTableRow();
$tableRowC->setCurrencyCode("USD");
$tableRowC->setDescription("Come to the final event");
$tableRowC->setFinalUrls(array("http://www.contoso.com/womenshoesale"));
$tableRowC->setHeader("Final Event");
$tableRowC->setPrice(9.99);
$tableRowC->setPriceQualifier('From');
$tableRowC->setPriceUnit('PerDay');
$tableRows[] = $tableRowC;
$extension->setTableRows($tableRows);
$adExtensions[] = $extension;
$extension = new ReviewAdExtension();
$extension->setIsExact(true);
$extension->setSource("Review Source Name");
$extension->setText("Review Text");
// The Url of the third-party review. This is not your business Url.
$extension->setUrl("http://review.contoso.com");
$adExtensions[] = $extension;
$extension = new SitelinkAdExtension();
$extension->setDescription1("Simple & Transparent.");
$extension->setDescription2("No Upfront Cost.");
$extension->setDisplayText("Women's Shoe Sale");
$extension->setFinalUrls(array("http://www.contoso.com/womenshoesale"));
$adExtensions[] = $extension;
$extension = new StructuredSnippetAdExtension();
$extension->setHeader("Brands");
$extension->setValues(array("Windows", "Xbox", "Skype"));
$adExtensions[] = $extension;
// Add all extensions to the account's ad extension library
print("-----\r\nAddAdExtensions:\r\n");
$request = new AddAdExtensionsRequest(
[
'AccountId' => self::CUSTOMER_ACCOUNT_ID,
'AdExtensions' => $adExtensions
]
);
$response = self::$campaignManagementServiceApi->addAdExtensions($request);
$adExtensionIdentities = $response->getAdExtensionIdentities();
print("AdExtensionIdentities:\r\n");
print_r($adExtensionIdentities);
print("NestedPartialErrors:\r\n");
print_r($response->getNestedPartialErrors());
// DeleteAdExtensionsAssociations, SetAdExtensionsAssociations, and GetAdExtensionsEditorialReasons
// operations each require a list of type AdExtensionIdToEntityIdAssociation.
$adExtensionIdToEntityIdAssociations = array();
// GetAdExtensionsByIds requires a list of type long.
$adExtensionIds = array();
// Loop through the list of extension IDs and build any required data structures
// for subsequent operations.
for ($index = 0; $index < count($adExtensionIdentities); $index++) {
if (!empty($adExtensionIdentities[$index]) && $adExtensionIdentities[$index]->getId() !== null) {
$adExtensionIdToEntityIdAssociations[$index] = new AdExtensionIdToEntityIdAssociation();
$adExtensionIdToEntityIdAssociations[$index]->setAdExtensionId($adExtensionIdentities[$index]->getId());
$adExtensionIdToEntityIdAssociations[$index]->setEntityId($campaignIds[0]);
$adExtensionIds[$index] = $adExtensionIdentities[$index]->getId();
}
};
// Associate the ad extensions with the campaign.
print("-----\r\nSetAdExtensionsAssociations:\r\n");
$request = new SetAdExtensionsAssociationsRequest(
[
'AccountId' => self::CUSTOMER_ACCOUNT_ID,
'AdExtensionIdToEntityIdAssociations' => $adExtensionIdToEntityIdAssociations,
'AssociationType' => AssociationType::CAMPAIGN
]
);
$response = self::$campaignManagementServiceApi->setAdExtensionsAssociations($request);
print("PartialErrors:\r\n");
print_r($response->getPartialErrors());
self::assertEmpty($response->getPartialErrors());
// Get editorial rejection reasons for the respective ad extension and entity associations.
print("-----\r\nGetAdExtensionsEditorialReasons:\r\n");
$request = new GetAdExtensionsEditorialReasonsRequest(
[
'AccountId' => self::CUSTOMER_ACCOUNT_ID,
'AdExtensionIdToEntityIdAssociations' => $adExtensionIdToEntityIdAssociations,
'AssociationType' => AssociationType::CAMPAIGN
]
);
$response = self::$campaignManagementServiceApi->getAdExtensionsEditorialReasons($request);
$adExtensionEditorialReasonCollection = $response->getEditorialReasons();
print("EditorialReasons:\r\n");
print_r($adExtensionEditorialReasonCollection);
print("PartialErrors:\r\n");
print_r($response->getPartialErrors());
self::assertEmpty($response->getPartialErrors());
// Get only the location extensions and remove scheduling.
$adExtensionsTypeFilter = array(
AdExtensionsTypeFilter::LOCATION_AD_EXTENSION,
AdExtensionsTypeFilter::CALL_AD_EXTENSION
);
// In this example partial errors will be returned for indices where the ad extensions
// are not location ad extensions.
// This is an example, and ideally you would only send the required ad extension IDs.
print("-----\r\nGetAdExtensionsByIds:\r\n");
$request = new GetAdExtensionsByIdsRequest(
[
'AccountId' => self::CUSTOMER_ACCOUNT_ID,
'AdExtensionIds' => $adExtensionIds,
'AdExtensionType' => $adExtensionsTypeFilter,
'ReturnAdditionalFields' => null
]
);
$response = self::$campaignManagementServiceApi->getAdExtensionsByIds($request);
$adExtensions = $response->getAdExtensions();
print("AdExtensions:\r\n");
print_r($adExtensions);
print("PartialErrors:\r\n");
print_r($response->getPartialErrors());
self::assertNotEmpty($response->getPartialErrors());
$updateExtensions = array();
foreach ($adExtensions as $extension) {
// GetAdExtensionsByIds will return a nil element if the request filters / conditions were not met.
if (!empty($extension) && $extension->getId() !== null) {
// Remove read-only elements that would otherwise cause the update operation to fail.
$updateExtension = $extension;
$updateExtension->offsetUnset('Version');
$updateExtension->offsetUnset('GeoCodeStatus');
// If you set the Scheduling element null, any existing scheduling set for the ad extension will remain unchanged.
// If you set this to any non-null Schedule object, you are effectively replacing existing scheduling
// for the ad extension. In this example, we will remove any existing scheduling by setting this element
// to an empty Schedule object.
$updateExtension->setScheduling(new Schedule());
$updateExtensions[] = $updateExtension;
}
}
print("-----\r\nUpdateAdExtensions:\r\n");
$request = new UpdateAdExtensionsRequest(
[
'AccountId' => self::CUSTOMER_ACCOUNT_ID,
'AdExtensions' => $updateExtensions
]
);
$response = self::$campaignManagementServiceApi->updateAdExtensions($request);
print_r($request);
print("NestedPartialErrors:\r\n");
print_r($response->getNestedPartialErrors());
self::assertEmpty($response->getNestedPartialErrors());
print("Removed scheduling from the location ad extensions.\r\n");
// Get only the location extension to output the result.
print("-----\r\nGetAdExtensionsByIds:\r\n");
$request = new GetAdExtensionsByIdsRequest(
[
'AccountId' => self::CUSTOMER_ACCOUNT_ID,
'AdExtensionIds' => $adExtensionIds,
'AdExtensionType' => $adExtensionsTypeFilter,
'ReturnAdditionalFields' => null
]
);
$response = self::$campaignManagementServiceApi->getAdExtensionsByIds($request);
print("AdExtensions:\r\n");
print_r($response->getAdExtensions());
print("PartialErrors:\r\n");
print_r($response->getPartialErrors());
self::assertNotEmpty($response->getPartialErrors());
self::assertNotEmpty($response->getAdExtensions());
foreach ($response->getAdExtensions() as $adExtension) {
if (!empty($adExtension) && $adExtension->getId() !== null) {
self::assertNull($adExtension->getScheduling());
}
}
// Delete the ad extension associations, ad extensions, and campaign, that were previously added.
// At this point the ad extensions are still available in the account's ad extensions library.
print("-----\r\nDeleteAdExtensionsAssociations:\r\n");
$request = new DeleteAdExtensionsAssociationsRequest(
[
'AccountId' => self::CUSTOMER_ACCOUNT_ID,
'AdExtensionIdToEntityIdAssociations' => $adExtensionIdToEntityIdAssociations,
'AssociationType' => AssociationType::CAMPAIGN
]
);
$response = self::$campaignManagementServiceApi->deleteAdExtensionsAssociations($request);
print("PartialErrors:\r\n");
print_r($response->getPartialErrors());
self::assertEmpty($response->getPartialErrors());
// Deletes the ad extensions from the account's ad extension library.
print("-----\r\nDeleteAdExtensions:\r\n");
$request = new DeleteAdExtensionsRequest(
[
'AccountId' => self::CUSTOMER_ACCOUNT_ID,
'AdExtensionIds' => $adExtensionIds
]
);
$response = self::$campaignManagementServiceApi->deleteAdExtensions($request);
print("PartialErrors:\r\n");
print_r($response->getPartialErrors());
self::assertEmpty($response->getPartialErrors());
print("Deleted ad extensions.\r\n");
// Delete the account's media that was used for the image ad extension.
print("-----\r\nDeleteMedia:\r\n");
$request = new DeleteMediaRequest(
[
'AccountId' => self::CUSTOMER_ACCOUNT_ID,
'MediaIds' => $mediaIds
]
);
$response = self::$campaignManagementServiceApi->deleteMedia($request);
print("PartialErrors:\r\n");
print_r($response->getPartialErrors());
self::assertEmpty($response->getPartialErrors());
foreach ($mediaIds as $id) {
printf("Deleted Media Id %s\r\n", $id);
}
// Delete the campaign and everything it contains e.g., ad groups and ads.
self::deleteCampaignsRequest($campaignIds);
}
}
import uuid
from auth_helper import *
from openapi_client.models.campaign import *
# Media file path - update with your own image
MEDIA_FILE_PATH = "c:\\dev\\media\\"
IMAGE_AD_EXTENSION_FILE_NAME = "imageadextension300x200.png"
def main(authorization_data):
try:
# Create a search campaign
print("Creating campaign...")
campaign = Campaign(
name="Women's Shoes " + str(uuid.uuid4()),
budget_type=BudgetLimitType.DAILYBUDGETSTANDARD,
daily_budget=50.00,
languages=['All'],
time_zone='PacificTimeUSCanadaTijuana',
campaign_type=CampaignType.SEARCH
)
add_campaigns_request = AddCampaignsRequest(
account_id=authorization_data.account_id,
campaigns=[campaign]
)
add_campaigns_response = campaign_service.add_campaigns(
add_campaigns_request=add_campaigns_request
)
campaign_ids = add_campaigns_response.CampaignIds
print(f"Created Campaign ID: {campaign_ids[0]}")
# Create ad extensions
print("\nCreating ad extensions...")
ad_extensions = []
# Action Ad Extension
action_extension = ActionAdExtension(
action_type=ActionAdExtensionActionType.ACTNOW,
final_urls=["http://www.contoso.com/womenshoesale"],
language="English",
status=AdExtensionStatus.ACTIVE
)
ad_extensions.append(action_extension)
# Call Ad Extension with scheduling
call_extension = CallAdExtension(
country_code="US",
phone_number="2065550100",
is_call_only=False
)
# Schedule for Monday-Friday 9am-9pm
call_day_time_ranges = []
for day in [Day.MONDAY, Day.TUESDAY, Day.WEDNESDAY, Day.THURSDAY, Day.FRIDAY]:
day_time = DayTime(
day=day,
start_hour=9,
start_minute=Minute.ZERO,
end_hour=21,
end_minute=Minute.ZERO
)
call_day_time_ranges.append(day_time)
from datetime import datetime
current_year = datetime.now().year
call_scheduling = Schedule(
day_time_ranges=call_day_time_ranges,
use_searcher_time_zone=False,
start_date=None,
end_date=Date(day=31, month=12, year=current_year)
)
call_extension.Scheduling = call_scheduling
ad_extensions.append(call_extension)
# Callout Ad Extension
callout_extension = CalloutAdExtension(
text="Callout Text"
)
ad_extensions.append(callout_extension)
# Location Ad Extension
location_extension = LocationAdExtension(
phone_number="206-555-0100",
company_name="Alpine Ski House",
address=Address(
street_address="1234 Washington Place",
street_address2="Suite 1210",
city_name="Woodinville",
province_name="WA",
country_code="US",
postal_code="98608"
)
)
# Schedule for Saturday morning
location_day_time = DayTime(
day=Day.SATURDAY,
start_hour=9,
start_minute=Minute.ZERO,
end_hour=12,
end_minute=Minute.ZERO
)
location_scheduling = Schedule(
day_time_ranges=[location_day_time],
use_searcher_time_zone=False,
start_date=None,
end_date=Date(day=31, month=12, year=current_year)
)
location_extension.Scheduling = location_scheduling
ad_extensions.append(location_extension)
# Price Ad Extension
price_extension = PriceAdExtension(
language="English",
price_extension_type="Events",
table_rows=[
PriceTableRow(
currency_code="USD",
description="Come to the event",
final_urls=["http://www.contoso.com/womenshoesale"],
header="New Event",
price=9.99,
price_qualifier="From",
price_unit="PerDay"
),
PriceTableRow(
currency_code="USD",
description="Come to the next event",
final_urls=["http://www.contoso.com/womenshoesale"],
header="Next Event",
price=9.99,
price_qualifier="From",
price_unit="PerDay"
),
PriceTableRow(
currency_code="USD",
description="Come to the final event",
final_urls=["http://www.contoso.com/womenshoesale"],
header="Final Event",
price=9.99,
price_qualifier="From",
price_unit="PerDay"
)
]
)
ad_extensions.append(price_extension)
# Review Ad Extension
review_extension = ReviewAdExtension(
is_exact=True,
source="Review Source Name",
text="Review Text",
url="http://review.contoso.com"
)
ad_extensions.append(review_extension)
# Sitelink Ad Extension
sitelink_extension = SitelinkAdExtension(
description1="Simple & Transparent.",
description2="No Upfront Cost.",
display_text="Women's Shoe Sale",
final_urls=["http://www.contoso.com/womenshoesale"]
)
ad_extensions.append(sitelink_extension)
# Structured Snippet Ad Extension
structured_snippet_extension = StructuredSnippetAdExtension(
header="Brands",
values=["Windows", "Xbox", "Skype"]
)
ad_extensions.append(structured_snippet_extension)
# Add all extensions to the account's ad extension library
add_extensions_request = AddAdExtensionsRequest(
account_id=authorization_data.account_id,
ad_extensions=ad_extensions
)
add_extensions_response = campaign_service.add_ad_extensions(
add_ad_extensions_request=add_extensions_request
)
ad_extension_identities = add_extensions_response.AdExtensionIdentities
print(f"Added {len(ad_extension_identities)} ad extensions")
if add_extensions_response.NestedPartialErrors:
print(f"Nested Partial Errors: {add_extensions_response.NestedPartialErrors}")
# Build associations
ad_extension_id_to_entity_id_associations = []
ad_extension_ids = []
for identity in ad_extension_identities:
if identity and identity.Id:
association = AdExtensionIdToEntityIdAssociation(
ad_extension_id=identity.Id,
entity_id=campaign_ids[0]
)
ad_extension_id_to_entity_id_associations.append(association)
ad_extension_ids.append(identity.Id)
# Associate the ad extensions with the campaign
print("\nAssociating ad extensions with campaign...")
set_associations_request = SetAdExtensionsAssociationsRequest(
account_id=authorization_data.account_id,
ad_extension_id_to_entity_id_associations=ad_extension_id_to_entity_id_associations,
association_type=AssociationType.CAMPAIGN
)
set_associations_response = campaign_service.set_ad_extensions_associations(
set_ad_extensions_associations_request=set_associations_request
)
if set_associations_response.PartialErrors:
print(f"Partial Errors: {set_associations_response.PartialErrors}")
else:
print("Ad extensions successfully associated with campaign")
# Get editorial rejection reasons
print("\nGetting editorial reasons...")
get_editorial_request = GetAdExtensionsEditorialReasonsRequest(
account_id=authorization_data.account_id,
ad_extension_id_to_entity_id_associations=ad_extension_id_to_entity_id_associations,
association_type=AssociationType.CAMPAIGN
)
editorial_response = campaign_service.get_ad_extensions_editorial_reasons(
get_ad_extensions_editorial_reasons_request=get_editorial_request
)
if editorial_response.EditorialReasons:
print(f"Editorial Reasons: {editorial_response.EditorialReasons}")
# Get location and call extensions
print("\nGetting location and call extensions...")
get_extensions_request = GetAdExtensionsByIdsRequest(
account_id=authorization_data.account_id,
ad_extension_ids=ad_extension_ids,
ad_extension_type= AdExtensionsTypeFilter.LOCATIONADEXTENSION | AdExtensionsTypeFilter.CALLADEXTENSION
,
return_additional_fields=None
)
get_extensions_response = campaign_service.get_ad_extensions_by_ids(
get_ad_extensions_by_ids_request=get_extensions_request
)
extensions_to_update = []
for extension in get_extensions_response.AdExtensions:
if extension and extension.Id:
# Remove scheduling
extension.Scheduling = Schedule()
extensions_to_update.append(extension)
# Update extensions to remove scheduling
if extensions_to_update:
print("\nUpdating extensions to remove scheduling...")
update_request = UpdateAdExtensionsRequest(
account_id=authorization_data.account_id,
ad_extensions=extensions_to_update
)
update_response = campaign_service.update_ad_extensions(
update_ad_extensions_request=update_request
)
if update_response.NestedPartialErrors:
print(f"Nested Partial Errors: {update_response.NestedPartialErrors}")
else:
print("Removed scheduling from extensions")
# Clean up - delete associations
print("\nDeleting ad extension associations...")
delete_associations_request = DeleteAdExtensionsAssociationsRequest(
account_id=authorization_data.account_id,
ad_extension_id_to_entity_id_associations=ad_extension_id_to_entity_id_associations,
association_type=AssociationType.CAMPAIGN
)
delete_associations_response = campaign_service.delete_ad_extensions_associations(
delete_ad_extensions_associations_request=delete_associations_request
)
if delete_associations_response.PartialErrors:
print(f"Partial Errors: {delete_associations_response.PartialErrors}")
# Delete ad extensions
print("Deleting ad extensions...")
delete_extensions_request = DeleteAdExtensionsRequest(
account_id=authorization_data.account_id,
ad_extension_ids=ad_extension_ids
)
delete_extensions_response = campaign_service.delete_ad_extensions(
delete_ad_extensions_request=delete_extensions_request
)
if delete_extensions_response.PartialErrors:
print(f"Partial Errors: {delete_extensions_response.PartialErrors}")
else:
print("Deleted ad extensions")
# Delete campaign
print("Deleting campaign...")
delete_campaigns_request = DeleteCampaignsRequest(
account_id=authorization_data.account_id,
campaign_ids=campaign_ids
)
campaign_service.delete_campaigns(
delete_campaigns_request=delete_campaigns_request
)
print(f"Deleted Campaign ID {campaign_ids[0]}")
except Exception as ex:
print(f"Error occurred: {str(ex)}")
if __name__ == '__main__':
print("Loading the web service client...")
authorization_data = AuthorizationData(
account_id=None,
customer_id=None,
developer_token=DEVELOPER_TOKEN,
authentication=None,
)
authenticate(authorization_data)
campaign_service = ServiceClient(
service='CampaignManagementService',
version=13,
authorization_data=authorization_data,
environment=ENVIRONMENT,
)
main(authorization_data)