Skip to content

Working with Product Partition Trees

Anash P. Oommen edited this page May 25, 2016 · 6 revisions

Introduction

AdWords API .NET library provides a set of shopping utility classes to simplify working with product partitions (also known as product groups) in shopping campaigns. These utility classes provides two broad set of functionality:

  1. Ability to work with product partition as a single tree instead of a list of independent adgroup criteria
  2. Factory methods for creating various criteria types.

This guide shows you how to work with the shopping utility classes.

Main classes

Shopping utilities consists of three main classes.

Class name Description
ProductPartitionTree Represents the product partition tree in a shopping ad group. It is a container for a root ProductPartitionNode, and also handles applying changes made to the tree under the root.
ProductPartitionNode Represents a node within the product partition tree. A product partition node wraps a shopping product partition criterion, and has functionality for setting bids, excluding criteria, as well as working with child nodes.
ProductDimensions A class that provides factory methods for constructing various product dimension nodes.

Creating a product partition tree

There are two ways of creating a product partition tree.

1. Download the tree from the ad group

You can use the DownloadAdGroupTree method to download a product partition tree from a given ad group as follows:

ProductPartitionTree partitionTree =
    ProductPartitionTree.DownloadAdGroupTree(user, adGroupId);

2. Build the tree from an existing set of criteria

If you have a list of existing ProductPartition criteria, then you may create a ProductPartitionTree as follows:

List<AdGroupCriterion> existingAdGroupCriteria = new List<AdGroupCriterion>();
long adGroupId = INSERT_ADGROUP_ID_HERE;
…
ProductPartitionTree partitionTree = ProductPartitionTree.CreateAdGroupTree(
    adGroupId, existingAdGroupCriteria);

Note that this method will ignore the adgroup ID in individual AdGroupCriterion objects and the ID specified in adGroupId parameter will be used.

You may also construct a ProductPartitionTree from a list of fresh criteria that doesn’t belong to any ad group as follows:

List<AdGroupCriterion> newAdGroupCriteria = new List<AdGroupCriterion>();
…
ProductPartitionTree partitionTree = ProductPartitionTree.CreateAdGroupTree(
    newAdGroupCriteria);

Navigating the tree

To navigate the tree, you need to start with the root node of the ProductPartitionTree. You can then walk the tree recursively as follows:

ProductPartitionTree tree = ...;
ProductPartitionNode rootNode = tree.Root;

WalkTree(rootNode);

void WalkTree(ProductPartitionNode root) {
  ProductDimension dimension = root.Dimension;
  // Process the node or the underlying dimension.
  // ...
  if (root.IsSubdivision) {
    foreach (ProductPartitionNode childNode in root.Children) {
      WalkTree(childNode);
    }
  }
}

Adding new child nodes

To add a new child node, you need to create a product dimension (or a ProductPartitionNode) and use the AddChild method to add it as a child node of the desired parent node. Also, keep in mind that you can add a child node to an existing node only if it is a subdivision node. It it isn’t, you need to convert the node first into a subdivision node using the AsSubdivision() method. The code snippet below shows the details:

ProductPartitionNode rootNode = tree.Root;

// Ensure that root node is a subdivision.
rootNode.AsSubdivision();

// Add a unit node under root node for brand = "CoolBrand".
ProductPartitionNode coolBrandNode = rootNode.AddChild(
    ProductDimensions.CreateBrand("CoolBrand"));

The ProductDimensions class provides factory methods to help create various ProductDimension types. The table below lists the details:

Method Description
CreateType(ProductDimensionType productDimensionType, string productTypeValue)
CreateType(ProductDimensionType productDimensionType)
Creates a new ProductType node.
CreateCanonicalCondition(
ProductCanonicalConditionCondition condition)
CreateCanonicalCondition()
Creates a new ProductCanonicalCondition node.
CreateBiddingCategory(ProductDimensionType productDimensionType, long biddingCategoryId)
CreateBiddingCategory(ProductDimensionType productDimensionType)
Creates a ProductBiddingCategory node.
CreateOfferId(string offerId)
CreateOfferId()
Creates a ProductOfferId node.
CreateBrand(string brand)
CreateBrand()
Creates a ProductBrand node.
CreateCustomAttribute(ProductDimensionType productDimensionType, string attributeValue)
CreateCustomAttribute(ProductDimensionType productDimensionType)
Creates a ProductCustomAttribute node
CreateChannel(ShoppingProductChannel channel)
CreateChannel()
Creates a ProductChannel node.
CreateChannelExclusivity(
ShoppingProductChannelExclusivity channelExclusivity)
CreateChannelExclusivity()
Creates a ProductChannelExclusivity node.

Every Subdivision node should have a catch-all node called the Everything else node. In the table above, the second function in each row creates an Everything else node for the corresponding product dimension.

Removing child nodes

You may remove a child node using the RemoveChild method. This method will throw an error if the desired child node is not found under the parent node. You may use the HasChild method to check if a given parent node has a child node that matches a given dimension, then use the GetChild method to get the corresponding ProductPartitionNode, and finally remove the node using RemoveChild method as shown below:

ProductPartitionNode rootNode = tree.Root;

// Create a product brand node for “CoolBrand”.
ProductBrand coolBrand = ProductDimensions.CreateBrand("CoolBrand");

// Search and remove “CoolBrand” from the root.
if (rootNode.HasChild(coolBrand)) {
  ProductPartitionNode childNode = rootNode.GetChild(coolBrand);
  childNode.RemoveChild(coolBrand);
}

Bidding and Exclusion

You may exclude or bid on a leaf node (also called a Unit node), but not on a subdivision node. ProductPartitionNode has utility methods to check if a given node is a unit not. If a node isn’t of the correct type, you may change the node type by using AsBiddableUnit or AsExcludedUnit respectively. Keep in mind that if either of these methods is invoked for a subdivision node, then all its child nodes will be removed automatically.

The following code snippet shows the usage of these methods:

// Select your root node.
ProductPartitionNode parentNode = partitionTree.Root;

// Ensure that parentNode is a subdivision.
parentNode = parentNode.AsSubdivision();

// Add a unit node for condition = NEW.
ProductPartitionNode newConditionNode = parentNode.AddChild(
    ProductDimensions.CreateCanonicalCondition(
        ProductCanonicalConditionCondition.NEW));
newConditionNode.AsBiddableUnit().CpcBid = 200000;

// Exclude everything else.
ProductPartitionNode everythingElseNode = parentNode.AddChild(
    ProductDimensions.CreateCanonicalCondition()).AsExCludedUnit();

Pushing changes to AdWords

Once you have made all the tree transformations, you can generate a list of operations corresponding to the changes you made using the GetMutateOperations method of the product partition tree, and then use AdGroupCriterionService.mutate method to push the changes to AdWords. The following code snippet shows how this may be done.

// Make the mutate request, using the operations returned by
// the ProductPartitionTree.
AdGroupCriterionOperation[] mutateOperations =
    partitionTree.GetMutateOperations();

if (mutateOperations.Length == 0) {
  Console.WriteLine("Skipping the mutate call because the original " +
      "tree and the current tree are logically identical.");
} else {
  adGroupCriterionService.mutate(mutateOperations);
}

// The request was successful, so create a new ProductPartitionTree
// based on the updated state of the ad group.
partitionTree = ProductPartitionTree.DownloadAdGroupTree(user, adGroupId);

Code example

You can refer to the AddProductPartitionTree code example under ShoppingCampaigns category for an end-to-end code example.

Final notes

While ProductPartitionTree class simplifies product partition management, it doesn’t protect you from building a tree that is syntactically correct, but logically invalid. E.g. It doesn’t validate that the tree can only be 7 levels deep, you cannot partition by the same criteria more than once in a tree hierarchy, etc. It is the developer’s responsibility to ensure these conditions are met when building the tree. If you try to upload a tree that is logically invalid, then AdGroupCriterionService.mutate call will fail, and you may examine the response to figure out what went wrong.