Java
// Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.ads.googleads.examples.advancedoperations; import static com.google.ads.googleads.examples.utils.CodeSampleHelper.getShortPrintableDateTime; import com.beust.jcommander.Parameter; import com.google.ads.googleads.examples.utils.ArgumentNames; import com.google.ads.googleads.examples.utils.CodeSampleParams; import com.google.ads.googleads.lib.GoogleAdsClient; import com.google.ads.googleads.v11.common.ExpandedTextAdInfo; import com.google.ads.googleads.v11.enums.AdCustomizerPlaceholderFieldEnum.AdCustomizerPlaceholderField; import com.google.ads.googleads.v11.enums.FeedAttributeTypeEnum.FeedAttributeType; import com.google.ads.googleads.v11.enums.PlaceholderTypeEnum.PlaceholderType; import com.google.ads.googleads.v11.errors.GoogleAdsError; import com.google.ads.googleads.v11.errors.GoogleAdsException; import com.google.ads.googleads.v11.resources.Ad; import com.google.ads.googleads.v11.resources.AdGroupAd; import com.google.ads.googleads.v11.resources.AttributeFieldMapping; import com.google.ads.googleads.v11.resources.Feed; import com.google.ads.googleads.v11.resources.FeedAttribute; import com.google.ads.googleads.v11.resources.FeedItem; import com.google.ads.googleads.v11.resources.FeedItemAttributeValue; import com.google.ads.googleads.v11.resources.FeedItemTarget; import com.google.ads.googleads.v11.resources.FeedMapping; import com.google.ads.googleads.v11.services.AdGroupAdOperation; import com.google.ads.googleads.v11.services.AdGroupAdServiceClient; import com.google.ads.googleads.v11.services.FeedItemOperation; import com.google.ads.googleads.v11.services.FeedItemServiceClient; import com.google.ads.googleads.v11.services.FeedItemTargetOperation; import com.google.ads.googleads.v11.services.FeedItemTargetServiceClient; import com.google.ads.googleads.v11.services.FeedMappingOperation; import com.google.ads.googleads.v11.services.FeedMappingServiceClient; import com.google.ads.googleads.v11.services.FeedOperation; import com.google.ads.googleads.v11.services.FeedServiceClient; import com.google.ads.googleads.v11.services.GoogleAdsServiceClient; import com.google.ads.googleads.v11.services.GoogleAdsServiceClient.SearchPagedResponse; import com.google.ads.googleads.v11.services.MutateAdGroupAdResult; import com.google.ads.googleads.v11.services.MutateAdGroupAdsResponse; import com.google.ads.googleads.v11.services.MutateFeedItemResult; import com.google.ads.googleads.v11.services.MutateFeedItemTargetsResponse; import com.google.ads.googleads.v11.services.MutateFeedItemsResponse; import com.google.ads.googleads.v11.services.MutateFeedMappingsResponse; import com.google.ads.googleads.v11.services.MutateFeedsResponse; import com.google.ads.googleads.v11.services.SearchGoogleAdsRequest; import com.google.ads.googleads.v11.utils.ResourceNames; import com.google.common.collect.ImmutableList; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.joda.time.DateTime; /** * Adds an ad customizer feed and associates it with the customer. Then it adds an ad that uses the * feed to populate dynamic data. */ public class AddAdCustomizer { // We're doing only searches by resource_name in this example, we can set page size = 1. private static final int PAGE_SIZE = 1; // We're creating two different ad groups to be dynamically populated by the same feed. private static final int NUMBER_OF_AD_GROUPS = 2; private static class AddAdCustomizerParams extends CodeSampleParams { @Parameter(names = ArgumentNames.CUSTOMER_ID, required = true) private Long customerId; @Parameter(names = ArgumentNames.AD_GROUP_IDS, required = true) private List<Long> adGroupIds; } public static void main(String[] args) throws IOException { AddAdCustomizerParams params = new AddAdCustomizerParams(); if (!params.parseArguments(args)) { // Either pass the required parameters for this example on the command line, or insert them // into the code here. See the parameter class definition above for descriptions. params.customerId = Long.parseLong("INSERT_CUSTOMER_ID_HERE"); params.adGroupIds = Arrays.asList( Long.parseLong("INSERT_AD_GROUP_ID_HERE"), Long.parseLong("INSERT_AD_GROUP_ID_HERE")); } GoogleAdsClient googleAdsClient = null; try { googleAdsClient = GoogleAdsClient.newBuilder().fromPropertiesFile().build(); } catch (FileNotFoundException fnfe) { System.err.printf( "Failed to load GoogleAdsClient configuration from file. Exception: %s%n", fnfe); System.exit(1); } catch (IOException ioe) { System.err.printf("Failed to create GoogleAdsClient. Exception: %s%n", ioe); System.exit(1); } try { new AddAdCustomizer().runExample(googleAdsClient, params); } catch (GoogleAdsException gae) { // GoogleAdsException is the base class for most exceptions thrown by an API request. // Instances of this exception have a message and a GoogleAdsFailure that contains a // collection of GoogleAdsErrors that indicate the underlying causes of the // GoogleAdsException. System.err.printf( "Request ID %s failed due to GoogleAdsException. Underlying errors:%n", gae.getRequestId()); int i = 0; for (GoogleAdsError googleAdsError : gae.getGoogleAdsFailure().getErrorsList()) { System.err.printf(" Error %d: %s%n", i++, googleAdsError); } System.exit(1); } } /** * Runs the example. * * @param googleAdsClient the Google Ads API client. * @param params the example parameters. * @throws GoogleAdsException if an API request failed with one or more service errors. */ private void runExample(GoogleAdsClient googleAdsClient, AddAdCustomizerParams params) { if (params.adGroupIds.size() != NUMBER_OF_AD_GROUPS) { throw new IllegalArgumentException( "Please pass exactly two ad group IDs in the adGroupId parameter."); } String feedName = "Ad Customizer example feed " + getShortPrintableDateTime(); // Create a feed to be used as the ad customizer. String adCustomizerFeedResourceName = createAdCustomizerFeed(googleAdsClient, params.customerId, feedName); // Retrieve the attributes for the newly created feed. Map<String, FeedAttribute> adCustomizerFeedAttributes = getFeedAttributes(googleAdsClient, params.customerId, adCustomizerFeedResourceName); // Map the feed to the ad customizer placeholder type to mark it as an ad customizer. createAdCustomizerMapping( googleAdsClient, params.customerId, adCustomizerFeedResourceName, adCustomizerFeedAttributes); // Create the feed items that will fill the placeholders in the ads customized by the feed. List<String> feedItemResourceNames = createFeedItems( googleAdsClient, params.customerId, adCustomizerFeedResourceName, adCustomizerFeedAttributes); // Create a feed item targeting to associate the feed items with specific ad groups to // prevent them from being used in other ways. createFeedItemTargets( googleAdsClient, params.customerId, params.adGroupIds, feedItemResourceNames); // Create ads with the customizations provided by the feed items. createAdsWithCustomizations(googleAdsClient, params.customerId, params.adGroupIds, feedName); } /** * Creates a feed to be used for ad customization. * * @param googleAdsClient the Google Ads API client. * @param customerId the client customer ID. * @param feedName the name of the feed to create. * @return the resource name of the newly created feed. */ private String createAdCustomizerFeed( GoogleAdsClient googleAdsClient, long customerId, String feedName) { // Creates three feed attributes: a name, a price and a date. The attribute names are arbitrary // choices and will be used as placeholders in the ad text fields. FeedAttribute nameAttribute = FeedAttribute.newBuilder().setName("Name").setType(FeedAttributeType.STRING).build(); FeedAttribute priceAttribute = FeedAttribute.newBuilder().setName("Price").setType(FeedAttributeType.STRING).build(); FeedAttribute dateAttribute = FeedAttribute.newBuilder().setName("Date").setType(FeedAttributeType.DATE_TIME).build(); Feed adCustomizerFeed = Feed.newBuilder() .setName(feedName) .addAttributes(nameAttribute) .addAttributes(priceAttribute) .addAttributes(dateAttribute) .build(); FeedOperation feedOperation = FeedOperation.newBuilder().setCreate(adCustomizerFeed).build(); try (FeedServiceClient feedServiceClient = googleAdsClient.getLatestVersion().createFeedServiceClient()) { MutateFeedsResponse response = feedServiceClient.mutateFeeds(Long.toString(customerId), ImmutableList.of(feedOperation)); String feedResourceName = response.getResults(0).getResourceName(); System.out.printf("Added feed with resource name %s.%n", feedResourceName); return feedResourceName; } } /** * Retrieves all the attributes for a feed and returns them in a map using the attribute names as * keys. * * @param googleAdsClient the Google Ads API client. * @param customerId the client customer ID. * @param feedResourceName the resource name of the feed. * @return the attributes of the feed. */ private Map<String, FeedAttribute> getFeedAttributes( GoogleAdsClient googleAdsClient, long customerId, String feedResourceName) { String query = String.format( "SELECT feed.attributes, feed.name FROM feed WHERE feed.resource_name = '%s'", feedResourceName); SearchGoogleAdsRequest request = SearchGoogleAdsRequest.newBuilder() .setCustomerId(Long.toString(customerId)) .setPageSize(PAGE_SIZE) .setQuery(query) .build(); Map<String, FeedAttribute> feedAttributes = new HashMap<>(); try (GoogleAdsServiceClient googleAdsServiceClient = googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { SearchPagedResponse searchPagedResponse = googleAdsServiceClient.search(request); Feed feed = searchPagedResponse.iterateAll().iterator().next().getFeed(); System.out.printf( "Found the following attributes for feed with name '%s':%n", feed.getName()); for (FeedAttribute feedAttribute : feed.getAttributesList()) { System.out.printf( "\t'%s' with id %d and type '%s'%n", feedAttribute.getName(), feedAttribute.getId(), feedAttribute.getType()); feedAttributes.put(feedAttribute.getName(), feedAttribute); } } return feedAttributes; } /** * Creates a feed mapping and sets the feed as an ad customizer feed. * * @param googleAdsClient the Google Ads API client. * @param customerId the client customer ID. * @param feedResourceName the resource name of the feed. * @param feedAttributes the attributes of the feed. */ private void createAdCustomizerMapping( GoogleAdsClient googleAdsClient, long customerId, String feedResourceName, Map<String, FeedAttribute> feedAttributes) { // Map the feed attributes to ad customizer placeholder fields. // For a full list of ad customizer placeholder fields, see // https://developers.google.com/google-ads/api/reference/rpc/latest/AdCustomizerPlaceholderFieldEnum.AdCustomizerPlaceholderField AttributeFieldMapping nameFieldMapping = AttributeFieldMapping.newBuilder() .setFeedAttributeId(feedAttributes.get("Name").getId()) .setAdCustomizerField(AdCustomizerPlaceholderField.STRING) .build(); AttributeFieldMapping priceFieldMapping = AttributeFieldMapping.newBuilder() .setFeedAttributeId(feedAttributes.get("Price").getId()) .setAdCustomizerField(AdCustomizerPlaceholderField.PRICE) .build(); AttributeFieldMapping dateFieldMapping = AttributeFieldMapping.newBuilder() .setFeedAttributeId(feedAttributes.get("Date").getId()) .setAdCustomizerField(AdCustomizerPlaceholderField.DATE) .build(); FeedMapping feedMapping = FeedMapping.newBuilder() .setFeed(feedResourceName) // Sets the feed to the AD_CUSTOMIZER placeholder type. .setPlaceholderType(PlaceholderType.AD_CUSTOMIZER) .addAttributeFieldMappings(nameFieldMapping) .addAttributeFieldMappings(priceFieldMapping) .addAttributeFieldMappings(dateFieldMapping) .build(); FeedMappingOperation feedMappingOperation = FeedMappingOperation.newBuilder().setCreate(feedMapping).build(); try (FeedMappingServiceClient feedMappingServiceClient = googleAdsClient.getLatestVersion().createFeedMappingServiceClient()) { MutateFeedMappingsResponse response = feedMappingServiceClient.mutateFeedMappings( Long.toString(customerId), ImmutableList.of(feedMappingOperation)); System.out.printf( "Added feed mapping with resource name %s.%n", response.getResults(0).getResourceName()); } } /** * Creates two different feed items to enable two different ad customizations. * * @param googleAdsClient the Google Ads API client. * @param customerId the client customer ID. * @param feedResourceName the resource name of the feed. * @param feedAttributes the attributes of the feed. * @return the resource names of the feed items. */ private List<String> createFeedItems( GoogleAdsClient googleAdsClient, long customerId, String feedResourceName, Map<String, FeedAttribute> feedAttributes) { List<FeedItemOperation> feedItemOperations = new ArrayList<>(); DateTime marsDate = DateTime.now().withDayOfMonth(1).withHourOfDay(0).withMinuteOfHour(0); feedItemOperations.add( createFeedItemOperation( "Mars", "$1234.56", marsDate.toString("yyyyMMdd HHmmss"), feedResourceName, feedAttributes)); DateTime venusDate = DateTime.now().withDayOfMonth(15).withHourOfDay(0).withMinuteOfHour(0); feedItemOperations.add( createFeedItemOperation( "Venus", "$1450.00", venusDate.toString("yyyyMMdd HHmmss"), feedResourceName, feedAttributes)); try (FeedItemServiceClient feedItemServiceClient = googleAdsClient.getLatestVersion().createFeedItemServiceClient()) { List<String> feedItemResourceNames = new ArrayList<>(); MutateFeedItemsResponse response = feedItemServiceClient.mutateFeedItems(Long.toString(customerId), feedItemOperations); System.out.printf("Added %d feed items:%n", response.getResultsCount()); for (MutateFeedItemResult result : response.getResultsList()) { String feedItemResourceName = result.getResourceName(); feedItemResourceNames.add(feedItemResourceName); System.out.printf("Added feed item with resource name %s.%n", feedItemResourceName); } return feedItemResourceNames; } } /** * Helper function to create a FeedItemOperation. * * @param name the value of the Name attribute. * @param price the value of the Price attribute. * @param date the value of the Date attribute. * @param feedResourceName the resource name of the feed. * @param feedAttributes the attributes to be set on the feed. * @return a FeedItemOperation to create a feed item. */ private FeedItemOperation createFeedItemOperation( String name, String price, String date, String feedResourceName, Map<String, FeedAttribute> feedAttributes) { FeedItemAttributeValue nameAttributeValue = FeedItemAttributeValue.newBuilder() .setFeedAttributeId(feedAttributes.get("Name").getId()) .setStringValue(name) .build(); FeedItemAttributeValue priceAttributeValue = FeedItemAttributeValue.newBuilder() .setFeedAttributeId(feedAttributes.get("Price").getId()) .setStringValue(price) .build(); FeedItemAttributeValue dateAttributeValue = FeedItemAttributeValue.newBuilder() .setFeedAttributeId(feedAttributes.get("Date").getId()) .setStringValue(date) .build(); FeedItem feedItem = FeedItem.newBuilder() .setFeed(feedResourceName) .addAttributeValues(nameAttributeValue) .addAttributeValues(priceAttributeValue) .addAttributeValues(dateAttributeValue) .build(); return FeedItemOperation.newBuilder().setCreate(feedItem).build(); } /** * Restricts the feed items to work only with a specific ad group; this prevents the feed items * from being used elsewhere and makes sure they are used only for customizing a specific ad * group. * * @param googleAdsClient the Google Ads API client. * @param customerId the client customer ID. * @param adGroupIds the ad group IDs to bind the feed items to. * @param feedItemResourceNames the resource names of the feed items. */ private void createFeedItemTargets( GoogleAdsClient googleAdsClient, long customerId, List<Long> adGroupIds, List<String> feedItemResourceNames) { // Bind each feed item to a specific ad group to make sure it will only be used to customize // ads inside that ad group; using the feed item elsewhere will result in an error. for (int i = 0; i < feedItemResourceNames.size(); i++) { String feedItemResourceName = feedItemResourceNames.get(i); Long adGroupId = adGroupIds.get(i); FeedItemTarget feedItemTarget = FeedItemTarget.newBuilder() .setAdGroup(ResourceNames.adGroup(customerId, adGroupId)) .setFeedItem(feedItemResourceName) .build(); FeedItemTargetOperation feedItemTargetOperation = FeedItemTargetOperation.newBuilder().setCreate(feedItemTarget).build(); try (FeedItemTargetServiceClient feedItemTargetServiceClient = googleAdsClient.getLatestVersion().createFeedItemTargetServiceClient()) { MutateFeedItemTargetsResponse response = feedItemTargetServiceClient.mutateFeedItemTargets( Long.toString(customerId), ImmutableList.of(feedItemTargetOperation)); String feedItemTargetResourceName = response.getResults(0).getResourceName(); System.out.printf( "Added feed item target with resource name '%s'.%n", feedItemTargetResourceName); } } } /** * Creates expanded text ads that use the ad customizer feed to populate the placeholders. * * @param googleAdsClient the Google Ads API client. * @param customerId the client customer ID. * @param adGroupIds the ad group IDs in which to create the ads. * @param feedName the name of the feed. */ private void createAdsWithCustomizations( GoogleAdsClient googleAdsClient, long customerId, List<Long> adGroupIds, String feedName) { // Creates an expanded text ad using the feed attribute names as placeholders. ExpandedTextAdInfo expandedTextAdInfo = ExpandedTextAdInfo.newBuilder() .setHeadlinePart1(String.format("Luxury cruise to {=%s.Name}", feedName)) .setHeadlinePart2(String.format("Only {=%s.Price}", feedName)) .setDescription(String.format("Offer ends in {=countdown(%s.Date)}!", feedName)) .build(); Ad ad = Ad.newBuilder() .setExpandedTextAd(expandedTextAdInfo) .addFinalUrls("http://www.example.com") .build(); List<AdGroupAdOperation> adGroupAdOperations = new ArrayList<>(); // Creates the same ad in all ad groups. When they serve, they will show different values, // since they match different feed items. for (Long adGroupId : adGroupIds) { AdGroupAd adGroupAd = AdGroupAd.newBuilder() .setAd(ad) .setAdGroup(ResourceNames.adGroup(customerId, adGroupId)) .build(); AdGroupAdOperation adGroupAdOperation = AdGroupAdOperation.newBuilder().setCreate(adGroupAd).build(); adGroupAdOperations.add(adGroupAdOperation); } try (AdGroupAdServiceClient adGroupAdServiceClient = googleAdsClient.getLatestVersion().createAdGroupAdServiceClient()) { MutateAdGroupAdsResponse response = adGroupAdServiceClient.mutateAdGroupAds(Long.toString(customerId), adGroupAdOperations); System.out.printf("Added %d ads:%n", response.getResultsCount()); for (MutateAdGroupAdResult result : response.getResultsList()) { System.out.printf("Added an ad with resource name '%s'.%n", result.getResourceName()); } } } }
C#
// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using CommandLine; using Google.Ads.Gax.Examples; using Google.Ads.GoogleAds.Lib; using Google.Ads.GoogleAds.V11.Common; using Google.Ads.GoogleAds.V11.Errors; using Google.Ads.GoogleAds.V11.Resources; using Google.Ads.GoogleAds.V11.Services; using System; using System.Collections.Generic; using System.Linq; using static Google.Ads.GoogleAds.V11.Enums.AdCustomizerPlaceholderFieldEnum.Types; using static Google.Ads.GoogleAds.V11.Enums.FeedAttributeTypeEnum.Types; using static Google.Ads.GoogleAds.V11.Enums.PlaceholderTypeEnum.Types; namespace Google.Ads.GoogleAds.Examples.V11 { /// <summary> /// This code example adds an ad customizer feed and associates it with the customer. /// Then it adds an ad that uses the feed to populate dynamic data. /// </summary> public class AddAdCustomizer : ExampleBase { /// <summary> /// Command line options for running the <see cref="AddAdCustomizer"/> example. /// </summary> public class Options : OptionsBase { /// <summary> /// The Google Ads customer ID for which the call is made. /// </summary> [Option("customerId", Required = true, HelpText = "The Google Ads customer ID for which the call is made.")] public long CustomerId { get; set; } /// <summary> /// ID of the ad groups to which ad customizers are added. /// </summary> [Option("adGroupIds", Required = true, HelpText = "ID of the ad groups to which ad customizers are added.")] public IEnumerable<long> AdGroupIds { get; set; } } /// <summary> /// Main method, to run this code example as a standalone application. /// </summary> /// <param name="args">The command line arguments.</param> public static void Main(string[] args) { Options options = ExampleUtilities.ParseCommandLine<Options>(args); AddAdCustomizer codeExample = new AddAdCustomizer(); Console.WriteLine(codeExample.Description); codeExample.Run(new GoogleAdsClient(), options.CustomerId, options.AdGroupIds.ToArray()); } /// <summary> /// Returns a description about the code example. /// </summary> public override string Description => "This code example adds an ad customizer feed and associates it with the customer. " + "Then it adds an ad that uses the feed to populate dynamic data."; /// <summary> /// Runs the code example. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <param name="adGroupIds">ID of the ad groups to which ad customizers are added.</param> public void Run(GoogleAdsClient client, long customerId, long[] adGroupIds) { // Get the AdGroupBidModifierService. AdGroupBidModifierServiceClient adGroupBidModifierService = client.GetService(Services.V11.AdGroupBidModifierService); string feedName = "Ad_Customizer_example_feed_" + ExampleUtilities.GetShortRandomString(); try { // Create a feed to be used as the ad customizer. string adCustomizerFeedResourceName = CreateAdCustomizerFeed(client, customerId, feedName); // Retrieve the attributes for the newly created feed. Dictionary<string, FeedAttribute> adCustomizerFeedAttributes = GetFeedAttributes(client, customerId, adCustomizerFeedResourceName); // Map the feed to the ad customizer placeholder type to mark it as an // ad customizer. CreateAdCustomizerMapping(client, customerId, adCustomizerFeedResourceName, adCustomizerFeedAttributes); // Create the feed items that will fill the placeholders in the ads customized by // the feed. List<string> feedItemResourceNames = CreateFeedItems(client, customerId, adCustomizerFeedResourceName, adCustomizerFeedAttributes); // Create a feed item targeting to associate the feed items with specific // ad groups to prevent them from being used in other ways. CreateFeedItemTargets(client, customerId, adGroupIds, feedItemResourceNames); // Create ads with the customizations provided by the feed items. CreateAdsWithCustomizations(client, customerId, adGroupIds, feedName); } catch (GoogleAdsException e) { Console.WriteLine("Failure:"); Console.WriteLine($"Message: {e.Message}"); Console.WriteLine($"Failure: {e.Failure}"); Console.WriteLine($"Request ID: {e.RequestId}"); throw; } } /// <summary> /// Creates a feed to be used for ad customization. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <param name="feedName">Name of the feed.</param> /// <returns>The resource name of the newly created feed.</returns> private string CreateAdCustomizerFeed(GoogleAdsClient client, long customerId, string feedName) { // Get the FeedServiceClient. FeedServiceClient feedService = client.GetService(Services.V11.FeedService); // Creates three feed attributes: a name, a price and a date. The attribute names // are arbitrary choices and will be used as placeholders in the ad text fields. FeedAttribute nameAttribute = new FeedAttribute() { Name = "Name", Type = FeedAttributeType.String }; FeedAttribute priceAttribute = new FeedAttribute() { Name = "Price", Type = FeedAttributeType.String }; FeedAttribute dateAttribute = new FeedAttribute() { Name = "Date", Type = FeedAttributeType.DateTime }; Feed adCustomizerFeed = new Feed() { Name = feedName, Attributes = { nameAttribute, priceAttribute, dateAttribute } }; FeedOperation feedOperation = new FeedOperation() { Create = adCustomizerFeed }; MutateFeedsResponse response = feedService.MutateFeeds(customerId.ToString(), new[] { feedOperation }); string feedResourceName = response.Results[0].ResourceName; Console.WriteLine($"Added feed with resource name '{feedResourceName}'."); return feedResourceName; } /// <summary> /// Retrieves all the attributes for a feed and returns them in a map using the /// attribute names as keys. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <param name="feedResourceName">The resource name of the feed.</param> /// <returns>The attributes of the feed.</returns> private Dictionary<string, FeedAttribute> GetFeedAttributes(GoogleAdsClient client, long customerId, string feedResourceName) { // Get the GoogleAdsServiceClient. GoogleAdsServiceClient googleAdsService = client.GetService(Services.V11.GoogleAdsService); string query = $"SELECT feed.attributes, feed.name FROM feed WHERE " + $"feed.resource_name = '{feedResourceName}'"; SearchGoogleAdsRequest request = new SearchGoogleAdsRequest() { CustomerId = customerId.ToString(), Query = query }; Dictionary<string, FeedAttribute> feedAttributes = new Dictionary<string, FeedAttribute>(); Feed feed = googleAdsService.Search(request).First().Feed; Console.WriteLine($"Found the following attributes for feed with name '{feed.Name}'"); foreach (FeedAttribute feedAttribute in feed.Attributes) { Console.WriteLine($"\t'{feedAttribute.Name}' with id {feedAttribute.Id} and " + $"type '{feedAttribute.Type}'"); feedAttributes[feedAttribute.Name] = feedAttribute; } return feedAttributes; } /// <summary> /// Creates a feed mapping and sets the feed as an ad customizer feed. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <param name="feedResourceName">The resource name of the feed.</param> /// <param name="feedAttributes">The attributes of the feed.</param> private void CreateAdCustomizerMapping(GoogleAdsClient client, long customerId, string feedResourceName, Dictionary<string, FeedAttribute> feedAttributes) { // Get the FeedMappingService. FeedMappingServiceClient feedMappingService = client.GetService(Services.V11.FeedMappingService); // Map the feed attributes to ad customizer placeholder fields. // For a full list of ad customizer placeholder fields, see // https://developers.google.com/google-ads/api/reference/rpc/latest/AdCustomizerPlaceholderFieldEnum.AdCustomizerPlaceholderField AttributeFieldMapping nameFieldMapping = new AttributeFieldMapping() { FeedAttributeId = feedAttributes["Name"].Id, AdCustomizerField = AdCustomizerPlaceholderField.String }; AttributeFieldMapping priceFieldMapping = new AttributeFieldMapping() { FeedAttributeId = feedAttributes["Price"].Id, AdCustomizerField = AdCustomizerPlaceholderField.Price }; AttributeFieldMapping dateFieldMapping = new AttributeFieldMapping() { FeedAttributeId = feedAttributes["Date"].Id, AdCustomizerField = AdCustomizerPlaceholderField.Date }; FeedMapping feedMapping = new FeedMapping() { Feed = feedResourceName, PlaceholderType = PlaceholderType.AdCustomizer, AttributeFieldMappings = { nameFieldMapping, priceFieldMapping, dateFieldMapping } }; FeedMappingOperation operation = new FeedMappingOperation() { Create = feedMapping }; MutateFeedMappingsResponse response = feedMappingService.MutateFeedMappings(customerId.ToString(), new[] { operation }); Console.WriteLine($"Added feed mapping with resource name" + $" '{response.Results[0].ResourceName}'."); } /// <summary> /// Creates two different feed items to enable two different ad customizations. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <param name="feedResourceName">The resource name of the feed.</param> /// <param name="feedAttributes">The attributes of the feed.</param> /// <returns>The resource names of the feed items.</returns> private List<string> CreateFeedItems(GoogleAdsClient client, long customerId, string feedResourceName, Dictionary<string, FeedAttribute> feedAttributes) { // Get the FeedItemServiceClient. FeedItemServiceClient feedItemService = client.GetService(Services.V11.FeedItemService); List<FeedItemOperation> feedItemOperations = new List<FeedItemOperation>(); DateTime marsDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1); feedItemOperations.Add( CreateFeedItemOperation("Mars", "$1234.56", marsDate.ToString("yyyyMMdd HHmmss"), feedResourceName, feedAttributes)); DateTime venusDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 15); feedItemOperations.Add( CreateFeedItemOperation("Venus", "$1450.00", venusDate.ToString("yyyyMMdd HHmmss"), feedResourceName, feedAttributes)); List<string> feedItemResourceNames = new List<string>(); MutateFeedItemsResponse response = feedItemService.MutateFeedItems(customerId.ToString(), feedItemOperations); Console.WriteLine($"Added {response.Results.Count} feed items:"); foreach (MutateFeedItemResult result in response.Results) { string feedItemResourceName = result.ResourceName; feedItemResourceNames.Add(feedItemResourceName); Console.WriteLine($"Added feed item with resource name '{feedItemResourceName}'."); } return feedItemResourceNames; } /// <summary> /// Helper function to create a FeedItemOperation. /// </summary> /// <param name="name">The value of the Name attribute.</param> /// <param name="price">The value of the Price attribute.</param> /// <param name="date">The value of the Date attribute.</param> /// <param name="feedResourceName">The resource name of the feed.</param> /// <param name="feedAttributes">The attributes to be set on the feed.</param> /// <returns>A FeedItemOperation to create a feed item.</returns> private FeedItemOperation CreateFeedItemOperation(string name, string price, string date, string feedResourceName, Dictionary<string, FeedAttribute> feedAttributes) { FeedItemAttributeValue nameAttributeValue = new FeedItemAttributeValue() { FeedAttributeId = feedAttributes["Name"].Id, StringValue = name }; FeedItemAttributeValue priceAttributeValue = new FeedItemAttributeValue() { FeedAttributeId = feedAttributes["Price"].Id, StringValue = price }; FeedItemAttributeValue dateAttributeValue = new FeedItemAttributeValue() { FeedAttributeId = feedAttributes["Date"].Id, StringValue = date }; FeedItem feedItem = new FeedItem() { Feed = feedResourceName, AttributeValues = { nameAttributeValue, priceAttributeValue, dateAttributeValue } }; return new FeedItemOperation() { Create = feedItem }; } /// <summary> /// Restricts the feed items to work only with a specific ad group; this prevents the /// feed items from being used elsewhere and makes sure they are used only for /// customizing a specific ad group. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <param name="adGroupIds">The ad group IDs to bind the feed items to..</param> /// <param name="feedItemResourceNames">The resource names of the feed items.</param> private void CreateFeedItemTargets(GoogleAdsClient client, long customerId, long[] adGroupIds, List<string> feedItemResourceNames) { // Get the FeedItemTargetServiceClient. FeedItemTargetServiceClient feedItemTargetService = client.GetService(Services.V11.FeedItemTargetService); // Bind each feed item to a specific ad group to make sure it will only be used to // customize ads inside that ad group; using the feed item elsewhere will result // in an error. for (int i = 0; i < feedItemResourceNames.Count; i++) { string feedItemResourceName = feedItemResourceNames[i]; long adGroupId = adGroupIds[i]; FeedItemTarget feedItemTarget = new FeedItemTarget() { AdGroup = ResourceNames.AdGroup(customerId, adGroupId), FeedItem = feedItemResourceName }; FeedItemTargetOperation feedItemTargetOperation = new FeedItemTargetOperation() { Create = feedItemTarget }; MutateFeedItemTargetsResponse response = feedItemTargetService.MutateFeedItemTargets(customerId.ToString(), new[] { feedItemTargetOperation }); string feedItemTargetResourceName = response.Results[0].ResourceName; Console.WriteLine($"Added feed item target with resource name " + $"'{response.Results[0].ResourceName}'."); } } /// <summary> /// Creates expanded text ads that use the ad customizer feed to populate the placeholders. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <param name="adGroupIds">The ad group IDs in which to create the ads.</param> /// <param name="feedName">Name of the feed.</param> private void CreateAdsWithCustomizations(GoogleAdsClient client, long customerId, long[] adGroupIds, string feedName) { // Get the AdGroupAdServiceClient. AdGroupAdServiceClient adGroupAdService = client.GetService(Services.V11.AdGroupAdService); // Creates an expanded text ad using the feed attribute names as placeholders. Ad ad = new Ad() { ExpandedTextAd = new ExpandedTextAdInfo() { HeadlinePart1 = $"Luxury cruise to {{={feedName}.Name}}", HeadlinePart2 = $"Only {{={feedName}.Price}}", Description = $"Offer ends in {{=countdown({feedName}.Date)}}!" }, FinalUrls = { "http://www.example.com" } }; List<AdGroupAdOperation> adGroupAdOperations = new List<AdGroupAdOperation>(); // Creates the same ad in all ad groups. When they serve, they will show // different values, since they match different feed items. foreach (long adGroupId in adGroupIds) { AdGroupAd adGroupAd = new AdGroupAd() { Ad = ad, AdGroup = ResourceNames.AdGroup(customerId, adGroupId) }; adGroupAdOperations.Add(new AdGroupAdOperation() { Create = adGroupAd }); } MutateAdGroupAdsResponse response = adGroupAdService.MutateAdGroupAds(customerId.ToString(), adGroupAdOperations); Console.WriteLine($"Added {response.Results.Count} ads:"); foreach (MutateAdGroupAdResult result in response.Results) { Console.WriteLine($"Added an ad with resource name '{result.ResourceName}'."); } } } }
PHP
<?php /** * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Google\Ads\GoogleAds\Examples\AdvancedOperations; require __DIR__ . '/../../vendor/autoload.php'; use DateTime; use GetOpt\GetOpt; use Google\Ads\GoogleAds\Examples\Utils\ArgumentNames; use Google\Ads\GoogleAds\Examples\Utils\ArgumentParser; use Google\Ads\GoogleAds\Examples\Utils\Helper; use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder; use Google\Ads\GoogleAds\Lib\V11\GoogleAdsClient; use Google\Ads\GoogleAds\Lib\V11\GoogleAdsClientBuilder; use Google\Ads\GoogleAds\Lib\V11\GoogleAdsException; use Google\Ads\GoogleAds\Util\V11\ResourceNames; use Google\Ads\GoogleAds\V11\Common\ExpandedTextAdInfo; use Google\Ads\GoogleAds\V11\Enums\AdCustomizerPlaceholderFieldEnum\AdCustomizerPlaceholderField; use Google\Ads\GoogleAds\V11\Enums\FeedAttributeTypeEnum\FeedAttributeType; use Google\Ads\GoogleAds\V11\Enums\FeedOriginEnum\FeedOrigin; use Google\Ads\GoogleAds\V11\Enums\PlaceholderTypeEnum\PlaceholderType; use Google\Ads\GoogleAds\V11\Errors\GoogleAdsError; use Google\Ads\GoogleAds\V11\Resources\Ad; use Google\Ads\GoogleAds\V11\Resources\AdGroupAd; use Google\Ads\GoogleAds\V11\Resources\AttributeFieldMapping; use Google\Ads\GoogleAds\V11\Resources\Feed; use Google\Ads\GoogleAds\V11\Resources\FeedAttribute; use Google\Ads\GoogleAds\V11\Resources\FeedItem; use Google\Ads\GoogleAds\V11\Resources\FeedItemAttributeValue; use Google\Ads\GoogleAds\V11\Resources\FeedItemTarget; use Google\Ads\GoogleAds\V11\Resources\FeedMapping; use Google\Ads\GoogleAds\V11\Services\AdGroupAdOperation; use Google\Ads\GoogleAds\V11\Services\FeedItemOperation; use Google\Ads\GoogleAds\V11\Services\FeedItemTargetOperation; use Google\Ads\GoogleAds\V11\Services\FeedMappingOperation; use Google\Ads\GoogleAds\V11\Services\FeedOperation; use Google\ApiCore\ApiException; /** * Adds an ad customizer feed and associates it with the customer. Then it adds an ad that uses the * feed to populate dynamic data. */ class AddAdCustomizer { private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE'; private const AD_GROUP_ID_1 = 'INSERT_AD_GROUP_ID_1_HERE'; private const AD_GROUP_ID_2 = 'INSERT_AD_GROUP_ID_2_HERE'; // We're creating two different ad groups to be dynamically populated by the same feed. private const NUMBER_OF_AD_GROUPS = 2; // We're doing only searches by resource_name in this example, we can set page size = 1. private const PAGE_SIZE = 1; public static function main() { // Either pass the required parameters for this example on the command line, or insert them // into the constants above. $options = (new ArgumentParser())->parseCommandArguments([ ArgumentNames::CUSTOMER_ID => GetOpt::REQUIRED_ARGUMENT, ArgumentNames::AD_GROUP_IDS => GetOpt::MULTIPLE_ARGUMENT ]); // Generate a refreshable OAuth2 credential for authentication. $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build(); // Construct a Google Ads client configured from a properties file and the // OAuth2 credentials above. $googleAdsClient = (new GoogleAdsClientBuilder())->fromFile() ->withOAuth2Credential($oAuth2Credential) ->build(); try { self::runExample( $googleAdsClient, $options[ArgumentNames::CUSTOMER_ID] ?: self::CUSTOMER_ID, $options[ArgumentNames::AD_GROUP_IDS] ?: [self::AD_GROUP_ID_1, self::AD_GROUP_ID_2] ); } catch (GoogleAdsException $googleAdsException) { printf( "Request with ID '%s' has failed.%sGoogle Ads failure details:%s", $googleAdsException->getRequestId(), PHP_EOL, PHP_EOL ); foreach ($googleAdsException->getGoogleAdsFailure()->getErrors() as $error) { /** @var GoogleAdsError $error */ printf( "\t%s: %s%s", $error->getErrorCode()->getErrorCode(), $error->getMessage(), PHP_EOL ); } exit(1); } catch (ApiException $apiException) { printf( "ApiException was thrown with message '%s'.%s", $apiException->getMessage(), PHP_EOL ); exit(1); } } /** * Runs the example. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID * @param array $adGroupIds the ad group IDs */ public static function runExample( GoogleAdsClient $googleAdsClient, int $customerId, array $adGroupIds ) { if (count($adGroupIds) != self::NUMBER_OF_AD_GROUPS) { throw new \InvalidArgumentException( 'Please pass exactly ' . self::NUMBER_OF_AD_GROUPS . ' ad group IDs in the adGroupIds parameter.' ); } $feedName = 'Ad Customizer example feed ' . Helper::getShortPrintableDatetime(); // Create a feed to be used for ad customization. $adCustomizerFeedResourceName = self::createAdCustomizerFeed( $googleAdsClient, $customerId, $feedName ); // Retrieve the attributes of the feed. $adCustomizerFeedAttributes = self::getFeedAttributes( $googleAdsClient, $customerId, $adCustomizerFeedResourceName ); // Map the feed to the ad customizer placeholder fields. self::createAdCustomizerMapping( $googleAdsClient, $customerId, $adCustomizerFeedResourceName, $adCustomizerFeedAttributes ); // Create feed items to be used to customize ads. $feedItemResourceNames = self::createFeedItems( $googleAdsClient, $customerId, $adCustomizerFeedResourceName, $adCustomizerFeedAttributes ); // Set the feed to be used only with the specified ad groups. self::createFeedItemTargets( $googleAdsClient, $customerId, $adGroupIds, $feedItemResourceNames ); // Create ads that use the feed for customization. self::createAdsWithCustomizations( $googleAdsClient, $customerId, $adGroupIds, $feedName ); } /** * Creates a feed to be used for ad customization. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID in which to create the feed * @param string $feedName the name of the feed to create * @return string the resource name of the newly created feed */ private static function createAdCustomizerFeed( GoogleAdsClient $googleAdsClient, int $customerId, string $feedName ) { // Creates three feed attributes: a name, a price and a date. The attribute names are // arbitrary choices and will be used as placeholders in the ad text fields. $nameAttribute = new FeedAttribute(['type' => FeedAttributeType::STRING, 'name' => 'Name']); $priceAttribute = new FeedAttribute(['type' => FeedAttributeType::STRING, 'name' => 'Price']); $dateAttribute = new FeedAttribute(['type' => FeedAttributeType::DATE_TIME, 'name' => 'Date']); // Creates the feed. $feed = new Feed([ 'name' => $feedName, 'attributes' => [$nameAttribute, $priceAttribute, $dateAttribute], 'origin' => FeedOrigin::USER ]); // Creates a feed operation for creating a feed. $feedOperation = new FeedOperation(); $feedOperation->setCreate($feed); // Issues a mutate request to add the feed. $feedServiceClient = $googleAdsClient->getFeedServiceClient(); $feedResponse = $feedServiceClient->mutateFeeds($customerId, [$feedOperation]); $feedResourceName = $feedResponse->getResults()[0]->getResourceName(); printf("Added feed with resource name '%s'.%s", $feedResourceName, PHP_EOL); return $feedResourceName; } /** * Retrieves attributes for a feed. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID * @param string $feedResourceName the resource name of the feed * @return array the feed attributes, keyed by attribute name */ private static function getFeedAttributes( GoogleAdsClient $googleAdsClient, int $customerId, string $feedResourceName ) { $query = "SELECT feed.attributes, feed.name FROM feed " . "WHERE feed.resource_name = '$feedResourceName'"; $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); $response = $googleAdsServiceClient->search($customerId, $query, ['pageSize' => self::PAGE_SIZE]); /** @var Feed $feed */ $feed = $response->getIterator()->current()->getFeed(); $feedDetails = []; printf( "Found the following attributes for feed with name %s:%s", $feed->getName(), PHP_EOL ); foreach ($feed->getAttributes() as $feedAttribute) { /** @var FeedAttribute $feedAttribute */ $feedDetails[$feedAttribute->getName()] = $feedAttribute->getId(); printf( "\t'%s' with id %d and type '%s'%s", $feedAttribute->getName(), $feedAttribute->getId(), FeedAttributeType::name($feedAttribute->getType()), PHP_EOL ); } return $feedDetails; } /** * Creates a feed mapping for a given feed. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID * @param string $adCustomizerFeedResourceName the resource name of the ad customizer feed * @param array $feedDetails an associative array from feed attribute names to their IDs */ private static function createAdCustomizerMapping( GoogleAdsClient $googleAdsClient, int $customerId, string $adCustomizerFeedResourceName, array $feedDetails ) { // Maps the feed attribute IDs to the field ID constants. $nameFieldMapping = new AttributeFieldMapping([ 'feed_attribute_id' => $feedDetails['Name'], 'ad_customizer_field' => AdCustomizerPlaceholderField::STRING ]); $priceFieldMapping = new AttributeFieldMapping([ 'feed_attribute_id' => $feedDetails['Price'], 'ad_customizer_field' => AdCustomizerPlaceholderField::PRICE ]); $dateFieldMapping = new AttributeFieldMapping([ 'feed_attribute_id' => $feedDetails['Date'], 'ad_customizer_field' => AdCustomizerPlaceholderField::DATE ]); // Creates the feed mapping. $feedMapping = new FeedMapping([ 'placeholder_type' => PlaceholderType::AD_CUSTOMIZER, 'feed' => $adCustomizerFeedResourceName, 'attribute_field_mappings' => [$nameFieldMapping, $priceFieldMapping, $dateFieldMapping] ]); // Creates the operation. $feedMappingOperation = new FeedMappingOperation(); $feedMappingOperation->setCreate($feedMapping); // Issues a mutate request to add the feed mapping. $feedMappingServiceClient = $googleAdsClient->getFeedMappingServiceClient(); $response = $feedMappingServiceClient->mutateFeedMappings( $customerId, [$feedMappingOperation] ); // Displays the results. foreach ($response->getResults() as $result) { printf( "Created feed mapping with resource name '%s'.%s", $result->getResourceName(), PHP_EOL ); } } /** * Creates two different feed items to enable two different ad customizations. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID * @param string $adCustomizerFeedResourceName the resource name of the feed * @param array $adCustomizerFeedAttributes the attributes of the feed * @return string[] the created feed item resource names */ private static function createFeedItems( GoogleAdsClient $googleAdsClient, int $customerId, string $adCustomizerFeedResourceName, array $adCustomizerFeedAttributes ) { $feedItemOperations = []; $feedItemOperations[] = self::createFeedItemOperation( 'Mars', '$1234.56', date_format(new DateTime('first day of this month'), 'Ymd His'), $adCustomizerFeedResourceName, $adCustomizerFeedAttributes ); $feedItemOperations[] = self::createFeedItemOperation( 'Venus', '$6543.21', // Set the date to the 15th of the current month. date_format(DateTime::createFromFormat('d', '15'), 'Ymd His'), $adCustomizerFeedResourceName, $adCustomizerFeedAttributes ); // Adds the feed items. $feedItemServiceClient = $googleAdsClient->getFeedItemServiceClient(); $response = $feedItemServiceClient->mutateFeedItems($customerId, $feedItemOperations); $feedItemResourceNames = []; // Displays the results. foreach ($response->getResults() as $result) { printf( "Created feed item with resource name '%s'.%s", $result->getResourceName(), PHP_EOL ); $feedItemResourceNames[] = $result->getResourceName(); } return $feedItemResourceNames; } /** * Creates a FeedItemOperation. * * @param string $name the value of the Name attribute * @param string $price the value of the Price attribute * @param string $date the value of the Date attribute * @param string $adCustomizerFeedResourceName the resource name of the feed * @param array $adCustomizerFeedAttributes the attributes to be set on the feed * @return FeedItemOperation the feed item operation to create a feed item */ private static function createFeedItemOperation( string $name, string $price, string $date, string $adCustomizerFeedResourceName, array $adCustomizerFeedAttributes ) { $nameAttributeValue = new FeedItemAttributeValue([ 'feed_attribute_id' => $adCustomizerFeedAttributes['Name'], 'string_value' => $name ]); $priceAttributeValue = new FeedItemAttributeValue([ 'feed_attribute_id' => $adCustomizerFeedAttributes['Price'], 'string_value' => $price ]); $dateAttributeValue = new FeedItemAttributeValue([ 'feed_attribute_id' => $adCustomizerFeedAttributes['Date'], 'string_value' => $date ]); $feedItem = new FeedItem([ 'feed' => $adCustomizerFeedResourceName, 'attribute_values' => [$nameAttributeValue, $priceAttributeValue, $dateAttributeValue] ]); $feedItemOperation = new FeedItemOperation(); $feedItemOperation->setCreate($feedItem); return $feedItemOperation; } /** * Restricts the feed items to work only with a specific ad group; this prevents the feed items * from being used elsewhere and makes sure they are used only for customizing a specific ad * group. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID * @param array $adGroupIds the ad group IDs to bind the feed items to * @param array $feedItemResourceNames the resource names of the feed items */ private static function createFeedItemTargets( GoogleAdsClient $googleAdsClient, int $customerId, array $adGroupIds, array $feedItemResourceNames ) { // Bind each feed item to a specific ad group to make sure it will only be used to customize // ads inside that ad group; using the feed item elsewhere will result in an error. for ($i = 0; $i < count($feedItemResourceNames); $i++) { $feedItemResourceName = $feedItemResourceNames[$i]; $adGroupId = $adGroupIds[$i]; $feedItemTarget = new FeedItemTarget([ 'feed_item' => $feedItemResourceName, 'ad_group' => ResourceNames::forAdGroup($customerId, $adGroupId) ]); // Creates the operation. $feedItemTargetOperation = new FeedItemTargetOperation(); $feedItemTargetOperation->setCreate($feedItemTarget); // Issues a mutate request to add the feed item target. $feedItemTargetServiceClient = $googleAdsClient->getFeedItemTargetServiceClient(); $feedItemTargetResponse = $feedItemTargetServiceClient->mutateFeedItemTargets( $customerId, [$feedItemTargetOperation] ); $feedItemTargetResourceName = $feedItemTargetResponse->getResults()[0]->getResourceName(); printf( "Added feed item target with resource name '%s'.%s", $feedItemTargetResourceName, PHP_EOL ); } } /** * Creates expanded text ads that use the ad customizer feed to populate the placeholders. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the client customer ID * @param array $adGroupIds the ad group IDs in which to create the ads * @param string $feedName the name of the feed */ private static function createAdsWithCustomizations( GoogleAdsClient $googleAdsClient, int $customerId, array $adGroupIds, string $feedName ) { $expandedTextAdInfo = new ExpandedTextAdInfo([ 'headline_part1' => "Luxury cruise to {=$feedName.Name}", 'headline_part2' => "Only {=$feedName.Price}", 'description' => "Offer ends in {=countdown($feedName.Date)}!" ]); $ad = new Ad([ 'expanded_text_ad' => $expandedTextAdInfo, 'final_urls' => ['http://www.example.com'] ]); $adGroupAdOperations = []; foreach ($adGroupIds as $adGroupId) { $adGroupAd = new AdGroupAd([ 'ad' => $ad, 'ad_group' => ResourceNames::forAdGroup($customerId, $adGroupId) ]); $adGroupAdOperation = new AdGroupAdOperation(); $adGroupAdOperation->setCreate($adGroupAd); $adGroupAdOperations[] = $adGroupAdOperation; } // Issues a mutate request to add the ads. $adGroupAdServiceClient = $googleAdsClient->getAdGroupAdServiceClient(); $adGroupAdResponse = $adGroupAdServiceClient->mutateAdGroupAds( $customerId, $adGroupAdOperations ); printf('Added %d ads:%s', count($adGroupAdResponse->getResults()), PHP_EOL); foreach ($adGroupAdResponse->getResults() as $result) { printf("Added an ad with resource name '%s'.%s", $result->getResourceName(), PHP_EOL); } } } AddAdCustomizer::main();
Python
#!/usr/bin/env python # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Adds an ad customizer feed and associates it with a given customer. It then adds an ad that uses the feed to populate dynamic data. """ import argparse from datetime import datetime import sys from uuid import uuid4 from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException def main(client, customer_id, ad_group_ids): """The main method that creates all necessary entities for the example. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. ad_group_ids: a list of ad group IDs. """ feed_name = f"Ad customizer example feed {uuid4()}" ad_customizer_feed_resource_name = _create_add_customizer_feed( client, customer_id, feed_name ) ad_customizer_feed_attributes = _get_feed_attributes( client, customer_id, ad_customizer_feed_resource_name ) _create_ad_customizer_mapping( client, customer_id, ad_customizer_feed_resource_name, ad_customizer_feed_attributes, ) feed_item_resource_names = _create_feed_items( client, customer_id, ad_customizer_feed_resource_name, ad_customizer_feed_attributes, ) _create_feed_item_targets( client, customer_id, ad_group_ids, feed_item_resource_names ) _create_ads_with_customizations( client, customer_id, ad_group_ids, feed_name ) def _create_add_customizer_feed(client, customer_id, feed_name): """Creates a feed to be used for ad customization. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. feed_name: the name of the feed to create. Returns: A str of a resource name for the newly created feed. """ # Creates three feed attributes: a name, a price and a date. # The attribute names are arbitrary choices and will be used as # placeholders in the ad text fields. feed_attr_type_enum = client.enums.FeedAttributeTypeEnum name_attr = client.get_type("FeedAttribute") name_attr.type_ = feed_attr_type_enum.STRING name_attr.name = "Name" price_attr = client.get_type("FeedAttribute") price_attr.type_ = feed_attr_type_enum.STRING price_attr.name = "Price" date_attr = client.get_type("FeedAttribute") date_attr.type_ = feed_attr_type_enum.DATE_TIME date_attr.name = "Date" feed_operation = client.get_type("FeedOperation") feed = feed_operation.create feed.name = feed_name feed.attributes.extend([name_attr, price_attr, date_attr]) feed.origin = client.enums.FeedOriginEnum.USER feed_service = client.get_service("FeedService") response = feed_service.mutate_feeds( customer_id=customer_id, operations=[feed_operation] ) resource_name = response.results[0].resource_name print(f"Added feed with resource name {resource_name}") return resource_name def _get_feed_attributes(client, customer_id, feed_resource_name): """Retrieves attributes for a feed. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. feed_resource_name: the resource name of the feed. Returns: A dict of feed attributes, keyed by attribute name. """ query = f""" SELECT feed.attributes, feed.name FROM feed WHERE feed.resource_name = "{feed_resource_name}" """ ga_service = client.get_service("GoogleAdsService") search_request = client.get_type("SearchGoogleAdsRequest") search_request.customer_id = customer_id search_request.query = query search_request.page_size = 1 results = ga_service.search(request=search_request) feed = list(results)[0].feed print(f"Found the following attributes for feed with name {feed.name}") feed_details = {} for feed_attribute in feed.attributes: name = feed_attribute.name feed_attr_id = feed_attribute.id feed_type = feed_attribute.type_.name feed_details[name] = feed_attr_id print(f"\t{name} with id {feed_attr_id} and type {feed_type}.") return feed_details def _create_ad_customizer_mapping( client, customer_id, ad_customizer_feed_resource_name, feed_details, ): """Creates a feed mapping for a given feed. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. ad_customizer_feed_resource_name: the resource name of the ad customizer feed. feed_details: a dict mapping feed attribute names to their IDs. """ placeholder_field_enum = client.enums.AdCustomizerPlaceholderFieldEnum # Map the feed attributes to ad customizer placeholder fields. For a full # list of ad customizer placeholder fields, see: # https://developers.google.com/google-ads/api/reference/rpc/latest/AdCustomizerPlaceholderFieldEnum.AdCustomizerPlaceholderField name_field_mapping = client.get_type("AttributeFieldMapping") name_field_mapping.feed_attribute_id = feed_details["Name"] name_field_mapping.ad_customizer_field = placeholder_field_enum.STRING price_field_mapping = client.get_type("AttributeFieldMapping") price_field_mapping.feed_attribute_id = feed_details["Price"] price_field_mapping.ad_customizer_field = placeholder_field_enum.PRICE date_field_mapping = client.get_type("AttributeFieldMapping") date_field_mapping.feed_attribute_id = feed_details["Date"] date_field_mapping.ad_customizer_field = placeholder_field_enum.DATE feed_mapping_op = client.get_type("FeedMappingOperation") feed_mapping = feed_mapping_op.create feed_mapping.feed = ad_customizer_feed_resource_name feed_mapping.placeholder_type = ( client.enums.PlaceholderTypeEnum.AD_CUSTOMIZER ) feed_mapping.attribute_field_mappings.extend( [name_field_mapping, price_field_mapping, date_field_mapping] ) feed_mapping_service = client.get_service("FeedMappingService") response = feed_mapping_service.mutate_feed_mappings( customer_id=customer_id, operations=[feed_mapping_op] ) for result in response.results: print( "Created feed mapping with resource name " f"{result.resource_name}" ) def _create_feed_items( client, customer_id, ad_customizer_feed_resource_name, ad_customizer_feed_attributes, ): """Creates two feed items to enable two different ad customizations. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. ad_customizer_feed_resource_name: the resource name of the ad customizer feed. ad_customizer_feed_attributes: a dict mapping feed attribute names to their IDs. Returns: A list of feed item resource name strs. """ feed_item_operations = [] feed_item_operations.append( _create_feed_item_operation( client, "Mars", "$1234.56", # Set the date to the 1st of the current month. datetime.now().replace(day=1).strftime("%Y%m%d %H%M%S"), ad_customizer_feed_resource_name, ad_customizer_feed_attributes, ) ) feed_item_operations.append( _create_feed_item_operation( client, "Venus", "$6543.21", # Set the date to the 15th of the current month. datetime.now().replace(day=15).strftime("%Y%m%d %H%M%S"), ad_customizer_feed_resource_name, ad_customizer_feed_attributes, ) ) feed_item_service = client.get_service("FeedItemService") response = feed_item_service.mutate_feed_items( customer_id=customer_id, operations=feed_item_operations ) return [feed_item.resource_name for feed_item in response.results] def _create_feed_item_operation( client, name, price, date, ad_customizer_feed_resource_name, ad_customizer_feed_attributes, ): """Creates a FeedItemOperation. Args: client: an initialized GoogleAdsClient instance. name: a str value for the name attribute of the feed_item price: a str value for the price attribute of the feed_item date: a str value for the date attribute of the feed_item ad_customizer_feed_resource_name: the resource name of the ad customizer feed. ad_customizer_feed_attributes: a dict mapping feed attribute names to their IDs. Returns: A FeedItemOperation that creates a FeedItem """ name_attr_value = client.get_type("FeedItemAttributeValue") name_attr_value.feed_attribute_id = ad_customizer_feed_attributes["Name"] name_attr_value.string_value = name price_attr_value = client.get_type("FeedItemAttributeValue") price_attr_value.feed_attribute_id = ad_customizer_feed_attributes["Price"] price_attr_value.string_value = price date_attr_value = client.get_type("FeedItemAttributeValue") date_attr_value.feed_attribute_id = ad_customizer_feed_attributes["Date"] date_attr_value.string_value = date feed_item_op = client.get_type("FeedItemOperation") feed_item = feed_item_op.create feed_item.feed = ad_customizer_feed_resource_name feed_item.attribute_values.extend( [name_attr_value, price_attr_value, date_attr_value] ) return feed_item_op def _create_feed_item_targets( client, customer_id, ad_group_ids, feed_item_resource_names ): """Restricts the feed items to work only with a specific ad group. This prevents the feed items from being used elsewhere and makes sure they are used only for customizing a specific ad group. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. ad_group_ids: a list of ad group IDs. feed_item_resource_names: a list of feed item resource name strs. """ ad_group_service = client.get_service("AdGroupService") feed_item_target_service = client.get_service("FeedItemTargetService") # Bind each feed item to a specific ad group to make sure it will only be # used to customize ads inside that ad group; using the feed item elsewhere # will result in an error. for i, resource_name in enumerate(feed_item_resource_names): ad_group_id = ad_group_ids[i] feed_item_target_op = client.get_type("FeedItemTargetOperation") feed_item_target = feed_item_target_op.create feed_item_target.feed_item = resource_name feed_item_target.ad_group = ad_group_service.ad_group_path( customer_id, ad_group_id ) response = feed_item_target_service.mutate_feed_item_targets( customer_id=customer_id, operations=[feed_item_target_op] ) print( "Added feed item target with resource name " f"{response.results[0].resource_name}" ) def _create_ads_with_customizations( client, customer_id, ad_group_ids, feed_name ): """Creates expanded text ads that use the ad customizer feed. The expanded text ads use the ad customizer feed to populate the placeholders. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. ad_group_ids: a list of ad group IDs. feed_name: the name of the feed to create. """ ad_group_service = client.get_service("AdGroupService") ad_group_ad_service = client.get_service("AdGroupAdService") ad_group_ad_operations = [] for ad_group_id in ad_group_ids: ad_group_ad_operation = client.get_type("AdGroupAdOperation") ad_group_ad = ad_group_ad_operation.create ad_group_ad.ad_group = ad_group_service.ad_group_path( customer_id, ad_group_id ) ad_group_ad.ad.final_urls.append("http://www.example.com") ad_group_ad.ad.expanded_text_ad.headline_part1 = ( f"Luxury cruise to {{={feed_name}.Name}}" ) ad_group_ad.ad.expanded_text_ad.headline_part2 = ( f"Only {{={feed_name}.Price}}" ) # See this documentation for an explanation of how countdown ad # customizers work: https://support.google.com/google-ads/answer/6193743?hl=en ad_group_ad.ad.expanded_text_ad.description = ( f"Offer ends in {{=countdown({feed_name}.Date)}}!" ) ad_group_ad_operations.append(ad_group_ad_operation) response = ad_group_ad_service.mutate_ad_group_ads( customer_id=customer_id, operations=ad_group_ad_operations ) print(f"Added {len(response.results)} ads:") for ad in response.results: print(f"Added an ad with resource name {ad.resource_name}") if __name__ == "__main__": # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client = GoogleAdsClient.load_from_storage(version="v10") parser = argparse.ArgumentParser( description=( "Adds an ad customizer feed and associates it with a customer." ) ) # The following argument(s) should be provided to run the example. parser.add_argument( "-c", "--customer_id", type=str, required=True, help="The Google Ads customer ID.", ) parser.add_argument( "-a", "--ad_group_ids", nargs=2, type=str, required=True, help="Space-delimited list of ad group IDs.", ) args = parser.parse_args() try: main(googleads_client, args.customer_id, args.ad_group_ids) except GoogleAdsException as ex: print( f'Request with ID "{ex.request_id}" failed with status ' f'"{ex.error.code().name}" and includes the following errors:' ) for error in ex.failure.errors: print(f'Error with message "{error.message}".') if error.location: for field_path_element in error.location.field_path_elements: print(f"\t\tOn field: {field_path_element.field_name}") sys.exit(1)
Ruby
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Adds an ad customizer feed and associates it with the customer. Then it adds # an ad that uses the feed to populate dynamic data. require 'date' require 'google/ads/google_ads' require 'optparse' def add_ad_customizer(customer_id, ad_group_ids) # GoogleAdsClient will read a config file from # ENV['HOME']/google_ads_config.rb when called without parameters client = Google::Ads::GoogleAds::GoogleAdsClient.new if ad_group_ids.size != NUMBER_OF_AD_GROUPS raise "Please pass exactly #{NUMBER_OF_AD_GROUPS} ad group IDs in the " \ "ad_group_ids parameter." end feed_name = "Ad Customizer example feed #{(Time.new.to_f * 1000).to_i}" # Create a feed to be used for ad customization ad_customizer_feed_resource_name = create_ad_customizer_feed( client, customer_id, feed_name) # Retrieve the attributes of the feed. ad_customizer_feed_attributes = get_feed_attributes( client, customer_id, ad_customizer_feed_resource_name) # Map the feed to the ad customizer placeholder fields. create_ad_customizer_mapping( client, customer_id, ad_customizer_feed_resource_name, ad_customizer_feed_attributes, ) # Create feed items to be used to customize ads. feed_item_resource_names = create_feed_items( client, customer_id, ad_customizer_feed_resource_name, ad_customizer_feed_attributes, ) # Set the feed to be used only with the specified ad groups. create_feed_item_targets( client, customer_id, ad_group_ids, feed_item_resource_names, ) # Create ads that use the feed for customization. create_ads_with_customizations( client, customer_id, ad_group_ids, feed_name, ) end # Creates a feed to be used for ad customization. def create_ad_customizer_feed( client, customer_id, feed_name) # Creates a feed operation for creating a feed. operation = client.operation.create_resource.feed do |feed| feed.name = feed_name # Creates three feed attributes: a name, a price and a date. The attribute # names are arbitrary choices and will be used as placeholders in the ad # text fields. feed.attributes << client.resource.feed_attribute do |a| a.type = :STRING a.name = "Name" end feed.attributes << client.resource.feed_attribute do |a| a.type = :STRING a.name = "Price" end feed.attributes << client.resource.feed_attribute do |a| a.type = :DATE_TIME a.name = "Date" end feed.origin = :USER end # Issues a mutate request to add the feed. feed_response = client.service.feed.mutate_feeds( customer_id: customer_id, operations: [operation], ) feed_resource_name = feed_response.results.first.resource_name puts "Added a feed with resource name #{feed_resource_name}." feed_resource_name end # Retrieves attributes for a feed. def get_feed_attributes( client, customer_id, ad_customizer_feed_resource_name) query = <<~QUERY SELECT feed.attributes, feed.name FROM feed WHERE feed.resource_name = "#{ad_customizer_feed_resource_name}" QUERY response = client.service.google_ads.search( customer_id: customer_id, query: query, page_size: PAGE_SIZE, ) feed = response.first.feed feed_details = {} puts "Found the following attributes for feed with name #{feed.name}:" feed.attributes.each do |a| feed_details[a.name.to_sym] = a.id puts "\t#{a.name} with id #{a.id} and type #{a.type}" end feed_details end # Creates a feed mapping for a given feed. def create_ad_customizer_mapping( client, customer_id, ad_customizer_feed_resource_name, ad_customizer_feed_attributes) # Creates the operation. operation = client.operation.create_resource.feed_mapping do |fm| fm.placeholder_type = :AD_CUSTOMIZER fm.feed = ad_customizer_feed_resource_name # Maps the feed attribute IDs to the field ID constants. fm.attribute_field_mappings << client.resource.attribute_field_mapping do |af| af.feed_attribute_id = ad_customizer_feed_attributes[:Name] af.ad_customizer_field = :STRING end fm.attribute_field_mappings << client.resource.attribute_field_mapping do |af| af.feed_attribute_id = ad_customizer_feed_attributes[:Price] af.ad_customizer_field = :PRICE end fm.attribute_field_mappings << client.resource.attribute_field_mapping do |af| af.feed_attribute_id = ad_customizer_feed_attributes[:Date] af.ad_customizer_field = :DATE end end # Issues a mutate request to add the feed mapping. response = client.service.feed_mapping.mutate_feed_mappings( customer_id: customer_id, operations: [operation], ) # Displays the results. response.results.each do |result| puts "Created feed mapping with resource name: #{result.resource_name}" end end # Creates two different feed items to enable two different ad customizations. def create_feed_items( client, customer_id, ad_customizer_feed_resource_name, ad_customizer_feed_attributes) feed_item_operations = [] feed_item_operations << create_feed_item_operation( client, "Mars", "$1234.56", # Set the date to the 1st of the current month. DateTime.new(Date.today.year, Date.today.month, 1, 0, 0, 0).strftime("%Y%m%d %H%M%S"), ad_customizer_feed_resource_name, ad_customizer_feed_attributes, ) feed_item_operations << create_feed_item_operation( client, "Venus", "$6543.21", # Set the date to the 15th of the current month. DateTime.new(Date.today.year, Date.today.month, 15, 0, 0, 0).strftime("%Y%m%d %H%M%S"), ad_customizer_feed_resource_name, ad_customizer_feed_attributes, ) # Adds the feed items. response = client.service.feed_item.mutate_feed_items( customer_id: customer_id, operations: feed_item_operations, ) feed_item_resource_names = [] response.results.each do |result| puts "Created feed item with resource name #{result.resource_name}" feed_item_resource_names << result.resource_name end feed_item_resource_names end # Creates a FeedItemOperation. def create_feed_item_operation( client, name, price, date, ad_customizer_feed_resource_name, ad_customizer_feed_attributes) client.operation.create_resource.feed_item do |item| item.feed = ad_customizer_feed_resource_name item.attribute_values << client.resource.feed_item_attribute_value do |v| v.feed_attribute_id = ad_customizer_feed_attributes[:Name] v.string_value = name end item.attribute_values << client.resource.feed_item_attribute_value do |v| v.feed_attribute_id = ad_customizer_feed_attributes[:Price] v.string_value = price end item.attribute_values << client.resource.feed_item_attribute_value do |v| v.feed_attribute_id = ad_customizer_feed_attributes[:Date] v.string_value = date end end end # Restricts the feed items to work only with a specific ad group; this prevents # the feed items from being used elsewhere and makes sure they are used only for # customizing a specific ad group. def create_feed_item_targets( client, customer_id, ad_group_ids, feed_item_resource_names) # Bind each feed item to a specific ad group to make sure it will only be # used to customize ads inside that ad group; using the feed item elsewhere # will result in an error. feed_item_resource_names.size.times do |i| feed_item_resource_name = feed_item_resource_names[i] ad_group_id = ad_group_ids[i] # Creates the operation. operation = client.operation.create_resource.feed_item_target do |t| t.feed_item = feed_item_resource_name t.ad_group = client.path.ad_group(customer_id, ad_group_id) end # Issues a mutate request to add the feed item target. response = client.service.feed_item_target.mutate_feed_item_targets( customer_id: customer_id, operations: [operation], ) puts "Added feed item target with resource name #{response.results.first.resource_name}." end end # Creates expanded text ads that use the ad customizer feed to populate the # placeholders. def create_ads_with_customizations( client, customer_id, ad_group_ids, feed_name) operations = [] ad_group_ids.each do |ad_group_id| operations << client.operation.create_resource.ad_group_ad do |aga| aga.ad = client.resource.ad do |ad| ad.expanded_text_ad = client.resource.expanded_text_ad_info do |eta| eta.headline_part1 = "Luxury cruise to {=#{feed_name}.Name}" eta.headline_part2 = "Only {=#{feed_name}.Price}" eta.description = "Offer ends in {=countdown(#{feed_name}.Date)}!" end ad.final_urls << "http://www.example.com" end aga.ad_group = client.path.ad_group(customer_id, ad_group_id) end end # Issues a mutate request to add the ads. response = client.service.ad_group_ad.mutate_ad_group_ads( customer_id: customer_id, operations: operations, ) puts "Added #{response.results.size} ads:" response.results.each do |result| puts "Added an ad with resource name #{result.resource_name}." end end if __FILE__ == $0 # We're creating two different ad groups to be dynamically populated by # the same feed. NUMBER_OF_AD_GROUPS = 2 # We're doing only searches by resource_name in this example, # we can set page size = 1. PAGE_SIZE = 1; options = {} # The following parameter(s) should be provided to run the example. You can # either specify these by changing the INSERT_XXX_ID_HERE values below, or on # the command line. # # Parameters passed on the command line will override any parameters set in # code. # # Running the example with -h will print the command line usage. options[:customer_id] = 'INSERT_CUSTOMER_ID_HERE' options[:ad_group_ids] = [ 'INSERT_AD_GROUP_ID_1_HERE', 'INSERT_AD_GORUP_ID_2_HERE', ] OptionParser.new do |opts| opts.banner = sprintf('Usage: %s [options]', File.basename(__FILE__)) opts.separator '' opts.separator 'Options:' opts.on('-C', '--customer-id CUSTOMER-ID', String, 'Customer ID') do |v| options[:customer_id] = v end opts.on('-A', '--ad-group-ids AD-GROUP-IDS', String, "#{NUMBER_OF_AD_GROUPS} AdGroup IDs (comma-separated)") do |v| options[:ad_group_ids] = v.split(',') end opts.on('-B', '--bid-modifier-value BID-MODIFIER-VALUE', String, 'Bid Modifier Value') do |v| options[:bid_modifier_value] = v end opts.separator '' opts.separator 'Help:' opts.on_tail('-h', '--help', 'Show this message') do puts opts exit end end.parse! begin add_ad_customizer( options.fetch(:customer_id).tr("-", ""), options[:ad_group_ids], ) rescue Google::Ads::GoogleAds::Errors::GoogleAdsError => e e.failure.errors.each do |error| STDERR.printf("Error with message: %s\n", error.message) if error.location error.location.field_path_elements.each do |field_path_element| STDERR.printf("\tOn field: %s\n", field_path_element.field_name) end end error.error_code.to_h.each do |k, v| next if v == :UNSPECIFIED STDERR.printf("\tType: %s\n\tCode: %s\n", k, v) end end raise end end
Perl
#!/usr/bin/perl -w # # Copyright 2019, Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Adds an ad customizer feed and associates it with the customer. Then it adds an # ad that uses the feed to populate dynamic data. use strict; use warnings; use utf8; use FindBin qw($Bin); use lib "$Bin/../../lib"; use Google::Ads::GoogleAds::Client; use Google::Ads::GoogleAds::Utils::GoogleAdsHelper; use Google::Ads::GoogleAds::V11::Resources::FeedAttribute; use Google::Ads::GoogleAds::V11::Resources::Feed; use Google::Ads::GoogleAds::V11::Resources::AttributeFieldMapping; use Google::Ads::GoogleAds::V11::Resources::FeedMapping; use Google::Ads::GoogleAds::V11::Resources::FeedItemAttributeValue; use Google::Ads::GoogleAds::V11::Resources::FeedItem; use Google::Ads::GoogleAds::V11::Resources::FeedItemTarget; use Google::Ads::GoogleAds::V11::Resources::Ad; use Google::Ads::GoogleAds::V11::Resources::AdGroupAd; use Google::Ads::GoogleAds::V11::Common::ExpandedTextAdInfo; use Google::Ads::GoogleAds::V11::Enums::FeedAttributeTypeEnum qw(STRING DATE_TIME); use Google::Ads::GoogleAds::V11::Enums::FeedOriginEnum qw(USER); use Google::Ads::GoogleAds::V11::Enums::AdCustomizerPlaceholderFieldEnum; use Google::Ads::GoogleAds::V11::Enums::PlaceholderTypeEnum qw(AD_CUSTOMIZER); use Google::Ads::GoogleAds::V11::Services::FeedService::FeedOperation; use Google::Ads::GoogleAds::V11::Services::FeedMappingService::FeedMappingOperation; use Google::Ads::GoogleAds::V11::Services::FeedItemService::FeedItemOperation; use Google::Ads::GoogleAds::V11::Services::FeedItemTargetService::FeedItemTargetOperation; use Google::Ads::GoogleAds::V11::Services::AdGroupAdService::AdGroupAdOperation; use Google::Ads::GoogleAds::V11::Utils::ResourceNames; use Getopt::Long qw(:config auto_help); use Pod::Usage; use Cwd qw(abs_path); use Data::Uniqid qw(uniqid); use POSIX qw(strftime mktime); # We're doing only searches by resource_name in this example, we can set page size = 1. use constant PAGE_SIZE => 1; # We're creating two different ad groups to be dynamically populated by the same feed. use constant NUMBER_OF_AD_GROUPS => 2; # The following parameter(s) should be provided to run the example. You can # either specify these by changing the INSERT_XXX_ID_HERE values below, or on # the command line. # # Parameters passed on the command line will override any parameters set in # code. # # Running the example with -h will print the command line usage. my $customer_id = "INSERT_CUSTOMER_ID_HERE"; my $ad_group_id_1 = "INSERT_AD_GROUP_ID_1_HERE"; my $ad_group_id_2 = "INSERT_AD_GROUP_ID_2_HERE"; my $ad_group_ids = []; sub add_ad_customizer { my ($api_client, $customer_id, $ad_group_ids) = @_; die sprintf "Please pass exactly %d ad group IDs in the ad_group_ids parameter.\n", NUMBER_OF_AD_GROUPS if scalar @$ad_group_ids != NUMBER_OF_AD_GROUPS; my $feed_name = "Ad Customizer example feed " . uniqid(); # Create a feed to be used for ad customization. my $ad_customizer_feed_resource_name = create_ad_customizer_feed($api_client, $customer_id, $feed_name); # Retrieve the attributes of the feed. my $ad_customizer_feed_attributes = get_feed_attributes($api_client, $customer_id, $ad_customizer_feed_resource_name); # Map the feed to the ad customizer placeholder fields. create_ad_customizer_mapping( $api_client, $customer_id, $ad_customizer_feed_resource_name, $ad_customizer_feed_attributes ); # Create feed items to be used to customize ads. my $feed_item_resource_names = create_feed_items( $api_client, $customer_id, $ad_customizer_feed_resource_name, $ad_customizer_feed_attributes ); # Set the feed to be used only with the specified ad groups. create_feed_item_targets($api_client, $customer_id, $ad_group_ids, $feed_item_resource_names); # Create ads that use the feed for customization. create_ads_with_customizations($api_client, $customer_id, $ad_group_ids, $feed_name); return 1; } # Creates a feed to be used for ad customization. sub create_ad_customizer_feed { my ($api_client, $customer_id, $feed_name) = @_; # Create three feed attributes: a name, a price and a date. The attribute names # are arbitrary choices and will be used as placeholders in the ad text fields. my $name_attribute = Google::Ads::GoogleAds::V11::Resources::FeedAttribute->new({ type => STRING, name => "Name" }); my $price_attribute = Google::Ads::GoogleAds::V11::Resources::FeedAttribute->new({ type => STRING, name => "Price" }); my $date_attribute = Google::Ads::GoogleAds::V11::Resources::FeedAttribute->new({ type => DATE_TIME, name => "Date" }); # Create the feed. my $feed = Google::Ads::GoogleAds::V11::Resources::Feed->new({ name => $feed_name, attributes => [$name_attribute, $price_attribute, $date_attribute], origin => USER }); # Create a feed operation for creating a feed. my $feed_operation = Google::Ads::GoogleAds::V11::Services::FeedService::FeedOperation->new({ create => $feed }); # Issue a mutate request to add the feed. my $feeds_response = $api_client->FeedService()->mutate({ customerId => $customer_id, operations => [$feed_operation]}); my $feed_resource_name = $feeds_response->{results}[0]{resourceName}; printf "Added feed with resource name '%s'.\n", $feed_resource_name; return $feed_resource_name; } # Retrieves attributes for a feed. sub get_feed_attributes { my ($api_client, $customer_id, $feed_resource_name) = @_; my $search_query = "SELECT feed.attributes, feed.name FROM feed " . "WHERE feed.resource_name = '$feed_resource_name'"; my $search_response = $api_client->GoogleAdsService()->search({ customerId => $customer_id, query => $search_query, pageSize => PAGE_SIZE }); my $feed = $search_response->{results}[0]{feed}; my $feed_details = {}; printf "Found the following attributes for feed with name %s:\n", $feed->{name}; foreach my $feed_attribute (@{$feed->{attributes}}) { $feed_details->{$feed_attribute->{name}} = $feed_attribute->{id}; printf "\t'%s' with id %d and type '%s'\n", $feed_attribute->{name}, $feed_attribute->{id}, $feed_attribute->{type}; } return $feed_details; } # Creates a feed mapping for a given feed. sub create_ad_customizer_mapping { my ( $api_client, $customer_id, $ad_customizer_feed_resource_name, $ad_customizer_feed_attributes ) = @_; # Map the feed attribute IDs to the field ID constants. my $name_field_mapping = Google::Ads::GoogleAds::V11::Resources::AttributeFieldMapping->new({ feedAttributeId => $ad_customizer_feed_attributes->{Name}, adCustomizerField => Google::Ads::GoogleAds::V11::Enums::AdCustomizerPlaceholderFieldEnum::STRING, }); my $price_field_mapping = Google::Ads::GoogleAds::V11::Resources::AttributeFieldMapping->new({ feedAttributeId => $ad_customizer_feed_attributes->{Price}, adCustomizerField => Google::Ads::GoogleAds::V11::Enums::AdCustomizerPlaceholderFieldEnum::PRICE, }); my $date_field_mapping = Google::Ads::GoogleAds::V11::Resources::AttributeFieldMapping->new({ feedAttributeId => $ad_customizer_feed_attributes->{Date}, adCustomizerField => Google::Ads::GoogleAds::V11::Enums::AdCustomizerPlaceholderFieldEnum::DATE, }); # Create the feed mapping. my $feed_mapping = Google::Ads::GoogleAds::V11::Resources::FeedMapping->new({ placeholderType => AD_CUSTOMIZER, feed => $ad_customizer_feed_resource_name, attributeFieldMappings => [$name_field_mapping, $price_field_mapping, $date_field_mapping]}); # Create the operation. my $feed_mapping_operation = Google::Ads::GoogleAds::V11::Services::FeedMappingService::FeedMappingOperation ->new({ create => $feed_mapping }); # Issue a mutate request to add the feed mapping. my $feed_mappings_response = $api_client->FeedMappingService()->mutate({ customerId => $customer_id, operations => [$feed_mapping_operation]}); # Display the results. foreach my $result (@{$feed_mappings_response->{results}}) { printf "Created feed mapping with resource name '%s'.\n", $result->{resourceName}; } } # Creates two different feed items to enable two different ad customizations. sub create_feed_items { my ( $api_client, $customer_id, $ad_customizer_feed_resource_name, $ad_customizer_feed_attributes ) = @_; my $feed_item_operations = []; my ($sec, $min, $hour, $mday, $mon, $year) = localtime(time); push @$feed_item_operations, create_feed_item_operation( "Mars", '$1234.56', strftime("%Y%m%d %H%M%S", localtime(mktime(0, 0, 0, 1, $mon, $year))), $ad_customizer_feed_resource_name, $ad_customizer_feed_attributes ); push @$feed_item_operations, create_feed_item_operation( "Venus", '$6543.21', # Set the date to the 15th of the current month. strftime("%Y%m%d %H%M%S", localtime(mktime(0, 0, 0, 15, $mon, $year))), $ad_customizer_feed_resource_name, $ad_customizer_feed_attributes ); # Add the feed items. my $feed_items_response = $api_client->FeedItemService()->mutate({ customerId => $customer_id, operations => $feed_item_operations }); my $feed_item_resource_names = []; # Displays the results. foreach my $result (@{$feed_items_response->{results}}) { printf "Created feed item with resource name '%s'.\n", $result->{resourceName}; push @$feed_item_resource_names, $result->{resourceName}; } return $feed_item_resource_names; } # Creates a FeedItemOperation. sub create_feed_item_operation { my ( $name, $price, $date, $ad_customizer_feed_resource_name, $ad_customizer_feed_attributes ) = @_; my $name_attribute_value = Google::Ads::GoogleAds::V11::Resources::FeedItemAttributeValue->new({ feedAttributeId => $ad_customizer_feed_attributes->{Name}, stringValue => $name }); my $price_attribute_value = Google::Ads::GoogleAds::V11::Resources::FeedItemAttributeValue->new({ feedAttributeId => $ad_customizer_feed_attributes->{Price}, stringValue => $price }); my $date_attribute_value = Google::Ads::GoogleAds::V11::Resources::FeedItemAttributeValue->new({ feedAttributeId => $ad_customizer_feed_attributes->{Date}, stringValue => $date }); my $feed_item = Google::Ads::GoogleAds::V11::Resources::FeedItem->new({ feed => $ad_customizer_feed_resource_name, attributeValues => [$name_attribute_value, $price_attribute_value, $date_attribute_value]} ); return Google::Ads::GoogleAds::V11::Services::FeedItemService::FeedItemOperation-> new({ create => $feed_item }); } # Restricts the feed items to work only with a specific ad group; this prevents # the feed items from being used elsewhere and makes sure they are used only for # customizing a specific ad group. sub create_feed_item_targets { my ($api_client, $customer_id, $ad_group_ids, $feed_item_resource_names) = @_; # Bind each feed item to a specific ad group to make sure it will only be used # to customize ads inside that ad group; using the feed item elsewhere will # result in an error. for (my $i = 0 ; $i < scalar @$feed_item_resource_names ; $i++) { my $feed_item_resource_name = $feed_item_resource_names->[$i]; my $ad_group_id = $ad_group_ids->[$i]; my $feed_item_target = Google::Ads::GoogleAds::V11::Resources::FeedItemTarget->new({ feedItem => $feed_item_resource_name, adGroup => Google::Ads::GoogleAds::V11::Utils::ResourceNames::ad_group( $customer_id, $ad_group_id )}); # Create the operation. my $feed_item_target_operation = Google::Ads::GoogleAds::V11::Services::FeedItemTargetService::FeedItemTargetOperation ->new({ create => $feed_item_target }); # Issue a mutate request to add the feed item target. my $feed_item_targets_response = $api_client->FeedItemTargetService()->mutate({ customerId => $customer_id, operations => [$feed_item_target_operation]}); my $feed_item_target_resource_name = $feed_item_targets_response->{results}[0]{resourceName}; printf "Added feed item target with resource name '%s'.\n", $feed_item_target_resource_name; } } # Creates expanded text ads that use the ad customizer feed to populate the placeholders. sub create_ads_with_customizations { my ($api_client, $customer_id, $ad_group_ids, $feed_name) = @_; my $expanded_text_ad_info = Google::Ads::GoogleAds::V11::Common::ExpandedTextAdInfo->new({ headlinePart1 => "Luxury cruise to {=$feed_name.Name}", headlinePart2 => "Only {=$feed_name.Price}", description => "Offer ends in {=countdown($feed_name.Date)}!" }); my $ad = Google::Ads::GoogleAds::V11::Resources::Ad->new({ expandedTextAd => $expanded_text_ad_info, finalUrls => ["http://www.example.com"]}); my $ad_group_ad_operations = []; foreach my $ad_group_id (@$ad_group_ids) { my $ad_group_ad = Google::Ads::GoogleAds::V11::Resources::AdGroupAd->new({ ad => $ad, adGroup => Google::Ads::GoogleAds::V11::Utils::ResourceNames::ad_group( $customer_id, $ad_group_id )}); push @$ad_group_ad_operations, Google::Ads::GoogleAds::V11::Services::AdGroupAdService::AdGroupAdOperation ->new({ create => $ad_group_ad }); } # Issue a mutate request to add the ads. my $ad_group_ads_response = $api_client->AdGroupAdService()->mutate({ customerId => $customer_id, operations => $ad_group_ad_operations }); my $ad_group_ad_results = $ad_group_ads_response->{results}; printf "Added %d ads:\n", scalar @$ad_group_ad_results; foreach my $ad_group_ad_result (@$ad_group_ad_results) { printf "Added an ad with resource name '%s'.\n", $ad_group_ad_result->{resourceName}; } } # Don't run the example if the file is being included. if (abs_path($0) ne abs_path(__FILE__)) { return 1; } # Get Google Ads Client, credentials will be read from ~/googleads.properties. my $api_client = Google::Ads::GoogleAds::Client->new(); # By default examples are set to die on any server returned fault. $api_client->set_die_on_faults(1); # Parameters passed on the command line will override any parameters set in code. GetOptions( "customer_id=s" => \$customer_id, "ad_group_ids=i" => \@$ad_group_ids ); $ad_group_ids = [$ad_group_id_1, $ad_group_id_2] unless @$ad_group_ids; # Print the help message if the parameters are not initialized in the code nor # in the command line. pod2usage(2) if not check_params($customer_id, $ad_group_ids); # Call the example. add_ad_customizer($api_client, $customer_id =~ s/-//gr, $ad_group_ids); =pod =head1 NAME add_ad_customizer =head1 DESCRIPTION Adds an ad customizer feed and associates it with the customer. Then it adds an ad that uses the feed to populate dynamic data. =head1 SYNOPSIS add_ad_customizer.pl [options] -help Show the help message. -customer_id The Google Ads customer ID. -ad_group_ids The ad group IDs to bind the feed items to. =cut