Update Flights Feed Item String Attribute Value

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

import com.beust.jcommander.Parameter;
import com.google.ads.googleads.examples.remarketing.AddFlightsFeed;
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.lib.utils.FieldMasks;
import com.google.ads.googleads.v16.enums.FlightPlaceholderFieldEnum.FlightPlaceholderField;
import com.google.ads.googleads.v16.errors.GoogleAdsError;
import com.google.ads.googleads.v16.errors.GoogleAdsException;
import com.google.ads.googleads.v16.resources.FeedAttribute;
import com.google.ads.googleads.v16.resources.FeedItem;
import com.google.ads.googleads.v16.resources.FeedItemAttributeValue;
import com.google.ads.googleads.v16.services.FeedItemOperation;
import com.google.ads.googleads.v16.services.FeedItemServiceClient;
import com.google.ads.googleads.v16.services.GoogleAdsServiceClient;
import com.google.ads.googleads.v16.services.GoogleAdsServiceClient.SearchPagedResponse;
import com.google.ads.googleads.v16.services.MutateFeedItemResult;
import com.google.ads.googleads.v16.services.MutateFeedItemsResponse;
import com.google.ads.googleads.v16.services.SearchGoogleAdsRequest;
import com.google.ads.googleads.v16.utils.ResourceNames;
import com.google.common.collect.ImmutableList;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Map;

/**
 * Updates a FeedItemAttributeValue in a flights feed. To create a flights feed, run the
 * AddFlightsFeed example. This example is specific to feeds of type DYNAMIC_FLIGHT. The attribute
 * you are updating must be present on the feed. This example is specifically for updating the
 * StringValue of an attribute.
 */
public class UpdateFlightsFeedItemStringAttributeValue {
  private static final int PAGE_SIZE = 1_000;

  private static class UpdateFlightsFeedItemStringAttributeValueParams extends CodeSampleParams {

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

    @Parameter(names = ArgumentNames.FEED_ID, required = true)
    private long feedId;

    @Parameter(names = ArgumentNames.FEED_ITEM_ID, required = true)
    private long feedItemId;

    @Parameter(names = ArgumentNames.FLIGHT_PLACEHOLDER_FIELD_NAME, required = true)
    private String flightPlaceholderField;

    @Parameter(names = ArgumentNames.ATTRIBUTE_VALUE, required = true)
    private String attributeValue;
  }

  public static void main(String[] args) {
    UpdateFlightsFeedItemStringAttributeValueParams params =
        new UpdateFlightsFeedItemStringAttributeValueParams();
    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.feedId = Long.parseLong("INSERT_FEED_ID_HERE");
      params.feedItemId = Long.parseLong("INSERT_FEED_ITEM_ID_HERE");
      params.flightPlaceholderField = "INSERT_FLIGHT_PLACEHOLDER_FIELD_HERE";
      params.attributeValue = "INSERT_ATTRIBUTE_VALUE_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 UpdateFlightsFeedItemStringAttributeValue()
          .runExample(
              googleAdsClient,
              params.customerId,
              params.feedId,
              params.feedItemId,
              params.flightPlaceholderField,
              params.attributeValue);
    } 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 customerId the client customer ID.
   * @param feedId ID of the feed containing the feed item to be updated.
   * @param feedItemId ID of the feed item to be updated.
   * @param flightPlaceholderField the placeholder type for the attribute to be removed.
   * @param attributeValue String value with which to update the FeedAttributeValue.
   * @throws GoogleAdsException if an API request failed with one or more service errors.
   */
  private void runExample(
      GoogleAdsClient googleAdsClient,
      long customerId,
      long feedId,
      long feedItemId,
      String flightPlaceholderField,
      String attributeValue) {
    updateFeedItem(
        googleAdsClient, customerId, feedId, feedItemId, flightPlaceholderField, attributeValue);
  }

  /**
   * Updates attribute value of the feed item. In order to update a FeedItemAttributeValue you must
   * update the FeedItem.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the client customer ID.
   * @param feedId ID of the feed containing the feed item to be updated.
   * @param feedItemId ID of the feed item to be updated.
   * @param flightPlaceholderField the placeholder type for the attribute to be removed.
   * @param attributeValue String value with which to update the FeedAttributeValue.
   */
  private void updateFeedItem(
      GoogleAdsClient googleAdsClient,
      long customerId,
      long feedId,
      long feedItemId,
      String flightPlaceholderField,
      String attributeValue) {
    // Gets the feed resource name.
    String feedResourceName = ResourceNames.feed(customerId, feedId);

    // Gets a map of the placeholder values and feed attributes.
    Map<FlightPlaceholderField, FeedAttribute> feedAttributes =
        AddFlightsFeed.getFeed(googleAdsClient, customerId, feedResourceName);

    // Gets the ID of the attribute to update. This is needed to specify which
    // FeedItemAttributeValue will be updated in the given FeedItem.
    long attributeId =
        feedAttributes
            .get(FlightPlaceholderField.valueOf(flightPlaceholderField.toUpperCase()))
            .getId();
    // Gets the feed item resource name.
    String feedItemResourceName = ResourceNames.feedItem(customerId, feedId, feedItemId);
    // Retrieves the feed item and its associated attributes based on its resource name.
    FeedItem feedItem = getFeedItem(googleAdsClient, customerId, feedItemResourceName);
    // Creates the updated FeedItemAttributeValue.
    FeedItemAttributeValue feedItemAttributeValue =
        FeedItemAttributeValue.newBuilder()
            .setFeedAttributeId(attributeId)
            .setStringValue(attributeValue)
            .build();
    // Creates a new FeedItem from the existing FeedItem. Any FeedItemAttributeValues that are
    // not included in the updated FeedItem will be removed from the FeedItem, which is why you
    // must create the FeedItem from the existing FeedItem and set the field(s) that will be
    // updated.
    feedItem =
        feedItem.toBuilder()
            // Sets the attribute value of the FeedItem given its index relative to other attributes
            // in the FeedItem.
            .setAttributeValues(
                // Gets the index of the attribute value that will be updated.
                getAttributeIndex(feedItem, feedItemAttributeValue), feedItemAttributeValue)
            .build();

    // Creates the operation.
    FeedItemOperation operation =
        FeedItemOperation.newBuilder()
            .setUpdate(feedItem)
            .setUpdateMask(FieldMasks.allSetFieldsOf(feedItem))
            .build();

    // Creates the feed item service client.
    try (FeedItemServiceClient feedItemServiceClient =
        googleAdsClient.getLatestVersion().createFeedItemServiceClient()) {
      // Updates the feed item.
      MutateFeedItemsResponse response =
          feedItemServiceClient.mutateFeedItems(
              Long.toString(customerId), ImmutableList.of(operation));
      for (MutateFeedItemResult result : response.getResultsList()) {
        System.out.printf("Updated feed item with resource name '%s'.%n", result.getResourceName());
      }
    }
  }

  /**
   * Retrieves a feed item and its attribute values given a resource name.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the client customer ID.
   * @param feedItemResourceName feed item resource name.
   * @return FeedItem with the given resource name.
   */
  private FeedItem getFeedItem(
      GoogleAdsClient googleAdsClient, long customerId, String feedItemResourceName) {
    // Constructs the query.
    String query =
        "SELECT feed_item.attribute_values FROM feed_item WHERE feed_item.resource_name "
            + "= '"
            + feedItemResourceName
            + "'";

    // 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);
      // Returns the feed item attribute values.
      return searchPagedResponse.getPage().getResponse().getResults(0).getFeedItem();
    }
  }

  /**
   * Gets the ID of the attribute. This is needed to specify which FeedItemAttributeValue will be
   * updated in the given FeedItem.
   *
   * @param feedItem the FeedItem that will be updated.
   * @param newFeedItemAttributeValue the new FeedItemAttributeValue that will be updated.
   * @return int the index of the attribute.
   */
  private int getAttributeIndex(
      FeedItem feedItem, FeedItemAttributeValue newFeedItemAttributeValue) {
    Integer attributeIndex = null;

    // Loops through attribute values to find the index of the FeedItemAttributeValue to update
    for (FeedItemAttributeValue feedItemAttributeValue : feedItem.getAttributeValuesList()) {
      attributeIndex = (attributeIndex != null) ? attributeIndex + 1 : 0;
      // Checks if the current feedItemAttributeValue is the one we are updating
      if (feedItemAttributeValue.getFeedAttributeId()
          == newFeedItemAttributeValue.getFeedAttributeId()) {
        break;
      }
    }

    // Throws an exception if the attribute value is not found.
    if (attributeIndex == null) {
      new IllegalArgumentException(
          "No matching feed attribute for feed item attribute value: " + newFeedItemAttributeValue);
    }

    return attributeIndex;
  }
}

      

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.Gax.Util;
using Google.Ads.GoogleAds.Lib;
using Google.Ads.GoogleAds.V16.Errors;
using Google.Ads.GoogleAds.V16.Resources;
using Google.Ads.GoogleAds.V16.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using static Google.Ads.GoogleAds.V16.Enums.FlightPlaceholderFieldEnum.Types;

namespace Google.Ads.GoogleAds.Examples.V16
{
    /// <summary>
    /// This code example updates a FeedItemAttributeValue in a flights feed. To create a flights
    /// feed, run the AddFlightsFeed.cs. This code example is specific to feeds of type
    /// DYNAMIC_FLIGHT. The attribute you are updating must be present on the feed. This code
    /// example is specifically for updating the StringValue of an attribute.
    /// </summary>
    public class UpdateFlightsFeedItemStringAttributeValue : ExampleBase
    {
        /// <summary>
        /// Command line options for running the <see
        /// cref="UpdateFlightsFeedItemStringAttributeValue"/> example.
        /// </summary>
        public class Options : OptionsBase
        {
            /// <summary>
            /// The customer ID for which the call is made.
            /// </summary>
            [Option("customerId", Required = true, HelpText =
                "The customer ID for which the call is made.")]
            public long CustomerId { get; set; }

            /// <summary>
            /// ID of the feed containing the feed item to be updated.
            /// </summary>
            [Option("feedId", Required = true, HelpText =
                "ID of the feed containing the feed item to be updated.")]
            public long FeedId { get; set; }

            /// <summary>
            /// ID of the feed item to be updated.
            /// </summary>
            [Option("feedItemId", Required = true, HelpText =
                "ID of the feed item to be updated.")]
            public long FeedItemId { get; set; }

            /// <summary>
            /// The placeholder type for the attribute to be removed.
            /// </summary>
            [Option("flightPlaceholderFieldName", Required = true, HelpText =
                "The placeholder type for the attribute to be removed.")]
            public string FlightPlaceholderFieldName { get; set; }

            /// <summary>
            /// Value with which to update the FeedAttributeValue.
            /// </summary>
            [Option("attributeValue", Required = true, HelpText =
                "Value with which to update the FeedAttributeValue.")]
            public string AttributeValue { 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);

            UpdateFlightsFeedItemStringAttributeValue codeExample =
                new UpdateFlightsFeedItemStringAttributeValue();
            Console.WriteLine(codeExample.Description);
            codeExample.Run(new GoogleAdsClient(), options.CustomerId, options.FeedId,
                options.FeedItemId, options.FlightPlaceholderFieldName, options.AttributeValue);
        }

        /// <summary>
        /// Returns a description about the code example.
        /// </summary>
        public override string Description =>
            "This code example updates a FeedItemAttributeValue in a flights feed. To create a " +
            "flights feed, run the AddFlightsFeed.cs. This code example is specific to feeds of " +
            "type DYNAMIC_FLIGHT. The attribute you are updating must be present on the feed. " +
            "This code example is specifically for updating the StringValue of an attribute.";

        /// <summary>
        /// Runs the code example.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The customer ID for which the call is made.</param>
        /// <param name="feedId">ID of the feed containing the feed item to be updated.</param>
        /// <param name="feedItemId">ID of the feed item to be updated.</param>
        /// <param name="flightPlaceholderFieldName">
        /// The placeholder type for the attribute to be removed.
        /// </param>
        /// <param name="attributeValue">Value with which to update the FeedAttributeValue.</param>
        public void Run(GoogleAdsClient client, long customerId, long feedId, long feedItemId,
            string flightPlaceholderFieldName, string attributeValue)
        {
            try
            {
                UpdateFeedItem(client, customerId, feedId, feedItemId, flightPlaceholderFieldName,
                    attributeValue);
            }
            catch (GoogleAdsException e)
            {
                Console.WriteLine("Failure:");
                Console.WriteLine($"Message: {e.Message}");
                Console.WriteLine($"Failure: {e.Failure}");
                Console.WriteLine($"Request ID: {e.RequestId}");
                throw;
            }
        }

        /// <summary>
        /// Updates attribute value of the feed item. In order to update a FeedItemAttributeValue
        /// you must update the FeedItem.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The customer ID for which the call is made.</param>
        /// <param name="feedId">ID of the feed containing the feed item to be updated.</param>
        /// <param name="feedItemId">ID of the feed item to be updated.</param>
        /// <param name="flightPlaceholderFieldName">
        /// the placeholder type for the attribute to be updated.
        /// </param>
        /// <param name="attributeValue">
        /// String value with which to update the FeedAttributeValue.
        /// </param>
        private void UpdateFeedItem(GoogleAdsClient client, long customerId, long feedId,
            long feedItemId, string flightPlaceholderFieldName, string attributeValue)
        {
            // Get the FeedItemServiceClient.
            FeedItemServiceClient feedItemService =
                client.GetService(Services.V16.FeedItemService);

            // Gets the feed resource name.
            string feedResourceName = ResourceNames.Feed(customerId, feedId);

            // Gets a map of the placeholder values and feed attributes.
            Dictionary<FlightPlaceholderField, FeedAttribute> feedAttributes =
                GetFeed(client, customerId, feedResourceName);

            // Gets the ID of the attribute to update. This is needed to specify which
            // FeedItemAttributeValue will be updated in the given FeedItem.
            FlightPlaceholderField placeholderField = (FlightPlaceholderField) Enum.Parse(
                typeof(FlightPlaceholderField), flightPlaceholderFieldName);
            long attributeId = feedAttributes[placeholderField].Id;

            // Gets the feed item resource name.
            string feedItemResourceName = ResourceNames.FeedItem(customerId, feedId, feedItemId);
            // Retrieves the feed item and its associated attributes based on its resource name.
            FeedItem feedItem = GetFeedItem(client, customerId, feedItemResourceName);
            // Creates the updated FeedItemAttributeValue.
            FeedItemAttributeValue feedItemAttributeValue = new FeedItemAttributeValue()
            {
                FeedAttributeId = attributeId,
                StringValue = attributeValue
            };

            // Creates a new FeedItem from the existing FeedItem. Any FeedItemAttributeValues that
            // are not included in the updated FeedItem will be removed from the FeedItem, which is
            // why you must create the FeedItem from the existing FeedItem and set the field(s)
            // that will be updated.
            int attributeIndex = feedItem.AttributeValues
                .Select((item, index) => new { item, index })
                .Where(itemIndexPair =>
                    itemIndexPair.item.FeedAttributeId == feedItemAttributeValue.FeedAttributeId)
                .Select(itemIndexPair => itemIndexPair.index + 1)
                .FirstOrDefault() - 1;

            if (attributeIndex == -1)
            {
                throw new ArgumentException("No matching feed attribute found for " +
                    $"value '{feedItemAttributeValue}'.");
            }

            feedItem.AttributeValues[attributeIndex] = feedItemAttributeValue;

            // Creates the operation.
            FeedItemOperation operation = new FeedItemOperation()
            {
                Update = feedItem,
                UpdateMask = FieldMasks.AllSetFieldsOf(feedItem)
            };

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

            foreach (MutateFeedItemResult result in response.Results)
            {
                Console.WriteLine($"Updated feed item with resource name " +
                    $"'{result.ResourceName}'.");
            }
        }

        /// <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.V16.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>
        /// Retrieves a feed item and its attribute values given a resource name.
        /// </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="feedItemResourceName">Feed item resource name.</param>
        /// <returns>FeedItem with the given resource name.</returns>
        private FeedItem GetFeedItem(GoogleAdsClient client, long customerId,
            string feedItemResourceName)
        {
            // Get the GoogleAdsService.
            GoogleAdsServiceClient googleAdsService = client.GetService(
                Services.V16.GoogleAdsService);

            // Constructs the query.
            string query = "SELECT feed_item.attribute_values FROM feed_item WHERE " +
                $"feed_item.resource_name = '{feedItemResourceName}'";

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

            return googleAdsService.Search(request).First().FeedItem;
        }
    }
}

      

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\Feeds;

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\Lib\OAuth2TokenBuilder;
use Google\Ads\GoogleAds\Lib\V16\GoogleAdsClient;
use Google\Ads\GoogleAds\Lib\V16\GoogleAdsClientBuilder;
use Google\Ads\GoogleAds\Lib\V16\GoogleAdsException;
use Google\Ads\GoogleAds\Util\FieldMasks;
use Google\Ads\GoogleAds\Util\V16\ResourceNames;
use Google\Ads\GoogleAds\V16\Enums\FlightPlaceholderFieldEnum\FlightPlaceholderField;
use Google\Ads\GoogleAds\V16\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V16\Resources\FeedItemAttributeValue;
use Google\Ads\GoogleAds\V16\Services\FeedItemOperation;
use Google\Ads\GoogleAds\V16\Services\MutateFeedItemsRequest;
use Google\ApiCore\ApiException;

/**
 * Updates a feed item attribute value in a flights feed. To create a flights feed,
 * run the AddFlightsFeed example. This example is specific to feeds of type DYNAMIC_FLIGHT.
 * The attribute you are updating must be present on the feed.
 *
 * This example is specifically for updating the string attribute of a flights feed item,
 * but it can also be changed to work with other data types of an attribute and feed types.
 *
 * To make this work with other data types, replace `string_value` with the type of an attribute
 * you wish to update, when creating a FeedItemAttributeValue instance in this example.
 * To make this work with other feed types, replace the FlightPlaceholderField enum with the
 * equivalent one of your feed type, and replace Feeds::flightPlaceholderFieldsMapFor() with the
 * method that can return a similar value for your feed type. Check the
 * flightPlaceholderFieldsMapFor() method for details.
 */
class UpdateFlightsFeedItemStringAttributeValue
{
    private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE';
    private const FEED_ID = 'INSERT_FEED_ID_HERE';
    private const FEED_ITEM_ID = 'INSERT_FEED_ITEM_ID_HERE';
    private const FLIGHT_PLACEHOLDER_FIELD_NAME = 'INSERT_FLIGHT_PLACEHOLDER_FIELD_NAME_HERE';
    private const ATTRIBUTE_VALUE = 'INSERT_ATTRIBUTE_VALUE_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,
            ArgumentNames::FEED_ID => GetOpt::REQUIRED_ARGUMENT,
            ArgumentNames::FEED_ITEM_ID => GetOpt::REQUIRED_ARGUMENT,
            ArgumentNames::FLIGHT_PLACEHOLDER_FIELD_NAME => GetOpt::REQUIRED_ARGUMENT,
            ArgumentNames::ATTRIBUTE_VALUE => 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)
            // We set this value to true to show how to use GAPIC v2 source code. You can remove the
            // below line if you wish to use the old-style source code. Note that in that case, you
            // probably need to modify some parts of the code below to make it work.
            // For more information, see
            // https://developers.devsite.corp.google.com/google-ads/api/docs/client-libs/php/gapic.
            ->usingGapicV2Source(true)
            ->build();

        try {
            self::runExample(
                $googleAdsClient,
                $options[ArgumentNames::CUSTOMER_ID] ?: self::CUSTOMER_ID,
                $options[ArgumentNames::FEED_ID] ?: self::FEED_ID,
                $options[ArgumentNames::FEED_ITEM_ID] ?: self::FEED_ITEM_ID,
                $options[ArgumentNames::FLIGHT_PLACEHOLDER_FIELD_NAME]
                    ?: self::FLIGHT_PLACEHOLDER_FIELD_NAME,
                $options[ArgumentNames::ATTRIBUTE_VALUE]
                    ?: self::ATTRIBUTE_VALUE
            );
        } 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 int $feedId the ID of feed containing the feed item to be updated
     * @param int $feedItemId ID of the feed item to be updated
     * @param string $flightPlaceholderFieldName the flight placeholder field name for the attribute
     *     to be updated
     * @param string $attributeValue the new value to set the feed attribute to
     */
    public static function runExample(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        int $feedId,
        int $feedItemId,
        string $flightPlaceholderFieldName,
        string $attributeValue
    ) {
        // Gets a map of the placeholder values to feed attributes.
        $placeHoldersToFeedAttributesMap = Feeds::flightPlaceholderFieldsMapFor(
            ResourceNames::forFeed($customerId, $feedId),
            $customerId,
            $googleAdsClient
        );
        // Gets the ID of the feed attribute for the placeholder field. This is needed to specify
        // which feed item attribute value will be updated in the given feed item.
        $attributeId = $placeHoldersToFeedAttributesMap[
            FlightPlaceholderField::value($flightPlaceholderFieldName)]->getId();
        // Creates the updated feed item attribute value.
        $updatedFeedItemAttributeValue = new FeedItemAttributeValue([
            'feed_attribute_id' => $attributeId,
            'string_value' => $attributeValue
        ]);

        // Retrieves the feed item and its associated attributes based on the resource name.
        $feedItem = Feeds::feedItemFor(
            ResourceNames::forFeedItem($customerId, $feedId, $feedItemId),
            $customerId,
            $googleAdsClient
        );
        // Gets the index of the attribute value that will be updated in the feed item.
        $attributeIndex = Feeds::attributeIndexFor($updatedFeedItemAttributeValue, $feedItem);
        // Any feed item attribute values that are not included in the updated feed item will be
        // removed from the feed item, which is why you must create the feed item from the existing
        // feed item and its attribute values. Then, update only the attribute that you want.
        $feedItemAttributeValues = $feedItem->getAttributeValues();
        $feedItemAttributeValues[$attributeIndex] = $updatedFeedItemAttributeValue;
        $feedItem->setAttributeValues($feedItemAttributeValues);

        // Creates the feed item operation.
        $operation = new FeedItemOperation();
        $operation->setUpdate($feedItem);
        $operation->setUpdateMask(FieldMasks::allSetFieldsOf($feedItem));

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

UpdateFlightsFeedItemStringAttributeValue::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.
"""Updates a feed item attribute value in a flights feed.

To create a flights feed, run the remarketing/add_flights_feed.py example.
This example is specific to feeds of type DYNAMIC_FLIGHT. The attribute you are
updating must be present on the feed.

This example is specifically for updating the string attribute of a flights feed
item, but it can also be changed to work with other data types of an attribute
and feed types.

To make this work with other data types, replace `string_value` with the type of
an attribute you wish to update, when creating a FeedItemAttributeValue instance
in this example. To make this work with other feed types, replace the
FlightPlaceholderField enum with the equivalent one of your feed type, and
replace Feeds::flightPlaceholderFieldsMapFor() with the method that can return
a similar value for your feed type. Check the flightPlaceholderFieldsMapFor()
method for details.
"""

import argparse
import sys

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


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

    Args:
        client: an initialized GoogleAdsClient instance
        customer_id: a client customer ID
        feed_id: the ID of feed containing the feed item to be updated
        feed_item_id: The ID of the feed item to be updated
        flight_placeholder_field_name: the flight placeholder field name for
            the attribute to be updated
        attribute_value: the new value to set the feed attribute to
    """
    feed_service = client.get_service("FeedService")
    # Gets a map of the placeholder values to feed attributes.
    placeholders_to_feed_attribute_map = flight_placeholder_fields_map(
        client, customer_id, feed_service.feed_path(customer_id, feed_id)
    )
    # Gets the ID of the feed attribute for the placeholder field. This is
    # needed to specify which feed item attribute value will be updated in
    # the given feed item.
    flight_placeholder_field_enum = client.enums.FlightPlaceholderFieldEnum
    flight_placeholder_enum_value = getattr(
        flight_placeholder_field_enum, flight_placeholder_field_name
    )
    attribute_id = placeholders_to_feed_attribute_map[
        flight_placeholder_enum_value
    ].id

    # Creates the updated feed item attribute value.
    updated_feed_item_attribute_value = client.get_type(
        "FeedItemAttributeValue"
    )
    updated_feed_item_attribute_value.feed_attribute_id = attribute_id
    updated_feed_item_attribute_value.string_value = attribute_value

    # Retrieves the feed item and its associated attributes based on the
    # resource name.
    feed_item_service = client.get_service("FeedItemService")
    feed_item = get_feed_item(
        client,
        customer_id,
        feed_item_service.feed_item_path(customer_id, feed_id, feed_item_id),
    )

    # Gets the index of the attribute value that will be updated in the
    # feed item.
    attribute_index = get_attribute_index(
        updated_feed_item_attribute_value, feed_item
    )
    # Any feed item attribute values that are not included in the updated
    # feed item will be removed from the feed item, which is why you must
    # create the feed item from the existing feed item and its attribute
    # values. Then, update only the attribute that you want.
    feed_item_operation = client.get_type("FeedItemOperation")
    client.copy_from(feed_item_operation.update, feed_item)
    updated_feed_item = feed_item_operation.update
    client.copy_from(
        updated_feed_item.attribute_values[attribute_index],
        updated_feed_item_attribute_value,
    )

    # Create a field mask using the old feed_item and the updated_feed_item.
    client.copy_from(
        feed_item_operation.update_mask,
        protobuf_helpers.field_mask(feed_item._pb, updated_feed_item._pb),
    )

    response = feed_item_service.mutate_feed_items(
        customer_id=customer_id, operations=[feed_item_operation]
    )
    print(
        "Feed item with resource name: "
        f"'{response.results[0].resource_name}' was updated."
    )


def flight_placeholder_fields_map(client, customer_id, feed_resource_name):
    """Maps place holder fields and feed attributes for a flights feed.

    See FlightPlaceholderField.php for all available placeholder field values.

    Args:
        client: an initialized GoogleAdsClient instance
        customer_id: a client customer ID
        feed_resource_name: a resource name for a Feed

    Returns:
        a dict mapping placeholder fields to feed attributes
    """
    flight_placeholder_field_enum = client.enums.FlightPlaceholderFieldEnum

    return placeholder_field_maps(
        client,
        customer_id,
        feed_resource_name,
        {
            "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,
        },
    )


def placeholder_field_maps(
    client, customer_id, feed_resource_name, feed_attribute_names_map
):
    """Retrieves the placeholder fields to feed attributes map for a feed.

    The initial query retrieves the feed attributes, or columns, of the feed.
    Each feed attribute will also include the feed attribute ID, which will be
    used in a subsequent step.

    Then a map is created for the feed attributes (columns) and returned:
      - The keys are the placeholder types that the columns will be.
      - The values are the feed attributes.

    Args:
        client: an initialized GoogleAdsClient instance
        customer_id: a client customer ID
        feed_resource_name: a resource name for a Feed
        feed_attribute_names_map: the associative array mapping from feed
            attribute names to placeholder fields

    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 feed
    # resource name.
    query = f"""
        SELECT
          feed.attributes
        FROM feed
        WHERE feed.resource_name = '{feed_resource_name}'"""
    # Issues a search request. The page_size is set to 1 because we're only
    # requesting a single result.
    search_request = client.get_type("SearchGoogleAdsRequest")
    search_request.customer_id = customer_id
    search_request.query = query
    search_request.page_size = 1

    response = googleads_service.search(request=search_request)
    row = list(response)[0]
    # Gets the attributes list from the feed and creates a map with keys of
    # placeholder fields and values of feed attributes.
    feed_attributes = row.feed.attributes
    # Creates map with keys of placeholder fields and values of feed
    # attributes.
    return {
        feed_attribute_names_map[feed_attribute.name]: feed_attribute
        for feed_attribute in feed_attributes
    }


def get_feed_item(client, customer_id, feed_item_resource_name):
    """Retrieves a feed item and its attribute values given a resource name.

    Args:
        client: an initialized GoogleAdsClient instance
        customer_id: a client customer ID
        feed_resource_name: a resource name for a FeedItem

    Returns:
        a FeedItem instance
    """
    googleads_service = client.get_service("GoogleAdsService")
    # Constructs the query to get the feed item with attribute values.
    query = f"""
        SELECT
          feed_item.attribute_values
        FROM feed_item
        WHERE feed_item.resource_name = '{feed_item_resource_name}'"""

    search_request = client.get_type("SearchGoogleAdsRequest")
    search_request.customer_id = customer_id
    search_request.query = query
    search_request.page_size = 1
    response = googleads_service.search(request=search_request)

    # Returns the feed item attribute values, which belongs to the first item.
    # We can ensure it belongs to the first one because we specified the feed
    # item resource name in the query.
    return list(response)[0].feed_item


def get_attribute_index(target_feed_item_attribute_value, feed_item):
    """Gets the index of the target feed item attribute value.

    This is needed to specify which feed item attribute value will be updated
    in the given feed item.

    Args:
        target_feed_item_attribute_value: the new feed item attribute value that
            will be updated
        feed_item: the feed item that will be updated. It should be populated
            with the current attribute values

    Returns:
        the index number of the attribute
    """
    attribute_index = -1

    # Loops through attribute values to find the index of the feed item
    # attribute value to update.
    for feed_item_attribute_value in feed_item.attribute_values:
        attribute_index += 1
        # Checks if the current feedItemAttributeValue is the one we are
        # updating.
        if (
            feed_item_attribute_value.feed_attribute_id
            == target_feed_item_attribute_value.feed_attribute_id
        ):
            break

    if attribute_index == -1:
        raise ValueError(
            "No matching feed attribute for feed item attribute "
            f"ID: {feed_item_attribute_value.feed_attribute_id}"
        )

    return attribute_index


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="v16")

    parser = argparse.ArgumentParser(
        description="Updates a feed item attribute value in a flights feed."
    )
    # 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(
        "-f",
        "--feed_id",
        type=str,
        required=True,
        help="The ID of feed containing the feed item to be updated.",
    )
    parser.add_argument(
        "-i",
        "--feed_item_id",
        type=str,
        required=True,
        help="The ID of the feed item to be updated.",
    )
    parser.add_argument(
        "-p",
        "--flight_placeholder_field_name",
        type=str,
        required=True,
        help=(
            "The flight placeholder field name for the attribute to be "
            "updated.",
        ),
    )
    parser.add_argument(
        "-a",
        "--attribute_value",
        type=str,
        required=True,
        help="The new value to set the feed attribute to.",
    )
    args = parser.parse_args()

    try:
        main(
            googleads_client,
            args.customer_id,
            args.feed_id,
            args.feed_item_id,
            args.flight_placeholder_field_name,
            args.attribute_value,
        )
    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)

      

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.
#
# Updates a feed item attribute value in a flights feed. To create a flights
# feed, run the add_flights_feed example. This example is specific to feeds of
# type DYNAMIC_FLIGHT. The attribute you are updating must be present on the
# feed.
#
# This example is specifically for updating the string attribute of a
# flights feed item, but it can also be changed to work with other data types
# of an attribute and feed types.
#
# To make this work with other data types, replace `string_value` with the type
# of an attribute you wish to update, when creating a feed_item_attribute_value
# instance in this example.
# To make this work with other feed types, replace the
# flight_placeholder_field_name with the equivalent one of your feed type,
# and replace flight_placeholder_fields_map_for() with the method that can
# return a similar value for your feed type. Check the
# flight_placeholder_fields_map_for() method for details.

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

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

  # Gets a map of the placeholder values to feed attributes.
  placeholders_to_feed_attributes_map = flight_placeholder_fields_map_for(
    client,
    customer_id,
    client.path.feed(customer_id, feed_id),
  )

  # Gets the ID of the feed attribute for the placeholder field. This is
  # needed to specify which feed item attribute value will be updated in the
  # given feed item.
  attribute_id = placeholders_to_feed_attributes_map[
    flight_placeholder_field_name.to_sym].id

  # Retrieves the feed item and its associated attributes based on the resource
  # name.
  feed_item_resource_name = client.path.feed_item(customer_id, feed_id, feed_item_id)
  feed_item = feed_item_for(
    client,
    customer_id,
    feed_item_resource_name,
  )

  # Creates the updated feed item attribute value.
  updated_feed_item_attribute_value = client.resource.feed_item_attribute_value do |v|
    v.feed_attribute_id = attribute_id
    v.string_value = attribute_value
  end

  # Gets the index of the attribute value that will be updated in the feed item.
  attribute_index = attribute_index_for(
    updated_feed_item_attribute_value,
    feed_item,
  )

  # Any feed item attribute values that are not included in the feed item will
  # be removed, which is why you must retain all other feed attribute values
  # here.
  feed_item_attribute_values = feed_item.attribute_values
  puts feed_item_attribute_values
  feed_item_attribute_values[attribute_index] =
    client.resource.feed_item_attribute_value do |v|
      v.feed_attribute_id = attribute_id
      v.string_value = attribute_value
    end

  # Creates the feed item operation.
  operation = client.operation.update_resource.feed_item(feed_item_resource_name) do |item|
    item.attribute_values.replace(feed_item_attribute_values.to_a)
  end

  # Issues a mutate request to update 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 updated."
end

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

def feed_item_for(
  client,
  customer_id,
  feed_item_resource_name)
  # Constructs the query to get the feed item with attribute values.
  query = <<~QUERY
    SELECT feed_item.attribute_values
    FROM feed_item
    WHERE feed_item.resource_name = '#{feed_item_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,
  )

  # Returns the feed item attribute values, which belongs to the first item.
  # We can ensure it belongs to the first one because we specified the feed item
  # resource name in the query.
  response.first.feed_item
end

def attribute_index_for(
  target_feed_item_attribute_value,
  feed_item)
  attribute_index = -1

  # Loops through attribute values to find the index of the feed item attribute
  # value to update.
  feed_item.attribute_values.each do |value|
    attribute_index += 1
    # Checks if the current feedItemAttributeValue is the one we are updating
    if value.feed_attribute_id == target_feed_item_attribute_value.feed_attribute_id
      break
    end
  end

  if attribute_index == -1
    raise "No matching feed attribute for feed item attribute ID: " \
      "#{target_feed_item_attribute_value.feed_attribute_id}"
  end

  attribute_index
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'
  options[:feed_id] = 'INSERT_FEED_ID_HERE'
  options[:feed_item_id] = 'INSERT_FEED_ITEM_ID_HERE'
  options[:flight_placeholder_field_name] = 'INSERT_FLIGHT_PLACEHOLDER_FIELD_NAME_HERE'
  options[:attribute_value] = 'INSERT_ATTRIBUTE_VALUE_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('-F', '--feed-id FEED-ID', String, 'Feed Item ID') do |v|
      options[:feed_id] = v
    end

    opts.on('-f', '--feed-item-id FEED-ITEM-ID', String, 'Feed Item ID') do |v|
      options[:feed_item_id] = v
    end

    opts.on('-P', '--flight-placeholder-field-name FLIGHT-PLACEHOLDER-FIELD-NAME',
      String, 'Flight Placeholder Field Name') do |v|
      options[:flight_placeholder_field_name] = v
    end

    opts.on('-V', '--attribute-value ATTRIBUTE-VALUE', String, 'Attribute Value') do |v|
      options[:attribute_value] = v
    end

    opts.separator ''
    opts.separator 'Help:'

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

  begin
    update_flights_feed_item_string_attribute_value(
      options.fetch(:customer_id).tr("-", ""),
      options.fetch(:feed_id),
      options.fetch(:feed_item_id),
      options.fetch(:flight_placeholder_field_name),
      options.fetch(:attribute_value),
    )
  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.
#
# Updates a feed item attribute value in a flights feed. To create a flights feed,
# run the add_flights_feed.pl example. This example is specific to feeds of type
# DYNAMIC_FLIGHT. The attribute you are updating must be present on the feed.
# This example is specifically for updating the StringValue of an attribute.

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::Utils::FieldMasks;
use Google::Ads::GoogleAds::V16::Resources::FeedItemAttributeValue;
use Google::Ads::GoogleAds::V16::Services::FeedItemService::FeedItemOperation;
use Google::Ads::GoogleAds::V16::Utils::ResourceNames;

use Getopt::Long qw(:config auto_help);
use Pod::Usage;
use Cwd qw(abs_path);

require "$Bin/../remarketing/add_flights_feed.pl";

# 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 $feed_id                       = "INSERT_FEED_ID_HERE";
my $feed_item_id                  = "INSERT_FEED_ITEM_ID_HERE";
my $flight_placeholder_field_name = "INSERT_FLIGHT_PLACEHOLDER_FIELD_NAME_HERE";
my $attribute_value               = "INSERT_ATTRIBUTE_VALUE_HERE";

sub update_flights_feed_item_string_attribute_value {
  my ($api_client, $customer_id, $feed_id, $feed_item_id,
    $flight_placeholder_field_name,
    $attribute_value)
    = @_;

  # Get the feed resource name.
  my $feed_resource_name =
    Google::Ads::GoogleAds::V16::Utils::ResourceNames::feed($customer_id,
    $feed_id);

  # Get a hash of the placeholder values and feed attributes.
  my $feed_attributes =
    get_feed($api_client, $customer_id, $feed_resource_name);

  # Get the ID of the attribute to update. This is needed to specify which
  # FeedItemAttributeValue will be updated in the given FeedItem.
  my $attribute_id = $feed_attributes->{uc($flight_placeholder_field_name)}{id};

  # Get the feed item resource name.
  my $feed_item_resource_name =
    Google::Ads::GoogleAds::V16::Utils::ResourceNames::feed_item($customer_id,
    $feed_id, $feed_item_id);

  # Retrieve the feed item and its associated attributes based on its resource name.
  my $feed_item =
    get_feed_item($api_client, $customer_id, $feed_item_resource_name);

  # Create the updated FeedItemAttributeValue.
  my $feed_item_attribute_value =
    Google::Ads::GoogleAds::V16::Resources::FeedItemAttributeValue->new({
      feedAttributeId => $attribute_id,
      stringValue     => $attribute_value
    });

  # Get the index of the attribute value that will be updated.
  my $attribute_index = get_attribute_index($feed_item, $attribute_id);

  # Set the attribute value of the FeedItem given its index relative to other attributes
  # in the FeedItem.
  $feed_item->{attributeValues}[$attribute_index] = $feed_item_attribute_value;

  # Create a feed item operation.
  my $feed_item_operation =
    Google::Ads::GoogleAds::V16::Services::FeedItemService::FeedItemOperation->
    new({
      update     => $feed_item,
      updateMask => all_set_fields_of($feed_item)});

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

  printf "Updated feed item with resource name: '%s'.\n",
    $feed_items_response->{results}[0]{resourceName};

  return 1;
}

# Retrieves a feed item and its attribute values given a resource name.
sub get_feed_item {
  my ($api_client, $customer_id, $feed_item_resource_name) = @_;

  # Construct the search query.
  my $search_query =
    sprintf "SELECT feed_item.attribute_values FROM feed_item " .
    "WHERE feed_item.resource_name = '%s'", $feed_item_resource_name;

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

  return $search_response->{results}[0]{feedItem};
}

# Gets the index of the attribute value. This is needed to specify which
# FeedItemAttributeValue will be updated in the given FeedItem.
sub get_attribute_index {
  my ($feed_item, $attribute_id) = @_;

  my $attribute_index = -1;
  # Loop through attribute values to find the index of the FeedItemAttributeValue to update.
  while (my ($index, $attribute_value) = each @{$feed_item->{attributeValues}})
  {
    if ($attribute_value->{feedAttributeId} == $attribute_id) {
      $attribute_index = $index;
      last;
    }
  }

  # Die if the attribute value is not found.
  die "No matching feed attribute for feed item attribute value: " .
    $attribute_id
    if $attribute_index == -1;

  return $attribute_index;
}

# 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,
  "feed_id=i"                       => \$feed_id,
  "feed_item_id=i"                  => \$feed_item_id,
  "flight_placeholder_field_name=s" => \$flight_placeholder_field_name,
  "attribute_value=s"               => \$attribute_value
);

# 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, $feed_id, $feed_item_id,
  $flight_placeholder_field_name,
  $attribute_value);

# Call the example.
update_flights_feed_item_string_attribute_value(
  $api_client, $customer_id =~ s/-//gr,
  $feed_id,    $feed_item_id, $flight_placeholder_field_name,
  $attribute_value
);

=pod

=head1 NAME

update_flights_feed_item_string_attribute_value

=head1 DESCRIPTION

Updates a feed item attribute value in a flights feed. To create a flights feed,
run the add_flights_feed.pl example. This example is specific to feeds of type
DYNAMIC_FLIGHT. The attribute you are updating must be present on the feed. This
example is specifically for updating the StringValue of an attribute.

=head1 SYNOPSIS

update_flights_feed_item_string_attribute_value.pl [options]

    -help                               Show the help message.
    -customer_id                        The Google Ads customer ID.
    -feed_id                            The feed ID.
    -feed_item_id                       The feed item ID.
    -flight_placeholder_field_name      The flight placeholder field name for the
                                        attribute to be updated.
    -attribute_value                    The string value with which to update the
                                        FeedAttributeValue.

=cut