Register for one of our Google Ads API Migration Workshops (October 5, 2021 - October 14, 2021)

Creating Shopping Listing Groups

Shopping listing groups lets you partition your products into groups (referred to as product groups in the UI). You can group using multiple dimensions, letting you set bids or exclude products. Consider the tree below, where at the first level, the products have been divided by condition into New, Used and other product conditions. At the second level, the products in other product conditions have been divided by brand as "CoolBrand" products, "CheapBrand", and other brands.

Each node in the tree is either a subdivision or a unit, as defined by ListingGroupType. A subdivision introduces a new level in the tree, while units are leaves of the tree. Each subdivision must always be completely partitioned, so it must contain a node representing Other. In the example, the root and Product Condition: (Other) nodes are subdivisions. This tree structure with subdivisions and units lets you set bids at the unit level and also ensures that every product falls into one and only one unit node in the tree.

Nodes are objects of the ListingGroupInfo class, which contains the ListingGroupType field that indicates if the nodes are unit or subdivision. Setting ListingGroupInfo to listing_group of AdGroupCriterion will link it to the AdGroup.

Setting Manual CPC bids

You can set cpc_bid_micros of AdGroupCriterion on only unit nodes. Attempting to do so on subdivision nodes will fail with an error.

Listing dimensions

A ListingGroupInfo also has a case_value which is a ListingDimensionInfo that contains one of several dimension type. A ListingGroupInfo represents the values associated with your products, such as offer ID, brand, or product condition. A full description of the available ListingDimensionInfo types is available in the reference documentation.

Each child of a subdivision must have a case_value of the same ListingDimensionInfo subtype. Only the root node doesn't have a case_value.

Remember that each subdivision must contain an "empty" case_value of the correct type. This child is usually referred to as Other because it represents "all other values" for that ListingDimensionInfo.

See the code snippets below that add the first level of the listing group tree for more detail.

Java

private void runExample(
    GoogleAdsClient googleAdsClient,
    long customerId,
    long adGroupId,
    boolean replaceExistingTree) {
  // 1) Optional: Removes the existing listing group tree, if it already exists on the ad group.
  if (replaceExistingTree) {
    removeListingGroupTree(googleAdsClient, customerId, adGroupId);
  }
  // Creates a list of ad group criterion to add.q
  List<AdGroupCriterionOperation> operations = new ArrayList<>();

  // 2) Constructs the listing group tree "root" node.

  // Subdivision node: (Root node)
  AdGroupCriterion adGroupCriterionRoot =
      createListingGroupSubdivisionRoot(customerId, adGroupId, -1L);
  // Get the resource name that will be used for the root node.
  // This resource has not been created yet and will include the temporary ID as part of the
  // criterion ID.
  String adGroupCriterionResourceNameRoot = adGroupCriterionRoot.getResourceName();
  operations.add(AdGroupCriterionOperation.newBuilder().setCreate(adGroupCriterionRoot).build());

  // 3) Construct the listing group unit nodes for NEW, USED and other

  // Biddable Unit node: (Condition NEW node)
  // * Product Condition: NEW
  // * CPC bid: $0.20
  AdGroupCriterion adGroupCriterionConditionNew =
      createListingGroupUnitBiddable(
          customerId,
          adGroupId,
          adGroupCriterionResourceNameRoot,
          ListingDimensionInfo.newBuilder()
              .setProductCondition(
                  ProductConditionInfo.newBuilder().setCondition(ProductCondition.NEW).build())
              .build(),
          200_000L);
  operations.add(
      AdGroupCriterionOperation.newBuilder().setCreate(adGroupCriterionConditionNew).build());

  // Biddable Unit node: (Condition USED node)
  // * Product Condition: USED
  // * CPC bid: $0.10
  AdGroupCriterion adGroupCriterionConditionUsed =
      createListingGroupUnitBiddable(
          customerId,
          adGroupId,
          adGroupCriterionResourceNameRoot,
          ListingDimensionInfo.newBuilder()
              .setProductCondition(
                  ProductConditionInfo.newBuilder().setCondition(ProductCondition.USED).build())
              .build(),
          100_000L);
  operations.add(
      AdGroupCriterionOperation.newBuilder().setCreate(adGroupCriterionConditionUsed).build());

  // Sub-division node: (Condition "other" node)
  // * Product Condition: (not specified)
  AdGroupCriterion adGroupCriterionConditionOther =
      createListingGroupSubdivision(
          customerId,
          adGroupId,
          -2L,
          adGroupCriterionResourceNameRoot,
          ListingDimensionInfo.newBuilder()
              // All sibling nodes must have the same dimension type, even if they don't contain a
              // bid.
              // parent
              .setProductCondition(ProductConditionInfo.newBuilder().build())
              .build());
  // Gets the resource name that will be used for the condition other node.
  // This resource has not been created yet and will include the temporary ID as part of the
  // criterion ID.
  String adGroupCriterionResourceNameConditionOther =
      adGroupCriterionConditionOther.getResourceName();
  operations.add(
      AdGroupCriterionOperation.newBuilder().setCreate(adGroupCriterionConditionOther).build());

  // 4) Constructs the listing group unit nodes for CoolBrand, CheapBrand and other

  // Biddable Unit node: (Brand CoolBrand node)
  // * Brand: CoolBrand
  // * CPC bid: $0.90
  AdGroupCriterion adGroupCriterionBrandCoolBrand =
      createListingGroupUnitBiddable(
          customerId,
          adGroupId,
          adGroupCriterionResourceNameConditionOther,
          ListingDimensionInfo.newBuilder()
              .setProductBrand(ProductBrandInfo.newBuilder().setValue("CoolBrand").build())
              .build(),
          900_000L);
  operations.add(
      AdGroupCriterionOperation.newBuilder().setCreate(adGroupCriterionBrandCoolBrand).build());

  // Biddable Unit node: (Brand CheapBrand node)
  // * Brand: CheapBrand
  // * CPC bid: $0.01
  AdGroupCriterion adGroupCriterionBrandCheapBrand =
      createListingGroupUnitBiddable(
          customerId,
          adGroupId,
          adGroupCriterionResourceNameConditionOther,
          ListingDimensionInfo.newBuilder()
              .setProductBrand(ProductBrandInfo.newBuilder().setValue("CheapBrand").build())
              .build(),
          10_000L);
  operations.add(
      AdGroupCriterionOperation.newBuilder().setCreate(adGroupCriterionBrandCheapBrand).build());

  // Biddable Unit node: (Brand other node)
  // * Brand: CheapBrand
  // * CPC bid: $0.01
  AdGroupCriterion adGroupCriterionBrandOther =
      createListingGroupUnitBiddable(
          customerId,
          adGroupId,
          adGroupCriterionResourceNameConditionOther,
          ListingDimensionInfo.newBuilder()
              .setProductBrand(ProductBrandInfo.newBuilder().build())
              .build(),
          50_000L);
  operations.add(
      AdGroupCriterionOperation.newBuilder().setCreate(adGroupCriterionBrandOther).build());

  // Issues a mutate request to add the ad group criterion to the ad group.
  try (AdGroupCriterionServiceClient adGroupCriterionServiceClient =
      googleAdsClient.getLatestVersion().createAdGroupCriterionServiceClient()) {
    List<MutateAdGroupCriterionResult> mutateAdGroupCriteriaResults =
        adGroupCriterionServiceClient
            .mutateAdGroupCriteria(Long.toString(customerId), operations)
            .getResultsList();
    for (MutateAdGroupCriterionResult mutateAdGroupCriterionResult :
        mutateAdGroupCriteriaResults) {
      System.out.printf(
          "Added ad group criterion for listing group with resource name: '%s'%n",
          mutateAdGroupCriterionResult.getResourceName());
    }
  }
}
      
      

C#

public void Run(GoogleAdsClient client, long customerId, long adGroupId,
    bool replaceExistingTree)
{
    // Get the AdGroupCriterionService.
    AdGroupCriterionServiceClient adGroupCriterionService =
        client.GetService(Services.V8.AdGroupCriterionService);

    try
    {
        // 1) Optional: Remove the existing listing group tree, if it already exists on the
        // ad group.
        if (replaceExistingTree)
        {
            RemoveListingGroupTree(client, customerId, adGroupId);
        }
        // Create a list of ad group criterion to add
        List<AdGroupCriterionOperation> operations = new List<AdGroupCriterionOperation>();

        // 2) Construct the listing group tree "root" node.

        // Subdivision node: (Root node)
        AdGroupCriterion adGroupCriterionRoot = CreateListingGroupSubdivisionRoot(
            customerId, adGroupId, -1L);

        // Get the resource name that will be used for the root node.
        // This resource has not been created yet and will include the temporary ID as
        // part of the criterion ID.
        String adGroupCriterionResourceNameRoot = adGroupCriterionRoot.ResourceName;
        operations.Add(new AdGroupCriterionOperation()
        {
            Create = adGroupCriterionRoot
        });

        // 3) Construct the listing group unit nodes for NEW, USED and other

        // Biddable Unit node: (Condition NEW node)
        // * Product Condition: NEW
        // * CPC bid: $0.20
        AdGroupCriterion adGroupCriterionConditionNew =
            CreateListingGroupUnitBiddable(
                customerId,
                adGroupId,
                adGroupCriterionResourceNameRoot,
                new ListingDimensionInfo()
                {
                    ProductCondition = new ProductConditionInfo()
                    {
                        Condition = ProductCondition.New
                    }
                },
                200_000L);
        operations.Add(new AdGroupCriterionOperation()
        {
            Create = adGroupCriterionConditionNew
        });

        // Biddable Unit node: (Condition USED node)
        // * Product Condition: USED
        // * CPC bid: $0.10
        AdGroupCriterion adGroupCriterionConditionUsed =
            CreateListingGroupUnitBiddable(
                customerId,
                adGroupId,
                adGroupCriterionResourceNameRoot,
                new ListingDimensionInfo()
                {
                    ProductCondition = new ProductConditionInfo()
                    {
                        Condition = ProductCondition.Used
                    }
                },
                100_000L
            );
        operations.Add(new AdGroupCriterionOperation()
        {
            Create = adGroupCriterionConditionUsed
        });

        // Sub-division node: (Condition "other" node)
        // * Product Condition: (not specified)
        AdGroupCriterion adGroupCriterionConditionOther =
            CreateListingGroupSubdivision(
                customerId,
                adGroupId,
                -2L,
                adGroupCriterionResourceNameRoot,
                new ListingDimensionInfo()
                {
                    // All sibling nodes must have the same dimension type, even if they
                    // don't contain a bid.
                    ProductCondition = new ProductConditionInfo()
                }
            );
        // Get the resource name that will be used for the condition other node.
        // This resource has not been created yet and will include the temporary ID as
        // part of the criterion ID.
        String adGroupCriterionResourceNameConditionOther =
            adGroupCriterionConditionOther.ResourceName;
        operations.Add(new AdGroupCriterionOperation()
        {
            Create = adGroupCriterionConditionOther
        });

        // 4) Construct the listing group unit nodes for CoolBrand, CheapBrand and other

        // Biddable Unit node: (Brand CoolBrand node)
        // * Brand: CoolBrand
        // * CPC bid: $0.90
        AdGroupCriterion adGroupCriterionBrandCoolBrand =
            CreateListingGroupUnitBiddable(
                customerId,
                adGroupId,
                adGroupCriterionResourceNameConditionOther,
                new ListingDimensionInfo()
                {
                    ProductBrand = new ProductBrandInfo()
                    {
                        Value = "CoolBrand"
                    }
                },
                900_000L);
        operations.Add(new AdGroupCriterionOperation()
        {
            Create = adGroupCriterionBrandCoolBrand
        });

        // Biddable Unit node: (Brand CheapBrand node)
        // * Brand: CheapBrand
        // * CPC bid: $0.01
        AdGroupCriterion adGroupCriterionBrandCheapBrand =
            CreateListingGroupUnitBiddable(
                customerId,
                adGroupId,
                adGroupCriterionResourceNameConditionOther,
                new ListingDimensionInfo()
                {
                    ProductBrand = new ProductBrandInfo()
                    {
                        Value = "CheapBrand"
                    }
                },
                10_000L);

        operations.Add(new AdGroupCriterionOperation()
        {
            Create = adGroupCriterionBrandCheapBrand
        });

        // Biddable Unit node: (Brand other node)
        // * Brand: CheapBrand
        // * CPC bid: $0.01
        AdGroupCriterion adGroupCriterionBrandOther =
            CreateListingGroupUnitBiddable(
                customerId,
                adGroupId,
                adGroupCriterionResourceNameConditionOther,
                new ListingDimensionInfo()
                {
                    ProductBrand = new ProductBrandInfo()
                },
                50_000L);
        operations.Add(new AdGroupCriterionOperation()
        {
            Create = adGroupCriterionBrandOther
        });

        // Issues a mutate request to add the ad group criterion to the ad group.
        MutateAdGroupCriteriaResponse response =
            adGroupCriterionService.MutateAdGroupCriteria(
                customerId.ToString(), operations);

        // Display the results.
        foreach (MutateAdGroupCriterionResult mutateAdGroupCriterionResult
            in response.Results)
        {
            Console.WriteLine("Added ad group criterion for listing group with resource " +
                $"name: '{mutateAdGroupCriterionResult.ResourceName}.");
        }
    }
    catch (GoogleAdsException e)
    {
        Console.WriteLine("Failure:");
        Console.WriteLine($"Message: {e.Message}");
        Console.WriteLine($"Failure: {e.Failure}");
        Console.WriteLine($"Request ID: {e.RequestId}");
        throw;
    }
}
      
      

PHP

public static function runExample(
    GoogleAdsClient $googleAdsClient,
    int $customerId,
    int $adGroupId,
    bool $replaceExistingTree
) {
    // 1) Optional: Remove the existing listing group tree, if it already exists on the ad
    // group.
    if ($replaceExistingTree === 'true') {
        self::removeListingGroupTree($googleAdsClient, $customerId, $adGroupId);
    }
    // Create a list of ad group criteria to add.
    $operations = [];

    // 2) Construct the listing group tree "root" node.

    // Subdivision node: (Root node)
    $adGroupCriterionRoot = self::createListingGroupSubdivision($customerId, $adGroupId);
    // Get the resource name that will be used for the root node.
    // This resource has not been created yet and will include the temporary ID as part of the
    // criterion ID.
    $adGroupCriterionResourceNameRoot = $adGroupCriterionRoot->getResourceName();
    $operations[] = new AdGroupCriterionOperation(['create' => $adGroupCriterionRoot]);

    // 3) Construct the listing group unit nodes for NEW, USED and other.

    // Biddable Unit node: (Condition NEW node)
    // * Product Condition: NEW
    // * CPC bid: $0.20
    $adGroupCriterionConditionNew = self::createListingGroupUnitBiddable(
        $customerId,
        $adGroupId,
        $adGroupCriterionResourceNameRoot,
        new ListingDimensionInfo([
            'product_condition' => new ProductConditionInfo(
                ['condition' => ProductCondition::PBNEW]
            )
        ]),
        200000
    );
    $operations[] = new AdGroupCriterionOperation(['create' => $adGroupCriterionConditionNew]);

    // Biddable Unit node: (Condition USED node)
    // * Product Condition: USED
    // * CPC bid: $0.10
    $adGroupCriterionConditionUsed = self::createListingGroupUnitBiddable(
        $customerId,
        $adGroupId,
        $adGroupCriterionResourceNameRoot,
        new ListingDimensionInfo([
            'product_condition' => new ProductConditionInfo(
                ['condition' => ProductCondition::USED]
            )
        ]),
        100000
    );
    $operations[] = new AdGroupCriterionOperation(['create' => $adGroupCriterionConditionUsed]);

    // Sub-division node: (Condition "other" node)
    // * Product Condition: (not specified)
    $adGroupCriterionConditionOther = self::createListingGroupSubdivision(
        $customerId,
        $adGroupId,
        $adGroupCriterionResourceNameRoot,
        new ListingDimensionInfo([
            // All sibling nodes must have the same dimension type, even if they don't contain a
            // bid.
            'product_condition' => new ProductConditionInfo()
        ])
    );
    $operations[] =
        new AdGroupCriterionOperation(['create' => $adGroupCriterionConditionOther]);

    // Get the resource name that will be used for the condition other node.
    // This resource has not been created yet and will include the temporary ID as part of the
    // criterion ID.
    $adGroupCriterionResourceNameConditionOther =
        $adGroupCriterionConditionOther->getResourceName();

    // 4) Construct the listing group unit nodes for CoolBrand, CheapBrand and other.

    // Biddable Unit node: (Brand CoolBrand node)
    // * Brand: CoolBrand
    // * CPC bid: $0.90
    $adGroupCriterionBrandCoolBrand = self::createListingGroupUnitBiddable(
        $customerId,
        $adGroupId,
        $adGroupCriterionResourceNameConditionOther,
        new ListingDimensionInfo([
            'product_brand' => new ProductBrandInfo(['value' => 'CoolBrand'])
        ]),
        900000
    );
    $operations[] =
        new AdGroupCriterionOperation(['create' => $adGroupCriterionBrandCoolBrand]);

    // Biddable Unit node: (Brand CheapBrand node)
    // * Brand: CheapBrand
    // * CPC bid: $0.01
    $adGroupCriterionBrandCheapBrand = self::createListingGroupUnitBiddable(
        $customerId,
        $adGroupId,
        $adGroupCriterionResourceNameConditionOther,
        new ListingDimensionInfo([
            'product_brand' => new ProductBrandInfo(['value' => 'CheapBrand'])
        ]),
        10000
    );
    $operations[] =
        new AdGroupCriterionOperation(['create' => $adGroupCriterionBrandCheapBrand]);

    // Biddable Unit node: (Brand other node)
    // * CPC bid: $0.05
    $adGroupCriterionBrandOtherBrand = self::createListingGroupUnitBiddable(
        $customerId,
        $adGroupId,
        $adGroupCriterionResourceNameConditionOther,
        new ListingDimensionInfo([
            'product_brand' => new ProductBrandInfo()
        ]),
        50000
    );
    $operations[] =
        new AdGroupCriterionOperation(['create' => $adGroupCriterionBrandOtherBrand]);

    // Issues a mutate request.
    $adGroupCriterionServiceClient = $googleAdsClient->getAdGroupCriterionServiceClient();
    $response = $adGroupCriterionServiceClient->mutateAdGroupCriteria(
        $customerId,
        $operations
    );
    printf(
        'Added %d ad group criteria for listing group tree with the following resource '
        . 'names:%s',
        $response->getResults()->count(),
        PHP_EOL
    );
    foreach ($response->getResults() as $addedAdGroupCriterion) {
        /** @var AdGroupCriterion $addedAdGroupCriterion */
        print $addedAdGroupCriterion->getResourceName() . PHP_EOL;
    }
}
      
      

Python

def main(client, customer_id, ad_group_id, replace_existing_tree):
    """Adds a shopping listing group tree to a shopping ad group.

    Args:
        client: An initialized Google Ads client.
        customer_id: The Google Ads customer ID.
        ad_group_id: The ad group ID to which the node will be added.
        replace_existing_tree: Boolean, whether to replace the existing listing
            group tree on the ad group. Defaults to false.
    """
    # Get the AdGroupCriterionService client.
    ad_group_criterion_service = client.get_service("AdGroupCriterionService")

    # Optional: Remove the existing listing group tree, if it already exists
    # on the ad group. The example will throw a LISTING_GROUP_ALREADY_EXISTS
    # error if a listing group tree already exists and this option is not
    # set to true.
    if replace_existing_tree:
        _remove_listing_group_tree(client, customer_id, ad_group_id)

    # Create a list of ad group criteria operations.
    operations = []

    # Construct the listing group tree "root" node.
    # Subdivision node: (Root node)
    ad_group_criterion_root_operation = _create_listing_group_subdivision(
        client, customer_id, ad_group_id
    )

    # Get the resource name that will be used for the root node.
    # This resource has not been created yet and will include the temporary
    # ID as part of the criterion ID.
    ad_group_criterion_root_resource_name = (
        ad_group_criterion_root_operation.create.resource_name
    )
    operations.append(ad_group_criterion_root_operation)

    # Construct the listing group unit nodes for NEW, USED, and other.
    product_condition_enum = client.enums.ProductConditionEnum
    condition_dimension_info = client.get_type("ListingDimensionInfo")

    # Biddable Unit node: (Condition NEW node)
    # * Product Condition: NEW
    # * CPC bid: $0.20
    condition_dimension_info.product_condition.condition = (
        product_condition_enum.NEW
    )
    operations.append(
        _create_listing_group_unit_biddable(
            client,
            customer_id,
            ad_group_id,
            ad_group_criterion_root_resource_name,
            condition_dimension_info,
            200_000,
        )
    )

    # Biddable Unit node: (Condition USED node)
    # * Product Condition: USED
    # * CPC bid: $0.10
    condition_dimension_info.product_condition.condition = (
        product_condition_enum.USED
    )
    operations.append(
        _create_listing_group_unit_biddable(
            client,
            customer_id,
            ad_group_id,
            ad_group_criterion_root_resource_name,
            condition_dimension_info,
            100_000,
        )
    )

    # Sub-division node: (Condition "other" node)
    # * Product Condition: (not specified)
    # Note that all sibling nodes must have the same dimension type, even if
    # they don't contain a bid.
    client.copy_from(
        condition_dimension_info.product_condition,
        client.get_type("ProductConditionInfo"),
    )
    ad_group_criterion_other_operation = _create_listing_group_subdivision(
        client,
        customer_id,
        ad_group_id,
        ad_group_criterion_root_resource_name,
        condition_dimension_info,
    )
    # Get the resource name that will be used for the condition other node.
    # This resource has not been created yet and will include the temporary
    # ID as part of the criterion ID.
    ad_group_criterion_other_resource_name = (
        ad_group_criterion_other_operation.create.resource_name
    )
    operations.append(ad_group_criterion_other_operation)

    # Build the listing group nodes for CoolBrand, CheapBrand, and other.
    brand_dimension_info = client.get_type("ListingDimensionInfo")

    # Biddable Unit node: (Brand CoolBrand node)
    # * Brand: CoolBrand
    # * CPC bid: $0.90
    brand_dimension_info.product_brand.value = "CoolBrand"
    operations.append(
        _create_listing_group_unit_biddable(
            client,
            customer_id,
            ad_group_id,
            ad_group_criterion_other_resource_name,
            brand_dimension_info,
            900_000,
        )
    )

    # Biddable Unit node: (Brand CheapBrand node)
    # * Brand: CheapBrand
    # * CPC bid: $0.01
    brand_dimension_info.product_brand.value = "CheapBrand"
    operations.append(
        _create_listing_group_unit_biddable(
            client,
            customer_id,
            ad_group_id,
            ad_group_criterion_other_resource_name,
            brand_dimension_info,
            10_000,
        )
    )

    # Biddable Unit node: (Brand other node)
    # * CPC bid: $0.05
    client.copy_from(
        brand_dimension_info.product_brand,
        client.get_type("ProductBrandInfo"),
    )
    operations.append(
        _create_listing_group_unit_biddable(
            client,
            customer_id,
            ad_group_id,
            ad_group_criterion_other_resource_name,
            brand_dimension_info,
            50_000,
        )
    )

    # Add the ad group criteria.
    mutate_ad_group_criteria_response = (
        ad_group_criterion_service.mutate_ad_group_criteria(
            customer_id=customer_id, operations=operations
        )
    )

    # Print the results of the successful mutates.
    print(
        "Added ad group criteria for the listing group tree with the "
        "following resource names:"
    )
    for result in mutate_ad_group_criteria_response.results:
        print(f"\t{result.resource_name}")

    print(f"{len(mutate_ad_group_criteria_response.results)} criteria added.")
      
      

Ruby

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

  # 1) Optional: Remove the existing listing group tree, if it already exists
  # on the ad group.
  if should_replace_existing_tree
    remove_listing_group_tree(client, customer_id, ad_group_id)
  end

  # 2) Construct the listing group tree "root" node.

  # Subdivision node: (Root node)
  ad_group_criterion_root = create_listing_group_subdivision(
    client,
    customer_id,
    ad_group_id,
  )
  # This resource has not been created yet and will include the temporary ID as
  # part of the criterion ID.
  ad_group_criterion_root_resource_name = ad_group_criterion_root.resource_name
  operations = [client.operation.create_resource.ad_group_criterion(ad_group_criterion_root)]

  # 3) Construct the listing group unit nodes for NEW, USED, and other.

  # Biddable Unit node: (Condition NEW node)
  # * Product Condition: NEW
  # * CPC bid: $0.20
  listing_dimension_info = client.resource.listing_dimension_info do |ldi|
    ldi.product_condition = client.resource.product_condition_info do |pci|
      pci.condition = :NEW
    end
  end

  ad_group_criterion_condition_new = create_listing_group_unit_biddable(
    client,
    customer_id,
    ad_group_id,
    ad_group_criterion_root_resource_name,
    listing_dimension_info,
    200_000,
  )
  operation = client.operation.create_resource.ad_group_criterion(
    ad_group_criterion_condition_new
  )
  operations << operation

  # Biddable Unit node: (Condition USED node)
  # * Product Condition: USED
  # * CPC bid: $0.10
  listing_dimension_info = client.resource.listing_dimension_info do |ldi|
    ldi.product_condition = client.resource.product_condition_info do |pci|
      pci.condition = :USED
    end
  end
  ad_group_criterion_condition_used = create_listing_group_unit_biddable(
    client,
    customer_id,
    ad_group_id,
    ad_group_criterion_root_resource_name,
    listing_dimension_info,
    100_000,
  )
  operation = client.operation.create_resource.ad_group_criterion(
    ad_group_criterion_condition_used
  )
  operations << operation

  # Sub-division node: (Condition "other" node)
  # * Product Condition: (not specified)
  listing_dimension_info = client.resource.listing_dimension_info do |ldi|
    ldi.product_condition = client.resource.product_condition_info
  end
  ad_group_criterion_condition_other = create_listing_group_subdivision(
    client,
    customer_id,
    ad_group_id,
    ad_group_criterion_root_resource_name,
    listing_dimension_info,
  )
  operation = client.operation.create_resource.ad_group_criterion(
    ad_group_criterion_condition_other
  )
  operations << operation

  ad_group_criterion_condition_other_resource_name =
    ad_group_criterion_condition_other.resource_name

  # 4) Construct the listing group unit nodes for CoolBrand, CheapBrand, and
  # other.

  # Biddable Unit node: (Brand CoolBrand node)
  # * Brand: CoolBrand
  # * CPC bid: $0.90
  listing_dimension_info = client.resource.listing_dimension_info do |ldi|
    ldi.product_brand = client.resource.product_brand_info do |pbi|
      pbi.value = "CoolBrand"
    end
  end

  ad_group_criterion_brand_cool_brand = create_listing_group_unit_biddable(
    client,
    customer_id,
    ad_group_id,
    ad_group_criterion_condition_other_resource_name,
    listing_dimension_info,
    900_000,
  )
  operation = client.operation.create_resource.ad_group_criterion(
    ad_group_criterion_brand_cool_brand
  )
  operations << operation

  # Biddable Unit node: (Brand CheapBrand node)
  # * Brand: CheapBrand
  # * CPC bid: $0.01
  listing_dimension_info = client.resource.listing_dimension_info do |ldi|
    ldi.product_brand = client.resource.product_brand_info do |pbi|
      pbi.value = "CheapBrand"
    end
  end
  ad_group_criterion_brand_cheap_brand = create_listing_group_unit_biddable(
    client,
    customer_id,
    ad_group_id,
    ad_group_criterion_condition_other_resource_name,
    listing_dimension_info,
    10_000,
  )
  operation = client.operation.create_resource.ad_group_criterion(
    ad_group_criterion_brand_cheap_brand
  )
  operations << operation

  # Biddable Unit node: (Brand other node)
  # * CPC bid: $0.05
  listing_dimension_info = client.resource.listing_dimension_info do |ldi|
    ldi.product_brand = client.resource.product_brand_info
  end
  ad_group_criterion_brand_other_brand = create_listing_group_unit_biddable(
    client,
    customer_id,
    ad_group_id,
    ad_group_criterion_condition_other_resource_name,
    listing_dimension_info,
    50_000,
  )
  operation = client.operation.create_resource.ad_group_criterion(
    ad_group_criterion_brand_other_brand
  )
  operations << operation

  # Issue the mutate request.
  response = client.service.ad_group_criterion.mutate_ad_group_criteria(
    customer_id: customer_id,
    operations: operations,
  )

  total_count = 0
  response.results.each do |added_criterion|
    puts "Added ad group criterion with name: #{added_criterion.resource_name}"
    total_count += 1
  end
  puts "#{total_count} criteria added in total."
end
      
      

Perl

sub add_shopping_product_listing_group_tree {
  my ($api_client, $customer_id, $ad_group_id, $replace_existing_tree) = @_;

  # 1) Optional: Remove the existing listing group tree, if it already exists
  # on the ad group.
  if ($replace_existing_tree) {
    remove_listing_group_tree($api_client, $customer_id, $ad_group_id);
  }

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

  # 2) Construct the listing group tree "root" node.

  # Subdivision node: (Root node)
  my $ad_group_criterion_root =
    create_listing_group_subdivision($customer_id, $ad_group_id);
  # Get the resource name that will be used for the root node.
  # This resource has not been created yet and will include the temporary ID as
  # part of the criterion ID.
  my $ad_group_criterion_root_resource_name =
    $ad_group_criterion_root->{resourceName};
  push @$operations,
    Google::Ads::GoogleAds::V8::Services::AdGroupCriterionService::AdGroupCriterionOperation
    ->new({
      create => $ad_group_criterion_root
    });

  # 3) Construct the listing group unit nodes for NEW, USED, and other.

  # Biddable Unit node: (Condition NEW node)
  # * Product Condition: NEW
  # * CPC bid: $0.20
  my $ad_group_criterion_condition_new = create_listing_group_unit_biddable(
    $customer_id,
    $ad_group_id,
    $ad_group_criterion_root_resource_name,
    Google::Ads::GoogleAds::V8::Common::ListingDimensionInfo->new({
        productCondition =>
          Google::Ads::GoogleAds::V8::Common::ProductConditionInfo->new({
            condition => NEW
          })}
    ),
    200000
  );
  push @$operations,
    Google::Ads::GoogleAds::V8::Services::AdGroupCriterionService::AdGroupCriterionOperation
    ->new({
      create => $ad_group_criterion_condition_new
    });

  # Biddable Unit node: (Condition USED node)
  # * Product Condition: USED
  # * CPC bid: $0.10
  my $ad_group_criterion_condition_used = create_listing_group_unit_biddable(
    $customer_id,
    $ad_group_id,
    $ad_group_criterion_root_resource_name,
    Google::Ads::GoogleAds::V8::Common::ListingDimensionInfo->new({
        productCondition =>
          Google::Ads::GoogleAds::V8::Common::ProductConditionInfo->new({
            condition => USED
          })}
    ),
    100000
  );
  push @$operations,
    Google::Ads::GoogleAds::V8::Services::AdGroupCriterionService::AdGroupCriterionOperation
    ->new({
      create => $ad_group_criterion_condition_used
    });

  # Sub-division node: (Condition "other" node)
  # * Product Condition: (not specified)
  my $ad_group_criterion_condition_other = create_listing_group_subdivision(
    $customer_id,
    $ad_group_id,
    $ad_group_criterion_root_resource_name,
    Google::Ads::GoogleAds::V8::Common::ListingDimensionInfo->new({
        # All sibling nodes must have the same dimension type, even if they
        # don't contain a bid.
        productCondition =>
          Google::Ads::GoogleAds::V8::Common::ProductConditionInfo->new()}));
  push @$operations,
    Google::Ads::GoogleAds::V8::Services::AdGroupCriterionService::AdGroupCriterionOperation
    ->new({
      create => $ad_group_criterion_condition_other
    });

  # Get the resource name that will be used for the condition other node.
  # This resource has not been created yet and will include the temporary ID as
  # part of the criterion ID.
  my $ad_group_criterion_condition_other_resource_name =
    $ad_group_criterion_condition_other->{resourceName};

  # 4) Construct the listing group unit nodes for CoolBrand, CheapBrand, and
  # other.

  # Biddable Unit node: (Brand CoolBrand node)
  # * Brand: CoolBrand
  # * CPC bid: $0.90
  my $ad_group_criterion_brand_cool_brand = create_listing_group_unit_biddable(
    $customer_id,
    $ad_group_id,
    $ad_group_criterion_condition_other_resource_name,
    Google::Ads::GoogleAds::V8::Common::ListingDimensionInfo->new({
        productBrand =>
          Google::Ads::GoogleAds::V8::Common::ProductBrandInfo->new(
          {value => "CoolBrand"})}
    ),
    900000
  );
  push @$operations,
    Google::Ads::GoogleAds::V8::Services::AdGroupCriterionService::AdGroupCriterionOperation
    ->new({
      create => $ad_group_criterion_brand_cool_brand
    });

  # Biddable Unit node: (Brand CheapBrand node)
  # * Brand: CheapBrand
  # * CPC bid: $0.01
  my $ad_group_criterion_brand_cheap_brand = create_listing_group_unit_biddable(
    $customer_id,
    $ad_group_id,
    $ad_group_criterion_condition_other_resource_name,
    Google::Ads::GoogleAds::V8::Common::ListingDimensionInfo->new({
        productBrand =>
          Google::Ads::GoogleAds::V8::Common::ProductBrandInfo->new(
          {value => "CheapBrand"})}
    ),
    10000
  );
  push @$operations,
    Google::Ads::GoogleAds::V8::Services::AdGroupCriterionService::AdGroupCriterionOperation
    ->new({
      create => $ad_group_criterion_brand_cheap_brand
    });

  # Biddable Unit node: (Brand other node)
  # * CPC bid: $0.05
  my $ad_group_criterion_brand_other_brand = create_listing_group_unit_biddable(
    $customer_id,
    $ad_group_id,
    $ad_group_criterion_condition_other_resource_name,
    Google::Ads::GoogleAds::V8::Common::ListingDimensionInfo->new({
        productBrand =>
          Google::Ads::GoogleAds::V8::Common::ProductBrandInfo->new()}
    ),
    50000
  );
  push @$operations,
    Google::Ads::GoogleAds::V8::Services::AdGroupCriterionService::AdGroupCriterionOperation
    ->new({
      create => $ad_group_criterion_brand_other_brand
    });

  # Add the ad group criterion.
  my $ad_group_criteria_response =
    $api_client->AdGroupCriterionService()->mutate({
      customerId => $customer_id,
      operations => $operations
    });

  printf "Added %d ad group criteria for listing group tree with the " .
    "following resource names:\n",
    scalar @{$ad_group_criteria_response->{results}};

  foreach my $result (@{$ad_group_criteria_response->{results}}) {
    print $result->{resourceName}, "\n";
  }

  return 1;
}
      
      

Available dimensions for ListingDimensionInfo

There are multiple listing dimensions that can be part of a listing group (at an ad group level) or a listing scope (at a campaign level).

The following ListingDimensionInfo types can be used with shopping campaigns:

Temporary IDs

Ad group criteria are not assigned IDs until the mutate request that creates them is processed by the server. However, a ListingGroupInfo is invalid until it is complete, so whenever you create a subdivision you must also create at least one of its children and an Other node in the same request.

In order to set the parent_criterion_id of ListingGroupInfo for the child nodes created in the same request of the parent, you can use temporary criterion IDs. These are locally unique (rather than globally unique) identifiers that apply only within the context of a single mutate request. Any negative integer can be used as a temporary ID. In the code examples, the ID of the root ListingGroupInfo is set to -1.

When the request is processed, each AdGroupCriterion is assigned a positive global ID as usual.

Code examples

You can explore the code examples in each language by following the links below:

Languages File names
Java AddShoppingProductListingGroupTree.java