Add Flights Feed

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.remarketing;

import static com.google.ads.googleads.examples.utils.CodeSampleHelper.getPrintableDateTime;

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.enums.FeedAttributeTypeEnum.FeedAttributeType;
import com.google.ads.googleads.v11.enums.FlightPlaceholderFieldEnum.FlightPlaceholderField;
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.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.FeedMapping;
import com.google.ads.googleads.v11.services.FeedItemOperation;
import com.google.ads.googleads.v11.services.FeedItemServiceClient;
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.GoogleAdsRow;
import com.google.ads.googleads.v11.services.GoogleAdsServiceClient;
import com.google.ads.googleads.v11.services.GoogleAdsServiceClient.SearchPagedResponse;
import com.google.ads.googleads.v11.services.MutateFeedItemResult;
import com.google.ads.googleads.v11.services.MutateFeedItemsResponse;
import com.google.ads.googleads.v11.services.MutateFeedMappingResult;
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.common.collect.ImmutableList;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/** Adds a flights feed, creates the associated feed mapping, and adds a feed item. */
public class AddFlightsFeed {
  private static final int PAGE_SIZE = 1_000;

  private static class AddFlightsFeedParams extends CodeSampleParams {

    @Parameter(names = ArgumentNames.CUSTOMER_ID, required = true)
    private long customerId;
  }

  public static void main(String[] args) {
    AddFlightsFeedParams params = new AddFlightsFeedParams();
    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");
    }

    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 AddFlightsFeed().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 AddFlightsFeedParams for the example.
   * @throws GoogleAdsException if an API request failed with one or more service errors.
   */
  private void runExample(GoogleAdsClient googleAdsClient, AddFlightsFeedParams params) {
    // Creates a new flights feed.
    String feedResourceName = createFeed(googleAdsClient, params.customerId);
    // Get the newly creates feed's attributes and packages them into a map. This read operation
    // is required to retrieve the attribute IDs.
    Map<FlightPlaceholderField, FeedAttribute> feedAttributes =
        getFeed(googleAdsClient, params.customerId, feedResourceName);
    // Creates the feed mapping.
    createFeedMapping(googleAdsClient, params.customerId, feedAttributes, feedResourceName);
    // Creates a feed item.
    createFeedItem(googleAdsClient, params.customerId, feedAttributes, feedResourceName);
  }

  /**
   * Creates a flight feed.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the client customer ID.
   * @return a String of the feed resource name.
   */
  private String createFeed(GoogleAdsClient googleAdsClient, long customerId) {
    // Creates a Flight Description attribute.
    FeedAttribute flightDescriptionAttribute =
        FeedAttribute.newBuilder()
            .setType(FeedAttributeType.STRING)
            .setName("Flight Description")
            .build();
    // Creates a Destination ID attribute.
    FeedAttribute destinationIdAttribute =
        FeedAttribute.newBuilder()
            .setType(FeedAttributeType.STRING)
            .setName("Destination ID")
            .build();
    // Creates a Flight Price attribute.
    FeedAttribute flightPriceAttribute =
        FeedAttribute.newBuilder()
            .setType(FeedAttributeType.STRING)
            .setName("Flight Price")
            .build();
    // Creates a Flight Sale Price attribute.
    FeedAttribute flightSalesPriceAttribute =
        FeedAttribute.newBuilder()
            .setType(FeedAttributeType.STRING)
            .setName("Flight Sale Price")
            .build();
    // Creates a Final URLs attribute.
    FeedAttribute finalUrlsAttribute =
        FeedAttribute.newBuilder()
            .setType(FeedAttributeType.URL_LIST)
            .setName("Final URLs")
            .build();

    // Creates the feed.
    Feed feed =
        Feed.newBuilder()
            .setName("Flights Feed #" + getPrintableDateTime())
            .addAttributes(flightDescriptionAttribute)
            .addAttributes(destinationIdAttribute)
            .addAttributes(flightPriceAttribute)
            .addAttributes(flightSalesPriceAttribute)
            .addAttributes(finalUrlsAttribute)
            .build();

    // Creates the operation.
    FeedOperation operation = FeedOperation.newBuilder().setCreate(feed).build();

    // Creates the feed service client.
    try (FeedServiceClient feedServiceClient =
        googleAdsClient.getLatestVersion().createFeedServiceClient()) {
      // Adds the feed.
      MutateFeedsResponse response =
          feedServiceClient.mutateFeeds(String.valueOf(customerId), ImmutableList.of(operation));
      String feedResourceName = response.getResults(0).getResourceName();
      // Displays the result.
      System.out.printf("Feed with resource name '%s' was created.%n", feedResourceName);
      return feedResourceName;
    }
  }

  /**
   * Retrieves details about a feed. The initial query retrieves the FeedAttributes, or columns, of
   * the feed. Each FeedAttribute will also include the FeedAttributeId, which will be used in a
   * subsequent step. The example then inserts a new key, value pair into a map for each
   * FeedAttribute, which is the return value of the method. The keys are the placeholder types that
   * the columns will be. The values are the FeedAttributes.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the client customer ID.
   * @param feedResourceName the resource name of the feed.
   * @return a Map containing the FlightPlaceholderField and FeedAttribute.
   */
  public static Map<FlightPlaceholderField, FeedAttribute> getFeed(
      GoogleAdsClient googleAdsClient, long customerId, String feedResourceName) {
    // Constructs the query.
    String query =
        "SELECT feed.attributes FROM feed WHERE feed.resource_name = '" + feedResourceName + "'";

    // Constructs the request.
    SearchGoogleAdsRequest request =
        SearchGoogleAdsRequest.newBuilder()
            .setCustomerId(String.valueOf(customerId))
            .setPageSize(PAGE_SIZE)
            .setQuery(query)
            .build();

    // Issues the search request.
    try (GoogleAdsServiceClient googleAdsServiceClient =
        googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
      SearchPagedResponse searchPagedResponse = googleAdsServiceClient.search(request);
      // Gets the first result because we only need the single feed item we created previously.
      GoogleAdsRow googleAdsRow = searchPagedResponse.getPage().getResponse().getResults(0);
      // Gets the attributes list from the feed and creates a map with keys of each attribute and
      // values of each corresponding ID.
      List<FeedAttribute> feedAttributeList = googleAdsRow.getFeed().getAttributesList();
      // Creates a map to return.
      Map<FlightPlaceholderField, FeedAttribute> feedAttributes = new HashMap<>();
      // Loops through the feed attributes to populate the map.
      for (FeedAttribute feedAttribute : feedAttributeList) {
        switch (feedAttribute.getName()) {
          case "Flight Description":
            feedAttributes.put(FlightPlaceholderField.FLIGHT_DESCRIPTION, feedAttribute);
            break;
          case "Destination ID":
            feedAttributes.put(FlightPlaceholderField.DESTINATION_ID, feedAttribute);
            break;
          case "Flight Price":
            feedAttributes.put(FlightPlaceholderField.FLIGHT_PRICE, feedAttribute);
            break;
          case "Flight Sale Price":
            feedAttributes.put(FlightPlaceholderField.FLIGHT_SALE_PRICE, feedAttribute);
            break;
          case "Final URLs":
            feedAttributes.put(FlightPlaceholderField.FINAL_URLS, feedAttribute);
            break;
            // The full list of FlightPlaceholderFields can be found here
            // https://developers.google.com/google-ads/api/reference/rpc/latest/FlightPlaceholderFieldEnum.FlightPlaceholderField
          default:
            throw new Error("Invalid attribute name.");
        }
      }
      return feedAttributes;
    }
  }

  /**
   * Creates a feed mapping for a given feed.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the client customer ID.
   * @param feedAttributes the feed attributes.
   * @param feedResourceName the feed resource name.
   */
  private void createFeedMapping(
      GoogleAdsClient googleAdsClient,
      long customerId,
      Map<FlightPlaceholderField, FeedAttribute> feedAttributes,
      String feedResourceName) {
    // Maps the FeedAttributeIds to the fieldId constants.
    AttributeFieldMapping flightDescriptionMapping =
        AttributeFieldMapping.newBuilder()
            .setFeedAttributeId(
                feedAttributes.get(FlightPlaceholderField.FLIGHT_DESCRIPTION).getId())
            .setFlightField(FlightPlaceholderField.FLIGHT_DESCRIPTION)
            .build();
    AttributeFieldMapping destinationIdMapping =
        AttributeFieldMapping.newBuilder()
            .setFeedAttributeId(feedAttributes.get(FlightPlaceholderField.DESTINATION_ID).getId())
            .setFlightField(FlightPlaceholderField.DESTINATION_ID)
            .build();
    AttributeFieldMapping flightPriceMapping =
        AttributeFieldMapping.newBuilder()
            .setFeedAttributeId(feedAttributes.get(FlightPlaceholderField.FLIGHT_PRICE).getId())
            .setFlightField(FlightPlaceholderField.FLIGHT_PRICE)
            .build();
    AttributeFieldMapping flightSalePriceMapping =
        AttributeFieldMapping.newBuilder()
            .setFeedAttributeId(
                feedAttributes.get(FlightPlaceholderField.FLIGHT_SALE_PRICE).getId())
            .setFlightField(FlightPlaceholderField.FLIGHT_SALE_PRICE)
            .build();
    AttributeFieldMapping finalUrlsMapping =
        AttributeFieldMapping.newBuilder()
            .setFeedAttributeId(feedAttributes.get(FlightPlaceholderField.FINAL_URLS).getId())
            .setFlightField(FlightPlaceholderField.FINAL_URLS)
            .build();

    // Creates the feed mapping.
    FeedMapping feedMapping =
        FeedMapping.newBuilder()
            .setPlaceholderType(PlaceholderType.DYNAMIC_FLIGHT)
            .setFeed(feedResourceName)
            .addAttributeFieldMappings(flightDescriptionMapping)
            .addAttributeFieldMappings(destinationIdMapping)
            .addAttributeFieldMappings(flightPriceMapping)
            .addAttributeFieldMappings(flightSalePriceMapping)
            .addAttributeFieldMappings(finalUrlsMapping)
            .build();

    // Creates the operation.
    FeedMappingOperation operation =
        FeedMappingOperation.newBuilder().setCreate(feedMapping).build();

    // Adds the FeedMapping.
    try (FeedMappingServiceClient feedMappingServiceClient =
        googleAdsClient.getLatestVersion().createFeedMappingServiceClient()) {
      MutateFeedMappingsResponse response =
          feedMappingServiceClient.mutateFeedMappings(
              Long.toString(customerId), ImmutableList.of(operation));

      // Displays the results.
      for (MutateFeedMappingResult result : response.getResultsList()) {
        System.out.printf(
            "Created feed mapping with resource name '%s'.%n", result.getResourceName());
      }
    }
  }

  /**
   * Adds a new item to the feed.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the client customer ID.
   * @param feedAttributes the feed attributes.
   * @param feedResourceName the feed resource name.
   */
  private void createFeedItem(
      GoogleAdsClient googleAdsClient,
      long customerId,
      Map<FlightPlaceholderField, FeedAttribute> feedAttributes,
      String feedResourceName) {

    // Creates the flight description feed attribute value.
    FeedItemAttributeValue flightDescription =
        FeedItemAttributeValue.newBuilder()
            .setFeedAttributeId(
                feedAttributes.get(FlightPlaceholderField.FLIGHT_DESCRIPTION).getId())
            .setStringValue("Earth to Mars")
            .build();
    // Creates the destination ID feed attribute value.
    FeedItemAttributeValue destinationId =
        FeedItemAttributeValue.newBuilder()
            .setFeedAttributeId(feedAttributes.get(FlightPlaceholderField.DESTINATION_ID).getId())
            .setStringValue("Mars")
            .build();
    // Creates the flight price feed attribute value.
    FeedItemAttributeValue flightPrice =
        FeedItemAttributeValue.newBuilder()
            .setFeedAttributeId(feedAttributes.get(FlightPlaceholderField.FLIGHT_PRICE).getId())
            .setStringValue("499.99 USD")
            .build();
    // Creates the flight sale price feed attribute value.
    FeedItemAttributeValue flightSalePrice =
        FeedItemAttributeValue.newBuilder()
            .setFeedAttributeId(
                feedAttributes.get(FlightPlaceholderField.FLIGHT_SALE_PRICE).getId())
            .setStringValue("299.99 USD")
            .build();
    // Creates the final URLs feed attribute value.
    FeedItemAttributeValue finalUrls =
        FeedItemAttributeValue.newBuilder()
            .setFeedAttributeId(feedAttributes.get(FlightPlaceholderField.FINAL_URLS).getId())
            .addStringValues("http://www.example.com/flights/")
            .build();

    // Creates the FeedItem, specifying the Feed ID and the attributes created above.
    FeedItem feedItem =
        FeedItem.newBuilder()
            .setFeed(feedResourceName)
            .addAttributeValues(flightDescription)
            .addAttributeValues(destinationId)
            .addAttributeValues(flightPrice)
            .addAttributeValues(flightSalePrice)
            .addAttributeValues(finalUrls)
            .build();

    // Creates an operation to add the FeedItem.
    FeedItemOperation operation = FeedItemOperation.newBuilder().setCreate(feedItem).build();

    // Creates the feed item service client.
    try (FeedItemServiceClient feedItemServiceClient =
        googleAdsClient.getLatestVersion().createFeedItemServiceClient()) {
      // Adds the feed item.
      MutateFeedItemsResponse response =
          feedItemServiceClient.mutateFeedItems(
              Long.toString(customerId), ImmutableList.of(operation));
      for (MutateFeedItemResult result : response.getResultsList()) {
        System.out.printf("Created feed item 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.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.FeedAttributeTypeEnum.Types;
using static Google.Ads.GoogleAds.V11.Enums.FlightPlaceholderFieldEnum.Types;
using static Google.Ads.GoogleAds.V11.Enums.PlaceholderTypeEnum.Types;

namespace Google.Ads.GoogleAds.Examples.V11
{
    /// <summary>
    /// This code example adds a flights feed, creates the associated feed mapping, and
    /// adds a feed item. To update feeds, see UpdateFeedItemAttributeValue.cs.
    /// </summary>
    public class AddFlightsFeed : ExampleBase
    {
        /// <summary>
        /// Command line options for running the <see cref="AddFlightsFeed"/> example.
        /// </summary>
        public class Options : OptionsBase
        {
            /// <summary>
            /// The Google Ads customer ID to which the flights feed is added.
            /// </summary>
            [Option("customerId", Required = true, HelpText =
                "The Google Ads customer ID to which the flights feed is added.")]
            public long CustomerId { 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);

            AddFlightsFeed codeExample = new AddFlightsFeed();
            Console.WriteLine(codeExample.Description);
            codeExample.Run(new GoogleAdsClient(), options.CustomerId);
        }

        /// <summary>
        /// Returns a description about the code example.
        /// </summary>
        public override string Description =>
            "This code example adds a flights feed, creates the associated feed mapping, and " +
            "adds a feed item. To update feeds, see UpdateFeedItemAttributeValue.cs.";

        /// <summary>
        /// Runs the code example.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The Google Ads customer ID to which the flights feed is
        /// added.</param>
        public void Run(GoogleAdsClient client, long customerId)
        {
            try
            {
                // Creates a new flights feed.
                string feedResourceName = CreateFeed(client, customerId);

                // Get the newly creates feed's attributes and packages them into a map. This read
                // operation is required to retrieve the attribute IDs.
                Dictionary<FlightPlaceholderField, FeedAttribute> feedAttributes =
                    GetFeed(client, customerId, feedResourceName);

                // Creates the feed mapping.
                CreateFeedMapping(client, customerId, feedAttributes, feedResourceName);

                // Creates a feed item.
                CreateFeedItem(client, customerId, feedAttributes, feedResourceName);
            }
            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 the feed.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The Google Ads customer ID for which the flights feed is
        /// added.</param>
        /// <returns>Resource name of the newly created feed.</returns>
        private string CreateFeed(GoogleAdsClient client, long customerId)
        {
            // Get the FeedService.
            FeedServiceClient feedService = client.GetService(Services.V11.FeedService);

            // Creates a Flight Description attribute.
            FeedAttribute flightDescriptionAttribute = new FeedAttribute()
            {
                Type = FeedAttributeType.String,
                Name = "Flight Description"
            };

            // Creates a Destination ID attribute.
            FeedAttribute destinationIdAttribute = new FeedAttribute()
            {
                Type = FeedAttributeType.String,
                Name = "Destination ID"
            };

            // Creates a Flight Price attribute.
            FeedAttribute flightPriceAttribute = new FeedAttribute()
            {
                Type = FeedAttributeType.String,
                Name = "Flight Price"
            };

            // Creates a Flight Sale Price attribute.
            FeedAttribute flightSalesPriceAttribute = new FeedAttribute()
            {
                Type = FeedAttributeType.String,
                Name = "Flight Sale Price"
            };

            // Creates a Final URLs attribute.
            FeedAttribute finalUrlsAttribute = new FeedAttribute()
            {
                Type = FeedAttributeType.UrlList,
                Name = "Final URLs"
            };

            // Creates the feed.
            Feed feed = new Feed()
            {
                Name = "Flights Feed #" + ExampleUtilities.GetRandomString(),
                Attributes =
                {
                    flightDescriptionAttribute,
                    destinationIdAttribute,
                    flightPriceAttribute,
                    flightSalesPriceAttribute,
                    finalUrlsAttribute
                }
            };

            // Creates the operation.
            FeedOperation operation = new FeedOperation()
            {
                Create = feed
            };

            // Adds the feed.
            MutateFeedsResponse response =
                feedService.MutateFeeds(customerId.ToString(), new[] { operation });

            string feedResourceName = response.Results[0].ResourceName;

            // Displays the result.
            Console.WriteLine($"Feed with resource name '{feedResourceName}' was created.");
            return feedResourceName;
        }

        /// <summary>
        /// Retrieves details about a feed. The initial query retrieves the FeedAttributes,
        /// or columns, of the feed. Each FeedAttribute will also include the FeedAttributeId,
        /// which will be used in a subsequent step. The example then inserts a new key, value
        /// pair into a map for each FeedAttribute, which is the return value of the method.
        /// The keys are the placeholder types that the columns will be. The values are the
        /// FeedAttributes.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The Google Ads customer ID for which the flights feed is
        /// added.</param>
        /// <param name="feedResourceName">The resource name of the feed.</param>
        /// <returns>
        /// A Map containing the FlightPlaceholderField and FeedAttribute.
        /// </returns>
        public Dictionary<FlightPlaceholderField, FeedAttribute> GetFeed(
            GoogleAdsClient client, long customerId, string feedResourceName)
        {
            // Get the GoogleAdsService.
            GoogleAdsServiceClient googleAdsService = client.GetService(
                Services.V11.GoogleAdsService);

            // Constructs the query.
            string query = $"SELECT feed.attributes FROM feed WHERE feed.resource_name = " +
                $"'{feedResourceName}'";

            // Constructs the request.
            SearchGoogleAdsRequest request = new SearchGoogleAdsRequest()
            {
                CustomerId = customerId.ToString(),
                Query = query
            };

            // Issues the search request and get the first result, since we only need the
            // single feed item we created previously.
            GoogleAdsRow googleAdsRow = googleAdsService.Search(request).First();

            // Gets the attributes list from the feed and creates a map with keys of each attribute and
            // values of each corresponding ID.
            Dictionary<FlightPlaceholderField, FeedAttribute> feedAttributes =
                new Dictionary<FlightPlaceholderField, FeedAttribute>();

            // Loops through the feed attributes to populate the map.
            foreach (FeedAttribute feedAttribute in googleAdsRow.Feed.Attributes)
            {
                switch (feedAttribute.Name)
                {
                    case "Flight Description":
                        feedAttributes[FlightPlaceholderField.FlightDescription] = feedAttribute;
                        break;

                    case "Destination ID":
                        feedAttributes[FlightPlaceholderField.DestinationId] = feedAttribute;
                        break;

                    case "Flight Price":
                        feedAttributes[FlightPlaceholderField.FlightPrice] = feedAttribute;
                        break;

                    case "Flight Sale Price":
                        feedAttributes[FlightPlaceholderField.FlightSalePrice] = feedAttribute;
                        break;

                    case "Final URLs":
                        feedAttributes[FlightPlaceholderField.FinalUrls] = feedAttribute;
                        break;
                    // The full list of FlightPlaceholderFields can be found here
                    // https://developers.google.com/google-ads/api/reference/rpc/latest/FlightPlaceholderFieldEnum.FlightPlaceholderField
                    default:
                        throw new Exception("Invalid attribute name.");
                }
            }
            return feedAttributes;
        }

        /// <summary>
        /// Creates a feed mapping for a given feed.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The Google Ads customer ID for which the flights feed is
        /// added.</param>
        /// <param name="feedAttributes">The feed attributes.</param>
        /// <param name="feedResourceName">The resource name of the feed.</param>
        private void CreateFeedMapping(GoogleAdsClient client, long customerId,
            Dictionary<FlightPlaceholderField, FeedAttribute> feedAttributes,
            string feedResourceName)
        {
            // Get the FeedMappingServiceClient.
            FeedMappingServiceClient feedMappingService = client.GetService(
                Services.V11.FeedMappingService);

            // Maps the FeedAttributeIds to the fieldId constants.
            AttributeFieldMapping flightDescriptionMapping = new AttributeFieldMapping()
            {
                FeedAttributeId = feedAttributes[FlightPlaceholderField.FlightDescription].Id,
                FlightField = FlightPlaceholderField.FlightDescription
            };

            AttributeFieldMapping destinationIdMapping = new AttributeFieldMapping()
            {
                FeedAttributeId = feedAttributes[FlightPlaceholderField.DestinationId].Id,
                FlightField = FlightPlaceholderField.DestinationId
            };

            AttributeFieldMapping flightPriceMapping = new AttributeFieldMapping()
            {
                FeedAttributeId = feedAttributes[FlightPlaceholderField.FlightPrice].Id,
                FlightField = FlightPlaceholderField.FlightPrice
            };

            AttributeFieldMapping flightSalePriceMapping = new AttributeFieldMapping()
            {
                FeedAttributeId = feedAttributes[FlightPlaceholderField.FlightSalePrice].Id,
                FlightField = FlightPlaceholderField.FlightSalePrice
            };

            AttributeFieldMapping finalUrlsMapping = new AttributeFieldMapping()
            {
                FeedAttributeId = feedAttributes[FlightPlaceholderField.FinalUrls].Id,
                FlightField = FlightPlaceholderField.FinalUrls
            };

            // Creates the feed mapping.
            FeedMapping feedMapping = new FeedMapping()
            {
                PlaceholderType = PlaceholderType.DynamicFlight,
                Feed = feedResourceName,
                AttributeFieldMappings =
                {
                    flightDescriptionMapping,
                    destinationIdMapping,
                    flightPriceMapping,
                    flightSalePriceMapping,
                    finalUrlsMapping
                }
            };

            // Creates the operation.
            FeedMappingOperation operation = new FeedMappingOperation()
            {
                Create = feedMapping
            };

            // Adds the FeedMapping.
            MutateFeedMappingsResponse response = feedMappingService.MutateFeedMappings(
                customerId.ToString(), new[] { operation });

            // Displays the results.
            foreach (MutateFeedMappingResult result in response.Results)
            {
                Console.WriteLine($"Created feed mapping with resource name" +
                    $" '{result.ResourceName}'.");
            }
        }

        /// <summary>
        /// Adds a new item to the feed.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The Google Ads customer ID for which the flights feed is
        /// added.</param>
        /// <param name="feedAttributes">The feed attributes.</param>
        /// <param name="feedResourceName">The resource name of the feed.</param>
        private void CreateFeedItem(GoogleAdsClient client, long customerId,
            Dictionary<FlightPlaceholderField, FeedAttribute> feedAttributes,
            string feedResourceName)
        {
            // Get the FeedItemServiceClient.
            FeedItemServiceClient feedItemService = client.GetService(
                Services.V11.FeedItemService);

            // Creates the flight description feed attribute value.
            FeedItemAttributeValue flightDescription = new FeedItemAttributeValue()
            {
                FeedAttributeId = feedAttributes[FlightPlaceholderField.FlightDescription].Id,
                StringValue = "Earth to Mars"
            };

            // Creates the destination ID feed attribute value.
            FeedItemAttributeValue destinationId = new FeedItemAttributeValue()
            {
                FeedAttributeId = feedAttributes[FlightPlaceholderField.DestinationId].Id,
                StringValue = "Mars"
            };

            // Creates the flight price feed attribute value.
            FeedItemAttributeValue flightPrice = new FeedItemAttributeValue()
            {
                FeedAttributeId = feedAttributes[FlightPlaceholderField.FlightPrice].Id,
                StringValue = "499.99 USD"
            };

            // Creates the flight sale price feed attribute value.
            FeedItemAttributeValue flightSalePrice = new FeedItemAttributeValue()
            {
                FeedAttributeId = feedAttributes[FlightPlaceholderField.FlightSalePrice].Id,
                StringValue = "299.99 USD"
            };

            // Creates the final URLs feed attribute value.
            FeedItemAttributeValue finalUrls = new FeedItemAttributeValue()
            {
                FeedAttributeId = feedAttributes[FlightPlaceholderField.FinalUrls].Id,
                StringValues = { "http://www.example.com/flights/" }
            };

            // Creates the FeedItem, specifying the Feed ID and the attributes created above.
            FeedItem feedItem = new FeedItem()
            {
                Feed = feedResourceName,
                AttributeValues =
                {
                    flightDescription,
                    destinationId,
                    flightPrice,
                    flightSalePrice,
                    finalUrls
                }
            };

            // Creates an operation to add the FeedItem.
            FeedItemOperation operation = new FeedItemOperation()
            {
                Create = feedItem
            };

            // Adds the feed item.
            MutateFeedItemsResponse response =
                feedItemService.MutateFeedItems(customerId.ToString(),
                    new FeedItemOperation[] { operation });

            foreach (MutateFeedItemResult result in response.Results)
            {
                Console.WriteLine($"Created feed item 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\Remarketing;

require __DIR__ . '/../../vendor/autoload.php';

use GetOpt\GetOpt;
use Google\Ads\GoogleAds\Examples\Utils\ArgumentNames;
use Google\Ads\GoogleAds\Examples\Utils\ArgumentParser;
use Google\Ads\GoogleAds\Examples\Utils\Feeds;
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\V11\Enums\FeedAttributeTypeEnum\FeedAttributeType;
use Google\Ads\GoogleAds\V11\Enums\FlightPlaceholderFieldEnum\FlightPlaceholderField;
use Google\Ads\GoogleAds\V11\Enums\PlaceholderTypeEnum\PlaceholderType;
use Google\Ads\GoogleAds\V11\Errors\GoogleAdsError;
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\FeedMapping;
use Google\Ads\GoogleAds\V11\Services\FeedItemOperation;
use Google\Ads\GoogleAds\V11\Services\FeedMappingOperation;
use Google\Ads\GoogleAds\V11\Services\FeedOperation;
use Google\ApiCore\ApiException;

/** Adds a flights feed, creates the associated feed mapping, and adds a feed item. */
class AddFlightsFeed
{
    private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE';

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

        // 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
            );
        } 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
     */
    public static function runExample(GoogleAdsClient $googleAdsClient, int $customerId)
    {
        // Creates a new flights feed.
        $feedResourceName = self::createFeed($googleAdsClient, $customerId);
        // Gets the newly created feed's attributes and packages them into a map. This read
        // operation is required to retrieve the attribute IDs.
        $placeHoldersToFeedAttributesMap =
            Feeds::flightPlaceholderFieldsMapFor($feedResourceName, $customerId, $googleAdsClient);
        // Creates the feed mapping.
        self::createFeedMapping(
            $googleAdsClient,
            $customerId,
            $feedResourceName,
            $placeHoldersToFeedAttributesMap
        );
        // Creates a feed item.
        self::createFeedItem(
            $googleAdsClient,
            $customerId,
            $feedResourceName,
            $placeHoldersToFeedAttributesMap
        );
    }

    /**
     * Creates a feed that will be used as a flight feed.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @return string the feed resource name
     */
    private static function createFeed(GoogleAdsClient $googleAdsClient, int $customerId)
    {
        // Creates a flight description attribute.
        $flightDescriptionAttribute = new FeedAttribute([
            'type' =>  FeedAttributeType::STRING,
            'name' => 'Flight Description'
        ]);
        // Creates a destination ID attribute.
        $destinationIdAttribute = new FeedAttribute([
            'type' =>  FeedAttributeType::STRING,
            'name' => 'Destination ID'
        ]);
        // Creates a flight price attribute.
        $flightPriceAttribute = new FeedAttribute([
            'type' =>  FeedAttributeType::STRING,
            'name' => 'Flight Price'
        ]);
        // Creates a flight sale price attribute.
        $flightSalesPriceAttribute = new FeedAttribute([
            'type' =>  FeedAttributeType::STRING,
            'name' => 'Flight Sale Price'
        ]);
        // Creates a Final URLs attribute.
        $finalUrlsAttribute = new FeedAttribute([
            'type' =>  FeedAttributeType::URL_LIST,
            'name' => 'Final URLs'
        ]);

        // Creates the feed with the newly created feed attributes.
        $feed = new Feed([
            'name' => 'Flights Feed #' . Helper::getPrintableDatetime(),
            'attributes' => [
                $flightDescriptionAttribute,
                $destinationIdAttribute,
                $flightPriceAttribute,
                $flightSalesPriceAttribute,
                $finalUrlsAttribute
            ]
        ]);

        // Creates the feed operation.
        $operation = new FeedOperation();
        $operation->setCreate($feed);

        // Issues a mutate request to add the feed and print some information.
        $feedServiceClient = $googleAdsClient->getFeedServiceClient();
        $response = $feedServiceClient->mutateFeeds($customerId, [$operation]);
        $feedResourceName = $response->getResults()[0]->getResourceName();
        printf("Feed with resource name '%s' was created.%s", $feedResourceName, PHP_EOL);

        return $feedResourceName;
    }

    /**
     * Creates a feed mapping for a given feed.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param string $feedResourceName the feed resource name for creating a feed mapping
     * @param array $placeHoldersToFeedAttributesMap the map from placeholder fields to feed
     *      attributes
     */
    private static function createFeedMapping(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        string $feedResourceName,
        array $placeHoldersToFeedAttributesMap
    ) {
        // Maps the feed attribute IDs to the field ID constants.
        $flightDescriptionMapping = new AttributeFieldMapping([
            'feed_attribute_id' => $placeHoldersToFeedAttributesMap[
                FlightPlaceholderField::FLIGHT_DESCRIPTION]->getId(),
            'flight_field' => FlightPlaceholderField::FLIGHT_DESCRIPTION
        ]);
        $destinationIdMapping = new AttributeFieldMapping([
            'feed_attribute_id' => $placeHoldersToFeedAttributesMap[
                FlightPlaceholderField::DESTINATION_ID]->getId(),
            'flight_field' => FlightPlaceholderField::DESTINATION_ID
        ]);
        $flightPriceMapping = new AttributeFieldMapping([
            'feed_attribute_id' => $placeHoldersToFeedAttributesMap[
                FlightPlaceholderField::FLIGHT_PRICE]->getId(),
            'flight_field' => FlightPlaceholderField::FLIGHT_PRICE
        ]);
        $flightSalePriceMapping = new AttributeFieldMapping([
            'feed_attribute_id' => $placeHoldersToFeedAttributesMap[
                FlightPlaceholderField::FLIGHT_SALE_PRICE]->getId(),
            'flight_field' => FlightPlaceholderField::FLIGHT_SALE_PRICE
        ]);
        $finalUrlsMapping = new AttributeFieldMapping([
            'feed_attribute_id' => $placeHoldersToFeedAttributesMap[
                FlightPlaceholderField::FINAL_URLS]->getId(),
            'flight_field' => FlightPlaceholderField::FINAL_URLS
        ]);

        // Creates the feed mapping.
        $feedMapping = new FeedMapping([
            'placeholder_type' => PlaceholderType::DYNAMIC_FLIGHT,
            'feed' => $feedResourceName,
            'attribute_field_mappings' => [
                $flightDescriptionMapping,
                $destinationIdMapping,
                $flightPriceMapping,
                $flightSalePriceMapping,
                $finalUrlsMapping
            ]
        ]);

        // Creates the feed mapping operation.
        $operation = new FeedMappingOperation();
        $operation->setCreate($feedMapping);

        // Issues a mutate request to add the feed mapping and print some information.
        $feedMappingServiceClient = $googleAdsClient->getFeedMappingServiceClient();
        $response = $feedMappingServiceClient->mutateFeedMappings($customerId, [$operation]);
        printf(
            "Feed mapping with resource name '%s' was created.%s",
            $response->getResults()[0]->getResourceName(),
            PHP_EOL
        );
    }

    /**
     * Adds a new item to the feed.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param string $feedResourceName the feed resource name for creating a feed item
     * @param array $placeHoldersToFeedAttributesMap the map from placeholder fields to feed
     *      attributes
     */
    private static function createFeedItem(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        string $feedResourceName,
        array $placeHoldersToFeedAttributesMap
    ) {
        // Creates the flight description feed attribute value.
        $flightDescriptionAttributeValue = new FeedItemAttributeValue([
            'feed_attribute_id' => $placeHoldersToFeedAttributesMap[
                FlightPlaceholderField::FLIGHT_DESCRIPTION]->getId(),
            'string_value' => 'Earth to Mars'
        ]);
        // Creates the destination ID feed attribute value.
        $destinationIdAttributeValue = new FeedItemAttributeValue([
            'feed_attribute_id' => $placeHoldersToFeedAttributesMap[
                FlightPlaceholderField::DESTINATION_ID]->getId(),
            'string_value' => 'Mars'
        ]);
        // Creates the flight price feed attribute value.
        $flightPriceAttributeValue = new FeedItemAttributeValue([
            'feed_attribute_id' => $placeHoldersToFeedAttributesMap[
                FlightPlaceholderField::FLIGHT_PRICE]->getId(),
            'string_value' => '499.99 USD'
        ]);
        // Creates the flight sale price feed attribute value.
        $flightSalePriceAttributeValue = new FeedItemAttributeValue([
            'feed_attribute_id' => $placeHoldersToFeedAttributesMap[
                FlightPlaceholderField::FLIGHT_SALE_PRICE]->getId(),
            'string_value' => '299.99 USD'
        ]);
        // Creates the final URLs feed attribute value.
        $finalUrlsAttributeValue = new FeedItemAttributeValue([
            'feed_attribute_id'
                => $placeHoldersToFeedAttributesMap[FlightPlaceholderField::FINAL_URLS]->getId(),
            'string_values' => ['http://www.example.com/flights/']
        ]);

        // Creates the feed item, specifying the feed ID and the attributes created above.
        $feedItem = new FeedItem([
            'feed' => $feedResourceName,
            'attribute_values' => [
                $flightDescriptionAttributeValue,
                $destinationIdAttributeValue,
                $flightPriceAttributeValue,
                $flightSalePriceAttributeValue,
                $finalUrlsAttributeValue
            ]
        ]);

        // Creates the feed item operation.
        $operation = new FeedItemOperation();
        $operation->setCreate($feedItem);

        // Issues a mutate request to add the feed item and print some information.
        $feedItemServiceClient = $googleAdsClient->getFeedItemServiceClient();
        $response = $feedItemServiceClient->mutateFeedItems($customerId, [$operation]);
        printf(
            "Feed item with resource name '%s' was created.%s",
            $response->getResults()[0]->getResourceName(),
            PHP_EOL
        );
    }
}

AddFlightsFeed::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 a flights feed, creates associated field mapping, and adds feed item.
"""


import argparse
import sys
from uuid import uuid4

from google.ads.googleads.client import GoogleAdsClient
from google.ads.googleads.errors import GoogleAdsException

_DEFAULT_PAGE_SIZE = 10000


def main(client, customer_id):
    """The main method that creates all necessary entities for the example.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID.
    """
    # Creates a new flights feed.
    feed_resource_name = _create_feed(client, customer_id)

    print(f"Feed with resource name '{feed_resource_name}' was created.")

    # Gets the newly created feed's attributes and packages them into a map.
    # This read operation is required to retrieve the attribute IDs.
    placeholders_to_feed_attributes_map = _get_placeholder_fields_map(
        client, customer_id, feed_resource_name
    )

    # Creates the feed mapping.
    feed_mapping_resource_name = _create_feed_mapping(
        client,
        customer_id,
        feed_resource_name,
        placeholders_to_feed_attributes_map,
    )

    print(
        f"Feed mapping with resource name '{feed_mapping_resource_name}' "
        "was created."
    )

    # Creates a feed item.
    feed_item_resource_name = _create_feed_item(
        client,
        customer_id,
        feed_resource_name,
        placeholders_to_feed_attributes_map,
    )

    print(
        f"Feed item with resource name '{feed_item_resource_name}' was "
        "created."
    )


def _create_feed(client, customer_id):
    """Creates a feed that will be used as a flight feed.

    Args:
        client: An initialized GoogleAds client.
        customer_id: The Google Ads customer ID.

    Returns:
        A str resource name of the newly created feed.
    """
    feed_service = client.get_service("FeedService")
    feed_attribute_type_enum = client.enums.FeedAttributeTypeEnum

    # Creates the feed operation.
    feed_operation = client.get_type("FeedOperation")

    # Create the feed with feed attributes defined below.
    feed = feed_operation.create
    feed.name = f"Flights Feed #{uuid4()}"

    # Creates a flight description attribute.
    flight_description_attribute = client.get_type("FeedAttribute")
    flight_description_attribute.name = "Flight Description"
    flight_description_attribute.type_ = feed_attribute_type_enum.STRING

    # Creates a destination ID attribute.
    destination_id_attribute = client.get_type("FeedAttribute")
    destination_id_attribute.name = "Destination ID"
    destination_id_attribute.type_ = feed_attribute_type_enum.STRING

    # Creates a flight price attribute.
    flight_price_attribute = client.get_type("FeedAttribute")
    flight_price_attribute.name = "Flight Price"
    flight_price_attribute.type_ = feed_attribute_type_enum.STRING

    # Creates a flight sale price attribute.
    flight_sale_price_attribute = client.get_type("FeedAttribute")
    flight_sale_price_attribute.name = "Flight Sale Price"
    flight_sale_price_attribute.type_ = feed_attribute_type_enum.STRING

    # Creates a final URLs attribute.
    final_urls_attribute = client.get_type("FeedAttribute")
    final_urls_attribute.name = "Final URLs"
    final_urls_attribute.type_ = feed_attribute_type_enum.URL_LIST

    # append FeedAttributes to feed.attributes
    feed.attributes.extend(
        [
            flight_description_attribute,
            destination_id_attribute,
            flight_price_attribute,
            flight_sale_price_attribute,
            final_urls_attribute,
        ]
    )
    try:
        # Issues a mutate request to add the feed.
        feed_response = feed_service.mutate_feeds(
            customer_id=customer_id, operations=[feed_operation]
        )
    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"\tError 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)

    return feed_response.results[0].resource_name


def _create_feed_mapping(
    client, customer_id, feed_resource_name, placeholders_to_feed_attribute_map
):
    """Creates a feed mapping for a given feed.

    Args:
        client: An initialized GoogleAds client.
        customer_id: The Google Ads customer ID.
        feed_resource_name: A str feed resource name for creating a feed
            mapping.
        placeholders_to_feed_attribute_map: A dict mapping placeholder feeds to
            feed attributes.

    Returns:
        A str resource name of the newly created feed mapping.
    """
    feed_mapping_service = client.get_service("FeedMappingService")

    # Creates the feed mapping operation.
    feed_mapping_operation = client.get_type("FeedMappingOperation")

    # Create the feed with feed attributes defined below.
    feed_mapping = feed_mapping_operation.create
    feed_mapping.feed = feed_resource_name
    feed_mapping.placeholder_type = (
        client.enums.PlaceholderTypeEnum.DYNAMIC_FLIGHT
    )

    # Maps the feed attribute IDs to the field ID constants.
    placeholder_field_enum = client.enums.FlightPlaceholderFieldEnum
    flight_desc_enum_value = placeholder_field_enum.FLIGHT_DESCRIPTION
    desc_mapping = client.get_type("AttributeFieldMapping")
    desc_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[
        flight_desc_enum_value
    ].id
    desc_mapping.flight_field = flight_desc_enum_value

    flight_dest_id_enum_value = placeholder_field_enum.DESTINATION_ID
    dest_id_mapping = client.get_type("AttributeFieldMapping")
    dest_id_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[
        flight_dest_id_enum_value
    ].id
    dest_id_mapping.flight_field = flight_dest_id_enum_value

    flight_price_enum_value = placeholder_field_enum.FLIGHT_PRICE
    price_mapping = client.get_type("AttributeFieldMapping")
    price_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[
        flight_price_enum_value
    ].id
    price_mapping.flight_field = flight_price_enum_value

    flight_sale_price_enum_value = placeholder_field_enum.FLIGHT_SALE_PRICE
    sale_price_mapping = client.get_type("AttributeFieldMapping")
    sale_price_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[
        flight_sale_price_enum_value
    ].id
    sale_price_mapping.flight_field = flight_sale_price_enum_value

    flight_final_urls_enum_value = placeholder_field_enum.FINAL_URLS
    final_urls_mapping = client.get_type("AttributeFieldMapping")
    final_urls_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[
        flight_final_urls_enum_value
    ].id
    final_urls_mapping.flight_field = flight_final_urls_enum_value

    feed_mapping.attribute_field_mappings.extend(
        [
            desc_mapping,
            dest_id_mapping,
            price_mapping,
            sale_price_mapping,
            final_urls_mapping,
        ]
    )

    try:
        # Issues a mutate request to add the feed mapping.
        feed_mapping_response = feed_mapping_service.mutate_feed_mappings(
            customer_id=customer_id, operations=[feed_mapping_operation]
        )
    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"\tError 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)

    return feed_mapping_response.results[0].resource_name


def _create_feed_item(
    client, customer_id, feed_resource_name, placeholders_to_feed_attribute_map
):
    """Adds a new item to the feed.

    Args:
        client: An initialized GoogleAds client.
        customer_id: The Google Ads customer ID.
        feed_resource_name: A str feed resource name for creating a feed item.
        placeholders_to_feed_attribute_map: A dict mapping placeholder feeds to
            feed attributes.

    Returns:
        A str resource name of the newly created feed item.
    """
    feed_item_service = client.get_service("FeedItemService")

    # Creates the feed mapping operation.
    feed_item_operation = client.get_type("FeedItemOperation")

    # Create the feed item, with feed attributes created below.
    feed_item = feed_item_operation.create
    feed_item.feed = feed_resource_name

    placeholder_field_enum = client.enums.FlightPlaceholderFieldEnum

    # Returns a new instance of FeedItemAttributeValue when called.
    # This prevents the need to repeat these lines every time we need a new
    # FeedItemAttributeValue. Instead, we call feed_item_attribute_value()
    feed_item_attribute_value = lambda: client.get_type(
        "FeedItemAttributeValue"
    )

    # Creates the flight description feed attribute value.
    flight_desc_enum_value = placeholder_field_enum.FLIGHT_DESCRIPTION
    desc_mapping = feed_item_attribute_value()
    desc_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[
        flight_desc_enum_value
    ].id
    desc_mapping.string_value = "Earth to Mars"

    # Creates the destination ID feed attribute value.
    flight_dest_id_enum_value = placeholder_field_enum.DESTINATION_ID
    dest_id_mapping = feed_item_attribute_value()
    dest_id_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[
        flight_dest_id_enum_value
    ].id
    dest_id_mapping.string_value = "Mars"

    # Creates the flight price feed attribute value.
    flight_price_enum_value = placeholder_field_enum.FLIGHT_PRICE
    price_mapping = feed_item_attribute_value()
    price_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[
        flight_price_enum_value
    ].id
    price_mapping.string_value = "499.99 USD"

    # Creates the flight sale price feed attribute value.
    flight_sale_price_enum_value = placeholder_field_enum.FLIGHT_SALE_PRICE
    sale_price_mapping = feed_item_attribute_value()
    sale_price_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[
        flight_sale_price_enum_value
    ].id
    sale_price_mapping.string_value = "299.99 USD"

    # Creates the final URLs feed attribute value.
    flight_final_urls_enum_value = placeholder_field_enum.FINAL_URLS
    final_urls_mapping = feed_item_attribute_value()
    final_urls_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[
        flight_final_urls_enum_value
    ].id
    final_urls_mapping.string_values.append("http://www.example.com/flights")

    feed_item.attribute_values.extend(
        [
            desc_mapping,
            dest_id_mapping,
            price_mapping,
            sale_price_mapping,
            final_urls_mapping,
        ]
    )

    try:
        # Issues a mutate request to add the feed item.
        feed_item_response = feed_item_service.mutate_feed_items(
            customer_id=customer_id, operations=[feed_item_operation]
        )
    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"\tError 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)

    return feed_item_response.results[0].resource_name


def _get_placeholder_fields_map(client, customer_id, feed_resource_name):
    """Get mapping of placeholder fields to feed attributes for a flights feed.

    Args:
        client: An initialized GoogleAds client.
        customer_id: The Google Ads customer ID.
        feed_resource_name: A str feed resource name to get attributes from.

    Returns:
        A dict mapping placeholder fields to feed attributes.
    """
    googleads_service = client.get_service("GoogleAdsService")

    # Constructs the query to get the feed attributes for the specified
    # resource name.
    query = f"""
        SELECT
          feed.attributes
        FROM
          feed
        WHERE
          feed.resource_name = '{feed_resource_name}'"""

    # Issues a search request by specifying a page size.
    search_request = client.get_type("SearchGoogleAdsRequest")
    search_request.customer_id = customer_id
    search_request.query = query
    search_request.page_size = _DEFAULT_PAGE_SIZE
    response = googleads_service.search(request=search_request)

    try:
        # Gets the first result because we only need the single feed we created
        # previously.
        row = list(response)[0]
        feed_attributes = row.feed.attributes

        flight_placeholder_field_enum = client.enums.FlightPlaceholderFieldEnum
        feed_attribute_names_map = {
            "Flight Description": flight_placeholder_field_enum.FLIGHT_DESCRIPTION,
            "Destination ID": flight_placeholder_field_enum.DESTINATION_ID,
            "Flight Price": flight_placeholder_field_enum.FLIGHT_PRICE,
            "Flight Sale Price": flight_placeholder_field_enum.FLIGHT_SALE_PRICE,
            "Final URLs": flight_placeholder_field_enum.FINAL_URLS,
        }

        # Creates map with keys of placeholder fields and values of feed
        # attributes.
        placeholder_fields_map = {
            feed_attribute_names_map[feed_attribute.name]: feed_attribute
            for feed_attribute in feed_attributes
        }
    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"\tError 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)

    return placeholder_fields_map


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 a flights feed for specified 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.",
    )
    args = parser.parse_args()

    main(googleads_client, args.customer_id)

      

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.
#
# This code example adds a flights feed, creates the associated feed mapping,
# and adds a feed item.

require 'optparse'
require 'google/ads/google_ads'
require 'date'

def add_flights_feed(customer_id)
  # GoogleAdsClient will read a config file from
  # ENV['HOME']/google_ads_config.rb when called without parameters
  client = Google::Ads::GoogleAds::GoogleAdsClient.new

  # Creates a new flights feed.
  feed_resource_name = create_feed(client, customer_id)

  # Gets the newly created feed's attributes and packages them into a map.
  # This read operation is required to retrieve the attribute IDs.
  placeholders_to_feed_attribute_map = flight_placeholder_fields_map_for(
    client, customer_id, feed_resource_name)

  # Creates the feed mapping.
  create_feed_mapping(
    client,
    customer_id,
    feed_resource_name,
    placeholders_to_feed_attribute_map,
  )

  # Creates a feed item.
  create_feed_item(
    client,
    customer_id,
    feed_resource_name,
    placeholders_to_feed_attribute_map,
  )
end

# Creates a feed that will be used as a flight feed.
def create_feed(client, customer_id)
  # Creates the feed operation.
  operation = client.operation.create_resource.feed do |feed|
    feed.name = "Flights Feed ##{(Time.new.to_f * 1000).to_i}"
    feed.attributes << client.resource.feed_attribute do |fa|
      fa.type = :STRING
      fa.name = "Flight Description"
    end
    feed.attributes << client.resource.feed_attribute do |fa|
      fa.type = :STRING
      fa.name = "Destination ID"
    end
    feed.attributes << client.resource.feed_attribute do |fa|
      fa.type = :STRING
      fa.name = "Flight Price"
    end
    feed.attributes << client.resource.feed_attribute do |fa|
      fa.type = :STRING
      fa.name = "Flight Sale Price"
    end
    feed.attributes << client.resource.feed_attribute do |fa|
      fa.type = :URL_LIST
      fa.name = "Final URLs"
    end
  end

  # Issues a mutate request to add the feed and print some information.
  response = client.service.feed.mutate_feeds(
    customer_id: customer_id,
    operations: [operation],
  )
  feed_resource_name = response.results.first.resource_name
  puts "Feed with resource name #{feed_resource_name} was created."

  feed_resource_name
end

# Retrieves the place holder fields to feed attributes map for a flights feed.
def flight_placeholder_fields_map_for(
  client,
  customer_id,
  feed_resource_name
)
  # Constructs the query to get the feed attributes for the specified feed
  # resource name.
  query = <<~QUERY
    SELECT feed.attributes
    FROM feed
    WHERE feed.resource_name = '#{feed_resource_name}'
  QUERY

  # Issues a search request by specifying page size.
  response = client.service.google_ads.search(
    customer_id: customer_id,
    query: query,
    page_size: PAGE_SIZE,
  )

  # Flight feed attribute names map.
  feed_attribute_names_map = {
    :'Flight Description' => :FLIGHT_DESCRIPTION,
    :'Destination ID' => :DESTINATION_ID,
    :'Flight Price' => :FLIGHT_PRICE,
    :'Flight Sale Price' => :FLIGHT_SALE_PRICE,
    :'Final URLs' => :FINAL_URLS,
  }

  # Gets the attributes list from the feed and creates a map with keys of
  # placeholder fields and values of feed attributes.
  feed_attributes = response.first.feed.attributes
  placeholder_fields = []
  feed_attributes.each do |feed_attribute|
    unless feed_attribute_names_map.has_key?(feed_attribute.name.to_sym)
      raise "Invalid feed attribute name."
    end
    placeholder_fields << feed_attribute_names_map[feed_attribute.name.to_sym]
  end

  fields_map = {}
  placeholder_fields.zip(feed_attributes) {|a, b| fields_map[a.to_sym] = b }

  fields_map
end

# Creates a feed mapping for a given feed.
def create_feed_mapping(
  client,
  customer_id,
  feed_resource_name,
  placeholders_to_feed_attribute_map
)
  # Creates the feed mapping operation.
  operation = client.operation.create_resource.feed_mapping do |fm|
    fm.placeholder_type = :DYNAMIC_FLIGHT
    fm.feed = feed_resource_name
    fm.attribute_field_mappings << client.resource.attribute_field_mapping do |afm|
      afm.feed_attribute_id = placeholders_to_feed_attribute_map[:FLIGHT_DESCRIPTION].id
      afm.flight_field = :FLIGHT_DESCRIPTION
    end
    fm.attribute_field_mappings << client.resource.attribute_field_mapping do |afm|
      afm.feed_attribute_id = placeholders_to_feed_attribute_map[:DESTINATION_ID].id
      afm.flight_field = :DESTINATION_ID
    end
    fm.attribute_field_mappings << client.resource.attribute_field_mapping do |afm|
      afm.feed_attribute_id = placeholders_to_feed_attribute_map[:FLIGHT_PRICE].id
      afm.flight_field = :FLIGHT_PRICE
    end
    fm.attribute_field_mappings << client.resource.attribute_field_mapping do |afm|
      afm.feed_attribute_id = placeholders_to_feed_attribute_map[:FLIGHT_SALE_PRICE].id
      afm.flight_field = :FLIGHT_SALE_PRICE
    end
    fm.attribute_field_mappings << client.resource.attribute_field_mapping do |afm|
      afm.feed_attribute_id = placeholders_to_feed_attribute_map[:FINAL_URLS].id
      afm.flight_field = :FINAL_URLS
    end
  end

  # Issues a mutate request to add the feed mapping and print some information.
  response = client.service.feed_mapping.mutate_feed_mappings(
    customer_id: customer_id,
    operations: [operation],
  )
  puts "Feed mapping with resource name " \
    "#{response.results.first.resource_name} was created."
end

# Adds a new item to the feed.
def create_feed_item(
  client,
  customer_id,
  feed_resource_name,
  placeholders_to_feed_attribute_map
)
  # Creates the feed item operation.
  operation = client.operation.create_resource.feed_item do |fi|
    fi.feed = feed_resource_name
    fi.attribute_values << client.resource.feed_item_attribute_value do |v|
      v.feed_attribute_id = placeholders_to_feed_attribute_map[:FLIGHT_DESCRIPTION].id
      v.string_value = "Earth to Mars"
    end
    fi.attribute_values << client.resource.feed_item_attribute_value do |v|
      v.feed_attribute_id = placeholders_to_feed_attribute_map[:DESTINATION_ID].id
      v.string_value = "Mars"
    end
    fi.attribute_values << client.resource.feed_item_attribute_value do |v|
      v.feed_attribute_id = placeholders_to_feed_attribute_map[:FLIGHT_PRICE].id
      v.string_value = "499.99 USD"
    end
    fi.attribute_values << client.resource.feed_item_attribute_value do |v|
      v.feed_attribute_id = placeholders_to_feed_attribute_map[:FLIGHT_SALE_PRICE].id
      v.string_value = "299.99 USD"
    end
    fi.attribute_values << client.resource.feed_item_attribute_value do |v|
      v.feed_attribute_id = placeholders_to_feed_attribute_map[:FINAL_URLS].id
      v.string_values << "http://www.example.com/flights/"
    end
  end

  # Issues a mutate request to add the feed item and print some information.
  response = client.service.feed_item.mutate_feed_items(
    customer_id: customer_id,
    operations: [operation],
  )
  puts "Feed item with resource name " \
    "#{response.results.first.resource_name} was created."
end

if __FILE__ == $0
  PAGE_SIZE = 1000

  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'

  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.separator ''
    opts.separator 'Help:'

    opts.on_tail('-h', '--help', 'Show this message') do
      puts opts
      exit
    end
  end.parse!

  begin
    add_flights_feed(options.fetch(:customer_id).tr("-", ""))
  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.
#
# This example adds a flights feed, creates the associated feed mapping, and
# adds a feed item.

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::Enums::FeedAttributeTypeEnum
  qw(STRING URL_LIST);
use Google::Ads::GoogleAds::V11::Enums::FlightPlaceholderFieldEnum
  qw(FLIGHT_DESCRIPTION DESTINATION_ID FLIGHT_PRICE FLIGHT_SALE_PRICE FINAL_URLS);
use Google::Ads::GoogleAds::V11::Enums::PlaceholderTypeEnum qw(DYNAMIC_FLIGHT);
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 Getopt::Long qw(:config auto_help);
use Pod::Usage;
use Cwd qw(abs_path);
use Data::Uniqid qw(uniqid);

use constant PAGE_SIZE => 1000;

# 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";

sub add_flights_feed {
  my ($api_client, $customer_id) = @_;

  # Create a new flights feed.
  my $feed_resource_name = create_feed($api_client, $customer_id);

  # Get the newly created feed's attributes and package them into a hash. This read
  # operation is required to retrieve the attribute IDs.
  my $feed_attributes =
    get_feed($api_client, $customer_id, $feed_resource_name);

  # Create a feed mapping.
  create_feed_mapping($api_client, $customer_id, $feed_attributes,
    $feed_resource_name);

  # Create a feed item.
  create_feed_item($api_client, $customer_id, $feed_attributes,
    $feed_resource_name);

  return 1;
}

# Creates a flight feed.
sub create_feed {
  my ($api_client, $customer_id) = @_;

  # Create a Flight Description attribute.
  my $flight_description_attribute =
    Google::Ads::GoogleAds::V11::Resources::FeedAttribute->new({
      type => STRING,
      name => "Flight Description"
    });
  # Create a Destination ID attribute.
  my $destination_id_attribute =
    Google::Ads::GoogleAds::V11::Resources::FeedAttribute->new({
      type => STRING,
      name => "Destination ID"
    });
  # Create a Flight Price attribute.
  my $flight_price_attribute =
    Google::Ads::GoogleAds::V11::Resources::FeedAttribute->new({
      type => STRING,
      name => "Flight Price"
    });
  # Create a Flight Sale Price attribute.
  my $flight_sales_price_attribute =
    Google::Ads::GoogleAds::V11::Resources::FeedAttribute->new({
      type => STRING,
      name => "Flight Sale Price"
    });
  # Create a Final URLs attribute.
  my $final_urls_Attribute =
    Google::Ads::GoogleAds::V11::Resources::FeedAttribute->new({
      type => URL_LIST,
      name => "Final URLs"
    });

  # Create a feed.
  my $feed = Google::Ads::GoogleAds::V11::Resources::Feed->new({
      name       => "Flights Feed #" . uniqid(),
      attributes => [
        $flight_description_attribute, $destination_id_attribute,
        $flight_price_attribute,       $flight_sales_price_attribute,
        $final_urls_Attribute
      ]});

  # Create a feed operation.
  my $feed_operation =
    Google::Ads::GoogleAds::V11::Services::FeedService::FeedOperation->new(({
      create => $feed
    }));

  # 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 "Feed with resource name '%s' was created.\n", $feed_resource_name;

  return $feed_resource_name;
}

# Retrieves details about a feed. The initial query retrieves the FeedAttributes, or columns,
# of the feed. Each FeedAttribute will also include the FeedAttributeId, which will be used in
# a subsequent step. The example then inserts a new key, value pair into a hash for each
# FeedAttribute, which is the return value of the method. The keys are the placeholder types
# that the columns will be. The values are the FeedAttributes.
sub get_feed {
  my ($api_client, $customer_id, $feed_resource_name) = @_;

  # Construct the search query.
  my $search_query =
    sprintf "SELECT feed.attributes FROM feed WHERE feed.resource_name = '%s'",
    $feed_resource_name;

  my $search_response = $api_client->GoogleAdsService()->search({
    customerId => $customer_id,
    query      => $search_query,
    pageSize   => PAGE_SIZE
  });

  # Get the first result because we only need the single feed item we created previously.
  my $google_ads_row = $search_response->{results}[0];

  # Get the attributes list from the feed and create a hash with keys of each attribute and
  # values of each corresponding ID.
  my $feed_attribute_list = $google_ads_row->{feed}{attributes};

  # Create a hash to return.
  my $feed_attributes = {};
  # Loop through the feed attributes to populate the hash.
  foreach my $feed_attribute (@$feed_attribute_list) {
    my $feed_attribute_name = $feed_attribute->{name};

    # The full list of FlightPlaceholderFields can be found here
    # https://developers.google.com/google-ads/api/reference/rpc/latest/FlightPlaceholderFieldEnum.FlightPlaceholderField.
    if ($feed_attribute_name eq "Flight Description") {
      $feed_attributes->{FLIGHT_DESCRIPTION} = $feed_attribute;
    } elsif ($feed_attribute_name eq "Destination ID") {
      $feed_attributes->{DESTINATION_ID} = $feed_attribute;
    } elsif ($feed_attribute_name eq "Flight Price") {
      $feed_attributes->{FLIGHT_PRICE} = $feed_attribute;
    } elsif ($feed_attribute_name eq "Flight Sale Price") {
      $feed_attributes->{FLIGHT_SALE_PRICE} = $feed_attribute;
    } elsif ($feed_attribute_name eq "Final URLs") {
      $feed_attributes->{FINAL_URLS} = $feed_attribute;
    } else {
      die("Invalid attribute name.");
    }
  }

  return $feed_attributes;
}

# Creates a feed mapping for a given feed.
sub create_feed_mapping {
  my ($api_client, $customer_id, $feed_attributes, $feed_resource_name) = @_;

  # Map the FeedAttributeIds to the fieldId constants.
  my $flight_description_mapping =
    Google::Ads::GoogleAds::V11::Resources::AttributeFieldMapping->new({
      feedAttributeId => $feed_attributes->{FLIGHT_DESCRIPTION}{id},
      flightField     => FLIGHT_DESCRIPTION
    });
  my $destination_id_mapping =
    Google::Ads::GoogleAds::V11::Resources::AttributeFieldMapping->new({
      feedAttributeId => $feed_attributes->{DESTINATION_ID}{id},
      flightField     => DESTINATION_ID
    });
  my $flight_price_mapping =
    Google::Ads::GoogleAds::V11::Resources::AttributeFieldMapping->new({
      feedAttributeId => $feed_attributes->{FLIGHT_PRICE}{id},
      flightField     => FLIGHT_PRICE
    });
  my $flight_sale_price_mapping =
    Google::Ads::GoogleAds::V11::Resources::AttributeFieldMapping->new({
      feedAttributeId => $feed_attributes->{FLIGHT_SALE_PRICE}{id},
      flightField     => FLIGHT_SALE_PRICE
    });
  my $final_urls_mapping =
    Google::Ads::GoogleAds::V11::Resources::AttributeFieldMapping->new({
      feedAttributeId => $feed_attributes->{FINAL_URLS}{id},
      flightField     => FINAL_URLS
    });

  # Create a feed mapping.
  my $feed_mapping = Google::Ads::GoogleAds::V11::Resources::FeedMapping->new({
      placeholderType        => DYNAMIC_FLIGHT,
      feed                   => $feed_resource_name,
      attributeFieldMappings => [
        $flight_description_mapping, $destination_id_mapping,
        $flight_price_mapping,       $flight_sale_price_mapping,
        $final_urls_mapping
      ]});

  # Create a feed mapping operation.
  my $feed_mapping_operation =
    Google::Ads::GoogleAds::V11::Services::FeedMappingService::FeedMappingOperation
    ->new({
      create => $feed_mapping
    });

  # Add the feed mapping.
  my $feed_mappings_response = $api_client->FeedMappingService()->mutate({
      customerId => $customer_id,
      operations => [$feed_mapping_operation]});

  printf "Created feed mapping with resource name '%s'.\n",
    $feed_mappings_response->{results}[0]{resourceName};
}

# Adds a new item to the feed.
sub create_feed_item {
  my ($api_client, $customer_id, $feed_attributes, $feed_resource_name) = @_;

  # Create the flight description feed attribute value.
  my $flight_description =
    Google::Ads::GoogleAds::V11::Resources::FeedItemAttributeValue->new({
      feedAttributeId => $feed_attributes->{FLIGHT_DESCRIPTION}{id},
      stringValue     => "Earth to Mars"
    });
  # Create the destination ID feed attribute value.
  my $destination_id =
    Google::Ads::GoogleAds::V11::Resources::FeedItemAttributeValue->new({
      feedAttributeId => $feed_attributes->{DESTINATION_ID}{id},
      stringValue     => "Mars"
    });
  # Create the flight price feed attribute value.
  my $flight_price =
    Google::Ads::GoogleAds::V11::Resources::FeedItemAttributeValue->new({
      feedAttributeId => $feed_attributes->{FLIGHT_PRICE}{id},
      stringValue     => "499.99 USD"
    });
  # Create the flight sale price feed attribute value.
  my $flight_sale_price =
    Google::Ads::GoogleAds::V11::Resources::FeedItemAttributeValue->new({
      feedAttributeId => $feed_attributes->{FLIGHT_SALE_PRICE}{id},
      stringValue     => "299.99 USD"
    });
  # Create the final URLs feed attribute value.
  my $final_urls =
    Google::Ads::GoogleAds::V11::Resources::FeedItemAttributeValue->new({
      feedAttributeId => $feed_attributes->{FINAL_URLS}{id},
      stringValues    => ["http://www.example.com/flights/"]});

  # Create a feed item, specifying the Feed ID and the attributes created above.
  my $feed_item = Google::Ads::GoogleAds::V11::Resources::FeedItem->new({
      feed            => $feed_resource_name,
      attributeValues => [
        $flight_description, $destination_id, $flight_price,
        $flight_sale_price,  $final_urls
      ]});

  # Create a feed item operation.
  my $feed_item_operation =
    Google::Ads::GoogleAds::V11::Services::FeedItemService::FeedItemOperation->
    new({
      create => $feed_item
    });

  # Add the feed item.
  my $feed_items_response = $api_client->FeedItemService()->mutate({
      customerId => $customer_id,
      operations => [$feed_item_operation]});

  printf "Created feed item with resource name '%s'.\n",
    $feed_items_response->{results}[0]{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);

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

# Call the example.
add_flights_feed($api_client, $customer_id =~ s/-//gr);

=pod

=head1 NAME

add_flights_feed

=head1 DESCRIPTION

This example adds a flights feed, creates the associated feed mapping, and adds
a feed item.

=head1 SYNOPSIS

add_flights_feed.pl [options]

    -help                       Show the help message.
    -customer_id                The Google Ads customer ID.

=cut