Share your feedback about the AdWords API! Take our annual survey.

Migration Samples

The code samples below provide examples of common migration functions using the AdWords API. Client Library.

Migrate feed-based campaign level sitelinks to extension settings

' 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

Namespace Google.Api.Ads.AdWords.Examples.VB.v201809

  ''' <summary>
  ''' This code example migrates your feed based sitelinks at campaign level to
  ''' use extension settings. To learn more about extensionsettings, see
  ''' https://developers.google.com/adwords/api/docs/guides/extension-settings.
  ''' To learn more about migrating Feed based extensions to extension
  ''' settings, see
  ''' https://developers.google.com/adwords/api/docs/guides/migrate-to-extension-settings.
  ''' </summary>
  ''' <remarks>This code example doesn't migrate scheduling or feeditem-level campaign, adgroup,
  ''' keyword, Or geo targeting settings.</remarks>
  Public Class MigrateToExtensionSettings
    Inherits ExampleBase

    ''' <summary>
    ''' The placeholder type for sitelinks. See
    ''' https://developers.google.com/adwords/api/docs/appendix/placeholders for
    ''' the list of all supported placeholder types.
    ''' </summary>
    Private Const PLACEHOLDER_TYPE_SITELINKS As Integer = 1

    ''' <summary>
    ''' Holds the placeholder field IDs for sitelinks. See
    ''' https://developers.google.com/adwords/api/docs/appendix/placeholders for
    ''' the list of all supported placeholder types.
    ''' </summary>
    Private Class SiteLinkFields
      Public Const TEXT As Long = 1
      Public Const URL As Long = 2
      Public Const LINE2 As Long = 3
      Public Const LINE3 As Long = 4
      Public Const FINAL_URLS As Long = 5
      Public Const FINAL_MOBILE_URLS As Long = 6
      Public Const TRACKING_URL_TEMPLATE As Long = 7
    End Class

    ''' <summary>
    ''' A sitelink object read from a feed.
    ''' </summary>
    Private Class SiteLinkFromFeed

      ''' <summary>
      ''' The feed ID.
      ''' </summary>
      Private feedIdField As Long

      ''' <summary>
      ''' The feed item ID.
      ''' </summary>
      Private feedItemIdField As Long

      ''' <summary>
      ''' The sitelink text.
      ''' </summary>
      Private textField As String

      ''' <summary>
      ''' The sitelink URL.
      ''' </summary>
      Private urlField As String

      ''' <summary>
      ''' The sitelink final URLs.
      ''' </summary>
      Private finalUrlsField As String()

      ''' <summary>
      ''' The sitelink final Mobile URLs.
      ''' </summary>
      Private finalMobileUrlsField As String()

      ''' <summary>
      ''' The sitelink tracking URL template.
      ''' </summary>
      Private trackingUrlTemplateField As String

      ''' <summary>
      ''' The sitelink line2 details.
      ''' </summary>
      Private line2Field As String

      ''' <summary>
      ''' The sitelink line3 details.
      ''' </summary>
      Private line3Field As String

      ''' <summary>
      ''' Gets or sets the feed ID.
      ''' </summary>
      Public Property FeedId As Long
        Get
          Return feedIdField
        End Get
        Set(ByVal value As Long)
          feedIdField = value
        End Set
      End Property

      ''' <summary>
      ''' Gets or sets the feed item ID.
      ''' </summary>
      Public Property FeedItemId As Long
        Get
          Return feedItemIdField
        End Get
        Set(ByVal value As Long)
          feedItemIdField = value
        End Set
      End Property

      ''' <summary>
      ''' Gets or sets the sitelink text.
      ''' </summary>
      Public Property Text As String
        Get
          Return textField
        End Get
        Set(ByVal value As String)
          textField = value
        End Set
      End Property

      ''' <summary>
      ''' Gets or sets the sitelink URL.
      ''' </summary>
      Public Property Url As String
        Get
          Return urlField
        End Get
        Set(ByVal value As String)
          urlField = value
        End Set
      End Property

      ''' <summary>
      ''' Gets or sets the sitelink final URLs.
      ''' </summary>
      Public Property FinalUrls As String()
        Get
          Return finalUrlsField
        End Get
        Set(ByVal value As String())
          finalUrlsField = value
        End Set
      End Property

      ''' <summary>
      ''' Gets or sets the sitelink final Mobile URLs.
      ''' </summary>
      Public Property FinalMobileUrls As String()
        Get
          Return finalMobileUrlsField
        End Get
        Set(ByVal value As String())
          finalMobileUrlsField = value
        End Set
      End Property

      ''' <summary>
      ''' Gets or sets the tracking URL template.
      ''' </summary>
      Public Property TrackingUrlTemplate As String
        Get
          Return trackingUrlTemplateField
        End Get
        Set(ByVal value As String)
          trackingUrlTemplateField = value
        End Set
      End Property

      ''' <summary>
      ''' Gets or sets the sitelink line2 details.
      ''' </summary>
      Public Property Line2 As String
        Get
          Return line2Field
        End Get
        Set(ByVal value As String)
          line2Field = value
        End Set
      End Property

      ''' <summary>
      ''' Gets or sets the sitelink line3 details.
      ''' </summary>
      Public Property Line3 As String
        Get
          Return line3Field
        End Get
        Set(ByVal value As String)
          line3Field = value
        End Set
      End Property
    End Class

    ''' <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 MigrateToExtensionSettings
      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>
    ''' Returns a description about the code example.
    ''' </summary>
    Public Overrides ReadOnly Property Description() As String
      Get
        Return "This code example migrates your feed based sitelinks at campaign level to " &
            "use extension settings. To learn more about extensionsettings, see " &
            "https://developers.google.com/adwords/api/docs/guides/extension-settings. To " &
            "learn more about migrating Feed based extensions to extension settings, see " &
            "https://developers.google.com/adwords/api/docs/guides/migrate-to-extension-settings."
      End Get
    End Property

    ''' <summary>
    ''' Runs the code example.
    ''' </summary>
    ''' <param name="user">The AdWords user.</param>
    Public Sub Run(ByVal user As AdWordsUser)
      ' Get all the feeds from the user account.
      Dim feeds As Feed() = GetFeeds(user)

      For Each feed As Feed In feeds
        ' Retrieve all the sitelinks from the current feed.
        Dim feedItems As Dictionary(Of Long, SiteLinkFromFeed) = GetSiteLinksFromFeed(user,
                                                                                      feed.id)

        ' Get all the instances where a sitelink from this feed has been added
        ' to a campaign.
        Dim campaignFeeds As CampaignFeed() = GetCampaignFeeds(user, feed,
                                                               PLACEHOLDER_TYPE_SITELINKS)

        If Not campaignFeeds Is Nothing Then
          Dim allFeedItemsToDelete As New HashSet(Of Long)()

          For Each campaignFeed As CampaignFeed In campaignFeeds
            ' Retrieve the sitelinks that have been associated with this
            ' campaign.
            Dim feedItemIds As List(Of Long) = GetFeedItemsForCampaign(campaignFeed)
            Dim platformRestrictions As ExtensionSettingPlatform =
                GetPlatformRestrictionsForCampaign(campaignFeed)

            If feedItemIds.Count = 0 Then
              Console.WriteLine("Migration skipped for campaign feed with campaign ID {0} " &
                  "and feed ID {1} because no mapped feed item IDs were found in the campaign " &
                  "feed's matching function.", campaignFeed.campaignId, campaignFeed.feedId)
            Else
              ' Delete the campaign feed that associates the sitelinks from the
              ' feed to the campaign.
              DeleteCampaignFeed(user, campaignFeed)

              ' Create extension settings instead of sitelinks.
              CreateExtensionSetting(user, feedItems, campaignFeed.campaignId, feedItemIds,
                                     platformRestrictions)

              ' Mark the sitelinks from the feed for deletion.
              allFeedItemsToDelete.UnionWith(feedItemIds)
            End If
          Next
          ' Delete all the sitelinks from the feed.
          DeleteOldFeedItems(user, New List(Of Long)(allFeedItemsToDelete), feed.id)
        End If
      Next
    End Sub

    ''' <summary>
    ''' Gets the site links from a feed.
    ''' </summary>
    ''' <param name="user">The user that owns the feed.</param>
    ''' <param name="feedId">The feed ID.</param>
    ''' <returns>A dictionary of sitelinks from the feed, with key as the feed
    ''' item ID, and value as the sitelink.</returns>
    Private Function GetSiteLinksFromFeed(ByVal user As AdWordsUser, ByVal feedId As Long) As _
        Dictionary(Of Long, SiteLinkFromFeed)
      Dim siteLinks As New Dictionary(Of Long, SiteLinkFromFeed)()

      ' Retrieve all the feed items from the feed.
      Dim feedItems As FeedItem() = GetFeedItems(user, feedId)

      ' Retrieve the feed's attribute mapping.
      Dim feedMappings As Dictionary(Of Long, HashSet(Of Long)) = GetFeedMapping(user, feedId,
          PLACEHOLDER_TYPE_SITELINKS)

      If Not feedItems Is Nothing Then
        For Each feedItem As FeedItem In feedItems
          Dim sitelinkFromFeed As New SiteLinkFromFeed()
          sitelinkFromFeed.FeedId = feedItem.feedId
          sitelinkFromFeed.FeedItemId = feedItem.feedItemId

          For Each attributeValue As FeedItemAttributeValue In feedItem.attributeValues
            ' This attribute hasn't been mapped to a field.
            If Not feedMappings.ContainsKey(attributeValue.feedAttributeId) Then
              Continue For
            End If
            ' Get the list of all the fields to which this attribute has been mapped.
            For Each fieldId As Long In feedMappings(attributeValue.feedAttributeId)
              ' Read the appropriate value depending on the ID of the mapped
              ' field.
              Select Case fieldId
                Case SiteLinkFields.TEXT
                  sitelinkFromFeed.Text = attributeValue.stringValue

                Case SiteLinkFields.URL
                  sitelinkFromFeed.Url = attributeValue.stringValue

                Case SiteLinkFields.FINAL_URLS
                  sitelinkFromFeed.FinalUrls = attributeValue.stringValues

                Case SiteLinkFields.FINAL_MOBILE_URLS
                  sitelinkFromFeed.FinalMobileUrls = attributeValue.stringValues

                Case SiteLinkFields.TRACKING_URL_TEMPLATE
                  sitelinkFromFeed.TrackingUrlTemplate = attributeValue.stringValue

                Case SiteLinkFields.LINE2
                  sitelinkFromFeed.Line2 = attributeValue.stringValue

                Case SiteLinkFields.LINE3
                  sitelinkFromFeed.Line3 = attributeValue.stringValue
              End Select
            Next
          Next
          siteLinks.Add(feedItem.feedItemId, sitelinkFromFeed)
        Next
      End If
      Return siteLinks
    End Function

    ''' <summary>
    ''' Gets the feed mapping for a feed.
    ''' </summary>
    ''' <param name="user">The user that owns the feed.</param>
    ''' <param name="feedId">The feed ID.</param>
    ''' <param name="placeHolderType">Type of the place holder for which feed
    ''' mappings should be retrieved.</param>
    ''' <returns>A dictionary, with key as the feed attribute ID, and value as
    ''' the set of all fields which the attribute has a mapping to.</returns>
    Private Function GetFeedMapping(ByVal user As AdWordsUser, ByVal feedId As Long,
                                    ByVal placeHolderType As Long) _
                                    As Dictionary(Of Long, HashSet(Of Long))
      Using feedMappingService As FeedMappingService = DirectCast(user.GetService(
          AdWordsService.v201809.FeedMappingService), FeedMappingService)
        Dim page As FeedMappingPage = feedMappingService.query(String.Format(
          "SELECT FeedMappingId, AttributeFieldMappings where FeedId='{0}' and " &
          "PlaceholderType={1} and Status='ENABLED'", feedId, placeHolderType))

        Dim attributeMappings As New Dictionary(Of Long, HashSet(Of Long))()

        If Not (page.entries Is Nothing) Then
          ' Normally, a feed attribute is mapped only to one field. However,
          ' you may map it to more than one field if needed.
          For Each feedMapping As FeedMapping In page.entries
            For Each attributeMapping As AttributeFieldMapping In
                feedMapping.attributeFieldMappings
              If Not attributeMappings.ContainsKey(attributeMapping.feedAttributeId) Then
                attributeMappings(attributeMapping.feedAttributeId) = New HashSet(Of Long)()
              End If
              attributeMappings(attributeMapping.feedAttributeId).Add(attributeMapping.fieldId)
            Next
          Next
        End If
        Return attributeMappings
      End Using
    End Function

    ''' <summary>
    ''' Gets the feeds.
    ''' </summary>
    ''' <param name="user">The user for which feeds are retrieved.</param>
    ''' <returns>The list of feeds.</returns>
    Private Function GetFeeds(ByVal user As AdWordsUser) As Feed()
      ' TODO(b/67949201): This needs to handle paging
      Using feedService As FeedService = DirectCast(user.GetService(
          AdWordsService.v201809.FeedService), FeedService)
        Dim page As FeedPage = feedService.query("SELECT Id, Name, Attributes where " &
          "Origin='USER' and FeedStatus='ENABLED'")
        Return page.entries
      End Using
    End Function

    ''' <summary>
    ''' Gets the feed items in a feed.
    ''' </summary>
    ''' <param name="user">The user that owns the feed.</param>
    ''' <param name="feedId">The feed ID.</param>
    ''' <returns>The list of feed items in the feed.</returns>
    Private Function GetFeedItems(ByVal user As AdWordsUser, ByVal feedId As Long) As FeedItem()
      ' TODO(b/67949201): This needs to handle paging
      Using FeedItemService As FeedItemService = DirectCast(user.GetService(
          AdWordsService.v201809.FeedItemService), FeedItemService)
        Dim page As FeedItemPage = FeedItemService.query(String.Format("Select FeedItemId, " &
          "AttributeValues  where Status = 'ENABLED' and FeedId = '{0}'", feedId))
        Return page.entries
      End Using
    End Function

    ''' <summary>
    ''' Deletes the old feed items for which extension settings have been
    ''' created.
    ''' </summary>
    ''' <param name="user">The user that owns the feed items.</param>
    ''' <param name="feedItemIds">IDs of the feed items to be removed.</param>
    ''' <param name="feedId">ID of the feed that holds the feed items.</param>
    Private Sub DeleteOldFeedItems(ByVal user As AdWordsUser, ByVal feedItemIds As List(Of Long),
                                   ByVal feedId As Long)
      If feedItemIds.Count = 0 Then
        Return
      End If
      Dim operations As New List(Of FeedItemOperation)()
      For Each feedItemId As Long In feedItemIds
        Dim operation As New FeedItemOperation()
        operation.operator = [Operator].REMOVE

        operation.operand = New FeedItem()
        operation.operand.feedItemId = feedItemId
        operation.operand.feedId = feedId

        operations.Add(operation)
      Next
      Using feedItemService As FeedItemService = DirectCast(user.GetService(
          AdWordsService.v201809.FeedItemService), FeedItemService)
        feedItemService.mutate(operations.ToArray())
        Return
      End Using
    End Sub

    ''' <summary>
    ''' Creates the extension setting fo a list of feed items.
    ''' </summary>
    ''' <param name="user">The user for which extension settings are created.
    ''' </param>
    ''' <param name="feedItems">The list of all feed items.</param>
    ''' <param name="campaignId">ID of the campaign to which extension settings
    ''' are added.</param>
    ''' <param name="feedItemIds">IDs of the feed items for which extension
    ''' settings should be created.</param>
    ''' <param name="platformRestrictions">The platform restrictions for the
    ''' extension setting.</param>
    Private Sub CreateExtensionSetting(ByVal user As AdWordsUser, ByVal feedItems As _
                                       Dictionary(Of Long, SiteLinkFromFeed),
                                       ByVal campaignId As Long,
                                       ByVal feedItemIds As List(Of Long),
                                       ByVal platformRestrictions As ExtensionSettingPlatform)
      Dim extensionSetting As New CampaignExtensionSetting()
      extensionSetting.campaignId = campaignId
      extensionSetting.extensionType = FeedType.SITELINK
      extensionSetting.extensionSetting = New ExtensionSetting()

      Dim extensionFeedItems As New List(Of ExtensionFeedItem)()

      For Each feedItemId As Long In feedItemIds
        Dim feedItem As SiteLinkFromFeed = feedItems(feedItemId)

        Dim newFeedItem As New SitelinkFeedItem()
        newFeedItem.sitelinkText = feedItem.Text
        newFeedItem.sitelinkUrl = feedItem.Url
        newFeedItem.sitelinkFinalUrls = New UrlList()
        newFeedItem.sitelinkFinalUrls.urls = feedItem.FinalUrls
        newFeedItem.sitelinkFinalMobileUrls = New UrlList()
        newFeedItem.sitelinkFinalMobileUrls.urls = feedItem.FinalMobileUrls
        newFeedItem.sitelinkTrackingUrlTemplate = feedItem.TrackingUrlTemplate
        newFeedItem.sitelinkLine2 = feedItem.Line2
        newFeedItem.sitelinkLine3 = feedItem.Line3

        extensionFeedItems.Add(newFeedItem)
      Next
      extensionSetting.extensionSetting.extensions = extensionFeedItems.ToArray()
      extensionSetting.extensionSetting.platformRestrictions = platformRestrictions
      extensionSetting.extensionType = FeedType.SITELINK

      Using campaignExtensionSettingService As CampaignExtensionSettingService =
          DirectCast(user.GetService(AdWordsService.v201809.CampaignExtensionSettingService),
            CampaignExtensionSettingService)

        Dim operation As New CampaignExtensionSettingOperation()
        operation.operand = extensionSetting
        operation.operator = [Operator].ADD

        campaignExtensionSettingService.mutate(New CampaignExtensionSettingOperation() {operation})

        Return
      End Using
    End Sub

    ''' <summary>
    ''' Deletes a campaign feed.
    ''' </summary>
    ''' <param name="user">The AdWords user.</param>
    ''' <param name="campaignFeed">The campaign feed.</param>
    ''' <returns></returns>
    Private Function DeleteCampaignFeed(ByVal user As AdWordsUser,
                                        ByVal campaignFeed As CampaignFeed) As CampaignFeed
      Using campaignFeedService As CampaignFeedService = DirectCast(user.GetService(
          AdWordsService.v201809.CampaignFeedService), CampaignFeedService)

        Dim operation As New CampaignFeedOperation()
        operation.operand = campaignFeed
        operation.operator = [Operator].REMOVE

        Return campaignFeedService.mutate(New CampaignFeedOperation() {operation}).value(0)
      End Using
    End Function

    ''' <summary>
    ''' Gets the platform restrictions for sitelinks in a campaign.
    ''' </summary>
    ''' <param name="campaignFeed">The campaign feed.</param>
    ''' <returns>The platform restrictions.</returns>
    Private Function GetPlatformRestrictionsForCampaign(ByVal campaignFeed As CampaignFeed) As _
        ExtensionSettingPlatform
      Dim platformRestrictions As String = "NONE"

      If campaignFeed.matchingFunction.operator = FunctionOperator.AND Then

        For Each argument As FunctionArgumentOperand In campaignFeed.matchingFunction.lhsOperand
          ' Check if matchingFunction is of the form EQUALS(CONTEXT.DEVICE, 'Mobile').
          If TypeOf argument Is FunctionOperand Then
            Dim operand As FunctionOperand = CType(argument, FunctionOperand)
            If operand.value.operator = FunctionOperator.EQUALS Then
              Dim requestContextOperand As RequestContextOperand =
                  CType(operand.value.lhsOperand(0), RequestContextOperand)
              If (Not requestContextOperand Is Nothing) AndAlso
                (requestContextOperand.contextType =
                    RequestContextOperandContextType.DEVICE_PLATFORM) Then
                platformRestrictions = DirectCast(operand.value.rhsOperand(0),
                    ConstantOperand).stringValue
              End If
            End If
          End If
        Next
      End If

      Return CType([Enum].Parse(GetType(ExtensionSettingPlatform), platformRestrictions, True),
              ExtensionSettingPlatform)
    End Function

    ''' <summary>
    ''' Gets the list of feed items that are used by a campaign through a given
    ''' campaign feed.
    ''' </summary>
    ''' <param name="campaignFeed">The campaign feed.</param>
    ''' <returns>The list of feed items.</returns>
    Private Function GetFeedItemsForCampaign(ByVal campaignFeed As CampaignFeed) As List(Of Long)
      Dim feedItems As New List(Of Long)()

      Select Case campaignFeed.matchingFunction.operator
        Case FunctionOperator.IN
          ' Check if matchingFunction is of the form IN(FEED_ITEM_ID,{xxx,xxx}).
          ' Extract feedItems if applicable.
          feedItems.AddRange(GetFeedItemsFromArgument(campaignFeed.matchingFunction))

        Case FunctionOperator.AND
          ' Check each condition.

          For Each argument As FunctionArgumentOperand In campaignFeed.matchingFunction.lhsOperand
            ' Check if matchingFunction is of the form IN(FEED_ITEM_ID,{xxx,xxx}).
            ' Extract feedItems if applicable.
            If TypeOf argument Is FunctionOperand Then
              Dim operand As FunctionOperand = CType(argument, FunctionOperand)
              If operand.value.operator = FunctionOperator.IN Then
                feedItems.AddRange(GetFeedItemsFromArgument(operand.value))
              End If
            End If
          Next

        Case Else
          ' There are no other matching functions involving feeditem ids.
      End Select

      Return feedItems
    End Function

    Private Function GetFeedItemsFromArgument(ByVal func As [Function]) As List(Of Long)
      Dim feedItems As New List(Of Long)()

      If func.lhsOperand.Length = 1 Then
        Dim requestContextOperand As RequestContextOperand =
            CType(func.lhsOperand(0), RequestContextOperand)
        If Not (requestContextOperand Is Nothing) AndAlso
            (requestContextOperand.contextType = RequestContextOperandContextType.FEED_ITEM_ID) Then
          For Each argument As ConstantOperand In func.rhsOperand
            feedItems.Add(argument.longValue)
          Next
        End If
      End If

      Return feedItems
    End Function

    ''' <summary>
    ''' Gets the campaignfeeds that use a particular feed.
    ''' </summary>
    ''' <param name="user">The user that owns the feed.</param>
    ''' <param name="feed">The feed for which campaign feeds should be
    ''' retrieved.</param>
    ''' <param name="placeholderType">The type of placeholder to restrict
    ''' search.</param>
    ''' <returns>The list of campaignfeeds.</returns>
    Private Function GetCampaignFeeds(ByVal user As AdWordsUser, ByVal feed As Feed,
                                      ByVal placeholderType As Integer) As CampaignFeed()
      Using campaignFeedService As CampaignFeedService = DirectCast(user.GetService(
          AdWordsService.v201809.CampaignFeedService), CampaignFeedService)

        Dim page As CampaignFeedPage = campaignFeedService.query(String.Format(
          "SELECT CampaignId, MatchingFunction, PlaceholderTypes where Status='ENABLED' " &
          "and FeedId = '{0}' and PlaceholderTypes CONTAINS_ANY[{1}]", feed.id, placeholderType))
        Return page.entries
      End Using
    End Function

  End Class

End Namespace

Send feedback about...

AdWords API
AdWords API
Need help? Visit our support page.