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