Ява
// 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.
package com.google.ads.googleads.examples.shoppingads;
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.v17.common.ListingDimensionInfo;
import com.google.ads.googleads.v17.common.ListingGroupInfo;
import com.google.ads.googleads.v17.common.ProductBrandInfo;
import com.google.ads.googleads.v17.common.ProductConditionInfo;
import com.google.ads.googleads.v17.enums.AdGroupCriterionStatusEnum.AdGroupCriterionStatus;
import com.google.ads.googleads.v17.enums.ListingGroupTypeEnum.ListingGroupType;
import com.google.ads.googleads.v17.enums.ProductConditionEnum.ProductCondition;
import com.google.ads.googleads.v17.errors.GoogleAdsError;
import com.google.ads.googleads.v17.errors.GoogleAdsException;
import com.google.ads.googleads.v17.resources.AdGroupCriterion;
import com.google.ads.googleads.v17.services.AdGroupCriterionOperation;
import com.google.ads.googleads.v17.services.AdGroupCriterionServiceClient;
import com.google.ads.googleads.v17.services.GoogleAdsRow;
import com.google.ads.googleads.v17.services.GoogleAdsServiceClient;
import com.google.ads.googleads.v17.services.GoogleAdsServiceClient.SearchPagedResponse;
import com.google.ads.googleads.v17.services.MutateAdGroupCriteriaResponse;
import com.google.ads.googleads.v17.services.MutateAdGroupCriterionResult;
import com.google.ads.googleads.v17.services.SearchGoogleAdsRequest;
import com.google.ads.googleads.v17.utils.ResourceNames;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Adds a shopping listing group tree to a shopping ad group. The example will clear an existing
* listing group tree and rebuild it include the following tree structure:
*
* <pre>
* ProductCanonicalCondition NEW $0.20
* ProductCanonicalCondition USED $0.10
* ProductCanonicalCondition null (everything else)
* ProductBrand CoolBrand $0.90
* ProductBrand CheapBrand $0.01
* ProductBrand null (everything else) $0.50
* </pre>
*/
public class AddShoppingProductListingGroupTree {
private static class AddShoppingListingGroupParams extends CodeSampleParams {
@Parameter(names = ArgumentNames.CUSTOMER_ID, required = true)
private Long customerId;
@Parameter(names = ArgumentNames.AD_GROUP_ID, required = true)
private Long adGroupId;
@Parameter(names = ArgumentNames.REPLACE_EXISTING_TREE, required = true, arity = 1)
private Boolean replaceExistingTree;
}
public static void main(String[] args) {
AddShoppingListingGroupParams params = new AddShoppingListingGroupParams();
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 replace the existing listing group tree on an ad group set this parameter to
// true.
// This option will remove the existing listing group tree before creating a replacement.
params.replaceExistingTree = Boolean.parseBoolean("INSERT_REPLACE_EXISTING_TREE_HERE");
}
GoogleAdsClient googleAdsClient = null;
try {
googleAdsClient = GoogleAdsClient.newBuilder().fromPropertiesFile().build();
} catch (FileNotFoundException fnfe) {
System.err.printf(
"Failed to load GoogleAdsClient configuration from file. Exception: %s%n", fnfe);
System.exit(1);
} catch (IOException ioe) {
System.err.printf("Failed to create GoogleAdsClient. Exception: %s%n", ioe);
System.exit(1);
}
try {
new AddShoppingProductListingGroupTree()
.runExample(
googleAdsClient, params.customerId, params.adGroupId, params.replaceExistingTree);
} catch (GoogleAdsException gae) {
// GoogleAdsException is the base class for most exceptions thrown by an API request.
// Instances of this exception have a message and a GoogleAdsFailure that contains a
// collection of GoogleAdsErrors that indicate the underlying causes of the
// GoogleAdsException.
System.err.printf(
"Request ID %s failed due to GoogleAdsException. Underlying errors:%n",
gae.getRequestId());
int i = 0;
for (GoogleAdsError googleAdsError : gae.getGoogleAdsFailure().getErrorsList()) {
System.err.printf(" Error %d: %s%n", i++, googleAdsError);
}
System.exit(1);
}
}
/**
* Runs the example.
*
* @param googleAdsClient the Google Ads API client.
* @param customerId the client customer ID.
* @param adGroupId the ID of the ad group.
* @param replaceExistingTree replace the existing listing group tree on the ad group, if it
* already exists. The example will throw a 'LISTING_GROUP_ALREADY_EXISTS' error if listing
* group tree already exists and this option is not set to true.
* @throws GoogleAdsException if an API request failed with one or more service errors.
*/
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());
}
}
}
/**
* Removes all the ad group criteria that define the existing listing group tree for an ad group.
* Returns without an error if all listing group criterion are successfully removed.
*
* @param googleAdsClient the Google Ads API client.
* @param customerId the client customer ID.
* @param adGroupId the ID of the ad group that the new listing group tree will be removed from.
* @throws GoogleAdsException if an API request failed with one or more service errors.
*/
private void removeListingGroupTree(
GoogleAdsClient googleAdsClient, long customerId, long adGroupId) {
try (GoogleAdsServiceClient googleAdsServiceClient =
googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
String searchQuery =
"SELECT ad_group_criterion.resource_name "
+ "FROM ad_group_criterion "
+ "WHERE ad_group_criterion.type = LISTING_GROUP "
+ "AND ad_group_criterion.listing_group.parent_ad_group_criterion IS NULL "
+ String.format("AND ad_group.id = %d", adGroupId);
// Creates a request that will retrieve all listing groups where the parent ad group criterion
// is NULL (and hence the root node in the tree) for a given ad group id.
SearchGoogleAdsRequest request =
SearchGoogleAdsRequest.newBuilder()
.setCustomerId(Long.toString(customerId))
.setQuery(searchQuery)
.build();
// Issues the search request.
SearchPagedResponse searchPagedResponse = googleAdsServiceClient.search(request);
// Iterates over all rows in all pages to find the ad group criterion to remove.
for (GoogleAdsRow googleAdsRow : searchPagedResponse.iterateAll()) {
AdGroupCriterion adGroupCriterion = googleAdsRow.getAdGroupCriterion();
System.out.printf(
"Found ad group criterion with the resource name: '%s'.%n",
adGroupCriterion.getResourceName());
AdGroupCriterionOperation operation =
AdGroupCriterionOperation.newBuilder()
.setRemove(adGroupCriterion.getResourceName())
.build();
try (AdGroupCriterionServiceClient adGroupCriterionServiceClient =
googleAdsClient.getLatestVersion().createAdGroupCriterionServiceClient()) {
MutateAdGroupCriteriaResponse response =
adGroupCriterionServiceClient.mutateAdGroupCriteria(
Long.toString(customerId), Collections.singletonList(operation));
System.out.printf("Removed %d ad group criteria.%n", response.getResultsCount());
}
}
}
}
/**
* Creates a new criterion containing a biddable unit listing group node.
*
* @param customerId the client customer ID.
* @param adGroupId the ID of the ad group.
* @param parentAdGroupCriterionResourceName the resource name of the parent of this criterion.
* @param listingDimensionInfo the ListingDimensionInfo to be set for this listing group.
* @param cpcBidMicros the CPC bid for items in this listing group. This value should be specified
* in micros.
* @return the ad group criterion object that contains the biddable unit listing group node.
*/
private AdGroupCriterion createListingGroupUnitBiddable(
long customerId,
long adGroupId,
String parentAdGroupCriterionResourceName,
ListingDimensionInfo listingDimensionInfo,
long cpcBidMicros) {
String adGroupResourceName = ResourceNames.adGroup(customerId, adGroupId);
// Note: There are two approaches for creating new unit nodes:
// (1) Set the ad group resource name on the criterion (no temporary ID required).
// (2) Use a temporary ID to construct the criterion resource name and set it using
// setResourceName.
// In both cases you must set the parentAdGroupCriterionResourceName on the listing
// group for non-root nodes.
// This example demonstrates method (1).
AdGroupCriterion adGroupCriterion =
AdGroupCriterion.newBuilder()
// The ad group the listing group will be attached to.
.setAdGroup(adGroupResourceName)
.setStatus(AdGroupCriterionStatus.ENABLED)
.setListingGroup(
ListingGroupInfo.newBuilder()
// Sets the type as a UNIT, which will allow the group to be biddable.
.setType(ListingGroupType.UNIT)
// Sets the ad group criterion resource name for the parent listing group.
// This can include a temporary ID if the parent criterion is not yet created.
// Use StringValue to convert from a String to a compatible argument type.
.setParentAdGroupCriterion(parentAdGroupCriterionResourceName)
// Case values contain the listing dimension used for the node.
.setCaseValue(listingDimensionInfo)
.build())
// Sets the bid for this listing group unit.
// This will be used as the CPC bid for items that are included in this listing group
.setCpcBidMicros(cpcBidMicros)
.build();
return adGroupCriterion;
}
/**
* Creates a new criterion containing a subdivision listing group node.
*
* @param customerId the client customer ID.
* @param adGroupId the ID of the ad group.
* @param adGroupCriterionId the ID of the criterion. This value will used to construct the
* resource name. This can be a negative number if the criterion is yet to be created.
* @param parentAdGroupCriterionResourceName the resource name of the parent of this criterion.
* @param listingDimensionInfo the ListingDimensionInfo to be set for this listing group.
* @return the ad group criterion object that contains the subdivision listing group node.
*/
private AdGroupCriterion createListingGroupSubdivision(
long customerId,
long adGroupId,
long adGroupCriterionId,
String parentAdGroupCriterionResourceName,
ListingDimensionInfo listingDimensionInfo) {
String adGroupCriterionResourceName =
ResourceNames.adGroupCriterion(customerId, adGroupId, adGroupCriterionId);
AdGroupCriterion adGroupCriterion =
AdGroupCriterion.newBuilder()
// The resource name the criterion will be created with. This will define the ID for the
// ad group criterion.
.setResourceName(adGroupCriterionResourceName)
.setStatus(AdGroupCriterionStatus.ENABLED)
.setListingGroup(
ListingGroupInfo.newBuilder()
// Sets the type as a SUBDIVISION, which will allow the node to be the parent of
// another sub-tree.
.setType(ListingGroupType.SUBDIVISION)
// Sets the ad group criterion resource name for the parent listing group.
// This can include a temporary ID if the parent criterion is not yet created.
// Uses StringValue to convert from a String to a compatible argument type.
.setParentAdGroupCriterion(parentAdGroupCriterionResourceName)
// Case values contain the listing dimension used for the node.
.setCaseValue(listingDimensionInfo)
.build())
.build();
return adGroupCriterion;
}
/**
* Creates a new criterion containing a root subdivision listing group node.
*
* @param customerId the client customer ID.
* @param adGroupId the ID of the ad group.
* @param adGroupCriterionId the ID of the criterion. This value will used to construct the
* resource name. This can be a negative number if the criterion is yet to be created.
* @return the ad group criterion object that contains the listing group root node.
*/
private AdGroupCriterion createListingGroupSubdivisionRoot(
long customerId, long adGroupId, long adGroupCriterionId) {
String adGroupCriterionResourceName =
ResourceNames.adGroupCriterion(customerId, adGroupId, adGroupCriterionId);
AdGroupCriterion adGroupCriterion =
AdGroupCriterion.newBuilder()
// The resource name the criterion will be created with. This will define the ID for the
// ad group criterion.
.setResourceName(adGroupCriterionResourceName)
.setStatus(AdGroupCriterionStatus.ENABLED)
.setListingGroup(
ListingGroupInfo.newBuilder()
// Sets the type as a SUBDIVISION, which will allow the node to be the parent of
// another sub-tree.
.setType(ListingGroupType.SUBDIVISION)
.build())
.build();
return adGroupCriterion;
}
}
С#
// 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.
using CommandLine;
using Google.Ads.Gax.Examples;
using Google.Ads.GoogleAds.Lib;
using Google.Ads.GoogleAds.V17.Common;
using Google.Ads.GoogleAds.V17.Errors;
using Google.Ads.GoogleAds.V17.Resources;
using Google.Ads.GoogleAds.V17.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using static Google.Ads.GoogleAds.V17.Enums.AdGroupCriterionStatusEnum.Types;
using static Google.Ads.GoogleAds.V17.Enums.ListingGroupTypeEnum.Types;
using static Google.Ads.GoogleAds.V17.Enums.ProductConditionEnum.Types;
namespace Google.Ads.GoogleAds.Examples.V17
{
/// <summary>
/// This code example shows how to add a shopping listing group tree to a shopping ad group.
/// The example will clear an existing listing group tree and rebuild it include the following
/// tree structure:
///
/// <code>
/// ProductCanonicalCondition NEW $0.20
/// ProductCanonicalCondition USED $0.10
/// ProductCanonicalCondition null (everything else)
/// ProductBrand CoolBrand $0.90
/// ProductBrand CheapBrand $0.01
/// ProductBrand null (everything else) $0.50
/// </code>
/// </summary>
public class AddShoppingProductListingGroupTree : ExampleBase
{
/// <summary>
/// Command line options for running the <see cref="AddShoppingProductListingGroupTree"/>
/// example.
/// </summary>
public class Options : OptionsBase
{
/// <summary>
/// The Google Ads customer ID for which the call is made.
/// </summary>
[Option("customerId", Required = true, HelpText =
"The Google Ads customer ID for which the call is made.")]
public long CustomerId { get; set; }
/// <summary>
/// The ID of the ad group.
/// </summary>
[Option("adGroupId", Required = true, HelpText =
"The ID of the ad group.")]
public long AdGroupId { get; set; }
/// <summary>
/// The boolean to indicate whether to replace the existing listing group tree on the
/// ad group, if it already exists. The example will throw a
/// LISTING_GROUP_ALREADY_EXISTS error if listing group tree already exists and this
/// option is not set to true.
/// </summary>
[Option("replaceExistingTree", Required = true, HelpText =
"The boolean to indicate whether to replace the existing listing group tree on " +
"the ad group, if it already exists. The example will throw a " +
"LISTING_GROUP_ALREADY_EXISTS error if listing group tree already exists and " +
"this option is not set to true.")]
public bool ReplaceExistingTree { 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);
AddShoppingProductListingGroupTree codeExample =
new AddShoppingProductListingGroupTree();
Console.WriteLine(codeExample.Description);
codeExample.Run(new GoogleAdsClient(), options.CustomerId, options.AdGroupId,
options.ReplaceExistingTree);
}
/// <summary>
/// Returns a description about the code example.
/// </summary>
public override string Description =>
"This code example shows how to add a shopping listing group tree to a shopping ad " +
"group. The example will clear an existing listing group tree and rebuild it include " +
"the following tree structure:\n" +
"ProductCanonicalCondition NEW $0.20\n" +
"ProductCanonicalCondition USED $0.10\n" +
"ProductCanonicalCondition null (everything else)\n" +
" ProductBrand CoolBrand $0.90\n" +
" ProductBrand CheapBrand $0.01\n" +
" ProductBrand null (everything else) $0.50\n";
/// <summary>
/// Runs the code example.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
/// <param name="adGroupId">The ID of the ad group.</param>
/// <param name="replaceExistingTree">The boolean to indicate whether to replace the
/// existing listing group tree on the ad group, if it already exists. The example will
/// throw a <code>LISTING_GROUP_ALREADY_EXISTS</code> error if listing group tree already
/// exists and this option is not set to true.</param>
public void Run(GoogleAdsClient client, long customerId, long adGroupId,
bool replaceExistingTree)
{
// Get the AdGroupCriterionService.
AdGroupCriterionServiceClient adGroupCriterionService =
client.GetService(Services.V17.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;
}
}
/// <summary>
/// Removes all the ad group criteria that define the existing listing group tree for an
/// ad group. Returns without an error if all listing group criterion are successfully
/// removed.
/// </summary>
/// <param name="client">The Google Ads API client..</param>
/// <param name="customerId">The client customer ID.</param>
/// <param name="adGroupId">The ID of the ad group that the new listing group tree will
/// be removed from.</param>
/// <exception cref="GoogleAdsException">Thrown if an API request failed with one or more
/// service errors.</exception>
private void RemoveListingGroupTree(GoogleAdsClient client, long customerId,
long adGroupId)
{
// Get the GoogleAdsService.
GoogleAdsServiceClient googleAdsService = client.GetService(
Services.V17.GoogleAdsService);
// Get the AdGroupCriterionService.
AdGroupCriterionServiceClient adGroupCriterionService =
client.GetService(Services.V17.AdGroupCriterionService);
String searchQuery = "SELECT ad_group_criterion.resource_name FROM " +
"ad_group_criterion WHERE ad_group_criterion.type = LISTING_GROUP AND " +
"ad_group_criterion.listing_group.parent_ad_group_criterion IS NULL " +
$"AND ad_group.id = {adGroupId}";
// Creates a request that will retrieve all listing groups where the parent ad group
// criterion is NULL (and hence the root node in the tree) for a given ad group ID.
SearchGoogleAdsRequest request = new SearchGoogleAdsRequest()
{
CustomerId = customerId.ToString(),
Query = searchQuery
};
// Issues the search request.
GoogleAdsRow googleAdsRow = googleAdsService.Search(request).FirstOrDefault();
if (googleAdsRow == null)
{
return;
}
AdGroupCriterion adGroupCriterion = googleAdsRow.AdGroupCriterion;
Console.WriteLine("Found ad group criterion with the resource name: '{0}'.",
adGroupCriterion.ResourceName);
AdGroupCriterionOperation operation = new AdGroupCriterionOperation()
{
Remove = adGroupCriterion.ResourceName
};
MutateAdGroupCriteriaResponse response =
adGroupCriterionService.MutateAdGroupCriteria(
customerId.ToString(), new AdGroupCriterionOperation[] { operation });
Console.WriteLine($"Removed {response.Results.Count}.");
}
/// <summary>
/// Creates a new criterion containing a biddable unit listing group node.
/// </summary>
/// <param name="customerId">The client customer ID.</param>
/// <param name="adGroupId">The ID of the ad group.</param>
/// <param name="parentAdGroupCriterionResourceName">The resource name of the parent of
/// this criterion.</param>
/// <param name="listingDimensionInfo">The ListingDimensionInfo to be set for this listing
/// group.</param>
/// <param name="cpcBidMicros">The CPC bid for items in this listing group. This value
/// should be specified in micros.</param>
/// <returns>The ad group criterion object that contains the biddable unit listing group
/// node.</returns>
private AdGroupCriterion CreateListingGroupUnitBiddable(long customerId, long adGroupId,
String parentAdGroupCriterionResourceName, ListingDimensionInfo listingDimensionInfo,
long cpcBidMicros)
{
String adGroupResourceName = ResourceNames.AdGroup(customerId, adGroupId);
AdGroupCriterion adGroupCriterion = new AdGroupCriterion()
{
// The resource name the ad group the listing group node will be attached to unit.
// Note: Listing group units do not require temporary IDs if ad group resource name
// and parentAdGroupCriterionResourceName are specified. To use temporary IDs for
// unit criteria, use ResourceName property.
AdGroup = adGroupResourceName,
Status = AdGroupCriterionStatus.Enabled,
ListingGroup = new ListingGroupInfo()
{
// Set the type as a UNIT, which will allow the group to be biddable
Type = ListingGroupType.Unit,
// Set the ad group criterion resource name for the parent listing group.
// This can include a criterion ID if the parent criterion is not yet created.
// Use StringValue to convert from a String to a compatible argument type.
ParentAdGroupCriterion = parentAdGroupCriterionResourceName,
// Case values contain the listing dimension used for the node.
CaseValue = listingDimensionInfo
},
// Set the bid for this listing group unit.
// This will be used as the CPC bid for items that are included in this
// listing group
CpcBidMicros = cpcBidMicros
};
return adGroupCriterion;
}
/// <summary>
/// Creates a new criterion containing a subdivision listing group node.
/// </summary>
/// <param name="customerId">The client customer ID.</param>
/// <param name="adGroupId">The ID of the ad group.</param>
/// <param name="adGroupCriterionId">The ID of the criterion. This value will used to
/// construct the resource name. This can be a negative number if the criterion is yet to
/// be created.</param>
/// <param name="parentAdGroupCriterionResourceName">The resource name of the parent of
/// this criterion.</param>
/// <param name="listingDimensionInfo">The ListingDimensionInfo to be set for this listing
/// group.</param>
/// <returns>The ad group criterion object that contains the subdivision listing group
/// node.</returns>
private AdGroupCriterion CreateListingGroupSubdivision(long customerId, long adGroupId,
long adGroupCriterionId, String parentAdGroupCriterionResourceName,
ListingDimensionInfo listingDimensionInfo)
{
String adGroupCriterionResourceName = ResourceNames.AdGroupCriterion(
customerId, adGroupId, adGroupCriterionId);
AdGroupCriterion adGroupCriterion = new AdGroupCriterion()
{
// The resource name the criterion will be created with. This will define the
// ID for the ad group criterion.
ResourceName = adGroupCriterionResourceName,
Status = AdGroupCriterionStatus.Enabled,
ListingGroup = new ListingGroupInfo()
{
Type = ListingGroupType.Subdivision,
// Set the ad group criterion resource name for the parent listing group.
// This can include a criterion ID if the parent criterion is not yet created.
// Use StringValue to convert from a String to a compatible argument type.
ParentAdGroupCriterion = parentAdGroupCriterionResourceName,
// Case values contain the listing dimension used for the node.
CaseValue = listingDimensionInfo
}
};
return adGroupCriterion;
}
/// <summary>
/// Creates a new criterion containing a root subdivision listing group node.
/// </summary>
/// <param name="customerId">The client customer ID.</param>
/// <param name="adGroupId">The ID of the ad group.</param>
/// <param name="adGroupCriterionId">The ID of the criterion. This value will used to
/// construct the resource name. This can be a negative number if the criterion is yet
/// to be created.</param>
/// <returns>The ad group criterion object that contains the listing group root node.
/// </returns>
private AdGroupCriterion CreateListingGroupSubdivisionRoot(long customerId, long adGroupId,
long adGroupCriterionId)
{
String adGroupCriterionResourceName = ResourceNames.AdGroupCriterion(customerId,
adGroupId, adGroupCriterionId);
AdGroupCriterion adGroupCriterion = new AdGroupCriterion()
{
// The resource name the criterion will be created with. This will define the ID
// for the ad group criterion.
ResourceName = adGroupCriterionResourceName,
Status = AdGroupCriterionStatus.Enabled,
ListingGroup = new ListingGroupInfo()
{
// Set the type as a SUBDIVISION, which will allow the node to be the parent of
// another sub-tree.
Type = ListingGroupType.Subdivision
}
};
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\ShoppingAds;
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\V17\GoogleAdsClient;
use Google\Ads\GoogleAds\Lib\V17\GoogleAdsClientBuilder;
use Google\Ads\GoogleAds\Lib\V17\GoogleAdsException;
use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder;
use Google\Ads\GoogleAds\Util\V17\ResourceNames;
use Google\Ads\GoogleAds\V17\Common\ProductBrandInfo;
use Google\Ads\GoogleAds\V17\Common\ListingDimensionInfo;
use Google\Ads\GoogleAds\V17\Common\ListingGroupInfo;
use Google\Ads\GoogleAds\V17\Common\ProductConditionInfo;
use Google\Ads\GoogleAds\V17\Enums\AdGroupCriterionStatusEnum\AdGroupCriterionStatus;
use Google\Ads\GoogleAds\V17\Enums\ListingGroupTypeEnum\ListingGroupType;
use Google\Ads\GoogleAds\V17\Enums\ProductConditionEnum\ProductCondition;
use Google\Ads\GoogleAds\V17\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V17\Resources\AdGroupCriterion;
use Google\Ads\GoogleAds\V17\Services\AdGroupCriterionOperation;
use Google\Ads\GoogleAds\V17\Services\GoogleAdsRow;
use Google\Ads\GoogleAds\V17\Services\MutateAdGroupCriteriaRequest;
use Google\Ads\GoogleAds\V17\Services\SearchGoogleAdsRequest;
use Google\ApiCore\ApiException;
/**
* This example shows how to add a shopping listing group tree to a shopping ad group. The example
* will optionally clear an existing listing group tree and rebuild it to include the following tree
* structure:
*
* <pre>
* ProductCanonicalCondition NEW $0.20
* ProductCanonicalCondition USED $0.10
* ProductCanonicalCondition null (everything else)
* ProductBrand CoolBrand $0.90
* ProductBrand CheapBrand $0.01
* ProductBrand null (everything else) $0.50
* </pre>
*/
class AddShoppingProductListingGroupTree
{
private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE';
private const AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE';
private const REPLACE_EXISTING_TREE = 'INSERT_BOOLEAN_TRUE_OR_FALSE_HERE';
public static function main()
{
// Either pass the required parameters for this example on the command line, or insert them
// into the constants above.
$options = (new ArgumentParser())->parseCommandArguments([
ArgumentNames::CUSTOMER_ID => GetOpt::REQUIRED_ARGUMENT,
ArgumentNames::AD_GROUP_ID => GetOpt::REQUIRED_ARGUMENT,
ArgumentNames::REPLACE_EXISTING_TREE => GetOpt::REQUIRED_ARGUMENT
]);
// Generate a refreshable OAuth2 credential for authentication.
$oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();
// Construct a Google Ads client configured from a properties file and the
// OAuth2 credentials above.
$googleAdsClient = (new GoogleAdsClientBuilder())->fromFile()
->withOAuth2Credential($oAuth2Credential)
// We set this value to true to show how to use GAPIC v2 source code. You can remove the
// below line if you wish to use the old-style source code. Note that in that case, you
// probably need to modify some parts of the code below to make it work.
// For more information, see
// https://developers.devsite.corp.google.com/google-ads/api/docs/client-libs/php/gapic.
->usingGapicV2Source(true)
->build();
try {
self::runExample(
$googleAdsClient,
$options[ArgumentNames::CUSTOMER_ID] ?: self::CUSTOMER_ID,
$options[ArgumentNames::AD_GROUP_ID]
?: self::AD_GROUP_ID,
$options[ArgumentNames::REPLACE_EXISTING_TREE]
?: self::REPLACE_EXISTING_TREE
);
} 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 bool $replaceExistingTree true if it should replace the existing listing group
* tree on the ad group, if it already exists. The example will throw a
* 'LISTING_GROUP_ALREADY_EXISTS' error if listing group tree already exists and this option
* is not set to true
*/
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;
}
}
/**
* Removes all the ad group criteria that define the existing listing group tree for an ad
* group.
*
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
* @param int $customerId the customer ID
* @param int $adGroupId the ID of ad group that the existing listing group tree will be
* removed from
*/
private static function removeListingGroupTree(
GoogleAdsClient $googleAdsClient,
int $customerId,
int $adGroupId
) {
$googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
// Creates a query that retrieves a listing group tree.
$query = 'SELECT ad_group_criterion.resource_name '
. 'FROM ad_group_criterion '
. 'WHERE ad_group_criterion.type = LISTING_GROUP '
. 'AND ad_group_criterion.listing_group.parent_ad_group_criterion IS NULL '
. 'AND ad_group.id = ' . $adGroupId;
// Issues a search request.
$response =
$googleAdsServiceClient->search(SearchGoogleAdsRequest::build($customerId, $query));
$operations = [];
// Iterates over all rows in all pages and prints the requested field values for
// the listing group tree in each row.
foreach ($response->iterateAllElements() as $googleAdsRow) {
/** @var GoogleAdsRow $googleAdsRow */
$adGroupCriterion = $googleAdsRow->getAdGroupCriterion();
printf(
"Found an ad group criterion with the resource name: '%s'.%s",
$adGroupCriterion->getResourceName(),
PHP_EOL
);
// Creates an ad group criterion operation.
$adGroupCriterionOperation = new AdGroupCriterionOperation();
$adGroupCriterionOperation->setRemove($adGroupCriterion->getResourceName());
$operations[] = $adGroupCriterionOperation;
}
if (count($operations) > 0) {
// Issues a mutate request.
$adGroupCriterionServiceClient = $googleAdsClient->getAdGroupCriterionServiceClient();
$response = $adGroupCriterionServiceClient->mutateAdGroupCriteria(
MutateAdGroupCriteriaRequest::build($customerId, $operations)
);
printf("Removed %d ad group criteria.%s", $response->getResults()->count(), PHP_EOL);
}
}
/**
* Creates a new criterion containing a subdivision listing group node. If the parent ad group
* criterion resource name is not specified, this method creates a root node.
*
* @param int $customerId the customer ID
* @param int $adGroupId the ad group ID
* @param string|null $parentAdGroupCriterionResourceName the resource name of the parent of
* this criterion. If null, this method will create a root of the tree
* @param ListingDimensionInfo|null $listingDimensionInfo the listing dimension info to be set
* for this listing group. This is required for non-root subdivisions
* @return AdGroupCriterion the ad group criterion that contains the listing group root node
*/
private static function createListingGroupSubdivision(
int $customerId,
int $adGroupId,
string $parentAdGroupCriterionResourceName = null,
ListingDimensionInfo $listingDimensionInfo = null
) {
static $tempId = 0;
$listingGroupInfo = new ListingGroupInfo([
// Set the type as a SUBDIVISION, which will allow the node to be the parent of
// another sub-tree.
'type' => ListingGroupType::SUBDIVISION
]);
// If $parentAdGroupCriterionResourceName and $listingDimensionInfo are not null, create
// a non-root division by setting its parent and case value.
if (!is_null($parentAdGroupCriterionResourceName) && !is_null($listingDimensionInfo)) {
// Set the ad group criterion resource name for the parent listing group.
// This can include a temporary ID if the parent criterion is not yet created.
$listingGroupInfo->setParentAdGroupCriterion($parentAdGroupCriterionResourceName);
// Case values contain the listing dimension used for the node.
$listingGroupInfo->setCaseValue($listingDimensionInfo);
}
$adGroupCriterion = new AdGroupCriterion([
// The resource name the criterion will be created with. This will define the ID for the
// ad group criterion.
'resource_name' => ResourceNames::forAdGroupCriterion(
$customerId,
$adGroupId,
// Specify a decreasing negative number as a temporary ad group criterion ID. The
// ad group criterion will get the real ID when created on the server.
--$tempId
),
'status' => AdGroupCriterionStatus::ENABLED,
'listing_group' => $listingGroupInfo
]);
return $adGroupCriterion;
}
/**
* Creates a new criterion containing a biddable unit listing group node.
*
* @param int $customerId the customer ID
* @param int $adGroupId the ad group ID
* @param string $parentAdGroupCriterionResourceName the resource name of the parent of this
* criterion
* @param ListingDimensionInfo $listingDimensionInfo the listing dimension info to be set for
* this listing group
* @param int $cpcBidMicros the CPC bid for items in this listing group. This value should be
* specified
* @return AdGroupCriterion the ad group criterion that contains the biddable unit listing
* group node
*/
private static function createListingGroupUnitBiddable(
int $customerId,
int $adGroupId,
string $parentAdGroupCriterionResourceName,
ListingDimensionInfo $listingDimensionInfo,
int $cpcBidMicros
) {
// Note: There are two approaches for creating new unit nodes:
// (1) Set the ad group resource name on the criterion (no temporary ID required).
// (2) Use a temporary ID to construct the criterion resource name and set it using
// setResourceName.
// In both cases you must set the parentAdGroupCriterionResourceName on the listing
// group for non-root nodes.
// This example demonstrates method (1).
$adGroupCriterion = new AdGroupCriterion([
// The ad group the listing group will be attached to.
'ad_group' => ResourceNames::forAdGroup($customerId, $adGroupId),
'status' => AdGroupCriterionStatus::ENABLED,
'listing_group' => new ListingGroupInfo([
// Set the type as a UNIT, which will allow the group to be biddable.
'type' => ListingGroupType::UNIT,
// Set the ad group criterion resource name for the parent listing group.
// This can include a temporary ID if the parent criterion is not yet created.
'parent_ad_group_criterion' => $parentAdGroupCriterionResourceName,
// Case values contain the listing dimension used for the node.
'case_value' => $listingDimensionInfo
]),
// Set the bid for this listing group unit.
// This will be used as the CPC bid for items that are included in this listing group.
'cpc_bid_micros' => $cpcBidMicros
]);
return $adGroupCriterion;
}
}
AddShoppingProductListingGroupTree::main();
Питон
#!/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.
"""Adds a shopping listing group tree to a shopping ad group.
The example will clear an existing listing group tree and rebuild it include the
following tree structure:
ProductCanonicalCondition NEW $0.20
ProductCanonicalCondition USED $0.10
ProductCanonicalCondition null (everything else)
ProductBrand CoolBrand $0.90
ProductBrand CheapBrand $0.01
ProductBrand null (everything else) $0.50
"""
import argparse
import sys
from google.ads.googleads.client import GoogleAdsClient
from google.ads.googleads.errors import GoogleAdsException
last_criterion_id = 0
def next_id():
"""Returns 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.
Returns:
The string representation of a negative integer.
"""
global last_criterion_id
last_criterion_id -= 1
return str(last_criterion_id)
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.")
def remove_listing_group_tree(client, customer_id, ad_group_id):
"""Removes ad group criteria for an ad group's existing listing group tree.
Args:
client: An initialized Google Ads client.
customer_id: The Google Ads customer ID.
ad_group_id: The ad group ID from which to remove the listing group
tree.
"""
# Get the GoogleAdsService client.
googleads_service = client.get_service("GoogleAdsService")
print("Removing existing listing group tree...")
# Create a search Google Ads request that will retrieve all listing groups
# where the parent ad group criterion is NULL (and hence the root node in
# the tree) for a given ad group id.
query = f"""
SELECT ad_group_criterion.resource_name
FROM ad_group_criterion
WHERE
ad_group_criterion.type = LISTING_GROUP
AND ad_group_criterion.listing_group.parent_ad_group_criterion IS NULL
AND ad_group.id = {ad_group_id}"""
results = googleads_service.search(customer_id=customer_id, query=query)
ad_group_criterion_operations = []
# Iterate over all rows to find the ad group criteria to remove.
for row in results:
criterion = row.ad_group_criterion
print(
"Found an ad group criterion with resource name: "
f"'{criterion.resource_name}'."
)
ad_group_criterion_operation = client.get_type(
"AdGroupCriterionOperation"
)
ad_group_criterion_operation.remove = criterion.resource_name
ad_group_criterion_operations.append(ad_group_criterion_operation)
if ad_group_criterion_operations:
# Remove the ad group criteria that define the listing group tree.
ad_group_criterion_service = client.get_service(
"AdGroupCriterionService"
)
response = ad_group_criterion_service.mutate_ad_group_criteria(
customer_id=customer_id, operations=ad_group_criterion_operations
)
print(f"Removed {len(response.results)} ad group criteria.")
def create_listing_group_subdivision(
client,
customer_id,
ad_group_id,
parent_ad_group_criterion_resource_name=None,
listing_dimension_info=None,
):
"""Creates a new criterion containing a subdivision listing group node.
If the parent ad group criterion resource name or listing dimension info are
not specified, this method creates a root node.
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.
parent_ad_group_criterion_resource_name: The string resource name of the
parent node to which this listing will be attached.
listing_dimension_info: A ListingDimensionInfo object containing details
for this listing.
Returns:
An AdGroupCriterionOperation containing a populated ad group criterion.
"""
# Create an ad group criterion operation and populate the criterion.
operation = client.get_type("AdGroupCriterionOperation")
ad_group_criterion = operation.create
# The resource name the criterion will be created with. This will define
# the ID for the ad group criterion.
ad_group_criterion.resource_name = client.get_service(
"AdGroupCriterionService"
).ad_group_criterion_path(customer_id, ad_group_id, next_id())
ad_group_criterion.status = client.enums.AdGroupCriterionStatusEnum.ENABLED
listing_group_info = ad_group_criterion.listing_group
# Set the type as a SUBDIVISION, which will allow the node to be the
# parent of another sub-tree.
listing_group_info.type_ = client.enums.ListingGroupTypeEnum.SUBDIVISION
# If parent_ad_group_criterion_resource_name and listing_dimension_info
# are not null, create a non-root division by setting its parent and case
# value.
if (
parent_ad_group_criterion_resource_name
and listing_dimension_info != None
):
# Set the ad group criterion resource name for the parent listing group.
# This can include a temporary ID if the parent criterion is not yet
# created.
listing_group_info.parent_ad_group_criterion = (
parent_ad_group_criterion_resource_name
)
# Case values contain the listing dimension used for the node.
client.copy_from(listing_group_info.case_value, listing_dimension_info)
return operation
def create_listing_group_unit_biddable(
client,
customer_id,
ad_group_id,
parent_ad_group_criterion_resource_name,
listing_dimension_info,
cpc_bid_micros=None,
):
"""Creates a new criterion containing a biddable unit listing group node.
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.
parent_ad_group_criterion_resource_name: The string resource name of the
parent node to which this listing will be attached.
listing_dimension_info: A ListingDimensionInfo object containing details
for this listing.
cpc_bid_micros: The cost-per-click bid for this listing in micros.
Returns:
An AdGroupCriterionOperation with a populated create field.
"""
# Note: There are two approaches for creating new unit nodes:
# (1) Set the ad group resource name on the criterion (no temporary ID
# required).
# (2) Use a temporary ID to construct the criterion resource name and set
# it to the 'resourceName' attribute.
# In both cases you must set the parent ad group criterion's resource name
# on the listing group for non-root nodes.
# This example demonstrates method (1).
operation = client.get_type("AdGroupCriterionOperation")
criterion = operation.create
criterion.ad_group = client.get_service("AdGroupService").ad_group_path(
customer_id, ad_group_id
)
criterion.status = client.enums.AdGroupCriterionStatusEnum.ENABLED
# Set the bid for this listing group unit.
# This will be used as the CPC bid for items that are included in this
# listing group.
if cpc_bid_micros:
criterion.cpc_bid_micros = cpc_bid_micros
listing_group = criterion.listing_group
# Set the type as a UNIT, which will allow the group to be biddable.
listing_group.type_ = client.enums.ListingGroupTypeEnum.UNIT
# Set the ad group criterion resource name for the parent listing group.
# This can have a temporary ID if the parent criterion is not yet created.
listing_group.parent_ad_group_criterion = (
parent_ad_group_criterion_resource_name
)
# Case values contain the listing dimension used for the node.
if listing_dimension_info != None:
client.copy_from(listing_group.case_value, listing_dimension_info)
return operation
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Add shopping product listing group tree to a shopping ad "
"group."
)
# 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=str,
required=True,
help="The ID of the ad group that will receive the listing group tree.",
)
parser.add_argument(
"-r",
"--replace_existing_tree",
action="store_true",
required=False,
default=False,
help="Optional, whether to replace the existing listing group tree on "
"the ad group if one already exists. Defaults to false.",
)
args = parser.parse_args()
# GoogleAdsClient will read the google-ads.yaml configuration file in the
# home directory if none is specified.
googleads_client = GoogleAdsClient.load_from_storage(version="v17")
try:
main(
googleads_client,
args.customer_id,
args.ad_group_id,
args.replace_existing_tree,
)
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)
Руби
#!/usr/bin/env ruby
# Encoding: utf-8
#
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This example shows how to add a shopping listing group tree to a shopping ad
# group. The example will optionally clear an existing listing group tree and
# rebuild it to include the following tree structure:
#
# ProductCanonicalCondition NEW $0.20
# ProductCanonicalCondition USED $0.10
# ProductCanonicalCondition null (everything else)
# ProductBrand CoolBrand $0.90
# ProductBrand CheapBrand $0.01
# ProductBrand null (everything else) $0.50
require 'optparse'
require 'google/ads/google_ads'
require 'date'
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
def remove_listing_group_tree(client, customer_id, ad_group_id)
ga_service = client.service.google_ads
query = <<~QUERY
SELECT
ad_group_criterion.resource_name
FROM
ad_group_criterion
WHERE
ad_group_criterion.type = LISTING_GROUP
AND
ad_group_criterion.listing_group.parent_ad_group_criterion IS NULL
AND
ad_group.id = #{ad_group_id}
QUERY
response = ga_service.search(customer_id: customer_id, query: query, page_size: PAGE_SIZE)
operations = response.map do |row|
criterion = row.ad_group_criterion
puts "Found an ad group criterion with resource name: #{criterion.resource_name}"
client.operation.remove_resource.ad_group_criterion(criterion.resource_name)
end
if operations.any?
response = client.service.ad_group_criterion.mutate_ad_group_criteria(
customer_id: customer_id,
operations: operations,
)
puts "Removed #{response.results.count} ad group criteria."
end
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_id
@id ||= 0
@id -= 1
end
def create_listing_group_subdivision(
client,
customer_id,
ad_group_id,
parent_ad_group_criterion_name = nil,
listing_dimension_info = nil
)
client.resource.ad_group_criterion do |criterion|
criterion.resource_name = client.path.ad_group_criterion(
customer_id,
ad_group_id,
next_id,
)
criterion.status = :ENABLED
criterion.listing_group = client.resource.listing_group_info do |listing_group_info|
listing_group_info.type = :SUBDIVISION
if parent_ad_group_criterion_name && listing_dimension_info
listing_group_info.parent_ad_group_criterion = parent_ad_group_criterion_name
listing_group_info.case_value = listing_dimension_info
end
end
end
end
def create_listing_group_unit_biddable(client, customer_id, ad_group_id,
parent_ad_group_criterion_name, listing_dimension_info, cpc_bid_micros)
# Note: There are two approaches for creating new unit nodes:
# (1) Set the ad group resource name on the criterion (no temporary ID
# required).
# (2) Use a temporary ID to construct the criterion resource name and set it
# using the client.path utility.
# In both cases you must set the parent ad group criterion's resource name on
# the listing group for non-root nodes.
# This example demonstrates method (1).
client.resource.ad_group_criterion do |criterion|
criterion.ad_group = client.path.ad_group(customer_id, ad_group_id)
criterion.status = :ENABLED
criterion.cpc_bid_micros = cpc_bid_micros
criterion.listing_group = client.resource.listing_group_info do |listing_group|
# The type UNIT allows the group to be biddable.
listing_group.type = :UNIT
listing_group.parent_ad_group_criterion = parent_ad_group_criterion_name
listing_group.case_value = listing_dimension_info
end
end
end
if __FILE__ == $0
PAGE_SIZE = 1000
options = {}
# The following parameter(s) should be provided to run the example. You can
# either specify these by changing the INSERT_XXX_ID_HERE values below, or on
# the command line.
#
# Parameters passed on the command line will override any parameters set in
# code.
#
# Running the example with -h will print the command line usage.
options[:customer_id] = 'INSERT_CUSTOMER_ID_HERE'
options[:ad_group_id] = 'INSERT_AD_GROUP_ID_HERE'
# Specifying any value for this field on the command line will override this
# to true.
options[:should_replace_existing_tree] = false
OptionParser.new do |opts|
opts.banner = sprintf("Usage: #{File.basename(__FILE__)} [options]")
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', String, 'Ad Group ID') do |v|
options[:ad_group_id] = v
end
opts.on('-r', '--replace-existing-tree REPLACE-EXISTING-TREE',
TrueClass, 'Create Default Listing Group') do |v|
options[:should_replace_existing_tree] = v
end
opts.separator ''
opts.separator 'Help:'
opts.on_tail('-h', '--help', 'Show this message') do
puts opts
exit
end
end.parse!
begin
add_shopping_product_listing_group_tree(
options.fetch(:customer_id).tr("-", ""),
options.fetch(:ad_group_id),
options.fetch(:should_replace_existing_tree),
)
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
Перл
#!/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 shopping listing group tree to a shopping ad
# group. The example will optionally clear an existing listing group tree and
# rebuild it to include the following tree structure:
#
# ProductCanonicalCondition NEW $0.20
# ProductCanonicalCondition USED $0.10
# ProductCanonicalCondition null (everything else)
# ProductBrand CoolBrand $0.90
# ProductBrand CheapBrand $0.01
# ProductBrand null (everything else) $0.50
use strict;
use warnings;
use utf8;
use FindBin qw($Bin);
use lib "$Bin/../../lib";
use Google::Ads::GoogleAds::Client;
use Google::Ads::GoogleAds::Utils::GoogleAdsHelper;
use Google::Ads::GoogleAds::Utils::SearchGoogleAdsIterator;
use Google::Ads::GoogleAds::V17::Resources::AdGroupCriterion;
use Google::Ads::GoogleAds::V17::Common::ListingGroupInfo;
use Google::Ads::GoogleAds::V17::Common::ListingDimensionInfo;
use Google::Ads::GoogleAds::V17::Common::ProductConditionInfo;
use Google::Ads::GoogleAds::V17::Common::ProductBrandInfo;
use Google::Ads::GoogleAds::V17::Enums::ListingGroupTypeEnum
qw(SUBDIVISION UNIT);
use Google::Ads::GoogleAds::V17::Enums::AdGroupCriterionStatusEnum qw(ENABLED);
use Google::Ads::GoogleAds::V17::Enums::ProductConditionEnum qw(NEW USED);
use
Google::Ads::GoogleAds::V17::Services::AdGroupCriterionService::AdGroupCriterionOperation;
use
Google::Ads::GoogleAds::V17::Services::GoogleAdsService::SearchGoogleAdsRequest;
use Google::Ads::GoogleAds::V17::Utils::ResourceNames;
use Getopt::Long qw(:config auto_help);
use Pod::Usage;
use Cwd qw(abs_path);
use Data::Uniqid qw(uniqid);
# 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";
my $replace_existing_tree = undef;
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::V17::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::V17::Common::ListingDimensionInfo->new({
productCondition =>
Google::Ads::GoogleAds::V17::Common::ProductConditionInfo->new({
condition => NEW
})}
),
200000
);
push @$operations,
Google::Ads::GoogleAds::V17::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::V17::Common::ListingDimensionInfo->new({
productCondition =>
Google::Ads::GoogleAds::V17::Common::ProductConditionInfo->new({
condition => USED
})}
),
100000
);
push @$operations,
Google::Ads::GoogleAds::V17::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::V17::Common::ListingDimensionInfo->new({
# All sibling nodes must have the same dimension type, even if they
# don't contain a bid.
productCondition =>
Google::Ads::GoogleAds::V17::Common::ProductConditionInfo->new()}));
push @$operations,
Google::Ads::GoogleAds::V17::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::V17::Common::ListingDimensionInfo->new({
productBrand =>
Google::Ads::GoogleAds::V17::Common::ProductBrandInfo->new(
{value => "CoolBrand"})}
),
900000
);
push @$operations,
Google::Ads::GoogleAds::V17::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::V17::Common::ListingDimensionInfo->new({
productBrand =>
Google::Ads::GoogleAds::V17::Common::ProductBrandInfo->new(
{value => "CheapBrand"})}
),
10000
);
push @$operations,
Google::Ads::GoogleAds::V17::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::V17::Common::ListingDimensionInfo->new({
productBrand =>
Google::Ads::GoogleAds::V17::Common::ProductBrandInfo->new()}
),
50000
);
push @$operations,
Google::Ads::GoogleAds::V17::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;
}
# Removes all the ad group criteria that define the existing listing group
# tree for an ad group.
sub remove_listing_group_tree {
my ($api_client, $customer_id, $ad_group_id) = @_;
my $search_query =
"SELECT ad_group_criterion.resource_name " .
"FROM ad_group_criterion WHERE ad_group_criterion.type = LISTING_GROUP " .
"AND ad_group_criterion.listing_group.parent_ad_group_criterion IS NULL " .
"AND ad_group.id = $ad_group_id";
# Create a search Google Ads request that will retrieve all listing groups
# where the parent ad group criterion is NULL (and hence the root node in
# the tree) for a given ad group id.
my $search_request =
Google::Ads::GoogleAds::V17::Services::GoogleAdsService::SearchGoogleAdsRequest
->new({
customerId => $customer_id,
query => $search_query
});
# Get the GoogleAdsService.
my $google_ads_service = $api_client->GoogleAdsService();
my $iterator = Google::Ads::GoogleAds::Utils::SearchGoogleAdsIterator->new({
service => $google_ads_service,
request => $search_request
});
my $operations = [];
# Iterate over all rows in all pages to find the ad group criterion to remove.
while ($iterator->has_next) {
my $google_ads_row = $iterator->next;
my $ad_group_criterion = $google_ads_row->{adGroupCriterion};
printf "Found an ad group criterion with the resource name: '%s'.\n",
$ad_group_criterion->{resourceName};
# Create an ad group criterion operation.
my $ad_group_criterion_operation =
Google::Ads::GoogleAds::V17::Services::AdGroupCriterionService::AdGroupCriterionOperation
->new({
remove => $ad_group_criterion->{resourceName}});
push @$operations, $ad_group_criterion_operation;
}
if (scalar @$operations) {
# Remove the ad group criterion that define the listing group tree.
my $ad_group_criteria_response =
$api_client->AdGroupCriterionService()->mutate({
customerId => $customer_id,
operations => $operations
});
printf "Removed %d ad group criteria.\n",
scalar @{$ad_group_criteria_response->{results}};
}
}
# Creates a new criterion containing a subdivision listing group node. If
# the parent ad group criterion resource name is not specified, this method
# creates a root node.
sub create_listing_group_subdivision {
my ($customer_id, $ad_group_id, $parent_ad_group_criterion_resource_name,
$listing_dimension_info)
= @_;
my $listing_group_info =
Google::Ads::GoogleAds::V17::Common::ListingGroupInfo->new({
# Set the type as a SUBDIVISION, which will allow the node to be the
# parent of another sub-tree.
'type' => SUBDIVISION
});
# If $parent_ad_group_criterion_resource_name and $listing_dimension_info
# are not null, create a non-root division by setting its parent and case value.
if ($parent_ad_group_criterion_resource_name and $listing_dimension_info) {
# Set the ad group criterion resource name for the parent listing group.
# This can include a temporary ID if the parent criterion is not yet created.
$listing_group_info->{parentAdGroupCriterion} =
$parent_ad_group_criterion_resource_name;
# Case values contain the listing dimension used for the node.
$listing_group_info->{caseValue} = $listing_dimension_info;
}
my $ad_group_criterion =
Google::Ads::GoogleAds::V17::Resources::AdGroupCriterion->new({
# The resource name the criterion will be created with. This will define
# the ID for the ad group criterion.
resourceName =>
Google::Ads::GoogleAds::V17::Utils::ResourceNames::ad_group_criterion(
$customer_id, $ad_group_id, next_id()
),
status => ENABLED,
listingGroup => $listing_group_info
});
return $ad_group_criterion;
}
# Creates a new criterion containing a biddable unit listing group node.
sub create_listing_group_unit_biddable {
my ($customer_id, $ad_group_id, $parent_ad_group_criterion_resource_name,
$listing_dimension_info, $cpc_bid_micros)
= @_;
# Note: There are two approaches for creating new unit nodes:
# (1) Set the ad group resource name on the criterion (no temporary ID
# required).
# (2) Use a temporary ID to construct the criterion resource name and set it
# to the 'resourceName' attribute.
# In both cases you must set the parent ad group criterion's resource name on
# the listing group for non-root nodes.
# This example demonstrates method (1).
my $ad_group_criterion =
Google::Ads::GoogleAds::V17::Resources::AdGroupCriterion->new({
adGroup => Google::Ads::GoogleAds::V17::Utils::ResourceNames::ad_group(
$customer_id, $ad_group_id
),
status => ENABLED,
listingGroup =>
Google::Ads::GoogleAds::V17::Common::ListingGroupInfo->new({
# Set the type as a UNIT, which will allow the group to be biddable.
type => UNIT,
# Set the ad group criterion resource name for the parent listing group.
# This can include a temporary ID if the parent criterion is not yet created.
parentAdGroupCriterion => $parent_ad_group_criterion_resource_name,
# Case values contain the listing dimension used for the node.
caseValue => $listing_dimension_info
}
),
# Set the bid for this listing group unit.
# This will be used as the CPC bid for items that are included in this
# listing group.
cpcBidMicros => $cpc_bid_micros
});
return $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,
"replace_existing_tree=s" => \$replace_existing_tree
);
# 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);
# Call the example.
add_shopping_product_listing_group_tree($api_client, $customer_id =~ s/-//gr,
$ad_group_id, $replace_existing_tree);
=pod
=head1 NAME
add_shopping_product_listing_group_tree
=head1 DESCRIPTION
This example shows how to add a shopping listing group tree to a shopping ad group.
The example will optionally clear an existing listing group tree and rebuild it to
include the following tree structure:
ProductCanonicalCondition NEW $0.20
ProductCanonicalCondition USED $0.10
ProductCanonicalCondition null (everything else)
ProductBrand CoolBrand $0.90
ProductBrand CheapBrand $0.01
ProductBrand null (everything else) $0.50
=head1 SYNOPSIS
add_shopping_product_listing_group_tree.pl [options]
-help Show the help message.
-customer_id The Google Ads customer ID.
-ad_group_id The ad group ID.
-replace_existing_tree [optional] Replace the existing listing group tree
on the ad group, if it already exists.
=cut