Add Hotel Listing Group Tree

Java

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

package com.google.ads.googleads.examples.hotelads;

import com.beust.jcommander.Parameter;
import com.google.ads.googleads.examples.utils.ArgumentNames;
import com.google.ads.googleads.examples.utils.CodeSampleParams;
import com.google.ads.googleads.lib.GoogleAdsClient;
import com.google.ads.googleads.v11.common.HotelClassInfo;
import com.google.ads.googleads.v11.common.HotelCountryRegionInfo;
import com.google.ads.googleads.v11.common.ListingDimensionInfo;
import com.google.ads.googleads.v11.common.ListingGroupInfo;
import com.google.ads.googleads.v11.enums.AdGroupCriterionStatusEnum.AdGroupCriterionStatus;
import com.google.ads.googleads.v11.enums.ListingGroupTypeEnum.ListingGroupType;
import com.google.ads.googleads.v11.errors.GoogleAdsError;
import com.google.ads.googleads.v11.errors.GoogleAdsException;
import com.google.ads.googleads.v11.resources.AdGroupCriterion;
import com.google.ads.googleads.v11.services.AdGroupCriterionOperation;
import com.google.ads.googleads.v11.services.AdGroupCriterionServiceClient;
import com.google.ads.googleads.v11.services.MutateAdGroupCriteriaResponse;
import com.google.ads.googleads.v11.services.MutateAdGroupCriterionResult;
import com.google.ads.googleads.v11.utils.ResourceNames;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.LongStream;

/**
 * This example shows how to add a hotel listing group tree, which has two levels. The first level
 * is partitioned by the hotel class. The second level is partitioned by the country region.
 *
 * <p>Each level is composed of two types of nodes: `UNIT` and `SUBDIVISION`. `UNIT` nodes serve as
 * leaf nodes in a tree and can have bid amount set. `SUBDIVISION` nodes serve as internal nodes
 * where a subtree will be built. The `SUBDIVISION` node cannot have bid amount set. See
 * https://developers.google.com/google-ads/api/docs/hotel-ads/overview for more information.
 *
 * <p>Note: Only one listing group tree can be added per ad group. Attempting to add another listing
 * group tree to an ad group that already has one will fail.
 */
public class AddHotelListingGroupTree {

  private static Iterator<Long> idGenerator;

  private static class AddHotelListingGroupTreeParams extends CodeSampleParams {

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

    @Parameter(names = ArgumentNames.AD_GROUP_ID, required = true)
    private Long adGroupId;

    // Specify the CPC bid micro amount to be set on a created ad group criterion.
    // For simplicity, each ad group criterion will use the below amount equally. In practice, you
    // probably want to use different values for each ad group criterion.
    @Parameter(names = ArgumentNames.PERCENT_CPC_BID_MICRO_AMOUNT)
    private Long percentCpcBidMicroAmount = 1_000_000L;
  }

  public static void main(String[] args) {
    AddHotelListingGroupTreeParams params = new AddHotelListingGroupTreeParams();
    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.adGroupId = Long.parseLong("INSERT_AD_GROUP_ID_HERE");
      // Optional: To use a different CPC bid micro value from the default (1_000_000), uncomment
      // the line below and insert the desired CPC bid micro value.
      // params.percentCpcBidMicroAmount = Long.parseInt("INSERT_PERCENT_CPC_BID_MICRO_AMOUNT");
    }

    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 AddHotelListingGroupTree()
          .runExample(
              googleAdsClient,
              params.customerId,
              params.adGroupId,
              params.percentCpcBidMicroAmount);
    } 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);
    }
  }

  /**
   * Constructor used to create iterator for generating temporary criterion IDs, which are negative
   * integers.
   *
   * <p>When creating a tree, we need to specify the parent-child relationships between nodes.
   * However, until a criterion has been created on the server we do not have a criterion ID with
   * which to refer to it.
   *
   * <p>Instead we can specify temporary IDs that are specific to a single mutate request. Once a
   * criterion is created, it is assigned an ID as normal and the temporary ID will no longer refer
   * to it.
   */
  AddHotelListingGroupTree() {
    idGenerator = LongStream.iterate(-1L, prev -> prev - 1).iterator();
  }

  /**
   * Runs the example.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the client customer ID.
   * @param adGroupId the ID of the ad group.
   * @param percentCpcBidMicroAmount the percent CPC bid micro amount to set on created ad group
   *     criteria.
   * @throws GoogleAdsException if an API request failed with one or more service errors.
   */
  private void runExample(
      GoogleAdsClient googleAdsClient,
      long customerId,
      long adGroupId,
      long percentCpcBidMicroAmount) {
    List<AdGroupCriterionOperation> operations = new ArrayList<>();

    // Creates the root of the tree as a SUBDIVISION node.
    String rootResourceName =
        addRootNode(customerId, adGroupId, operations, percentCpcBidMicroAmount);

    // Creates child nodes of level 1, partitioned by the hotel class info.
    String otherHotelResourceName =
        addLevel1Nodes(
            customerId, adGroupId, rootResourceName, operations, percentCpcBidMicroAmount);

    // Creates child nodes of level 2, partitioned by the hotel country region info.
    addLevel2Nodes(
        customerId, adGroupId, otherHotelResourceName, operations, percentCpcBidMicroAmount);

    try (AdGroupCriterionServiceClient adGroupCriterionServiceClient =
        googleAdsClient.getLatestVersion().createAdGroupCriterionServiceClient()) {
      MutateAdGroupCriteriaResponse response =
          adGroupCriterionServiceClient.mutateAdGroupCriteria(
              String.valueOf(customerId), operations);

      System.out.printf("Added %d listing group info entities.%n", response.getResultsCount());
      for (MutateAdGroupCriterionResult result : response.getResultsList()) {
        System.out.println(result.getAdGroupCriterion().getResourceName());
      }
    }
  }

  /**
   * Creates the root node of the listing group tree and adds its create operation to the operations
   * list.
   *
   * @param customerId the customer ID.
   * @param adGroupId the ad group ID.
   * @param operations the operations.
   * @param percentCpcBidMicroAmount the CPC bid micro amount to set on created ad group criteria.
   * @return the root node's resource name
   */
  private static String addRootNode(
      long customerId,
      long adGroupId,
      List<AdGroupCriterionOperation> operations,
      long percentCpcBidMicroAmount) {
    // Creates the root of the tree as a SUBDIVISION node.
    ListingGroupInfo root =
        ListingGroupInfo.newBuilder().setType(ListingGroupType.SUBDIVISION).build();
    AdGroupCriterion rootAdGroupCriterion =
        createAdGroupCriterion(customerId, adGroupId, root, percentCpcBidMicroAmount);
    AdGroupCriterionOperation operation = generateCreateOperation(rootAdGroupCriterion);
    operations.add(operation);
    return rootAdGroupCriterion.getResourceName();
  }

  /**
   * Creates child nodes of level 1, partitioned by the hotel class info.
   *
   * @param customerId the customer ID.
   * @param adGroupId the ad group ID.
   * @param rootResourceName the resource name of the root node.
   * @param operations the operations list.
   * @param percentCpcBidMicroAmount the CPC bid micro amount to set on created ad group criteria.
   * @return the "other hotel classes" node's resource name, which serves as a parent node for the
   *     next level.
   */
  private static String addLevel1Nodes(
      long customerId,
      long adGroupId,
      String rootResourceName,
      List<AdGroupCriterionOperation> operations,
      long percentCpcBidMicroAmount) {
    // Creates hotel class info and dimension info for 5-star hotels.
    ListingDimensionInfo fiveStarredDimensionInfo =
        ListingDimensionInfo.newBuilder()
            .setHotelClass(HotelClassInfo.newBuilder().setValue(5).build())
            .build();
    // Creates listing group info for 5-star hotels as a UNIT node.
    ListingGroupInfo fiveStarredUnit =
        ListingGroupInfo.newBuilder()
            .setType(ListingGroupType.UNIT)
            .setParentAdGroupCriterion(rootResourceName)
            .setCaseValue(fiveStarredDimensionInfo)
            .build();
    // Creates an ad group criterion for 5-star hotels.
    AdGroupCriterion fiveStarredAdGroupCriterion =
        createAdGroupCriterion(customerId, adGroupId, fiveStarredUnit, percentCpcBidMicroAmount);
    // Decrements the temp ID for the next ad group criterion.
    AdGroupCriterionOperation operation = generateCreateOperation(fiveStarredAdGroupCriterion);
    operations.add(operation);

    // You can also create more UNIT nodes for other hotel classes by copying the above code in
    // this method and modifying the value passed to HotelClassInfo() to the value you want.
    // For instance, passing 4 instead of 5 in the above code will create a UNIT node of 4-star
    // hotels instead.

    // Creates hotel class info and dimension info for other hotel classes by not specifying
    // any attributes on those object.
    ListingDimensionInfo otherHotelsDimensionInfo =
        ListingDimensionInfo.newBuilder()
            .setHotelClass(HotelClassInfo.newBuilder().build())
            .build();
    // Creates listing group info for other hotel classes as a SUBDIVISION node, which will be
    // used as a parent node for children nodes of the next level.
    ListingGroupInfo otherHotelsSubdivision =
        createListingGroupInfo(
            ListingGroupType.SUBDIVISION, rootResourceName, otherHotelsDimensionInfo);
    // Creates an ad group criterion for other hotel classes.
    AdGroupCriterion otherHotelsAdGroupCriterion =
        createAdGroupCriterion(
            customerId, adGroupId, otherHotelsSubdivision, percentCpcBidMicroAmount);
    operation = generateCreateOperation(otherHotelsAdGroupCriterion);
    operations.add(operation);

    return otherHotelsAdGroupCriterion.getResourceName();
  }

  /**
   * Creates child nodes of level 2, partitioned by the country region.
   *
   * @param customerId the customer ID.
   * @param adGroupId the ad group ID.
   * @param parentResourceName the resource name of the parent node.
   * @param operations the operations list.
   * @param percentCpcBidMicroAmount the CPC bid micro amount to set on created ad group criteria.
   *     criteria
   */
  private static void addLevel2Nodes(
      long customerId,
      long adGroupId,
      String parentResourceName,
      List<AdGroupCriterionOperation> operations,
      long percentCpcBidMicroAmount) {
    // The criterion ID for Japan is 2392.
    // See https://developers.google.com/google-ads/api/reference/data/geotargets for criteria IDs
    // of other countries.
    long japanGeoTargetConstantId = 2392;
    ListingDimensionInfo japanDimensionInfo =
        ListingDimensionInfo.newBuilder()
            // Creates hotel country region info and dimension info for hotels in Japan.
            .setHotelCountryRegion(
                HotelCountryRegionInfo.newBuilder()
                    .setCountryRegionCriterion(
                        ResourceNames.geoTargetConstant(japanGeoTargetConstantId))
                    .build())
            .build();
    // Creates hotel country region info and dimension info for hotels in Japan.
    ListingGroupInfo japanHotelsUnit =
        createListingGroupInfo(ListingGroupType.UNIT, parentResourceName, japanDimensionInfo);
    // Creates an ad group criterion for hotels in Japan.
    AdGroupCriterion japanHotelsAdGroupCriterion =
        createAdGroupCriterion(customerId, adGroupId, japanHotelsUnit, percentCpcBidMicroAmount);
    // Decrements the temp ID for the next ad group criterion.
    AdGroupCriterionOperation operation = generateCreateOperation(japanHotelsAdGroupCriterion);
    operations.add(operation);

    // Creates hotel class info and dimension info for hotels in other regions.
    ListingDimensionInfo otherHotelRegionsDimensionInfo =
        ListingDimensionInfo.newBuilder()
            .setHotelCountryRegion(HotelCountryRegionInfo.newBuilder().build())
            .build();
    // Creates listing group info for hotels in other regions as a UNIT node.
    // The "others" node is always required for every level of the tree.
    ListingGroupInfo otherHotelRegionsUnit =
        createListingGroupInfo(
            ListingGroupType.UNIT, parentResourceName, otherHotelRegionsDimensionInfo);
    // Creates an ad group criterion for other hotel country regions.
    AdGroupCriterion otherHotelRegionsAdGroupCriterion =
        createAdGroupCriterion(
            customerId, adGroupId, otherHotelRegionsUnit, percentCpcBidMicroAmount);
    operation = generateCreateOperation(otherHotelRegionsAdGroupCriterion);
    operations.add(operation);
  }

  /**
   * Creates the listing group info with the provided parameters.
   *
   * @param listingGroupType the listing group type.
   * @param parentCriterionResourceName the resource name of parent criterion ID of the listing
   *     group info.
   * @param caseValue the dimension info for the listing group.
   * @return the created listing group info
   */
  private static ListingGroupInfo createListingGroupInfo(
      ListingGroupType listingGroupType,
      String parentCriterionResourceName,
      ListingDimensionInfo caseValue) {
    return ListingGroupInfo.newBuilder()
        .setType(listingGroupType)
        .setParentAdGroupCriterion(parentCriterionResourceName)
        .setCaseValue(caseValue)
        .build();
  }

  /**
   * Creates an ad group criterion from the provided listing group info. Bid amount will be set on
   * the created ad group criterion when listing group info type is `UNIT`. Setting bid amount for
   * `SUBDIVISION` types is not allowed.
   *
   * @param customerId the customer ID.
   * @param adGroupId the ad group ID.
   * @param listingGroupInfo the listing group info.
   * @param percentCpcBidMicroAmount the CPC bid micro amount to set for the ad group criterion.
   * @return the created ad group criterion
   */
  private static AdGroupCriterion createAdGroupCriterion(
      long customerId,
      long adGroupId,
      ListingGroupInfo listingGroupInfo,
      long percentCpcBidMicroAmount) {
    AdGroupCriterion.Builder adGroupCriterionBuilder =
        AdGroupCriterion.newBuilder()
            .setStatus(AdGroupCriterionStatus.ENABLED)
            .setListingGroup(listingGroupInfo)
            .setResourceName(
                ResourceNames.adGroupCriterion(customerId, adGroupId, idGenerator.next()));

    // Bids are valid only for UNIT nodes.
    if (listingGroupInfo.getType() == ListingGroupType.UNIT) {
      adGroupCriterionBuilder.setPercentCpcBidMicros(percentCpcBidMicroAmount);
    }

    return adGroupCriterionBuilder.build();
  }

  /**
   * Creates an operation for creating the specified ad group criterion.
   *
   * @param adGroupCriterion the ad group criterion to create an operation for.
   * @return the created ad group criterion operation
   */
  private static AdGroupCriterionOperation generateCreateOperation(
      AdGroupCriterion adGroupCriterion) {
    return AdGroupCriterionOperation.newBuilder().setCreate(adGroupCriterion).build();
  }
}

      

C#

// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using CommandLine;
using Google.Ads.Gax.Examples;
using Google.Ads.GoogleAds.Lib;
using Google.Ads.GoogleAds.V11.Common;
using Google.Ads.GoogleAds.V11.Errors;
using Google.Ads.GoogleAds.V11.Resources;
using Google.Ads.GoogleAds.V11.Services;
using System;
using System.Collections.Generic;
using static Google.Ads.GoogleAds.V11.Enums.AdGroupCriterionStatusEnum.Types;
using static Google.Ads.GoogleAds.V11.Enums.ListingGroupTypeEnum.Types;

namespace Google.Ads.GoogleAds.Examples.V11
{
    /// <summary>
    /// This example shows how to add a hotel listing group tree, which has two levels. The first
    /// level is partitioned by the hotel class. The second level is partitioned by the country
    /// region.
    ///
    /// Each level is composed of two types of nodes: `UNIT` and `SUBDIVISION`.
    /// `UNIT` nodes serve as a leaf node in a tree and can have bid amount set.
    /// `SUBDIVISION` nodes serve as an internal node where a subtree will be built. The
    /// `SUBDIVISION` node can't have bid amount set.
    /// See https://developers.google.com/google-ads/api/docs/hotel-ads/overview for more information.
    ///
    /// Note: Only one listing group tree can be added. Attempting to add another listing group tree
    /// to an ad group that already has one will fail.
    /// </summary>
    public class AddHotelListingGroupTree : ExampleBase
    {
        /// <summary>
        /// Command line options for running the <see cref="AddHotelListingGroupTree"/> example.
        /// </summary>
        public class Options : OptionsBase
        {
            /// <summary>
            /// The Google Ads customer ID.
            /// </summary>
            [Option("customerId", Required = true, HelpText =
                "The Google Ads customer ID.")]
            public long CustomerId { get; set; }

            /// <summary>
            /// The ad group ID of the ad group to which the hotel listing will be added.
            /// </summary>
            [Option("adGroupId", Required = true, HelpText =
                "The ad group ID of the ad group to which the hotel listing will be added.")]
            public long AdGroupId { get; set; }

            /// <summary>
            /// The CPC bid micro amount to be set on created ad group criteria.
            /// </summary>
            [Option("percentCpcBidMicroAmount", Required = true, HelpText =
                "The CPC bid micro amount to be set on created ad group criteria.")]
            public long PercentCpcBidMicroAmount { 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);

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

        // The next temporary criterion ID to be used, which is a negative integer.

        // When creating a tree, we need to specify the parent-child relationships between nodes.
        // However, until a criterion has been created on the server we do not have a criterion ID
        // with which to refer to it.

        // Instead, we can specify temporary IDs that are specific to a single mutate request. Once
        // a criterion is created, it is assigned an ID as normal and the temporary ID will no
        // longer refer to it.
        private int nextTempId = -1;

        /// <summary>
        /// Returns a description about the code example.
        /// </summary>
        public override string Description =>
            "This example shows how to add a hotel listing group tree, which has two levels. The " +
            "first level is partitioned by the hotel class. The second level is partitioned by " +
            "the country region.\n\n" +
            "Each level is composed of two types of nodes: `UNIT` and `SUBDIVISION`.\n" +
            "\t'UNIT' nodes serve as a leaf node in a tree and can have bid amount set.\n" +
            "\t'SUBDIVISION' nodes serve as an internal node where a subtree will be built. The " +
            "'SUBDIVISION' node can't have bid amount set.\n" +
            "See https://developers.google.com/google-ads/api/docs/hotel-ads/overview for more " +
            "information.\n\n" +
            "Note: Only one listing group tree can be added. Attempting to add another listing " +
            "group tree to an ad group that already has one will fail.";

        /// <summary>
        /// Runs the code example.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The Google Ads customer ID.</param>
        /// <param name="adGroupId">The ad group ID of the ad group to which the hotel listing will
        /// be added.</param>
        /// <param name="percentCpcBidMicroAmount">The CPC bid micro amount to be set on created
        /// ad group criteria.</param>
        public void Run(GoogleAdsClient client, long customerId, long adGroupId,
            long percentCpcBidMicroAmount)
        {
            // Get the AdGroupCriterionService client.
            AdGroupCriterionServiceClient adGroupCriterionService =
                client.GetService(Services.V11.AdGroupCriterionService);

            List<AdGroupCriterionOperation> operations = new List<AdGroupCriterionOperation>();

            try
            {
                // Creates the root of the tree as a SUBDIVISION node.
                string rootResourceName = AddRootNode(customerId, adGroupId, operations,
                    percentCpcBidMicroAmount);

                // Creates child nodes of level 1, partitioned by the hotel class info.
                string otherHotelResourceName = AddLevel1Nodes(customerId, adGroupId,
                    rootResourceName, operations, percentCpcBidMicroAmount);

                // Creates child nodes of level 2, partitioned by the hotel country region info.
                AddLevel2Nodes(customerId, adGroupId, otherHotelResourceName, operations,
                    percentCpcBidMicroAmount);

                // Adds the listing group and prints the resulting node resource names.
                MutateAdGroupCriteriaResponse response =
                    adGroupCriterionService.MutateAdGroupCriteria(customerId.ToString(),
                        operations);

                Console.WriteLine($"Added {response.Results.Count} listing group info entities " +
                    "with resource names:");
                foreach (MutateAdGroupCriterionResult adGroupCriterionResult in response.Results)
                {
                    Console.WriteLine($"\t{adGroupCriterionResult.ResourceName}");
                }
            }
            catch (GoogleAdsException e)
            {
                Console.WriteLine("Failure:");
                Console.WriteLine($"Message: {e.Message}");
                Console.WriteLine($"Failure: {e.Failure}");
                Console.WriteLine($"Request ID: {e.RequestId}");
                throw;
            }
        }

        /// <summary>
        /// Creates the root node of the listing group tree and adds its create operation to the
        /// operations list.
        /// </summary>
        /// <param name="customerId">The Google Ads customer ID.</param>
        /// <param name="adGroupId">The ad group ID to which the hotel listing group will be
        ///     added.</param>
        /// <param name="operations">A list of AdGroupCriterionOperations.</param>
        /// <param name="percentCpcBidMicroAmount">The CPC bid micro amount to be set on created
        ///     ad group criteria.</param>
        /// <returns>The string resource name of the root of the tree.</returns>
        private string AddRootNode(long customerId, long adGroupId,
            List<AdGroupCriterionOperation> operations, long percentCpcBidMicroAmount)
        {
            // Create the root of the tree as a SUBDIVISION node.
            ListingGroupInfo rootListingGroupInfo =
                CreateListingGroupInfo(ListingGroupType.Subdivision);

            AdGroupCriterion rootAdGroupCriterion = CreateAdGroupCriterion(customerId, adGroupId,
                rootListingGroupInfo, percentCpcBidMicroAmount);

            // Create an operation and add it to the list of operations.
            operations.Add(new AdGroupCriterionOperation
            {
                Create = rootAdGroupCriterion
            });

            // Decrement the temp ID for the next ad group criterion.
            nextTempId--;

            return rootAdGroupCriterion.ResourceName;
        }

        /// <summary>
        /// Creates child nodes on level 1, partitioned by the hotel class info.
        /// </summary>
        /// <param name="customerId">The Google Ads customer ID.</param>
        /// <param name="adGroupId">The ad group ID to which the hotel listing group will be
        /// added.</param>
        /// <param name="rootResourceName">The string resource name of the listing group's root
        /// node.</param>
        /// <param name="operations">A list of AdGroupCriterionOperations.</param>
        /// <param name="percentCpcBidMicroAmount">The CPC bid micro amount to be set on created
        /// ad group criteria.</param>
        /// <returns>The string resource name of the "other hotel classes" node, which serves as the
        /// parent node for the next level of the listing tree.</returns>
        private string AddLevel1Nodes(long customerId, long adGroupId, string rootResourceName,
            List<AdGroupCriterionOperation> operations, long percentCpcBidMicroAmount)
        {
            // Create listing dimension info for 5-star class hotels.
            ListingDimensionInfo fiveStarredListingDimensionInfo = new ListingDimensionInfo
            {
                HotelClass = new HotelClassInfo
                {
                    Value = 5
                }
            };

            // Create a listing group info for 5-star hotels as a UNIT node.
            ListingGroupInfo fiveStarredUnit = CreateListingGroupInfo(ListingGroupType.Unit,
                rootResourceName, fiveStarredListingDimensionInfo);

            // Create an ad group criterion for 5-star hotels.
            AdGroupCriterion fiveStarredAdGroupCriterion = CreateAdGroupCriterion(customerId,
                adGroupId, fiveStarredUnit, percentCpcBidMicroAmount);

            // Create an operation and add it to the list of operations.
            operations.Add(new AdGroupCriterionOperation
            {
                Create = fiveStarredAdGroupCriterion
            });

            // Decrement the temp ID for the next ad group criterion.
            nextTempId--;

            // You can also create more UNIT nodes for other hotel classes by copying the above code
            // in this method and modifying the value passed to HotelClassInfo().
            // For instance, passing 4 instead of 5 in the above code will instead create a UNIT
            // node of 4-star hotels.

            // Create hotel class info and dimension info for other hotel classes by *not*
            // specifying any attributes on those object.
            ListingDimensionInfo otherHotelsListingDimensionInfo = new ListingDimensionInfo
            {
                HotelClass = new HotelClassInfo()
            };

            // Create listing group info for other hotel classes as a SUBDIVISION node, which will
            // be used as a parent node for children nodes of the next level.
            ListingGroupInfo otherHotelsSubdivisionListingGroupInfo = CreateListingGroupInfo
                (ListingGroupType.Subdivision, rootResourceName, otherHotelsListingDimensionInfo);

            // Create an ad group criterion for other hotel classes.
            AdGroupCriterion otherHotelsAdGroupCriterion = CreateAdGroupCriterion(customerId,
                adGroupId, otherHotelsSubdivisionListingGroupInfo, percentCpcBidMicroAmount);

            // Create an operation and add it to the list of operations.
            operations.Add(new AdGroupCriterionOperation
            {
                Create = otherHotelsAdGroupCriterion
            });

            // Decrement the temp ID for the next ad group criterion.
            nextTempId--;

            return otherHotelsAdGroupCriterion.ResourceName;
        }

        /// <summary>
        /// Creates child nodes on level 2, partitioned by the country region.
        /// </summary>
        /// <param name="customerId">The Google Ads customer ID.</param>
        /// <param name="adGroupId">The ad group ID to which the hotel listing group will be
        /// added.</param>
        /// <param name="parentResourceName">The resource name of the parent criterion for the
        /// nodes to be added at this level.</param>
        /// <param name="operations">A list of AdGroupCriterionOperations.</param>
        /// <param name="percentCpcBidMicroAmount">The CPC bid micro amount to be set on created
        /// ad group criteria.</param>
        private void AddLevel2Nodes(long customerId, long adGroupId, string parentResourceName,
            List<AdGroupCriterionOperation> operations, long percentCpcBidMicroAmount)
        {
            // Create hotel dimension info for hotels in Japan. The criterion ID for Japan is 2392.
            // See https://developers.google.com/google-ads/api/reference/data/geotargets for
            // criteria ID of other countries.
            ListingDimensionInfo japanListingDimensionInfo = new ListingDimensionInfo
            {
                HotelCountryRegion = new HotelCountryRegionInfo
                {
                    CountryRegionCriterion = ResourceNames.GeoTargetConstant(2392)
                }
            };

            // Create listing group info for hotels in Japan as a UNIT node.
            ListingGroupInfo japanHotelsUnit = CreateListingGroupInfo(ListingGroupType.Unit,
                parentResourceName, japanListingDimensionInfo);

            // Create an ad group criterion for hotels in Japan.
            AdGroupCriterion japanHotelsAdGroupCriterion = CreateAdGroupCriterion(customerId,
                adGroupId, japanHotelsUnit, percentCpcBidMicroAmount);

            // Create an operation and add it to the list of operations.
            operations.Add(new AdGroupCriterionOperation
            {
                Create = japanHotelsAdGroupCriterion
            });

            // Decrement the temp ID for the next ad group criterion.
            nextTempId--;

            // Create hotel class info and dimension info for hotels in other regions.
            ListingDimensionInfo otherHotelRegionsListingDimensionInfo = new ListingDimensionInfo
            {
                HotelCountryRegion = new HotelCountryRegionInfo()
            };

            // Create listing group info for hotels in other regions as a UNIT node.
            // The "others" node is always required for every level of the tree.
            ListingGroupInfo otherHotelRegionsUnit = CreateListingGroupInfo(
                ListingGroupType.Unit, parentResourceName, otherHotelRegionsListingDimensionInfo);

            // Create an ad group criterion for other hotel country regions.
            AdGroupCriterion otherHotelRegionsAdGroupCriterion =
                CreateAdGroupCriterion(customerId, adGroupId, otherHotelRegionsUnit,
                    percentCpcBidMicroAmount);

            // Create an operation and add it to the list of operations.
            operations.Add(new AdGroupCriterionOperation
            {
                Create = otherHotelRegionsAdGroupCriterion
            });

            // Decrement the temp ID for the next ad group criterion.
            nextTempId--;
        }

        /// <summary>
        /// Creates the listing group info with the provided parameters.
        /// </summary>
        /// <param name="listingGroupType">The listing group type.</param>
        /// <param name="parentCriterionResourceName">Optional resource name of the parent criterion
        ///     ID to set for this listing group info.</param>
        /// <param name="caseValue">Optional dimension info for the listing group.</param>
        /// <returns>A populated ListingGroupInfo.</returns>
        private ListingGroupInfo CreateListingGroupInfo(ListingGroupType listingGroupType,
            string parentCriterionResourceName = null, ListingDimensionInfo caseValue = null)
        {
            ListingGroupInfo listingGroupInfo = new ListingGroupInfo
            {
                Type = listingGroupType
            };

            if (parentCriterionResourceName != null)
            {
                listingGroupInfo.ParentAdGroupCriterion = parentCriterionResourceName;
                listingGroupInfo.CaseValue = caseValue;
            }

            return listingGroupInfo;
        }

        /// <summary>
        /// Creates an ad group criterion from the provided listing group info.
        /// Bid amount will be set on the created ad group criterion when listing group info type
        /// is `UNIT`. Setting bid amount for `SUBDIVISION` types is not allowed.
        /// </summary>
        /// <param name="customerId">The Google Ads customer ID.</param>
        /// <param name="adGroupId">The ad group ID to which the criterion will belong.</param>
        /// <param name="listingGroupInfo">The listing group info to apply to the criterion.</param>
        /// <param name="percentCpcBidMicroAmount">The CPC bid micro amount to set for the
        /// ad group criterion.</param>
        /// <returns>A populated ad group criterion.</returns>
        private AdGroupCriterion CreateAdGroupCriterion(long customerId, long adGroupId,
            ListingGroupInfo listingGroupInfo, long percentCpcBidMicroAmount)
        {
            AdGroupCriterion adGroupCriterion = new AdGroupCriterion
            {
                Status = AdGroupCriterionStatus.Enabled,
                ListingGroup = listingGroupInfo,
                ResourceName = ResourceNames.AdGroupCriterion(customerId, adGroupId, nextTempId)
            };

            // Bids are only valid for UNIT nodes.
            if (listingGroupInfo.Type == ListingGroupType.Unit)
            {
                adGroupCriterion.PercentCpcBidMicros = percentCpcBidMicroAmount;
            }

            return adGroupCriterion;
        }
    }
}

      

PHP

<?php

/**
 * Copyright 2018 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\HotelAds;

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\Lib\V11\GoogleAdsClient;
use Google\Ads\GoogleAds\Lib\V11\GoogleAdsClientBuilder;
use Google\Ads\GoogleAds\Lib\V11\GoogleAdsException;
use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder;
use Google\Ads\GoogleAds\Util\V11\ResourceNames;
use Google\Ads\GoogleAds\V11\Common\HotelClassInfo;
use Google\Ads\GoogleAds\V11\Common\HotelCountryRegionInfo;
use Google\Ads\GoogleAds\V11\Common\ListingDimensionInfo;
use Google\Ads\GoogleAds\V11\Common\ListingGroupInfo;
use Google\Ads\GoogleAds\V11\Enums\AdGroupStatusEnum\AdGroupStatus;
use Google\Ads\GoogleAds\V11\Enums\ListingGroupTypeEnum\ListingGroupType;
use Google\Ads\GoogleAds\V11\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V11\Resources\AdGroupCriterion;
use Google\Ads\GoogleAds\V11\Services\AdGroupCriterionOperation;
use Google\ApiCore\ApiException;

/**
 * This example shows how to add a hotel listing group tree, which has two levels. The first level
 * is partitioned by the hotel class. The second level is partitioned by the country region.
 *
 * Each level is composed of two types of nodes: `UNIT` and `SUBDIVISION`.
 * `UNIT` nodes serve as a leaf node in a tree and can have bid amount set.
 * `SUBDIVISION` nodes serve as an internal node where a subtree will be built. The `SUBDIVISION`
 * node can't have bid amount set.
 * See https://developers.google.com/google-ads/api/docs/hotel-ads/overview for more information.
 *
 * Note: Only one listing group tree can be added. Attempting to add another listing group tree to
 * an ad group that already has one will fail.
 */
class AddHotelListingGroupTree
{
    private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE';
    private const AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE';

    // Specify the CPC bid micro amount to be set on a created ad group criterion.
    // For simplicity, each ad group criterion will use the below amount equally. In practice, you
    // probably want to use different values for each ad group criterion.
    private const PERCENT_CPC_BID_MICRO_AMOUNT = 1000000;

    /**
     * @var int $nextTempId
     *
     * The next temporary criterion ID to be used, which is a negative integer.
     *
     * When creating a tree, we need to specify the parent-child relationships
     * between nodes. However, until a criterion has been created on the server
     * we do not have a criterion ID with which to refer to it.
     *
     * Instead we can specify temporary IDs that are specific to a single mutate
     * request. Once a criterion is created, it is assigned an ID as normal and
     * the temporary ID will no longer refer to it.
     */
    private static $nextTempId = -1;

    public static function main()
    {
        // Either pass the required parameters for this example on the command line, or insert them
        // into the constants above.
        $options = (new ArgumentParser())->parseCommandArguments([
            ArgumentNames::CUSTOMER_ID => GetOpt::REQUIRED_ARGUMENT,
            ArgumentNames::AD_GROUP_ID => GetOpt::REQUIRED_ARGUMENT,
            ArgumentNames::PERCENT_CPC_BID_MICRO_AMOUNT => GetOpt::OPTIONAL_ARGUMENT
        ]);

        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct a Google Ads client configured from a properties file and the
        // OAuth2 credentials above.
        $googleAdsClient = (new GoogleAdsClientBuilder())->fromFile()
            ->withOAuth2Credential($oAuth2Credential)
            ->build();

        try {
            self::runExample(
                $googleAdsClient,
                $options[ArgumentNames::CUSTOMER_ID] ?: self::CUSTOMER_ID,
                $options[ArgumentNames::AD_GROUP_ID] ?: self::AD_GROUP_ID,
                $options[ArgumentNames::PERCENT_CPC_BID_MICRO_AMOUNT]
                    ?: self::PERCENT_CPC_BID_MICRO_AMOUNT
            );
        } 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 $adGroupId the ad group ID
     * @param int $percentCpcBidMicroAmount the percent CPC bid micro amount to set on created ad
     *     group criteria
     */
    public static function runExample(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        int $adGroupId,
        int $percentCpcBidMicroAmount
    ) {
        $operations = [];

        // Creates the root of the tree as a SUBDIVISION node.
        $rootResourceName =
            self::addRootNode($customerId, $adGroupId, $operations, $percentCpcBidMicroAmount);

        // Creates child nodes of level 1, partitioned by the hotel class info.
        $otherHotelResourceName = self::addLevel1Nodes(
            $customerId,
            $adGroupId,
            $rootResourceName,
            $operations,
            $percentCpcBidMicroAmount
        );

        // Creates child nodes of level 2, partitioned by the hotel country region info.
        self::addLevel2Nodes(
            $customerId,
            $adGroupId,
            $otherHotelResourceName,
            $operations,
            $percentCpcBidMicroAmount
        );

        $adGroupCriterionServiceClient = $googleAdsClient->getAdGroupCriterionServiceClient();
        $response = $adGroupCriterionServiceClient->mutateAdGroupCriteria($customerId, $operations);

        printf("Added %d listing group info entities.%s", count($response->getResults()), PHP_EOL);
        foreach ($response->getResults() as $adGroupCriterion) {
            print $adGroupCriterion->getResourceName() . PHP_EOL;
        }
    }

    /**
     * Creates the root node of the listing group tree and adds its create operation to the
     * operations list.
     *
     * @param int $customerId the customer ID
     * @param int $adGroupId the ad group ID
     * @param AdGroupCriterionOperation[] $operations the operations
     * @param int $percentCpcBidMicroAmount the CPC bid micro amount to set on created ad group
     *     criteria
     * @return string the root node's resource name
     */
    private static function addRootNode(
        int $customerId,
        int $adGroupId,
        array &$operations,
        int $percentCpcBidMicroAmount
    ) {
        // Creates the root of the tree as a SUBDIVISION node.
        $root = self::createListingGroupInfo(ListingGroupType::SUBDIVISION);
        $rootAdGroupCriterion =
            self::createAdGroupCriterion($customerId, $adGroupId, $root, $percentCpcBidMicroAmount);
        $operation = self::generateCreateOperation($rootAdGroupCriterion);
        $operations[] = $operation;

        self::$nextTempId--;
        return $rootAdGroupCriterion->getResourceName();
    }

    /**
     * Creates child nodes of level 1, partitioned by the hotel class info.
     *
     * @param int $customerId the customer ID
     * @param int $adGroupId the ad group ID
     * @param string $rootResourceName the resource name of the root node
     * @param AdGroupCriterionOperation[] $operations the operations list
     * @param int $percentCpcBidMicroAmount the CPC bid micro amount to set on created ad group
     *     criteria
     * @return string the "other hotel classes" node's resource name, which serves as a parent node
     *     for the next level
     */
    private static function addLevel1Nodes(
        int $customerId,
        int $adGroupId,
        string $rootResourceName,
        array &$operations,
        int $percentCpcBidMicroAmount
    ) {
        // Creates hotel class info and dimension info for 5-star hotels.
        $fiveStarredDimensionInfo = new ListingDimensionInfo([
            'hotel_class' => new HotelClassInfo(['value' => 5])
        ]);
        // Creates listing group info for 5-star hotels as a UNIT node.
        $fiveStarredUnit = self::createListingGroupInfo(
            ListingGroupType::UNIT,
            $rootResourceName,
            $fiveStarredDimensionInfo
        );
        // Creates an ad group criterion for 5-star hotels.
        $fiveStarredAdGroupCriterion = self::createAdGroupCriterion(
            $customerId,
            $adGroupId,
            $fiveStarredUnit,
            $percentCpcBidMicroAmount
        );
        // Decrements the temp ID for the next ad group criterion.
        self::$nextTempId--;
        $operation = self::generateCreateOperation($fiveStarredAdGroupCriterion);
        $operations[] = $operation;

        // You can also create more UNIT nodes for other hotel classes by copying the above code in
        // this method and modifying the value passed to HotelClassInfo() to the value you want.
        // For instance, passing 4 instead of 5 in the above code will create a UNIT node of 4-star
        // hotels instead.

        // Creates hotel class info and dimension info for other hotel classes by *not* specifying
        // any attributes on those object.
        $othersHotelsDimensionInfo = new ListingDimensionInfo([
            'hotel_class' => new HotelClassInfo()
        ]);
        // Creates listing group info for other hotel classes as a SUBDIVISION node, which will be
        // used as a parent node for children nodes of the next level.
        $otherHotelsSubDivision = self::createListingGroupInfo(
            ListingGroupType::SUBDIVISION,
            $rootResourceName,
            $othersHotelsDimensionInfo
        );
        // Creates an ad group criterion for other hotel classes.
        $otherHotelsAdGroupCriterion = self::createAdGroupCriterion(
            $customerId,
            $adGroupId,
            $otherHotelsSubDivision,
            $percentCpcBidMicroAmount
        );
        $operation = self::generateCreateOperation($otherHotelsAdGroupCriterion);
        $operations[] = $operation;

        self::$nextTempId--;
        return $otherHotelsAdGroupCriterion->getResourceName();
    }

    /**
     * Creates child nodes of level 2, partitioned by the country region.
     *
     * @param int $customerId the customer ID
     * @param int $adGroupId the ad group ID
     * @param string $parentResourceName the resource name of parent criterion for all nodes at this
     *     level
     * @param AdGroupCriterionOperation[] $operations the operations list
     * @param int $percentCpcBidMicroAmount the CPC bid micro amount to set on created ad group
     *     criteria
     */
    private static function addLevel2Nodes(
        int $customerId,
        int $adGroupId,
        string $parentResourceName,
        array &$operations,
        int $percentCpcBidMicroAmount
    ) {
        // The criterion ID for Japan is 2392.
        // See https://developers.google.com/adwords/api/docs/appendix/geotargeting for criteria ID
        // of other countries.
        $japanGeoTargetConstantId = 2392;
        $japanDimensionInfo = new ListingDimensionInfo([
            // Creates hotel country region info and dimension info for hotels in Japan.
            'hotel_country_region' => new HotelCountryRegionInfo([
                'country_region_criterion' =>
                    ResourceNames::forGeoTargetConstant($japanGeoTargetConstantId)
            ])
        ]);
        // Creates listing group info for hotels in Japan as a UNIT node.
        $japanHotelsUnit = self::createListingGroupInfo(
            ListingGroupType::UNIT,
            $parentResourceName,
            $japanDimensionInfo
        );
        // Creates an ad group criterion for hotels in Japan.
        $japanHotelsAdGroupCriterion = self::createAdGroupCriterion(
            $customerId,
            $adGroupId,
            $japanHotelsUnit,
            $percentCpcBidMicroAmount
        );
        // Decrements the temp ID for the next ad group criterion.
        self::$nextTempId--;
        $operation = self::generateCreateOperation($japanHotelsAdGroupCriterion);
        $operations[] = $operation;

        // Creates hotel class info and dimension info for hotels in other regions.
        $otherHotelRegionsDimensionInfo = new ListingDimensionInfo([
            'hotel_country_region' => new HotelCountryRegionInfo()
        ]);
        // Creates listing group info for hotels in other regions as a UNIT node.
        // The "others" node is always required for every level of the tree.
        $otherHotelRegionsUnit = self::createListingGroupInfo(
            ListingGroupType::UNIT,
            $parentResourceName,
            $otherHotelRegionsDimensionInfo
        );
        // Creates an ad group criterion for other hotel country regions.
        $otherHotelRegionsAdGroupCriterion = self::createAdGroupCriterion(
            $customerId,
            $adGroupId,
            $otherHotelRegionsUnit,
            $percentCpcBidMicroAmount
        );
        $operation = self::generateCreateOperation($otherHotelRegionsAdGroupCriterion);
        $operations[] = $operation;
    }

    /**
     * Creates the listing group info with the provided parameters.
     *
     * @param int $listingGroupType the listing group type
     * @param string|null $parentCriterionResourceName optional, the resource name of parent
     *     criterion ID of the listing group info
     * @param ListingDimensionInfo|null $caseValue optional, the dimension info for the listing
     *     group
     * @return ListingGroupInfo the created listing group info
     */
    private static function createListingGroupInfo(
        int $listingGroupType,
        string $parentCriterionResourceName = null,
        ListingDimensionInfo $caseValue = null
    ) {
        $listingGroupInfo = new ListingGroupInfo([
            'type' => $listingGroupType
        ]);
        if (!is_null($parentCriterionResourceName)) {
            $listingGroupInfo->setParentAdGroupCriterion($parentCriterionResourceName);
            $listingGroupInfo->setCaseValue($caseValue);
        }

        return $listingGroupInfo;
    }

    /**
     * Creates an ad group criterion from the provided listing group info.
     * Bid amount will be set on the created ad group criterion when listing group info type is
     * `UNIT`. Setting bid amount for `SUBDIVISION` types is not allowed.
     *
     * @param int $customerId the customer ID
     * @param int $adGroupId the ad group ID
     * @param ListingGroupInfo $listingGroupInfo the listing group info
     * @param int $percentCpcBidMicroAmount the CPC bid micro amount to set for the ad group
     *     criterion
     * @return AdGroupCriterion the created ad group criterion
     */
    private static function createAdGroupCriterion(
        int $customerId,
        int $adGroupId,
        ListingGroupInfo $listingGroupInfo,
        int $percentCpcBidMicroAmount
    ) {
        $adGroupCriterion = new AdGroupCriterion([
            'status' => AdGroupStatus::ENABLED,
            'listing_group' => $listingGroupInfo,
            'resource_name' =>
                ResourceNames::forAdGroupCriterion($customerId, $adGroupId, self::$nextTempId)
        ]);

        // Bids are valid only for UNIT nodes.
        if ($listingGroupInfo->getType() == ListingGroupType::UNIT) {
            $adGroupCriterion->setPercentCpcBidMicros($percentCpcBidMicroAmount);
        }

        return $adGroupCriterion;
    }

    /**
     * Creates an operation for creating the specified ad group criterion.
     *
     * @param AdGroupCriterion $adGroupCriterion the ad group criterion to create an operation for
     * @return AdGroupCriterionOperation the created ad group criterion operation
     */
    private static function generateCreateOperation(AdGroupCriterion $adGroupCriterion)
    {
        $operation = new AdGroupCriterionOperation();
        $operation->setCreate($adGroupCriterion);

        return $operation;
    }
}

AddHotelListingGroupTree::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.
"""Shows how to add a hotel listing group tree with two levels.

The first level is partitioned by the hotel class. The second level is
partitioned by the country region.

Each level is composed of two types of nodes: UNIT and SUBDIVISION.
UNIT nodes serve as a leaf node in a tree and can have bid amount set.
SUBDIVISION nodes serve as an internal node where a subtree will be built. The
SUBDIVISION node can't have bid amount set.
See https://developers.google.com/google-ads/api/docs/hotel-ads/create-listing-groups
for more information.

Note: Only one listing group tree can be added. Attempting to add another
listing group tree to an ad group that already has one will fail.
"""


import argparse
import sys

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

# The next temporary criterion ID to be used, which is a negative integer.
#
# When creating a tree, we need to specify the parent-child relationships
# between nodes. However, until a criterion has been created on the server we do
# not have a criterion ID with which to refer to it.
#
# Instead, we can specify temporary IDs that are specific to a single mutate
# request. Once a criterion is created, it is assigned an ID as normal and the
# temporary ID will no longer refer to it.
#
# See https://developers.google.com/google-ads/api/docs/mutating/best-practices
# for further details.
next_temp_id = -1


def main(client, customer_id, ad_group_id, percent_cpc_bid_micro_amount):
    """Shows how to add a hotel listing group tree with two levels.

    Args:
        client: An initialized GoogleAdsClient instance.
        customer_id: The client customer ID string.
        ad_group_id: The ad group ID for which to the hotel listing will be
            added.
        percent_cpc_bid_micro_amount: The CPC bid micro amount to be set on a
            created ad group criterion.
    """
    # Get the AdGroupCriterionService client.
    ad_group_criterion_service = client.get_service("AdGroupCriterionService")

    operations = []

    # Creates the root of the tree as a SUBDIVISION node.
    root_resource_name = _add_root_node(
        client,
        customer_id,
        ad_group_id,
        operations,
        percent_cpc_bid_micro_amount,
    )

    # Creates child nodes of level 1, partitioned by the hotel class info.
    other_hotel_resource_name = _add_level1_nodes(
        client,
        customer_id,
        ad_group_id,
        root_resource_name,
        operations,
        percent_cpc_bid_micro_amount,
    )

    # Creates child nodes of level 2, partitioned by the hotel country
    # region info.
    _add_level2_nodes(
        client,
        customer_id,
        ad_group_id,
        other_hotel_resource_name,
        operations,
        percent_cpc_bid_micro_amount,
    )

    # Adds the listing group and prints the resulting node resource names.
    mutate_ad_group_criteria_response = (
        ad_group_criterion_service.mutate_ad_group_criteria(
            customer_id=customer_id, operations=operations
        )
    )
    results = mutate_ad_group_criteria_response.results
    print(
        f"Added {len(results)} listing group info entities with resource "
        "names:"
    )
    for ad_group_criterion_result in mutate_ad_group_criteria_response.results:
        print(f"\t'{ad_group_criterion_result.resource_name}'")


def _add_root_node(
    client, customer_id, ad_group_id, operations, percent_cpc_bid_micro_amount
):
    """Creates the root node of the listing group tree.

    Also adds its create operation to the operations list.

    Args:
        client: The Google Ads API client.
        customer_id: The Google Ads customer ID.
        ad_group_id: The ad group ID to which the hotel listing group will be
            added.
        operations: A list of AdGroupCriterionOperations.
        percent_cpc_bid_micro_amount: The CPC bid micro amount to be set on
            created ad group criteria.

    Returns:
        The string resource name of the root of the tree.
    """
    global next_temp_id

    # Create the root of the tree as a SUBDIVISION node.
    root_listing_group_info = _create_listing_group_info(
        client,
        client.enums.ListingGroupTypeEnum.SUBDIVISION,
    )

    root_ad_group_criterion = _create_ad_group_criterion(
        client,
        customer_id,
        ad_group_id,
        root_listing_group_info,
        percent_cpc_bid_micro_amount,
    )

    # Create an operation and add it to the list of operations.
    root_ad_group_criterion_operation = client.get_type(
        "AdGroupCriterionOperation"
    )
    client.copy_from(
        root_ad_group_criterion_operation.create, root_ad_group_criterion
    )
    operations.append(root_ad_group_criterion_operation)

    # Decrement the temp ID for the next ad group criterion.
    next_temp_id -= 1

    return root_ad_group_criterion.resource_name


def _add_level1_nodes(
    client,
    customer_id,
    ad_group_id,
    root_resource_name,
    operations,
    percent_cpc_bid_micro_amount,
):
    """Creates child nodes on level 1, partitioned by the hotel class info.

    Args:
        client: The Google Ads API client.
        customer_id: The Google Ads customer ID.
        ad_group_id: The ad group ID to which the hotel listing group will be
            added.
        root_resource_name: The string resource name of the listing group's root
            node.
        operations: A list of AdGroupCriterionOperations.
        percent_cpc_bid_micro_amount: The CPC bid micro amount to be set on
            created ad group criteria.

    Returns:
        The string resource name of the "other hotel classes" node, which serves
        as the parent node for the next level of the listing tree.
    """
    global next_temp_id

    # Create listing dimension info for 5-star class hotels.
    five_starred_listing_dimension_info = client.get_type(
        "ListingDimensionInfo"
    )
    five_starred_listing_dimension_info.hotel_class.value = 5

    # Create a listing group info for 5-star hotels as a UNIT node.
    five_starred_unit = _create_listing_group_info(
        client,
        client.enums.ListingGroupTypeEnum.UNIT,
        root_resource_name,
        five_starred_listing_dimension_info,
    )

    # Create an ad group criterion for 5-star hotels.
    five_starred_ad_group_criterion = _create_ad_group_criterion(
        client,
        customer_id,
        ad_group_id,
        five_starred_unit,
        percent_cpc_bid_micro_amount,
    )

    # Create an operation and add it to the list of operations.
    five_starred_ad_group_criterion_operation = client.get_type(
        "AdGroupCriterionOperation"
    )
    client.copy_from(
        five_starred_ad_group_criterion_operation.create,
        five_starred_ad_group_criterion,
    )
    operations.append(five_starred_ad_group_criterion_operation)

    # Decrement the temp ID for the next ad group criterion.
    next_temp_id -= 1

    # You can also create more UNIT nodes for other hotel classes by copying the
    # above code in this method and modifying the hotel class value.
    # For instance, passing 4 instead of 5 in the above code will instead create
    # a UNIT node of 4-star hotels.

    # Create hotel class info and dimension info without any specifying
    # attributes. This node will then represent hotel classes other than those
    # already covered by UNIT nodes at this level.
    other_hotels_listing_dimension_info = client.get_type(
        "ListingDimensionInfo"
    )
    # Set "hotel_class" as the oneof field on the ListingDimensionInfo object
    # without specifying the optional hotel_class field.
    client.copy_from(
        other_hotels_listing_dimension_info.hotel_class,
        client.get_type("HotelClassInfo"),
    )

    # Create listing group info for other hotel classes as a SUBDIVISION node,
    # which will be used as a parent node for children nodes of the next level.
    other_hotels_subdivision_listing_group_info = _create_listing_group_info(
        client,
        client.enums.ListingGroupTypeEnum.SUBDIVISION,
        root_resource_name,
        other_hotels_listing_dimension_info,
    )

    # Create an ad group criterion for other hotel classes.
    other_hotels_ad_group_criterion = _create_ad_group_criterion(
        client,
        customer_id,
        ad_group_id,
        other_hotels_subdivision_listing_group_info,
        percent_cpc_bid_micro_amount,
    )

    # Create an operation and add it to the list of operations.
    other_hotels_ad_group_criterion_operation = client.get_type(
        "AdGroupCriterionOperation"
    )
    client.copy_from(
        other_hotels_ad_group_criterion_operation.create,
        other_hotels_ad_group_criterion,
    )
    operations.append(other_hotels_ad_group_criterion_operation)

    # Decrement the temp ID for the next ad group criterion.
    next_temp_id -= 1

    return other_hotels_ad_group_criterion.resource_name


def _add_level2_nodes(
    client,
    customer_id,
    ad_group_id,
    parent_resource_name,
    operations,
    percent_cpc_bid_micro_amount,
):
    """Creates child nodes on level 2, partitioned by the country region.

    Args:
        client: The Google Ads API client.
        customer_id: The Google Ads customer ID.
        ad_group_id: The ad group ID to which the hotel listing group will be
            added.
        parent_resource_name: The string resource name of the parent criterion
            for the nodes to be added at this level.
        operations: A list of AdGroupCriterionOperations.
        percent_cpc_bid_micro_amount: The CPC bid micro amount to be set on
            created ad group criteria.
    Returns:
        The string resource name of the "other hotel classes" node, which serves
        as the parent node for the next level of the listing tree.
    """
    global next_temp_id

    # Create hotel dimension info for hotels in Japan. The criterion ID for
    # Japan is 2392. See:
    # https://developers.google.com/google-ads/api/reference/data/geotargets for
    # criteria ID of other countries.
    japan_listing_dimension_info = client.get_type("ListingDimensionInfo")
    japan_listing_dimension_info.hotel_country_region.country_region_criterion = client.get_service(
        "GeoTargetConstantService"
    ).geo_target_constant_path(
        2392
    )

    # Create listing group info for hotels in Japan as a UNIT node.
    japan_hotels_unit = _create_listing_group_info(
        client,
        client.enums.ListingGroupTypeEnum.UNIT,
        parent_resource_name,
        japan_listing_dimension_info,
    )

    # Create an ad group criterion for hotels in Japan.
    japan_hotels_ad_group_criterion = _create_ad_group_criterion(
        client,
        customer_id,
        ad_group_id,
        japan_hotels_unit,
        percent_cpc_bid_micro_amount,
    )

    # Create an operation and add it to the list of operations.
    japan_hotels_ad_group_criterion_operation = client.get_type(
        "AdGroupCriterionOperation"
    )
    client.copy_from(
        japan_hotels_ad_group_criterion_operation.create,
        japan_hotels_ad_group_criterion,
    )
    operations.append(japan_hotels_ad_group_criterion_operation)

    # Decrement the temp ID for the next ad group criterion.
    next_temp_id -= 1

    # Create hotel class info and dimension info for hotels in other regions.
    other_hotel_regions_listing_dimension_info = client.get_type(
        "ListingDimensionInfo"
    )
    # Set "hotel_country_region" as the oneof field on the ListingDimensionInfo
    # object without specifying the optional
    # hotel_country_region.country_region_criterion field.
    client.copy_from(
        other_hotel_regions_listing_dimension_info.hotel_country_region,
        client.get_type("HotelCountryRegionInfo"),
    )

    # Create listing group info for hotels in other regions as a UNIT node.
    # The "others" node is always required for every level of the tree.
    other_hotel_regions_unit = _create_listing_group_info(
        client,
        client.enums.ListingGroupTypeEnum.UNIT,
        parent_resource_name,
        other_hotel_regions_listing_dimension_info,
    )

    # Create an ad group criterion for other hotel country regions.
    other_hotel_regions_ad_group_criterion = _create_ad_group_criterion(
        client,
        customer_id,
        ad_group_id,
        other_hotel_regions_unit,
        percent_cpc_bid_micro_amount,
    )

    # Create an operation and add it to the list of operations.
    other_hotel_regions_ad_group_criterion_operation = client.get_type(
        "AdGroupCriterionOperation"
    )
    client.copy_from(
        other_hotel_regions_ad_group_criterion_operation.create,
        other_hotel_regions_ad_group_criterion,
    )
    operations.append(other_hotel_regions_ad_group_criterion_operation)

    # Decrement the temp ID for the next ad group criterion.
    next_temp_id -= 1


def _create_listing_group_info(
    client,
    listing_group_type,
    parent_criterion_resource_name=None,
    case_value=None,
):
    """Creates the listing group info with the provided parameters.

    Args:
        client: The Google Ads API client.
        listing_group_type: The listing group type.
        parent_criterion_resource_name: Optional resource name of the parent
            criterion ID to set for this listing group info.
        case_value: Optional dimension info for the listing group.
    Returns:
        A populated ListingGroupInfo object.
    """
    listing_group_info = client.get_type("ListingGroupInfo")
    listing_group_info.type_ = listing_group_type

    if parent_criterion_resource_name is not None and case_value is not None:
        listing_group_info.parent_ad_group_criterion = (
            parent_criterion_resource_name
        )
        client.copy_from(listing_group_info.case_value, case_value)

    return listing_group_info


def _create_ad_group_criterion(
    client,
    customer_id,
    ad_group_id,
    listing_group_info,
    percent_cpc_bid_micro_amount,
):
    """Creates an ad group criterion from the provided listing group info.

    Bid amount will be set on the created ad group criterion when listing group
    info type is UNIT. Setting bid amount for SUBDIVISION types is not
    allowed.

    Args:
        client: The Google Ads API client.
        customer_id: The Google Ads customer ID.
        ad_group_id: The ad group ID to which the hotel listing group will be
            added.
        listing_group_info: The listing group info to apply to the criterion.
        percent_cpc_bid_micro_amount: The CPC bid micro amount to be set on
            created ad group criteria.
    Returns:
        A populated AdGroupCriterion object.
    """
    ad_group_criterion = client.get_type("AdGroupCriterion")
    ad_group_criterion.status = client.enums.AdGroupCriterionStatusEnum.ENABLED
    client.copy_from(ad_group_criterion.listing_group, listing_group_info)
    ad_group_criterion.resource_name = client.get_service(
        "AdGroupCriterionService"
    ).ad_group_criterion_path(customer_id, ad_group_id, next_temp_id)

    # Bids are only valid for UNIT nodes.
    if listing_group_info.type_ == client.enums.ListingGroupTypeEnum.UNIT:
        ad_group_criterion.percent_cpc_bid_micros = percent_cpc_bid_micro_amount

    return ad_group_criterion


if __name__ == "__main__":
    # GoogleAdsClient will read the google-ads.yaml configuration file in the
    # home directory if none is specified.
    googleads_client = GoogleAdsClient.load_from_storage(version="v10")

    parser = argparse.ArgumentParser(
        description="Shows how to add a hotel listing group tree with two "
        "levels."
    )
    # The following argument(s) should be provided to run the example.
    parser.add_argument(
        "-c",
        "--customer_id",
        type=str,
        required=True,
        help="The Google Ads customer ID.",
    )
    parser.add_argument(
        "-a",
        "--ad_group_id",
        type=int,
        required=True,
        help="The ad group ID to which the hotel listing will be added.",
    )
    parser.add_argument(
        "-p",
        "--percent_cpc_bid_micro_amount",
        type=int,
        required=True,
        help="Specify the CPC bid micro amount to be set on a created ad group "
        "criterion. For simplicity, each ad group criterion will use the below "
        "amount equally. In practice, you probably want to use different "
        "values for each ad group criterion.",
    )
    args = parser.parse_args()

    try:
        main(
            googleads_client,
            args.customer_id,
            args.ad_group_id,
            args.percent_cpc_bid_micro_amount,
        )
    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.
#
# This example shows how to add a hotel listing group tree, which has two
# levels. The first level is partitioned by the hotel class. The second level
# is partitioned by the country region.
#
# Each level is composed of two types of nodes: `UNIT` and `SUBDIVISION`.
# `UNIT` nodes serve as a leaf node in a tree and can have bid amount set.
# `SUBDIVISION` nodes serve as an internal node where a subtree will be built.
# The `SUBDIVISION` node can't have bid amount set.
# See https://developers.google.com/google-ads/api/docs/hotel-ads/overview for
# more information.
#
# Note: Only one listing group tree can be added. Attempting to add another
# listing group tree to an ad group that already has one will fail.

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

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

  operations = []

  # Creates the root of the tree as a SUBDIVISION node.
  root_resource_name = add_root_node(
    client,
    customer_id,
    ad_group_id,
    operations,
    percent_cpc_bid_micro_amount,
  )

  # Creates child nodes of level 1, partitioned by the hotel class info.
  other_hotel_resource_name = add_level1_nodes(
    client,
    customer_id,
    ad_group_id,
    root_resource_name,
    operations,
    percent_cpc_bid_micro_amount,
  )

  # Creates child nodes of level 2, partitioned by the hotel country
  # region info.
  add_level2_nodes(
    client,
    customer_id,
    ad_group_id,
    other_hotel_resource_name,
    operations,
    percent_cpc_bid_micro_amount,
  )

  response = client.service.ad_group_criterion.mutate_ad_group_criteria(
    customer_id: customer_id,
    operations: operations,
  )

  puts "Added #{response.results.size} listing group info entities."
  response.results.each do |ad_group_criterion|
    puts "#{ad_group_criterion.resource_name}"
  end
end

# Creates the root node of the listing group tree and adds its create
# operation to the operations list.
def add_root_node(
  client,
  customer_id,
  ad_group_id,
  operations,
  percent_cpc_bid_micro_amount)
  # Creates the root of the tree as a SUBDIVISION node.
  root = create_listing_group_info(client, :SUBDIVISION)
  root_ad_group_criterion = create_ad_group_criterion(
    client,
    customer_id,
    ad_group_id,
    root,
    percent_cpc_bid_micro_amount,
  )
  operations << generate_create_operation(client, root_ad_group_criterion)
  root_ad_group_criterion.resource_name
end

# Creates child nodes of level 1, partitioned by the hotel class info.
def add_level1_nodes(
  client,
  customer_id,
  ad_group_id,
  root_resource_name,
  operations,
  percent_cpc_bid_micro_amount)
  # Creates hotel class info and dimension info for 5-star hotels.
  five_starred_dimension_info = client.resource.listing_dimension_info do |d|
    d.hotel_class = client.resource.hotel_class_info do |c|
      c.value = 5
    end
  end

  # Creates listing group info for 5-star hotels as a UNIT node.
  five_starred_unit = create_listing_group_info(
    client,
    :UNIT,
    root_resource_name,
    five_starred_dimension_info,
  )

  # Creates an ad group criterion for 5-star hotels.
  five_starred_ad_group_criterion = create_ad_group_criterion(
    client,
    customer_id,
    ad_group_id,
    five_starred_unit,
    percent_cpc_bid_micro_amount,
  )

  operations << generate_create_operation(
    client,
    five_starred_ad_group_criterion,
  )

  # You can also create more UNIT nodes for other hotel classes by copying the
  # above code in this method and modifying the value passed to HotelClassInfo()
  # to the value you want.
  # For instance, passing 4 instead of 5 in the above code will create a UNIT
  # node of 4-star hotels instead.

  # Creates hotel class info and dimension info for other hotel classes
  # by *not* specifying any attributes on those object.
  other_hotels_dimention_info = client.resource.listing_dimension_info do |d|
    d.hotel_class = client.resource.hotel_class_info
  end

  # Creates listing group info for other hotel classes as a SUBDIVISION node,
  # which will be used as a parent node for children nodes of the next level.
  other_hotels_subdivision = create_listing_group_info(
    client,
    :SUBDIVISION,
    root_resource_name,
    other_hotels_dimention_info,
  )

  # Creates an ad group criterion for other hotel classes.
  other_hotels_ad_group_criterion = create_ad_group_criterion(
    client,
    customer_id,
    ad_group_id,
    other_hotels_subdivision,
    percent_cpc_bid_micro_amount,
  )

  operations << generate_create_operation(
    client,
    other_hotels_ad_group_criterion,
  )

  other_hotels_ad_group_criterion.resource_name
end

# Creates child nodes of level 2, partitioned by the country region.
def add_level2_nodes(
  client,
  customer_id,
  ad_group_id,
  parent_resource_name,
  operations,
  percent_cpc_bid_micro_amount)
  # The criterion ID for Japan is 2392.
  # See https://developers.google.com/adwords/api/docs/appendix/geotargeting
  # for criteria ID of other countries.
  japan_geo_target_constant_id = 2392
  japan_dimension_info = client.resource.listing_dimension_info do |d|
    # Creates hotel country region info and dimension info for hotels in Japan.
    d.hotel_country_region = client.resource.hotel_country_region_info do |c|
      c.country_region_criterion = client.path.geo_target_constant(
        japan_geo_target_constant_id)
    end
  end

  # Creates listing group info for hotels in Japan as a UNIT node.
  japan_hotels_unit = create_listing_group_info(
    client,
    :UNIT,
    parent_resource_name,
    japan_dimension_info,
  )

  # Creates an ad group criterion for hotels in Japan.
  japan_hotels_ad_group_criterion = create_ad_group_criterion(
    client,
    customer_id,
    ad_group_id,
    japan_hotels_unit,
    percent_cpc_bid_micro_amount,
  )

  operations << generate_create_operation(
    client,
    japan_hotels_ad_group_criterion,
  )

  # Creates hotel class info and dimension info for hotels in other regions.
  other_hotel_regions_dimension_info = client.resource.listing_dimension_info do |d|
    d.hotel_country_region = client.resource.hotel_country_region_info
  end

  # Creates listing group info for hotels in other regions as a UNIT node.
  # The "others" node is always required for every level of the tree.
  other_hotel_regions_unit = create_listing_group_info(
    client,
    :UNIT,
    parent_resource_name,
    other_hotel_regions_dimension_info,
  )

  # Creates an ad group criterion for other hotel country regions.
  other_hotel_regions_ad_group_criterion = create_ad_group_criterion(
    client,
    customer_id,
    ad_group_id,
    other_hotel_regions_unit,
    percent_cpc_bid_micro_amount,
  )

  operations << generate_create_operation(
    client,
    other_hotel_regions_ad_group_criterion,
  )
end

# Creates the listing group info with the provided parameters.
def create_listing_group_info(
  client,
  listing_group_type,
  parent_criterion_resource_name = nil,
  case_value = nil)
  client.resource.listing_group_info do |g|
    g.type = listing_group_type
    unless parent_criterion_resource_name.nil?
      g.parent_ad_group_criterion = parent_criterion_resource_name
      g.case_value = case_value
    end
  end
end

# Creates an ad group criterion from the provided listing group info.
# Bid amount will be set on the created ad group criterion when listing group
# info type is `UNIT`. Setting bid amount for `SUBDIVISION` types is
# not allowed.
def create_ad_group_criterion(
  client,
  customer_id,
  ad_group_id,
  listing_group_info,
  percent_cpc_bid_micro_amount)
  client.resource.ad_group_criterion do |agc|
    agc.status = :ENABLED
    agc.listing_group = listing_group_info
    agc.resource_name = client.path.ad_group_criterion(
      customer_id, ad_group_id, next_temp_id)
    # Bids are valid only for UNIT nodes.
    if listing_group_info.type == :UNIT
      agc.percent_cpc_bid_micros = percent_cpc_bid_micro_amount
    end
  end
end

# Creates an operation for creating the specified ad group criterion.
def generate_create_operation(client, ad_group_criterion)
  client.operation.create_resource.ad_group_criterion(ad_group_criterion)
end

# Specify a decreasing negative number for temporary ad group criteria IDs. The
# ad group criteria will get real IDs when created on the server.
# Returns -1, -2, -3, etc. on subsequent calls.
def next_temp_id
  @id ||= 0
  @id -= 1
end

if __FILE__ == $0
  options = {}
  # The following parameter(s) should be provided to run the example. You can
  # either specify these by changing the INSERT_XXX_ID_HERE values below, or on
  # the command line.
  #
  # Parameters passed on the command line will override any parameters set in
  # code.
  #
  # Running the example with -h will print the command line usage.
  options[:customer_id] = 'INSERT_CUSTOMER_ID_HERE'
  options[:ad_group_id] = 'INSERT_AD_GROUP_ID_HERE'

  # Specify the CPC bid micro amount to be set on a created ad group criterion.
  # For simplicity, each ad group criterion will use the below amount equally.
  # In practice, you probably want to use different values for each ad group
  # criterion.
  options[:percent_cpc_bid_micro_amount] = 1_000_000

  OptionParser.new do |opts|
    opts.banner = sprintf('Usage: %s [options]', File.basename(__FILE__))
    opts.separator ''
    opts.separator 'Options:'
    opts.on('-C', '--customer-id CUSTOMER-ID', String, 'Customer ID') do |v|
      options[:customer_id] = v
    end

    opts.on('-A', '--ad-group-id AD-GROUP-ID', Integer,
        'Ad Group ID') do |v|
      options[:ad_group_id] = v
    end

    opts.on('-P', '--percent-cpc-bid-micro-amount PERCENT-CPC-BID-MICRO-AMOUNT',
        Integer, 'Percent CPC Bid Micro Amount') do |v|
      options[:percent_cpc_bid_micro_amount] = v
    end

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

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

  begin
    add_hotel_listing_group_tree(
      options.fetch(:customer_id).tr("-", ""),
      options.fetch(:ad_group_id),
      options[:percent_cpc_bid_micro_amount],
    )
  rescue Google::Ads::GoogleAds::Errors::GoogleAdsError => e
    e.failure.errors.each do |error|
      STDERR.printf("Error with message: %s\n", error.message)
      if error.location
        error.location.field_path_elements.each do |field_path_element|
          STDERR.printf("\tOn field: %s\n", field_path_element.field_name)
        end
      end
      error.error_code.to_h.each do |k, v|
        next if v == :UNSPECIFIED
        STDERR.printf("\tType: %s\n\tCode: %s\n", k, v)
      end
    end
    raise
  end
end

      

Perl

#!/usr/bin/perl -w
#
# Copyright 2019, Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This example shows how to add a hotel listing group tree, which has two
# levels. The first level is partitioned by the hotel class. The second
# level is partitioned by the country region.
#
# Each level is composed of two types of nodes: `UNIT` and `SUBDIVISION`.
# `UNIT` nodes serve as a leaf node in a tree and can have bid amount set.
# `SUBDIVISION` nodes serve as an internal node where a subtree will be
# built. The `SUBDIVISION` node can't have bid amount set.
# See https://developers.google.com/google-ads/api/docs/hotel-ads/overview
# for more information.
#
# Note: Only one listing group tree can be added. Attempting to add another
# listing group tree to an ad group that already has one will fail.

use strict;
use warnings;
use utf8;

use FindBin qw($Bin);
use lib "$Bin/../../lib";
use Google::Ads::GoogleAds::Client;
use Google::Ads::GoogleAds::Utils::GoogleAdsHelper;
use Google::Ads::GoogleAds::V11::Resources::AdGroupCriterion;
use Google::Ads::GoogleAds::V11::Common::ListingGroupInfo;
use Google::Ads::GoogleAds::V11::Common::ListingDimensionInfo;
use Google::Ads::GoogleAds::V11::Common::HotelClassInfo;
use Google::Ads::GoogleAds::V11::Common::HotelCountryRegionInfo;
use Google::Ads::GoogleAds::V11::Enums::ListingGroupTypeEnum
  qw(SUBDIVISION UNIT);
use Google::Ads::GoogleAds::V11::Enums::AdGroupCriterionStatusEnum qw(ENABLED);
use
  Google::Ads::GoogleAds::V11::Services::AdGroupCriterionService::AdGroupCriterionOperation;
use Google::Ads::GoogleAds::V11::Utils::ResourceNames;

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

# The following parameter(s) should be provided to run the example. You can
# either specify these by changing the INSERT_XXX_ID_HERE values below, or on
# the command line.
#
# Parameters passed on the command line will override any parameters set in
# code.
#
# Running the example with -h will print the command line usage.
my $customer_id = "INSERT_CUSTOMER_ID_HERE";
my $ad_group_id = "INSERT_AD_GROUP_ID_HERE";
# Specify the Percent CPC bid micro amount to be set on a created ad group
# criterion. For simplicity, each ad group criterion will use the below amount
# equally. In practice, you probably want to use different values for each ad
# group criterion.
my $percent_cpc_bid_micro_amount = 1000000;

sub add_hotel_listing_group_tree {
  my ($api_client, $customer_id, $ad_group_id, $percent_cpc_bid_micro_amount) =
    @_;

  # Create a list of ad group criteria operations to add.
  my $operations = [];

  # Create the root of the tree as a SUBDIVISION node.
  my $root_resource_name =
    add_root_node($customer_id, $ad_group_id, $operations,
    $percent_cpc_bid_micro_amount);

  # Create child nodes of level 1, partitioned by the hotel class info.
  my $other_hotel_resource_name =
    add_level_1_nodes($customer_id, $ad_group_id, $root_resource_name,
    $operations, $percent_cpc_bid_micro_amount);

  # Create child nodes of level 2, partitioned by the hotel country region info.
  add_level_2_nodes($customer_id, $ad_group_id, $other_hotel_resource_name,
    $operations, $percent_cpc_bid_micro_amount);

  my $ad_group_criteria_response =
    $api_client->AdGroupCriterionService()->mutate({
      customerId => $customer_id,
      operations => $operations
    });

  my $ad_group_criterion_results = $ad_group_criteria_response->{results};
  printf "Added %d listing group info entities:\n",
    scalar @$ad_group_criterion_results;

  foreach my $ad_group_criterion_result (@$ad_group_criterion_results) {
    printf "\t%s\n", $ad_group_criterion_result->{resourceName};
  }

  return 1;
}

# Creates the root node of the listing group tree and adds its create operation
# to the operations list.
sub add_root_node {
  my ($customer_id, $ad_group_id, $operations, $percent_cpc_bid_micro_amount) =
    @_;

  # Create the root of the tree as a SUBDIVISION node.
  my $root = create_listing_group_info(SUBDIVISION);
  my $root_ad_group_criterion =
    create_ad_group_criterion($customer_id, $ad_group_id, $root,
    $percent_cpc_bid_micro_amount);
  my $operation = generate_create_operation($root_ad_group_criterion);
  push @$operations, $operation;

  return $root_ad_group_criterion->{resourceName};
}

# Creates child nodes of level 1, partitioned by the hotel class info.
sub add_level_1_nodes {
  my ($customer_id, $ad_group_id, $root_resource_name, $operations,
    $percent_cpc_bid_micro_amount)
    = @_;

  # Create hotel class info and dimension info for 5-star hotels.
  my $five_starred_dimension_info =
    Google::Ads::GoogleAds::V11::Common::ListingDimensionInfo->new({
      hotelClass => Google::Ads::GoogleAds::V11::Common::HotelClassInfo->new({
          value => 5
        })});

  # Create listing group info for 5-star hotels as a UNIT node.
  my $five_starred_unit = create_listing_group_info(UNIT, $root_resource_name,
    $five_starred_dimension_info);

  # Create an ad group criterion for 5-star hotels.
  my $five_starred_ad_group_criterion =
    create_ad_group_criterion($customer_id, $ad_group_id, $five_starred_unit,
    $percent_cpc_bid_micro_amount);

  my $operation = generate_create_operation($five_starred_ad_group_criterion);
  push @$operations, $operation;

  # You can also create more UNIT nodes for other hotel classes by copying the
  # above code in this method and modifying the value passed to HotelClassInfo
  # to the value you want. For instance, passing 4 instead of 5 in the above code
  #  will create a UNIT node of 4-star hotels instead.

  # Create hotel class info and dimension info for other hotel classes by *not*
  # specifying any attributes on those object.
  my $others_hotels_dimension_info =
    Google::Ads::GoogleAds::V11::Common::ListingDimensionInfo->new({
      hotelClass => Google::Ads::GoogleAds::V11::Common::HotelClassInfo->new()}
    );

  # Create listing group info for other hotel classes as a SUBDIVISION node, which
  # will be used as a parent node for children nodes of the next level.
  my $other_hotels_subdivision =
    create_listing_group_info(SUBDIVISION, $root_resource_name,
    $others_hotels_dimension_info);

  # Create an ad group criterion for other hotel classes.
  my $other_hotels_ad_group_criterion =
    create_ad_group_criterion($customer_id, $ad_group_id,
    $other_hotels_subdivision, $percent_cpc_bid_micro_amount);

  $operation = generate_create_operation($other_hotels_ad_group_criterion);
  push @$operations, $operation;

  return $other_hotels_ad_group_criterion->{resourceName};
}

# Creates child nodes of level 2, partitioned by the country region.
sub add_level_2_nodes {
  my ($customer_id, $ad_group_id, $parent_resource_name, $operations,
    $percent_cpc_bid_micro_amount)
    = @_;

  # The criterion ID for Japan is 2392.
  # See https://developers.google.com/google-ads/api/reference/data/geotargets
  # for criteria ID of other countries.
  my $japan_geo_target_constant_id = 2392;
  my $japan_dimension_info =
    Google::Ads::GoogleAds::V11::Common::ListingDimensionInfo->new({
      # Create hotel country region info and dimension info for hotels in Japan.
      hotelCountryRegion =>
        Google::Ads::GoogleAds::V11::Common::HotelCountryRegionInfo->new({
          countryRegionCriterion =>
            Google::Ads::GoogleAds::V11::Utils::ResourceNames::geo_target_constant(
            $japan_geo_target_constant_id)})});

  # Create listing group info for hotels in Japan as a UNIT node.
  my $japan_hotels_unit = create_listing_group_info(UNIT, $parent_resource_name,
    $japan_dimension_info);

  # Create an ad group criterion for hotels in Japan.
  my $japan_hotels_ad_group_criterion =
    create_ad_group_criterion($customer_id, $ad_group_id, $japan_hotels_unit,
    $percent_cpc_bid_micro_amount);

  my $operation = generate_create_operation($japan_hotels_ad_group_criterion);
  push @$operations, $operation;

  # Create hotel class info and dimension info for hotels in other regions.
  my $other_hotel_regions_dimension_info =
    Google::Ads::GoogleAds::V11::Common::ListingDimensionInfo->new({
      hotelCountryRegion =>
        Google::Ads::GoogleAds::V11::Common::HotelCountryRegionInfo->new()});

  # Create listing group info for hotels in other regions as a UNIT node.
  # The "others" node is always required for every level of the tree.
  my $other_hotel_regions_unit =
    create_listing_group_info(UNIT, $parent_resource_name,
    $other_hotel_regions_dimension_info);

  # Create an ad group criterion for other hotel country regions.
  my $other_hotel_regions_ad_group_criterion =
    create_ad_group_criterion($customer_id, $ad_group_id,
    $other_hotel_regions_unit, $percent_cpc_bid_micro_amount);

  $operation =
    generate_create_operation($other_hotel_regions_ad_group_criterion);
  push @$operations, $operation;
}

# Creates the listing group info with the provided parameters.
sub create_listing_group_info {
  my ($listing_group_type, $parent_criterion_resource_name, $case_value) = @_;

  my $listing_group_info =
    Google::Ads::GoogleAds::V11::Common::ListingGroupInfo->new({
      type => $listing_group_type
    });

  if ($parent_criterion_resource_name) {
    $listing_group_info->{parentAdGroupCriterion} =
      $parent_criterion_resource_name;
    $listing_group_info->{caseValue} = $case_value;
  }

  return $listing_group_info;
}

# Creates an ad group criterion from the provided listing group info.
# Bid amount will be set on the created ad group criterion when listing group info type
# is `UNIT`. Setting bid amount for `SUBDIVISION` types is not allowed.
sub create_ad_group_criterion {
  my ($customer_id, $ad_group_id, $listing_group_info,
    $percent_cpc_bid_micro_amount)
    = @_;

  my $ad_group_criterion =
    Google::Ads::GoogleAds::V11::Resources::AdGroupCriterion->new({
      status       => ENABLED,
      listingGroup => $listing_group_info,
      resourceName =>
        Google::Ads::GoogleAds::V11::Utils::ResourceNames::ad_group_criterion(
        $customer_id, $ad_group_id, next_id())});

  # Bids are valid only for UNIT nodes.
  if ($listing_group_info->{type} eq UNIT) {
    $ad_group_criterion->{percentCpcBidMicros} = $percent_cpc_bid_micro_amount;
  }

  return $ad_group_criterion;
}

# Creates an operation for creating the specified ad group criterion.
sub generate_create_operation {
  my $ad_group_criterion = shift;
  return
    Google::Ads::GoogleAds::V11::Services::AdGroupCriterionService::AdGroupCriterionOperation
    ->new({
      create => $ad_group_criterion
    });
}

# Specifies a decreasing negative number for temporary ad group criteria IDs.
# The ad group criteria will get real IDs when created on the server.
# Returns -1, -2, -3, etc. on subsequent calls.
sub next_id {
  our $id ||= 0;
  $id -= 1;
}

# Don't run the example if the file is being included.
if (abs_path($0) ne abs_path(__FILE__)) {
  return 1;
}

# Get Google Ads Client, credentials will be read from ~/googleads.properties.
my $api_client = Google::Ads::GoogleAds::Client->new();

# By default examples are set to die on any server returned fault.
$api_client->set_die_on_faults(1);

# Parameters passed on the command line will override any parameters set in code.
GetOptions(
  "customer_id=s"                  => \$customer_id,
  "ad_group_id=i"                  => \$ad_group_id,
  "percent_cpc_bid_micro_amount=i" => \$percent_cpc_bid_micro_amount
);

# Print the help message if the parameters are not initialized in the code nor
# in the command line.
pod2usage(2)
  if
  not check_params($customer_id, $ad_group_id, $percent_cpc_bid_micro_amount);

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

=pod

=head1 NAME

add_hotel_listing_group_tree

=head1 DESCRIPTION

This example shows how to add a hotel listing group tree, which has two levels.
The first level is partitioned by the hotel class. The second level is partitioned
by the country region.

Each level is composed of two types of nodes: `UNIT` and `SUBDIVISION`.
`UNIT` nodes serve as a leaf node in a tree and can have bid amount set.
`SUBDIVISION` nodes serve as an internal node where a subtree will be built. The
`SUBDIVISION` node can't have bid amount set.
See https://developers.google.com/google-ads/api/docs/hotel-ads/overview for more information.

Note: Only one listing group tree can be added. Attempting to add another listing
group tree to an ad group that already has one will fail.

=head1 SYNOPSIS

add_hotel_listing_group_tree.pl [options]

    -help                           Show the help message.
    -customer_id                    The Google Ads customer ID.
    -ad_group_id                    The hotel ad group ID.
    -percent_cpc_bid_micro_amount   [optional] The percent CPC bid micro amount

=cut