Shopping listing groups lets you partition your products into groups. This is referred to as product groups in the UI. You can group using multiple dimensions, letting you include 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
.
You need at least one unit node to make a tree valid. That unit can be the root node, which then becomes the "All Products" division. Ads won't serve until you create a valid listing group tree.
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 Otherbecause 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 . V21 . 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( MutateAdGroupCriteriaRequest::build($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; } }