The AdWords API will sunset on April 27, 2022. Migrate to the Google Ads API to take advantage of the latest Google Ads features.

Shopping Campaign Samples

The code samples below provide examples for managing Shopping campaigns using the AdWords API. Client Library.

Build a product partition tree for an ad group

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

Imports Google.Api.Ads.AdWords.Lib
Imports Google.Api.Ads.AdWords.v201809
Imports Google.Api.Ads.AdWords.Util.Shopping.v201809

Namespace Google.Api.Ads.AdWords.Examples.VB.v201809
    ''' <summary>
    ''' This code example creates a ProductPartition tree.
    ''' </summary>
    Public Class AddProductPartitionTree
        Inherits ExampleBase

        ''' <summary>
        ''' Main method, to run this code example as a standalone application.
        ''' </summary>
        ''' <param name="args">The command line arguments.</param>
        Public Shared Sub Main(ByVal args As String())
            Dim codeExample As New AddProductPartitionTree
            Console.WriteLine(codeExample.Description)
            Try
                Dim adGroupId As Long = Long.Parse("INSERT_ADGROUP_ID_HERE")
                codeExample.Run(New AdWordsUser, adGroupId)
            Catch e As Exception
                Console.WriteLine("An exception occurred while running this code example. {0}",
                                  ExampleUtilities.FormatException(e))
            End Try
        End Sub

        ''' <summary>
        ''' Returns a description about the code example.
        ''' </summary>
        Public Overrides ReadOnly Property Description() As String
            Get
                Return "This code example creates a ProductPartition tree."
            End Get
        End Property

        ''' <summary>
        ''' Runs the code example.
        ''' </summary>
        ''' <param name="user">The AdWords user.</param>
        ''' <param name="adGroupId">The ad group to which product partition is
        ''' added.</param>
        Public Sub Run(ByVal user As AdWordsUser, ByVal adGroupId As Long)
            Using adGroupCriterionService As AdGroupCriterionService = CType(
                user.GetService(
                    AdWordsService.v201809.AdGroupCriterionService),
                AdGroupCriterionService)

                ' Build a new ProductPartitionTree using the ad group's current set of criteria.
                Dim partitionTree As ProductPartitionTree =
                        ProductPartitionTree.DownloadAdGroupTree(user, adGroupId)

                Console.WriteLine("Original tree: {0}", partitionTree)

                ' Clear out any existing criteria.
                Dim rootNode As ProductPartitionNode = partitionTree.Root.RemoveAllChildren()

                ' Make the root node a subdivision.
                rootNode = rootNode.AsSubdivision()

                ' Add a unit node for condition = NEW.
                Dim newConditionNode As ProductPartitionNode = rootNode.AddChild(
                    ProductDimensions.CreateCanonicalCondition(
                        ProductCanonicalConditionCondition.NEW))
                newConditionNode.AsBiddableUnit().CpcBid = 200000

                Dim usedConditionNode As ProductPartitionNode = rootNode.AddChild(
                    ProductDimensions.CreateCanonicalCondition(
                        ProductCanonicalConditionCondition.USED))
                usedConditionNode.AsBiddableUnit().CpcBid = 100000

                ' Add a subdivision node for condition = null (everything else).
                Dim otherConditionNode As ProductPartitionNode =
                        rootNode.AddChild(ProductDimensions.CreateCanonicalCondition()).
                        AsSubdivision()

                ' Add a unit node under condition = null for brand = "CoolBrand".
                Dim coolBrandNode As ProductPartitionNode = otherConditionNode.AddChild(
                    ProductDimensions.CreateBrand("CoolBrand"))
                coolBrandNode.AsBiddableUnit().CpcBid = 900000L

                ' Add a unit node under condition = null for brand = "CheapBrand".
                Dim cheapBrandNode As ProductPartitionNode = otherConditionNode.AddChild(
                    ProductDimensions.CreateBrand("CheapBrand"))
                cheapBrandNode.AsBiddableUnit().CpcBid = 10000L

                ' Add a subdivision node under condition = null for brand = null (everything else).
                Dim otherBrandNode As ProductPartitionNode = otherConditionNode.AddChild(
                    ProductDimensions.CreateBrand()).AsSubdivision()

                ' Add unit nodes under condition = null/brand = null.
                ' The value for each bidding category is a fixed ID for a specific
                ' category. You can retrieve IDs for categories from the ConstantDataService.
                ' See the 'GetProductCategoryTaxonomy' example for more details.

                ' Add a unit node under condition = null/brand = null for product type
                ' level 1 = 'Luggage & Bags'.
                Dim luggageAndBagNode As ProductPartitionNode = otherBrandNode.AddChild(
                    ProductDimensions.CreateBiddingCategory(
                        ProductDimensionType.BIDDING_CATEGORY_L1,
                        - 5914235892932915235L))
                luggageAndBagNode.AsBiddableUnit().CpcBid = 750000L

                ' Add a unit node under condition = null/brand = null for product type
                ' level 1 = null (everything else).
                Dim everythingElseNode As ProductPartitionNode = otherBrandNode.AddChild(
                    ProductDimensions.CreateBiddingCategory(
                        ProductDimensionType.BIDDING_CATEGORY_L1))
                everythingElseNode.AsBiddableUnit().CpcBid = 110000L

                Try
                    ' Make the mutate request, using the operations returned by the
                    ' ProductPartitionTree.
                    Dim mutateOperations As AdGroupCriterionOperation() =
                            partitionTree.GetMutateOperations()

                    If mutateOperations.Length = 0 Then
                        Console.WriteLine(
                            "Skipping the mutate call because the original tree and the " &
                            "current tree are logically identical.")
                    Else
                        adGroupCriterionService.mutate(mutateOperations)
                    End If

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

                    Console.WriteLine("Final tree: {0}", partitionTree)
                Catch e As Exception
                    Throw New System.ApplicationException("Failed to add bid modifiers to adgroup.",
                                                          e)
                End Try
            End Using
        End Sub
    End Class
End Namespace

Set a product scope for a campaign

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

Imports Google.Api.Ads.AdWords.Lib
Imports Google.Api.Ads.AdWords.v201809

Imports System
Imports System.Collections.Generic
Imports System.IO

Namespace Google.Api.Ads.AdWords.Examples.VB.v201809
    ''' <summary>
    ''' This code example restricts the products that will be included in the
    ''' campaign by setting a ProductScope.
    ''' </summary>
    Public Class AddProductScope
        Inherits ExampleBase

        ''' <summary>
        ''' Returns a description about the code example.
        ''' </summary>
        Public Overrides ReadOnly Property Description() As String
            Get
                Return "This code example restricts the products that will be included in the " &
                       "campaign by setting a ProductScope."
            End Get
        End Property

        ''' <summary>
        ''' Main method, to run this code example as a standalone application.
        ''' </summary>
        ''' <param name="args">The command line arguments.</param>
        Public Shared Sub Main(ByVal args As String())
            Dim codeExample As New AddProductScope
            Console.WriteLine(codeExample.Description)
            Try
                Dim campaignId As Long = Long.Parse("INSERT_CAMPAIGN_ID_HERE")
                codeExample.Run(New AdWordsUser, campaignId)
            Catch e As Exception
                Console.WriteLine("An exception occurred while running this code example. {0}",
                                  ExampleUtilities.FormatException(e))
            End Try
        End Sub

        ''' <summary>
        ''' Runs the code example.
        ''' </summary>
        ''' <param name="user">The AdWords user.</param>
        ''' <param name="campaignId">The campaign id to add product scope.</param>
        Public Sub Run(ByVal user As AdWordsUser, ByVal campaignId As Long)
            Using campaignCriterionService As CampaignCriterionService = CType(
                user.GetService(
                    AdWordsService.v201809.CampaignCriterionService),
                CampaignCriterionService)

                Dim productScope As New ProductScope()
                ' This set of dimensions is for demonstration purposes only. It would be
                ' extremely unlikely that you want to include so many dimensions in your
                ' product scope.
                Dim nexusBrand As New ProductBrand()
                nexusBrand.value = "Nexus"

                Dim newProducts As New ProductCanonicalCondition()
                newProducts.condition = ProductCanonicalConditionCondition.NEW

                Dim customAttribute As New ProductCustomAttribute()
                customAttribute.type = ProductDimensionType.CUSTOM_ATTRIBUTE_0
                customAttribute.value = "my attribute value"

                Dim bookOffer As New ProductOfferId()
                bookOffer.value = "book1"

                Dim mediaProducts As New ProductType()
                mediaProducts.type = ProductDimensionType.PRODUCT_TYPE_L1
                mediaProducts.value = "Media"

                Dim bookProducts As New ProductType()
                bookProducts.type = ProductDimensionType.PRODUCT_TYPE_L2
                bookProducts.value = "Books"

                ' The value for the bidding category is a fixed ID for the
                ' 'Luggage & Bags' category. You can retrieve IDs for categories from
                ' the ConstantDataService. See the 'GetProductCategoryTaxonomy' example
                ' for more details.
                Dim luggageBiddingCategory As New ProductBiddingCategory()
                luggageBiddingCategory.type = ProductDimensionType.BIDDING_CATEGORY_L1
                luggageBiddingCategory.value = - 5914235892932915235

                productScope.dimensions = New ProductDimension() { _
                                                                     nexusBrand, newProducts,
                                                                     bookOffer, mediaProducts,
                                                                     luggageBiddingCategory
                                                                 }

                Dim campaignCriterion As New CampaignCriterion()
                campaignCriterion.campaignId = campaignId
                campaignCriterion.criterion = productScope

                ' Create operation.
                Dim operation As New CampaignCriterionOperation()
                operation.operand = campaignCriterion
                operation.operator = [Operator].ADD

                Try
                    ' Make the mutate request.
                    Dim result As CampaignCriterionReturnValue = campaignCriterionService.mutate(
                        New CampaignCriterionOperation() {operation})

                    Console.WriteLine("Created a ProductScope criterion with ID '{0}'",
                                      result.value(0).criterion.id)
                Catch e As Exception
                    Throw _
                        New System.ApplicationException("Failed to set shopping product scope.", e)
                End Try
            End Using
        End Sub
    End Class
End Namespace

Add a Shopping campaign

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

Imports Google.Api.Ads.AdWords.Lib
Imports Google.Api.Ads.AdWords.Util.Shopping.v201809
Imports Google.Api.Ads.AdWords.v201809

Namespace Google.Api.Ads.AdWords.Examples.VB.v201809
    ''' <summary>
    ''' This code example adds a Shopping campaign.
    ''' </summary>
    Public Class AddShoppingCampaign
        Inherits ExampleBase

        ''' <summary>
        ''' Returns a description about the code example.
        ''' </summary>
        Public Overrides ReadOnly Property Description() As String
            Get
                Return "This code example adds a Shopping campaign."
            End Get
        End Property

        ''' <summary>
        ''' Main method, to run this code example as a standalone application.
        ''' </summary>
        ''' <param name="args">The command line arguments.</param>
        Public Shared Sub Main(ByVal args As String())
            Dim codeExample As New AddShoppingCampaign
            Console.WriteLine(codeExample.Description)
            Try
                Dim budgetId As Long = Long.Parse("INSERT_BUDGET_ID_HERE")
                Dim merchantId As Long = Long.Parse("INSERT_MERCHANT_ID_HERE")
                Dim createDefaultPartition As Boolean = False
                codeExample.Run(New AdWordsUser, budgetId, merchantId, createDefaultPartition)
            Catch e As Exception
                Console.WriteLine("An exception occurred while running this code example. {0}",
                                  ExampleUtilities.FormatException(e))
            End Try
        End Sub

        ''' <summary>
        ''' Runs the code example.
        ''' </summary>
        ''' <param name="user">The AdWords user.</param>
        ''' <param name="budgetId">The budget id.</param>
        ''' <param name="merchantId">The Merchant Center account id.</param>
        ''' <param name="createDefaultPartition">If set to true, a default
        ''' partition will be created. If running the AddProductPartition.cs
        ''' example right after this example, make sure this stays set to
        ''' false.</param>
        Public Sub Run(ByVal user As AdWordsUser, ByVal budgetId As Long, ByVal merchantId As Long,
                       ByVal createDefaultPartition As Boolean)
            Try
                Dim campaign As Campaign = CreateCampaign(user, budgetId, merchantId)
                Console.WriteLine("Campaign with name '{0}' and ID '{1}' was added.", campaign.name,
                                  campaign.id)

                Dim adGroup As AdGroup = CreateAdGroup(user, campaign)
                Console.WriteLine("Ad group with name '{0}' and ID '{1}' was added.", adGroup.name,
                                  adGroup.id)

                Dim adGroupAd As AdGroupAd = CreateProductAd(user, adGroup)
                Console.WriteLine("Product ad with ID {0}' was added.", adGroupAd.ad.id)

                If (createDefaultPartition) Then
                    CreateDefaultPartitionTree(user, adGroup.id)
                End If

            Catch e As Exception
                Throw New System.ApplicationException("Failed to create shopping campaign.", e)
            End Try
        End Sub

        ''' <summary>
        ''' Creates the default partition.
        ''' </summary>
        ''' <param name="user">The AdWords user.</param>
        ''' <param name="adGroupId">The ad group ID.</param>
        Private Sub CreateDefaultPartitionTree(ByVal user As AdWordsUser, ByVal adGroupId As Long)
            ' Get the AdGroupCriterionService.
            Dim adGroupCriterionService As AdGroupCriterionService = CType(
                user.GetService(
                    AdWordsService.v201809.AdGroupCriterionService),
                AdGroupCriterionService)

            ' Build a New ProductPartitionTree using an empty set of criteria.
            Dim partitionTree As ProductPartitionTree =
                    ProductPartitionTree.CreateAdGroupTree(adGroupId,
                                                           New List(Of AdGroupCriterion)())
            partitionTree.Root.AsBiddableUnit().CpcBid = 1000000

            Try
                ' Make the mutate request, using the operations returned by the
                ' ProductPartitionTree.
                Dim mutateOperations As AdGroupCriterionOperation() =
                        partitionTree.GetMutateOperations()

                If mutateOperations.Length = 0 Then
                    Console.WriteLine(
                        "Skipping the mutate call because the original tree and the current " +
                        "tree are logically identical.")
                Else
                    adGroupCriterionService.mutate(mutateOperations)
                End If

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

                Console.WriteLine("Final tree: {0}", partitionTree)
            Catch e As Exception
                Throw _
                    New System.ApplicationException("Failed to set shopping product partition.", e)
            End Try
        End Sub

        ''' <summary>
        ''' Creates the Product Ad.
        ''' </summary>
        ''' <param name="user">The AdWords user.</param>
        ''' <param name="adGroup">The ad group.</param>
        ''' <returns>The Product Ad.</returns>
        Private Function CreateProductAd(ByVal user As AdWordsUser,
                                         ByVal adGroup As AdGroup) As AdGroupAd
            Using adGroupAdService As AdGroupAdService = CType(
                user.GetService(
                    AdWordsService.v201809.AdGroupAdService),
                AdGroupAdService)

                ' Create product ad.
                Dim productAd As New ProductAd()

                ' Create ad group ad.
                Dim adGroupAd As New AdGroupAd()
                adGroupAd.adGroupId = adGroup.id
                adGroupAd.ad = productAd

                ' Create operation.
                Dim operation As New AdGroupAdOperation()
                operation.operand = adGroupAd
                operation.operator = [Operator].ADD

                ' Make the mutate request.
                Dim retval As AdGroupAdReturnValue = adGroupAdService.mutate(
                    New AdGroupAdOperation() {operation})

                Return retval.value(0)
            End Using
        End Function

        ''' <summary>
        ''' Creates the ad group in a Shopping campaign.
        ''' </summary>
        ''' <param name="user">The AdWords user.</param>
        ''' <param name="campaign">The Shopping campaign.</param>
        ''' <returns>The ad group.</returns>
        Private Function CreateAdGroup(ByVal user As AdWordsUser,
                                       ByVal campaign As Campaign) As AdGroup
            Using adGroupService As AdGroupService = CType(
                user.GetService(
                    AdWordsService.v201809.AdGroupService),
                AdGroupService)
                ' Create ad group.
                Dim adGroup As New AdGroup()
                adGroup.campaignId = campaign.id
                adGroup.name = "Ad Group #" & ExampleUtilities.GetRandomString()

                ' Create operation.
                Dim operation As New AdGroupOperation()
                operation.operand = adGroup
                operation.operator = [Operator].ADD

                ' Make the mutate request.
                Dim retval As AdGroupReturnValue = adGroupService.mutate(
                    New AdGroupOperation() {operation})
                Return retval.value(0)
            End Using
        End Function

        ''' <summary>
        ''' Creates the shopping campaign.
        ''' </summary>
        ''' <param name="user">The AdWords user.</param>
        ''' <param name="budgetId">The budget id.</param>
        ''' <param name="merchantId">The Merchant Center id.</param>
        ''' <returns>The Shopping campaign.</returns>
        Private Function CreateCampaign(ByVal user As AdWordsUser, ByVal budgetId As Long,
                                        ByVal merchantId As Long) As Campaign
            ' Get the required services.
            Dim campaignService As CampaignService = CType(
                user.GetService(
                    AdWordsService.v201809.CampaignService),
                CampaignService)

            ' Create campaign.
            Dim campaign As New Campaign()
            campaign.name = "Shopping campaign #" & ExampleUtilities.GetRandomString()

            ' The advertisingChannelType is what makes this a Shopping campaign.
            campaign.advertisingChannelType = AdvertisingChannelType.SHOPPING

            ' Recommendation: Set the campaign to PAUSED when creating it to prevent
            ' the ads from immediately serving. Set to ENABLED once you've added
            ' targeting and the ads are ready to serve.
            campaign.status = CampaignStatus.PAUSED

            ' Set shared budget (required).
            campaign.budget = New Budget()
            campaign.budget.budgetId = budgetId

            ' Set bidding strategy (required).
            Dim biddingStrategyConfiguration As New BiddingStrategyConfiguration()
            biddingStrategyConfiguration.biddingStrategyType = BiddingStrategyType.MANUAL_CPC

            campaign.biddingStrategyConfiguration = biddingStrategyConfiguration

            ' All Shopping campaigns need a ShoppingSetting.
            Dim shoppingSetting As New ShoppingSetting()
            shoppingSetting.salesCountry = "US"
            shoppingSetting.campaignPriority = 0
            shoppingSetting.merchantId = merchantId

            ' Enable Local Inventory Ads in your campaign.
            shoppingSetting.enableLocal = True
            campaign.settings = New Setting() {shoppingSetting}

            ' Create operation.
            Dim campaignOperation As New CampaignOperation()
            campaignOperation.operand = campaign
            campaignOperation.operator = [Operator].ADD

            ' Make the mutate request.
            Dim retval As CampaignReturnValue = campaignService.mutate(
                New CampaignOperation() {campaignOperation})

            Return retval.value(0)
        End Function
    End Class
End Namespace

Get the set of product bidding categories

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

Imports Google.Api.Ads.AdWords.Lib
Imports Google.Api.Ads.AdWords.v201809

Imports System
Imports System.Collections.Generic
Imports System.IO

Namespace Google.Api.Ads.AdWords.Examples.VB.v201809
    ''' <summary>
    ''' This code example fetches the set of valid ProductBiddingCategories.
    ''' </summary>
    Public Class GetProductCategoryTaxonomy
        Inherits ExampleBase

        ''' <summary>
        ''' Stores details about a product category and its hierarchy.
        ''' </summary>
        Class ProductCategory
            ''' <summary>
            ''' The product category id.
            ''' </summary>
            Private idField As Long

            ''' <summary>
            ''' The product category name.
            ''' </summary>
            Private nameField As String

            ''' <summary>
            ''' The product category children.
            ''' </summary>
            Private childrenField As New List(Of ProductCategory)

            ''' <summary>
            ''' Gets or sets the product category id.
            ''' </summary>
            Public Property Id() As Long
                Get
                    Return idField
                End Get
                Set(ByVal value As Long)
                    idField = value
                End Set
            End Property

            ''' <summary>
            ''' Gets or sets the product category name.
            ''' </summary>
            Public Property Name() As String
                Get
                    Return nameField
                End Get
                Set(ByVal value As String)
                    nameField = value
                End Set
            End Property

            ''' <summary>
            ''' Gets or sets the product category children.
            ''' </summary>
            Public ReadOnly Property Children() As List(Of ProductCategory)
                Get
                    Return childrenField
                End Get
            End Property
        End Class

        ''' <summary>
        ''' Returns a description about the code example.
        ''' </summary>
        Public Overrides ReadOnly Property Description() As String
            Get
                Return "This code example fetches the set of valid ProductBiddingCategories."
            End Get
        End Property

        ''' <summary>
        ''' Main method, to run this code example as a standalone application.
        ''' </summary>
        ''' <param name="args">The command line arguments.</param>
        Public Shared Sub Main(ByVal args As String())
            Dim codeExample As New GetProductCategoryTaxonomy
            Console.WriteLine(codeExample.Description)
            Try
                codeExample.Run(New AdWordsUser)
            Catch e As Exception
                Console.WriteLine("An exception occurred while running this code example. {0}",
                                  ExampleUtilities.FormatException(e))
            End Try
        End Sub

        ''' <summary>
        ''' Runs the code example.
        ''' </summary>
        ''' <param name="user">The AdWords user.</param>
        Public Sub Run(ByVal user As AdWordsUser)
            Using constantDataService As ConstantDataService = CType(
                user.GetService(
                    AdWordsService.v201809.ConstantDataService),
                ConstantDataService)

                Dim selector As New Selector()
                selector.predicates = New Predicate() { _
                                                          Predicate.In(
                                                              ProductBiddingCategoryData.Fields.
                                                                          Country,
                                                              New String() {"US"})
                                                      }

                Try
                    Dim results As ProductBiddingCategoryData() =
                            constantDataService.getProductBiddingCategoryData(selector)

                    Dim biddingCategories As New Dictionary(Of Long, ProductCategory)()
                    Dim rootCategories As New List(Of ProductCategory)()

                    For Each productBiddingCategory As ProductBiddingCategoryData In results
                        Dim id As Long = productBiddingCategory.dimensionValue.value
                        Dim parentId As Long = 0
                        Dim name As String = productBiddingCategory.displayValue(0).value

                        If Not (productBiddingCategory.parentDimensionValue Is Nothing) Then
                            parentId = productBiddingCategory.parentDimensionValue.value
                        End If

                        If Not biddingCategories.ContainsKey(id) Then
                            biddingCategories.Add(id, New ProductCategory())
                        End If

                        Dim category As ProductCategory = biddingCategories(id)

                        If (parentId <> 0) Then
                            If Not biddingCategories.ContainsKey(parentId) Then
                                biddingCategories.Add(parentId, New ProductCategory())
                            End If
                            Dim parent As ProductCategory = biddingCategories(parentId)
                            parent.Children.Add(category)
                        Else
                            rootCategories.Add(category)
                        End If

                        category.Id = id
                        category.Name = name
                    Next

                    DisplayProductCategories(rootCategories, "")
                Catch e As Exception
                    Throw New System.ApplicationException("Failed to create shopping campaign.", e)
                End Try
            End Using
        End Sub

        ''' <summary>
        ''' Displays the product categories.
        ''' </summary>
        ''' <param name="categories">The product categories.</param>
        ''' <param name="prefix">The prefix for display purposes.</param>
        Sub DisplayProductCategories(ByVal categories As List(Of ProductCategory),
                                     ByVal prefix As String)
            For Each category As ProductCategory In categories
                Console.WriteLine("{0}{1} [{2}]", prefix, category.Name, category.Id)
                DisplayProductCategories(category.Children, String.Format("{0}{1} > ",
                                                                          prefix, category.Name))
            Next
        End Sub
    End Class
End Namespace