Example: Adding and removing real estate listings

Assume you have Dynamic Remarketing ads for your real estate website. New listings get added to inventory, while sold properties get removed. The goal is to update your Dynamic Remarketing ads to reflect your current inventory.

Step 1 - Get information about your listings setup

In order to manage your real estate listings, you'll need to retrieve the feed.attributes of your Feed. In order to easily access this information later, create a Map that contains keys of type RealEstatePlaceholderField and values of type FeedAttribute. Assuming you use the same Map object to create your FeedMapping, as shown in this example, this map will serve as a convenient mechanism for creating each FeedItem in the following step.

Java

private Map<RealEstatePlaceholderField, 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<RealEstatePlaceholderField, FeedAttribute> feedAttributes = new HashMap<>();
    // Loops through each of the feed attributes and populates the map.
    for (FeedAttribute feedAttribute : feedAttributeList) {
      switch (feedAttribute.getName()) {
        case "Listing ID":
          feedAttributes.put(RealEstatePlaceholderField.LISTING_ID, feedAttribute);
          break;
        case "Listing Name":
          feedAttributes.put(RealEstatePlaceholderField.LISTING_NAME, feedAttribute);
          break;
        case "Final URLs":
          feedAttributes.put(RealEstatePlaceholderField.FINAL_URLS, feedAttribute);
          break;
        case "Image URL":
          feedAttributes.put(RealEstatePlaceholderField.IMAGE_URL, feedAttribute);
          break;
        case "Contextual Keywords":
          feedAttributes.put(RealEstatePlaceholderField.CONTEXTUAL_KEYWORDS, feedAttribute);
          break;
          // Optionally add other RealEstatePlaceholderFields.
        default:
          throw new Error("Invalid attribute name.");
      }
    }
    return feedAttributes;
  }
}
      

C#

public Dictionary<RealEstatePlaceholderField, FeedAttribute> GetFeed(
    GoogleAdsClient client, long customerId, string feedResourceName)
{
    // Get the GoogleAdsService.
    GoogleAdsServiceClient googleAdsService = client.GetService(
        Services.V15.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<RealEstatePlaceholderField, FeedAttribute> feedAttributes =
        new Dictionary<RealEstatePlaceholderField, FeedAttribute>();

    // Loops through the feed attributes to populate the map.
    foreach (FeedAttribute feedAttribute in googleAdsRow.Feed.Attributes)
    {
        switch (feedAttribute.Name)
        {
            case "Listing ID":
                feedAttributes[RealEstatePlaceholderField.ListingId] = feedAttribute;
                break;

            case "Listing Name":
                feedAttributes[RealEstatePlaceholderField.ListingName] = feedAttribute;
                break;

            case "Final URLs":
                feedAttributes[RealEstatePlaceholderField.FinalUrls] = feedAttribute;
                break;

            case "Image URL":
                feedAttributes[RealEstatePlaceholderField.ImageUrl] = feedAttribute;
                break;

            case "Contextual Keywords":
                feedAttributes[RealEstatePlaceholderField.ContextualKeywords] = feedAttribute;
                break;
            // The full list of RealEstatePlaceholderField can be found here
            // https://developers.google.com/google-ads/api/reference/rpc/latest/RealEstatePlaceholderFieldEnum.RealEstatePlaceholderField
            default:
                throw new Exception("Invalid attribute name.");
        }
    }
    return feedAttributes;
}
      

PHP

public static function realEstatePlaceholderFieldsMapFor(
    string $feedResourceName,
    int $customerId,
    GoogleAdsClient $googleAdsClient
) {
    return self::placeholderFieldsMapFor(
        $feedResourceName,
        $customerId,
        $googleAdsClient,
        [
            'Listing ID' => RealEstatePlaceholderField::LISTING_ID,
            'Listing Name' => RealEstatePlaceholderField::LISTING_NAME,
            'Final URLs' => RealEstatePlaceholderField::FINAL_URLS,
            'Image URL' => RealEstatePlaceholderField::IMAGE_URL,
            'Contextual Keywords' => RealEstatePlaceholderField::CONTEXTUAL_KEYWORDS
        ]
    );
}
      

Python

def get_placeholder_fields_map(client, customer_id, feed_resource_name):
    """Get mapping of placeholder fields to feed attributes.

    Note that this is only intended to produce a mapping for real estate feeds.

    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

        real_estate_placeholder_field_enum = (
            client.enums.RealEstatePlaceholderFieldEnum
        )
        feed_attribute_names_map = {
            "Listing ID": real_estate_placeholder_field_enum.LISTING_ID,
            "Listing Name": real_estate_placeholder_field_enum.LISTING_NAME,
            "Final URLs": real_estate_placeholder_field_enum.FINAL_URLS,
            "Image URL": real_estate_placeholder_field_enum.IMAGE_URL,
            "Contextual Keywords": real_estate_placeholder_field_enum.CONTEXTUAL_KEYWORDS,
        }

        # 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
      

Ruby

def real_estate_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,
  )

  # Real estate feed attribute names map.
  feed_attribute_names_map = {
    :'Listing ID' => :LISTING_ID,
    :'Listing Name' => :LISTING_NAME,
    :'Final URLs' => :FINAL_URLS,
    :'Image URL' => :IMAGE_URL,
    :'Contextual Keywords' => :CONTEXTUAL_KEYWORDS,
  }

  # 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
      

Perl

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 each of the feed attributes and populates the hash.
  foreach my $feed_attribute (@$feed_attribute_list) {
    my $feed_attribute_name = $feed_attribute->{name};

    if ($feed_attribute_name eq "Listing ID") {
      $feed_attributes->{LISTING_ID} = $feed_attribute;
    } elsif ($feed_attribute_name eq "Listing Name") {
      $feed_attributes->{LISTING_NAME} = $feed_attribute;
    } elsif ($feed_attribute_name eq "Final URLs") {
      $feed_attributes->{FINAL_URLS} = $feed_attribute;
    } elsif ($feed_attribute_name eq "Image URL") {
      $feed_attributes->{IMAGE_URL} = $feed_attribute;
    } elsif ($feed_attribute_name eq "Contextual Keywords") {
      $feed_attributes->{CONTEXTUAL_KEYWORDS} = $feed_attribute;
    } else {
      die("Invalid attribute name.");
    }
  }

  return $feed_attributes;
}
      

Step 2 - Construct operations to add the new listings

Now that the utility method above is in place, constructing the operations for adding new listings is straightforward. The basic steps for each new listing are:

  1. Get the mapping from RealEstatePlaceholderField to feed attribute ID using the utility method.
  2. For each attribute of the listing (listing ID, listing name, image URL, etc.), create a FeedItemAttributeValue with its feed_attribute_id set to the ID of the FeedAttribute found in the mapping for the corresponding FeedItemAttributeValue field.
  3. On the FeedItemAttributeValue, set the appropriate value for the attribute's field. For example, for listing ID, set the string_value field because the LISTING_ID field has a data type of STRING.
  4. Once you have all of the FeedItemAttributeValue objects, create a new FeedItem and set its feed to the resource name of your Feed, and its FeedItemAttributeValue objects to the collection of FeedItemAttributeValue objects.
  5. Create a new FeedItemOperation where the create operation is set to the FeedItem.

Java

private void createFeedItems(
    GoogleAdsClient googleAdsClient,
    long customerId,
    Map<RealEstatePlaceholderField, FeedAttribute> feedAttributes,
    String feedResourceName) {

  // Creates the listing ID feed attribute value.
  FeedItemAttributeValue listingId =
      FeedItemAttributeValue.newBuilder()
          .setFeedAttributeId(feedAttributes.get(RealEstatePlaceholderField.LISTING_ID).getId())
          .setStringValue("ABC123DEF")
          .build();
  // Creates the listing name feed attribute value.
  FeedItemAttributeValue listingName =
      FeedItemAttributeValue.newBuilder()
          .setFeedAttributeId(feedAttributes.get(RealEstatePlaceholderField.LISTING_NAME).getId())
          .setStringValue("Two bedroom with magnificent views")
          .build();
  // Creates the final URLs feed attribute value.
  FeedItemAttributeValue finalUrls =
      FeedItemAttributeValue.newBuilder()
          .setFeedAttributeId(feedAttributes.get(RealEstatePlaceholderField.FINAL_URLS).getId())
          .addStringValues("http://www.example.com/listings/")
          .build();

  // Optionally insert additional attributes here, such as address, city, description, etc.

  // Creates the image URL feed attribute value.
  FeedItemAttributeValue imageUrl =
      FeedItemAttributeValue.newBuilder()
          .setFeedAttributeId(feedAttributes.get(RealEstatePlaceholderField.IMAGE_URL).getId())
          .setStringValue("http://www.example.com/listings/images?listing_id=ABC123DEF")
          .build();
  // Creates the contextual keywords feed attribute value.
  FeedItemAttributeValue contextualKeywords =
      FeedItemAttributeValue.newBuilder()
          .setFeedAttributeId(
              feedAttributes.get(RealEstatePlaceholderField.CONTEXTUAL_KEYWORDS).getId())
          .addStringValues("beach community")
          .addStringValues("ocean view")
          .addStringValues("two bedroom")
          .build();

  // Creates the FeedItem, specifying the Feed ID and the attributes created above.
  FeedItem feedItem =
      FeedItem.newBuilder()
          .setFeed(feedResourceName)
          .addAttributeValues(listingId)
          .addAttributeValues(listingName)
          .addAttributeValues(finalUrls)
          // Optionally include additional attributes.
          .addAttributeValues(imageUrl)
          .addAttributeValues(contextualKeywords)
          .build();

  // Creates an operation to add the FeedItem. You can include multiple feed items in a single
  // operation.
  FeedItemOperation operation = FeedItemOperation.newBuilder().setCreate(feedItem).build();
  // Creates the feed item service client.
  try (FeedItemServiceClient feedItemServiceClient =
      googleAdsClient.getLatestVersion().createFeedItemServiceClient()) {
    // Adds the feed items.
    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#

private void CreateFeedItem(GoogleAdsClient client, long customerId,
    Dictionary<RealEstatePlaceholderField, FeedAttribute> feedAttributes,
    string feedResourceName)
{
    // Get the FeedItemServiceClient.
    FeedItemServiceClient feedItemService = client.GetService(
        Services.V15.FeedItemService);

    // Creates the listing ID feed attribute value.
    FeedItemAttributeValue listingId = new FeedItemAttributeValue()
    {
        FeedAttributeId = feedAttributes[RealEstatePlaceholderField.ListingId].Id,
        StringValue = "ABC123DEF"
    };

    // Creates the listing name feed attribute value.
    FeedItemAttributeValue listingName = new FeedItemAttributeValue()
    {
        FeedAttributeId = feedAttributes[RealEstatePlaceholderField.ListingName].Id,
        StringValue = "Two bedroom with magnificent views"
    };

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

    // Creates the image URL feed attribute value.
    FeedItemAttributeValue imageUrl = new FeedItemAttributeValue()
    {
        FeedAttributeId = feedAttributes[RealEstatePlaceholderField.ImageUrl].Id,
        StringValue = "http://www.example.com/listings/images?listing_id=ABC123DEF"
    };

    // Creates the contextual keywords feed attribute value.
    FeedItemAttributeValue contextualKeywords = new FeedItemAttributeValue()
    {
        FeedAttributeId = feedAttributes[RealEstatePlaceholderField.ContextualKeywords].Id,
        StringValues =
        {
            "beach community",
            "ocean view",
            "two bedroom",
        }
    };

    // Creates the FeedItem, specifying the Feed ID and the attributes created above.
    FeedItem feedItem = new FeedItem()
    {
        Feed = feedResourceName,
        AttributeValues =
        {
            listingId,
            listingName,
            finalUrls,
            imageUrl,
            contextualKeywords
        }
    };

    // 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

private static function createFeedItem(
    GoogleAdsClient $googleAdsClient,
    int $customerId,
    string $feedResourceName,
    array $placeHoldersToFeedAttributesMap
) {
    // Creates the listing ID feed attribute value.
    $listingIdAttributeValue = new FeedItemAttributeValue([
        'feed_attribute_id' => $placeHoldersToFeedAttributesMap[
            RealEstatePlaceholderField::LISTING_ID]->getId(),
        'string_value' => 'ABC123DEF'
    ]);
    // Creates the listing name feed attribute value.
    $listingNameAttributeValue = new FeedItemAttributeValue([
        'feed_attribute_id' => $placeHoldersToFeedAttributesMap[
            RealEstatePlaceholderField::LISTING_NAME]->getId(),
        'string_value' => 'Two bedroom with magnificent views'
    ]);
    // Creates the final URLs feed attribute value.
    $finalUrlsAttributeValue = new FeedItemAttributeValue([
        'feed_attribute_id' => $placeHoldersToFeedAttributesMap[
            RealEstatePlaceholderField::FINAL_URLS]->getId(),
        'string_values' => ['http://www.example.com/listings/']
    ]);
    // Creates the image URL feed attribute value.
    $imageUrlAttributeValue = new FeedItemAttributeValue([
        'feed_attribute_id'
            => $placeHoldersToFeedAttributesMap[RealEstatePlaceholderField::IMAGE_URL]->getId(),
        'string_value' => 'http://www.example.com/listings/images?listing_id=ABC123DEF'
    ]);
    // Creates the contextual keywords feed attribute value.
    $contextualKeywordsAttributeValue = new FeedItemAttributeValue([
        'feed_attribute_id' => $placeHoldersToFeedAttributesMap[
            RealEstatePlaceholderField::CONTEXTUAL_KEYWORDS]->getId(),
        'string_values' => ['beach community', 'ocean view', 'two bedroom']
    ]);

    // Creates the feed item, specifying the feed ID and the attributes created above.
    $feedItem = new FeedItem([
        'feed' => $feedResourceName,
        'attribute_values' => [
            $listingIdAttributeValue,
            $listingNameAttributeValue,
            $finalUrlsAttributeValue,
            $imageUrlAttributeValue,
            $contextualKeywordsAttributeValue
        ]
    ]);

    // 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(
        MutateFeedItemsRequest::build($customerId, [$operation])
    );
    printf(
        "Feed item with resource name '%s' was created.%s",
        $response->getResults()[0]->getResourceName(),
        PHP_EOL
    );
}
      

Python

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.RealEstatePlaceholderFieldEnum

    # Creates the listing ID feed attribute value.
    listing_id_enum_value = placeholder_field_enum.LISTING_ID
    listing_id_mapping = client.get_type("FeedItemAttributeValue")
    listing_id_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[
        listing_id_enum_value
    ].id
    listing_id_mapping.string_value = "ABC123DEF"

    # Creates the listing name feed attribute value.
    listing_name_enum_value = placeholder_field_enum.LISTING_NAME
    listing_name_mapping = client.get_type("FeedItemAttributeValue")
    listing_name_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[
        listing_name_enum_value
    ].id
    listing_name_mapping.string_value = "Two bedroom with magnificent views"

    # Creates the final URLs feed attribute value.
    final_urls_enum_value = placeholder_field_enum.FINAL_URLS
    final_urls_mapping = client.get_type("FeedItemAttributeValue")
    final_urls_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[
        final_urls_enum_value
    ].id
    final_urls_mapping.string_values.append("http://www.example.com/listings/")

    # Creates the image URL feed attribute value.
    image_url_enum_value = placeholder_field_enum.IMAGE_URL
    image_url_mapping = client.get_type("FeedItemAttributeValue")
    image_url_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[
        image_url_enum_value
    ].id
    image_url_mapping.string_value = (
        "http://www.example.com/listings/images?listing_id=ABC123DEF"
    )

    # Creates the contextual keywords feed attribute value.
    contextual_keywords_enum_value = placeholder_field_enum.CONTEXTUAL_KEYWORDS
    contextual_keywords_mapping = client.get_type("FeedItemAttributeValue")
    contextual_keywords_mapping.feed_attribute_id = (
        placeholders_to_feed_attribute_map[contextual_keywords_enum_value].id
    )
    contextual_keywords_mapping.string_values.extend(
        ["beach community", "ocean view", "two bedroom"]
    )

    feed_item.attribute_values.extend(
        [
            listing_id_mapping,
            listing_name_mapping,
            final_urls_mapping,
            image_url_mapping,
            contextual_keywords_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
      

Ruby

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[:LISTING_ID].id
      v.string_value = "ABC123DEF"
    end
    fi.attribute_values << client.resource.feed_item_attribute_value do |v|
      v.feed_attribute_id = placeholders_to_feed_attribute_map[:LISTING_NAME].id
      v.string_value = "Two bedroom with magnificent views"
    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/listings/"
    end
    fi.attribute_values << client.resource.feed_item_attribute_value do |v|
      v.feed_attribute_id = placeholders_to_feed_attribute_map[:IMAGE_URL].id
      v.string_value = "http://www.example.com/listings/images?listing_id=ABC123DEF"
    end
    fi.attribute_values << client.resource.feed_item_attribute_value do |v|
      v.feed_attribute_id = placeholders_to_feed_attribute_map[:CONTEXTUAL_KEYWORDS].id
      v.string_values += ["beach community", "ocean view", "two bedroom"]
    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
      

Perl

sub create_feed_item {
  my ($api_client, $customer_id, $feed_attributes, $feed_resource_name) = @_;

  # Create the listing ID feed attribute value.
  my $listing_id =
    Google::Ads::GoogleAds::V15::Resources::FeedItemAttributeValue->new({
      feedAttributeId => $feed_attributes->{LISTING_ID}{id},
      stringValue     => "ABC123DEF"
    });
  # Create the listing name feed attribute value.
  my $listing_name =
    Google::Ads::GoogleAds::V15::Resources::FeedItemAttributeValue->new({
      feedAttributeId => $feed_attributes->{LISTING_NAME}{id},
      stringValue     => "Two bedroom with magnificent views"
    });
  # Create the final URLs feed attribute value.
  my $final_urls =
    Google::Ads::GoogleAds::V15::Resources::FeedItemAttributeValue->new({
      feedAttributeId => $feed_attributes->{FINAL_URLS}{id},
      stringValue     => "http://www.example.com/listings/"
    });

  # Optionally insert additional attributes here, such as address, city, description, etc.

  # Create the image URL feed attribute value.
  my $image_url =
    Google::Ads::GoogleAds::V15::Resources::FeedItemAttributeValue->new({
      feedAttributeId => $feed_attributes->{IMAGE_URL}{id},
      stringValue     =>
        "http://www.example.com/listings/images?listing_id=ABC123DEF"
    });
  # Create the contextual keywords feed attribute value.
  my $contextual_keywords =
    Google::Ads::GoogleAds::V15::Resources::FeedItemAttributeValue->new({
      feedAttributeId => $feed_attributes->{CONTEXTUAL_KEYWORDS}{id},
      stringValues    => ["beach community", "ocean view", "two bedroom"]});

  # Create a feed item, specifying the Feed ID and the attributes created above.
  my $feed_item = Google::Ads::GoogleAds::V15::Resources::FeedItem->new({
      feed            => $feed_resource_name,
      attributeValues => [
        $listing_id, $listing_name, $final_urls,
        $image_url,  $contextual_keywords
      ]});

  # Create a feed item operation.
  my $feed_item_operation =
    Google::Ads::GoogleAds::V15::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};
}
      

Step 3 - Remove sold listings

The process for removing sold listings is even simpler—all you need is the FeedItem resource_name.

If you don't have the resource_name of a sold listing, you can use the Google Ads Query Language to construct a query that retrieves feed_item fields from a feed with a given resource name.

The basic steps for each listing you want to remove are:

  1. Create a new FeedItemOperation and set its remove operation to the resource name of the FeedItem you want to remove.
  2. Like any other mutate operation, pass the FeedItemOperation to the MutateFeedItemsRequest.

Java

private void removeAttributeFromFeedItem(
    GoogleAdsClient googleAdsClient,
    long customerId,
    long feedId,
    long feedItemId,
    String flightPlaceholderField) {
  // 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 feed item resource name.
  String feedItemResourceName = ResourceNames.feedItem(customerId, feedId, feedItemId);
  // Removes the attribute from the feed item.
  FeedItem feedItem =
      removeAttributeValueFromFeedItem(
          googleAdsClient,
          customerId,
          feedAttributes,
          feedItemResourceName,
          FlightPlaceholderField.valueOf(flightPlaceholderField.toUpperCase()));

  // 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());
    }
  }
}
      

C#

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

// Updates the feed item and prints the results.
MutateFeedItemsResponse response = feedItemServiceClient.MutateFeedItems
    (customerId.ToString(), new[] { operation });
foreach (MutateFeedItemResult result in response.Results)
{
    Console.WriteLine("Updated feed item with resource name " +
        $"'{result.ResourceName}'.");
}
      

PHP

// 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 to remove the value of"
    . " placeholder field type '%s'.%s",
    $response->getResults()[0]->getResourceName(),
    $flightPlaceholderFieldName,
    PHP_EOL
);
      

Python

# Gets the ID of the FeedAttribute for the placeholder field.
attribute_id = placeholders_to_feed_attributes_map[
    flight_placeholder_field_name
].id

# Retrieve the feed item and its associated attributes based on its resource
# name.
feed_item = get_feed_item(client, customer_id, feed_id, feed_item_id)

# Create the FeedItemAttributeValue that will be updated.
feed_item_attribute_value = client.get_type("FeedItemAttributeValue")
feed_item_attribute_value.feed_attribute_id = attribute_id

# Loop through the attribute values to find the index of the
# FeedItemAttributeValue to update.
attribute_index = -1
for attribute_value in feed_item.attribute_values:
    attribute_index += 1
    if (
        attribute_value.feed_attribute_id
        == feed_item_attribute_value.feed_attribute_id
    ):
        break

if attribute_index == -1:
    raise ValueError(
        "No matching feed attribute found for value "
        f"'{feed_item_attribute_value}'."
    )

# Returns the feed item with the removed FeedItemAttributeValue. Any
# FeedItemAttributeValues that are not included in the updated FeedItem will
# be removed from the FeedItem; you can easily accomplish this by removing
# items from the AttributeValues list.
feed_item.attribute_values.pop(attribute_index)
return feed_item
      

Ruby

# 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)
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 to remove the value of placeholder field type " \
  "#{flight_placeholder_field_name}."
      

Perl

# Create a feed item operation.
my $feed_item_operation =
  Google::Ads::GoogleAds::V15::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};