The code samples below provide examples of common extension functions using the AdWords API. Client Library.
Associate a Google My Business feed to that of a customer
// 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. using Google.Api.Ads.AdWords.Lib; using Google.Api.Ads.AdWords.v201809; using Google.Api.Ads.Common.Lib; using System; namespace Google.Api.Ads.AdWords.Examples.CSharp.v201809 { /// <summary> /// This code example adds a feed that syncs feed items from a Google /// My Business (GMB) account and associates the feed with a customer. /// </summary> public class AddGoogleMyBusinessLocationExtensions : ExampleBase { /// <summary> /// The placeholder type for location extensions. See the Placeholder /// reference page for a list of all the placeholder types and fields. /// /// https://developers.google.com/adwords/api/docs/appendix/placeholders /// </summary> private const int PLACEHOLDER_LOCATION = 7; /// <summary> /// Returns a description about the code example. /// </summary> public override string Description { get { return "This code example adds a feed that syncs feed items from a Google My " + "Business (GMB) account and associates the feed with a customer."; } } /// <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) { AddGoogleMyBusinessLocationExtensions codeExample = new AddGoogleMyBusinessLocationExtensions(); Console.WriteLine(codeExample.Description); AdWordsUser user = new AdWordsUser(); try { // The email address of either an owner or a manager of the GMB account. string gmbEmailAddress = "INSERT_GMB_EMAIL_ADDRESS_HERE"; // Refresh the access token so that there's a valid access token. user.OAuthProvider.RefreshAccessToken(); // If the gmbEmailAddress above is the same user you used to generate // your AdWords API refresh token, leave the assignment below unchanged. // Otherwise, to obtain an access token for your GMB account, run the // OAuth Token generator utility while logged in as the same user as // gmbEmailAddress. Copy and paste the AccessToken value into the // assignment below. string gmbAccessToken = user.OAuthProvider.Config.OAuth2AccessToken; // If the gmbEmailAddress above is for a GMB manager instead of the GMB // account owner, then set businessAccountIdentifier to the +Page ID of // a location for which the manager has access. See the location // extensions guide at // https://developers.google.com/adwords/api/docs/guides/feed-services-locations // for details. string businessAccountIdentifier = null; codeExample.Run(user, gmbEmailAddress, gmbAccessToken, businessAccountIdentifier); } catch (Exception e) { Console.WriteLine("An exception occurred while running this code example. {0}", ExampleUtilities.FormatException(e)); } } /// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> /// <param name="gmbEmailAddress">The email address for Google My Business /// account.</param> /// <param name="gmbAccessToken">The OAuth2 access token for Google /// My Business account.</param> /// <param name="businessAccountIdentifier">The account identifier for /// Google My Business account.</param> public void Run(AdWordsUser user, string gmbEmailAddress, string gmbAccessToken, string businessAccountIdentifier) { Feed gmbFeed = CreateGmbFeed(user, gmbEmailAddress, gmbAccessToken, businessAccountIdentifier); AddCustomerFeed(user, gmbFeed); } /// <summary> /// Create a feed that will sync to the Google My Business account /// specified by gmbEmailAddress. /// </summary> /// <param name="user">The user.</param> /// <param name="gmbEmailAddress">The GMB email address.</param> /// <param name="gmbAccessToken">The GMB access token.</param> /// <param name="businessAccountIdentifier">The GMB account identifier.</param> /// <returns>The newly created GMB feed.</returns> private static Feed CreateGmbFeed(AdWordsUser user, string gmbEmailAddress, string gmbAccessToken, string businessAccountIdentifier) { using (FeedService feedService = (FeedService) user.GetService(AdWordsService.v201809.FeedService)) { // Create a feed that will sync to the Google My Business account // specified by gmbEmailAddress. Do not add FeedAttributes to this object, // as AdWords will add them automatically because this will be a // system generated feed. Feed gmbFeed = new Feed { name = string.Format("Google My Business feed #{0}", ExampleUtilities.GetRandomString()) }; PlacesLocationFeedData feedData = new PlacesLocationFeedData { emailAddress = gmbEmailAddress, businessAccountIdentifier = businessAccountIdentifier, // Optional: specify labels to filter Google My Business listings. If // specified, only listings that have any of the labels set are // synchronized into FeedItems. labelFilters = new string[] { "Stores in New York City" } }; OAuthInfo oAuthInfo = new OAuthInfo { httpMethod = "GET", // Permissions for the AdWords API scope will also cover GMB. httpRequestUrl = user.Config.GetDefaultOAuth2Scope(), httpAuthorizationHeader = string.Format("Bearer {0}", gmbAccessToken) }; feedData.oAuthInfo = oAuthInfo; gmbFeed.systemFeedGenerationData = feedData; // Since this feed's feed items will be managed by AdWords, // you must set its origin to ADWORDS. gmbFeed.origin = FeedOrigin.ADWORDS; // Create an operation to add the feed. FeedOperation feedOperation = new FeedOperation { operand = gmbFeed, @operator = Operator.ADD }; try { // Add the feed. Since it is a system generated feed, AdWords will // automatically: // 1. Set up the FeedAttributes on the feed. // 2. Set up a FeedMapping that associates the FeedAttributes of the // feed with the placeholder fields of the LOCATION placeholder // type. FeedReturnValue addFeedResult = feedService.mutate(new FeedOperation[] { feedOperation }); Feed addedFeed = addFeedResult.value[0]; Console.WriteLine("Added GMB feed with ID {0}", addedFeed.id); return addedFeed; } catch (Exception e) { throw new System.ApplicationException("Failed to create GMB feed.", e); } } } /// <summary> /// Add a CustomerFeed that associates the feed with this customer for /// the LOCATION placeholder type. /// </summary> /// <param name="user">The AdWords user.</param> /// <param name="feed">The GMB feed.</param> void AddCustomerFeed(AdWordsUser user, Feed feed) { using (CustomerFeedService customerFeedService = (CustomerFeedService) user.GetService(AdWordsService.v201809.CustomerFeedService)) { // Add a CustomerFeed that associates the feed with this customer for // the LOCATION placeholder type. CustomerFeed customerFeed = new CustomerFeed { feedId = feed.id, placeholderTypes = new int[] { PLACEHOLDER_LOCATION } }; // Create a matching function that will always evaluate to true. Function customerMatchingFunction = new Function(); ConstantOperand constOperand = new ConstantOperand { type = ConstantOperandConstantType.BOOLEAN, booleanValue = true }; customerMatchingFunction.lhsOperand = new FunctionArgumentOperand[] { constOperand }; customerMatchingFunction.@operator = FunctionOperator.IDENTITY; customerFeed.matchingFunction = customerMatchingFunction; // Create an operation to add the customer feed. CustomerFeedOperation customerFeedOperation = new CustomerFeedOperation { operand = customerFeed, @operator = Operator.ADD }; // After the completion of the Feed ADD operation above the added feed // will not be available for usage in a CustomerFeed until the sync // between the AdWords and GMB accounts completes. The loop below // will retry adding the CustomerFeed up to ten times with an // exponential back-off policy. CustomerFeed addedCustomerFeed = null; AdWordsAppConfig config = new AdWordsAppConfig { RetryCount = 10 }; ErrorHandler errorHandler = new ErrorHandler(config); try { do { try { CustomerFeedReturnValue customerFeedResult = customerFeedService.mutate( new CustomerFeedOperation[] { customerFeedOperation }); addedCustomerFeed = customerFeedResult.value[0]; Console.WriteLine( "Added CustomerFeed for feed ID {0} and placeholder type {1}", addedCustomerFeed.feedId, addedCustomerFeed.placeholderTypes[0]); break; } catch (AdWordsApiException e) { ApiException apiException = (ApiException) e.ApiException; foreach (ApiError error in apiException.errors) { if (error is CustomerFeedError) { if ((error as CustomerFeedError).reason == CustomerFeedErrorReason .MISSING_FEEDMAPPING_FOR_PLACEHOLDER_TYPE) { errorHandler.DoExponentialBackoff(); errorHandler.IncrementRetriedAttempts(); } else { throw; } } } } } while (errorHandler.HaveMoreRetryAttemptsLeft()); // OPTIONAL: Create a CampaignFeed to specify which FeedItems to use at // the Campaign level. This will be similar to the CampaignFeed in the // AddSiteLinks example, except you can also filter based on the // business name and category of each FeedItem by using a // FeedAttributeOperand in your matching function. // OPTIONAL: Create an AdGroupFeed for even more fine grained control // over which feed items are used at the AdGroup level. } catch (Exception e) { throw new System.ApplicationException("Failed to create customer feed.", e); } } } } }
Associate a price extension to an account
// 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. using Google.Api.Ads.AdWords.Lib; using Google.Api.Ads.AdWords.v201809; using System; using System.Collections.Generic; using DayOfWeek = Google.Api.Ads.AdWords.v201809.DayOfWeek; namespace Google.Api.Ads.AdWords.Examples.CSharp.v201809 { /// <summary> /// This code example adds a price extension and associates it with an /// account. Campaign targeting is also set using the specified campaign ID. /// To get campaigns, run AddCampaigns.cs. /// </summary> public class AddPrices : ExampleBase { /// <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) { AddPrices codeExample = new AddPrices(); Console.WriteLine(codeExample.Description); try { long campaignId = long.Parse("INSERT_CAMPAIGN_ID_HERE"); codeExample.Run(new AdWordsUser(), campaignId); } catch (Exception e) { Console.WriteLine("An exception occurred while running this code example. {0}", ExampleUtilities.FormatException(e)); } } /// <summary> /// Returns a description about the code example. /// </summary> public override string Description { get { return "This code example adds a price extension and associates it with an " + "account. Campaign targeting is also set using the specified campaign ID. " + "To get campaigns, run AddCampaigns.cs."; } } /// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> /// <param name="campaignId">Id of the campaign to which sitelinks will /// be added.</param> public void Run(AdWordsUser user, long campaignId) { using (CustomerExtensionSettingService customerExtensionSettingService = (CustomerExtensionSettingService) user.GetService(AdWordsService.v201809 .CustomerExtensionSettingService)) { // Create the price extension feed item. PriceFeedItem priceFeedItem = new PriceFeedItem() { priceExtensionType = PriceExtensionType.SERVICES, // Price qualifier is optional. priceQualifier = PriceExtensionPriceQualifier.FROM, trackingUrlTemplate = "http://tracker.example.com/?u={lpurl}", language = "en", campaignTargeting = new FeedItemCampaignTargeting() { TargetingCampaignId = campaignId, }, scheduling = new FeedItemSchedule[] { new FeedItemSchedule() { dayOfWeek = DayOfWeek.SATURDAY, startHour = 10, startMinute = MinuteOfHour.ZERO, endHour = 22, endMinute = MinuteOfHour.ZERO }, new FeedItemSchedule() { dayOfWeek = DayOfWeek.SUNDAY, startHour = 10, startMinute = MinuteOfHour.ZERO, endHour = 18, endMinute = MinuteOfHour.ZERO } } }; // To create a price extension, at least three table rows are needed. List<PriceTableRow> priceTableRows = new List<PriceTableRow>(); string currencyCode = "USD"; priceTableRows.Add(CreatePriceTableRow("Scrubs", "Body Scrub, Salt Scrub", "http://www.example.com/scrubs", "http://m.example.com/scrubs", 60000000, currencyCode, PriceExtensionPriceUnit.PER_HOUR)); priceTableRows.Add(CreatePriceTableRow("Hair Cuts", "Once a month", "http://www.example.com/haircuts", "http://m.example.com/haircuts", 75000000, currencyCode, PriceExtensionPriceUnit.PER_MONTH)); priceTableRows.Add(CreatePriceTableRow("Skin Care Package", "Four times a month", "http://www.example.com/skincarepackage", null, 250000000, currencyCode, PriceExtensionPriceUnit.PER_MONTH)); priceFeedItem.tableRows = priceTableRows.ToArray(); // Create your campaign extension settings. This associates the sitelinks // to your campaign. CustomerExtensionSetting customerExtensionSetting = new CustomerExtensionSetting() { extensionType = FeedType.PRICE, extensionSetting = new ExtensionSetting() { extensions = new ExtensionFeedItem[] { priceFeedItem } } }; CustomerExtensionSettingOperation operation = new CustomerExtensionSettingOperation() { operand = customerExtensionSetting, @operator = Operator.ADD }; try { // Add the extensions. CustomerExtensionSettingReturnValue retVal = customerExtensionSettingService.mutate( new CustomerExtensionSettingOperation[] { operation }); if (retVal.value != null && retVal.value.Length > 0) { CustomerExtensionSetting newExtensionSetting = retVal.value[0]; Console.WriteLine("Extension setting with type '{0}' was added.", newExtensionSetting.extensionType); } else { Console.WriteLine("No extension settings were created."); } } catch (Exception e) { throw new System.ApplicationException("Failed to create extension settings.", e); } } } /// <summary> /// Creates a price table row. /// </summary> /// <param name="header">The row header.</param> /// <param name="description">The description text.</param> /// <param name="finalUrl">The final URL.</param> /// <param name="finalMobileUrl">The mobile final URL, or null if this field /// should not be set.</param> /// <param name="priceInMicros">The price in micros.</param> /// <param name="currencyCode">The currency code.</param> /// <param name="priceUnit">The price unit.</param> /// <returns>A price table row for creating price extension.</returns> private static PriceTableRow CreatePriceTableRow(string header, string description, string finalUrl, string finalMobileUrl, long priceInMicros, string currencyCode, PriceExtensionPriceUnit priceUnit) { PriceTableRow retval = new PriceTableRow() { header = header, description = description, finalUrls = new UrlList() { urls = new string[] { finalUrl } }, price = new MoneyWithCurrency() { currencyCode = currencyCode, money = new Money() { microAmount = priceInMicros } }, priceUnit = priceUnit }; // Optional: set the mobile final URLs. if (!string.IsNullOrEmpty(finalMobileUrl)) { retval.finalMobileUrls = new UrlList() { urls = new string[] { finalMobileUrl } }; } return retval; } } }
Add sitelinks to 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. using Google.Api.Ads.AdWords.Lib; using Google.Api.Ads.AdWords.v201809; using System; using System.Collections.Generic; using DayOfWeek = Google.Api.Ads.AdWords.v201809.DayOfWeek; namespace Google.Api.Ads.AdWords.Examples.CSharp.v201809 { /// <summary> /// This code example adds sitelinks to a campaign. To create a campaign, /// run AddCampaign.cs. /// </summary> public class AddSitelinks : ExampleBase { /// <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) { AddSitelinks codeExample = new AddSitelinks(); Console.WriteLine(codeExample.Description); try { long campaignId = long.Parse("INSERT_CAMPAIGN_ID_HERE"); codeExample.Run(new AdWordsUser(), campaignId); } catch (Exception e) { Console.WriteLine("An exception occurred while running this code example. {0}", ExampleUtilities.FormatException(e)); } } /// <summary> /// Returns a description about the code example. /// </summary> public override string Description { get { return "This code example adds sitelinks to a campaign. To create a campaign, run " + "AddCampaign.cs."; } } /// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> /// <param name="campaignId">Id of the campaign to which sitelinks will /// be added.</param> public void Run(AdWordsUser user, long campaignId) { using (CampaignExtensionSettingService campaignExtensionSettingService = (CampaignExtensionSettingService) user.GetService(AdWordsService.v201809 .CampaignExtensionSettingService)) { Customer customer = null; using (CustomerService customerService = (CustomerService) user.GetService(AdWordsService.v201809.CustomerService)) { // Find the matching customer and its time zone. The getCustomers method // will return a single Customer object corresponding to the session's // clientCustomerId. customer = customerService.getCustomers()[0]; Console.WriteLine("Found customer ID {0:###-###-####} with time zone '{1}'.", customer.customerId, customer.dateTimeZone); } List<ExtensionFeedItem> extensions = new List<ExtensionFeedItem>(); // Create your sitelinks. SitelinkFeedItem sitelink1 = new SitelinkFeedItem() { sitelinkText = "Store Hours", sitelinkFinalUrls = new UrlList() { urls = new string[] { "http://www.example.com/storehours" } } }; extensions.Add(sitelink1); DateTime startOfThanksGiving = new DateTime(DateTime.Now.Year, 11, 20, 0, 0, 0); DateTime endOfThanksGiving = new DateTime(DateTime.Now.Year, 11, 27, 23, 59, 59); // Add check to make sure we don't create a sitelink with end date in the // past. if (DateTime.Now < endOfThanksGiving) { // Show the Thanksgiving specials link only from 20 - 27 Nov. SitelinkFeedItem sitelink2 = new SitelinkFeedItem() { sitelinkText = "Thanksgiving Specials", sitelinkFinalUrls = new UrlList() { urls = new string[] { "http://www.example.com/thanksgiving" } }, startTime = string.Format("{0} {1}", startOfThanksGiving.ToString("yyyyMMdd HHmmss"), customer.dateTimeZone), endTime = string.Format("{0} {1}", endOfThanksGiving.ToString("yyyyMMdd HHmmss"), customer.dateTimeZone), // Target this sitelink for United States only. See // https://developers.google.com/adwords/api/docs/appendix/geotargeting // for valid geolocation codes. geoTargeting = new Location() { id = 2840 }, // Restrict targeting only to people physically within the United States. // Otherwise, this could also show to people interested in the United States // but not physically located there. geoTargetingRestriction = new FeedItemGeoRestriction() { geoRestriction = GeoRestriction.LOCATION_OF_PRESENCE } }; extensions.Add(sitelink2); } // Show the wifi details primarily for high end mobile users. SitelinkFeedItem sitelink3 = new SitelinkFeedItem() { sitelinkText = "Wifi available", sitelinkFinalUrls = new UrlList() { urls = new string[] { "http://www.example.com/mobile/wifi" } }, devicePreference = new FeedItemDevicePreference() { // See https://developers.google.com/adwords/api/docs/appendix/platforms // for device criteria IDs. devicePreference = 30001 }, // Target this sitelink for the keyword "free wifi". keywordTargeting = new Keyword() { text = "free wifi", matchType = KeywordMatchType.BROAD } }; extensions.Add(sitelink3); // Show the happy hours link only during Mon - Fri 6PM to 9PM. SitelinkFeedItem sitelink4 = new SitelinkFeedItem() { sitelinkText = "Happy hours", sitelinkFinalUrls = new UrlList() { urls = new string[] { "http://www.example.com/happyhours" }, }, scheduling = new FeedItemSchedule[] { new FeedItemSchedule() { dayOfWeek = DayOfWeek.MONDAY, startHour = 18, startMinute = MinuteOfHour.ZERO, endHour = 21, endMinute = MinuteOfHour.ZERO }, new FeedItemSchedule() { dayOfWeek = DayOfWeek.TUESDAY, startHour = 18, startMinute = MinuteOfHour.ZERO, endHour = 21, endMinute = MinuteOfHour.ZERO }, new FeedItemSchedule() { dayOfWeek = DayOfWeek.WEDNESDAY, startHour = 18, startMinute = MinuteOfHour.ZERO, endHour = 21, endMinute = MinuteOfHour.ZERO }, new FeedItemSchedule() { dayOfWeek = DayOfWeek.THURSDAY, startHour = 18, startMinute = MinuteOfHour.ZERO, endHour = 21, endMinute = MinuteOfHour.ZERO }, new FeedItemSchedule() { dayOfWeek = DayOfWeek.FRIDAY, startHour = 18, startMinute = MinuteOfHour.ZERO, endHour = 21, endMinute = MinuteOfHour.ZERO } } }; extensions.Add(sitelink4); // Create your campaign extension settings. This associates the sitelinks // to your campaign. CampaignExtensionSetting campaignExtensionSetting = new CampaignExtensionSetting { campaignId = campaignId, extensionType = FeedType.SITELINK, extensionSetting = new ExtensionSetting() { extensions = extensions.ToArray() } }; CampaignExtensionSettingOperation operation = new CampaignExtensionSettingOperation() { operand = campaignExtensionSetting, @operator = Operator.ADD }; try { // Add the extensions. CampaignExtensionSettingReturnValue retVal = campaignExtensionSettingService.mutate( new CampaignExtensionSettingOperation[] { operation }); // Display the results. if (retVal.value != null && retVal.value.Length > 0) { CampaignExtensionSetting newExtensionSetting = retVal.value[0]; Console.WriteLine( "Extension setting with type = {0} was added to campaign ID {1}.", newExtensionSetting.extensionType, newExtensionSetting.campaignId); } else { Console.WriteLine("No extension settings were created."); } } catch (Exception e) { throw new System.ApplicationException("Failed to create extension settings.", e); } } } } }
Add sitelinks to a campaign using feeds
// 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. using Google.Api.Ads.AdWords.Lib; using Google.Api.Ads.AdWords.v201809; using System; using System.Collections.Generic; namespace Google.Api.Ads.AdWords.Examples.CSharp.v201809 { /// <summary> /// This code example adds sitelinks to a campaign using feed services. /// To create a campaign, run AddCampaign.cs. To add sitelinks using the /// simpler ExtensionSetting services, see AddSitelinks.cs. /// </summary> public class AddSitelinksUsingFeeds : ExampleBase { /// <summary> /// Holds data about sitelinks in a feed. /// </summary> private class SitelinksDataHolder { /// <summary> /// The sitelink feed item IDs. /// </summary> private List<long> feedItemIds = new List<long>(); /// <summary> /// Gets the sitelink feed item IDs. /// </summary> public List<long> FeedItemIds { get { return feedItemIds; } } /// <summary> /// Gets or sets the feed ID. /// </summary> public long FeedId { get; set; } /// <summary> /// Gets or sets the link text feed attribute ID. /// </summary> public long LinkTextFeedAttributeId { get; set; } /// <summary> /// Gets or sets the link URL feed attribute ID. /// </summary> public long LinkFinalUrlFeedAttributeId { get; set; } /// <summary> /// Gets or sets the line 2 feed attribute ID. /// </summary> public long Line2FeedAttributeId { get; set; } /// <summary> /// Gets or sets the line 3 feed attribute ID. /// </summary> public long Line3FeedAttributeId { 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) { AddSitelinksUsingFeeds codeExample = new AddSitelinksUsingFeeds(); Console.WriteLine(codeExample.Description); try { long campaignId = long.Parse("INSERT_CAMPAIGN_ID_HERE"); long adGroupId = long.Parse("INSERT_ADGROUP_ID_HERE"); string feedName = "INSERT_FEED_NAME_HERE"; codeExample.Run(new AdWordsUser(), campaignId, feedName, adGroupId); } catch (Exception e) { Console.WriteLine("An exception occurred while running this code example. {0}", ExampleUtilities.FormatException(e)); } } /// <summary> /// Returns a description about the code example. /// </summary> public override string Description { get { return "This code example adds sitelinks to a campaign using feed services." + "To create a campaign, run AddCampaign.cs. To add sitelinks using the " + "simpler ExtensionSetting services, see AddSitelinks.cs."; } } /// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> /// <param name="campaignId">Id of the campaign with which sitelinks are associated. /// </param> /// <param name="adGroupId">Id of the adgroup to restrict targeting to.</param> /// <param name="feedName">Name of the feed to be created.</param> public void Run(AdWordsUser user, long campaignId, string feedName, long? adGroupId) { SitelinksDataHolder sitelinksData = new SitelinksDataHolder(); CreateSitelinksFeed(user, sitelinksData, feedName); CreateSitelinksFeedItems(user, sitelinksData); createSitelinksFeedMapping(user, sitelinksData); CreateSitelinksCampaignFeed(user, sitelinksData, campaignId); RestrictFeedItemToAdGroup(user, sitelinksData, adGroupId); } private static void RestrictFeedItemToGeoTarget(AdWordsUser user, FeedItem feedItem, long locationId) { FeedItemCriterionTarget criterionTarget = new FeedItemCriterionTarget() { feedId = feedItem.feedId, feedItemId = feedItem.feedItemId, // The IDs can be found in the documentation or retrieved with the // LocationCriterionService. criterion = new Location() { id = locationId, } }; using (FeedItemTargetService feedItemTargetService = (FeedItemTargetService) user.GetService( AdWordsService.v201809.FeedItemTargetService)) { FeedItemTargetOperation operation = new FeedItemTargetOperation() { @operator = Operator.ADD, operand = criterionTarget }; FeedItemTargetReturnValue retval = feedItemTargetService.mutate( new FeedItemTargetOperation[] { operation }); FeedItemCriterionTarget newLocationTarget = (FeedItemCriterionTarget) retval.value[0]; Console.WriteLine( "Feed item target for feed ID {0} and feed item ID {1}" + " was created to restrict serving to location ID {2}", newLocationTarget.feedId, newLocationTarget.feedItemId, newLocationTarget.criterion.id); } } private static void RestrictFeedItemToAdGroup(AdWordsUser user, SitelinksDataHolder sitelinksData, long? adGroupId) { // Optional: Restrict the first feed item to only serve with ads for the // specified ad group ID. FeedItemAdGroupTarget adGroupTarget = new FeedItemAdGroupTarget() { feedId = sitelinksData.FeedId, feedItemId = sitelinksData.FeedItemIds[0], adGroupId = adGroupId.Value }; using (FeedItemTargetService feedItemTargetService = (FeedItemTargetService) user.GetService( AdWordsService.v201809.FeedItemTargetService)) { FeedItemTargetOperation operation = new FeedItemTargetOperation() { @operator = Operator.ADD, operand = adGroupTarget }; FeedItemTargetReturnValue retval = feedItemTargetService.mutate( new FeedItemTargetOperation[] { operation }); FeedItemAdGroupTarget newAdGroupTarget = (FeedItemAdGroupTarget) retval.value[0]; Console.WriteLine( "Feed item target for feed ID {0} and feed item ID {1}" + " was created to restrict serving to ad group ID {2}", newAdGroupTarget.feedId, newAdGroupTarget.feedItemId, newAdGroupTarget.adGroupId); } } private static void CreateSitelinksFeed(AdWordsUser user, SitelinksDataHolder sitelinksData, string feedName) { using (FeedService feedService = (FeedService) user.GetService(AdWordsService.v201809.FeedService)) { // Create attributes. FeedAttribute textAttribute = new FeedAttribute() { type = FeedAttributeType.STRING, name = "Link Text" }; FeedAttribute finalUrlAttribute = new FeedAttribute() { type = FeedAttributeType.URL_LIST, name = "Link Final URLs" }; FeedAttribute line2Attribute = new FeedAttribute() { type = FeedAttributeType.STRING, name = "Line 2" }; FeedAttribute line3Attribute = new FeedAttribute() { type = FeedAttributeType.STRING, name = "Line 3" }; // Create the feed. Feed sitelinksFeed = new Feed() { name = feedName, attributes = new FeedAttribute[] { textAttribute, finalUrlAttribute, line2Attribute, line3Attribute }, origin = FeedOrigin.USER }; // Create operation. FeedOperation operation = new FeedOperation() { operand = sitelinksFeed, @operator = Operator.ADD }; // Add the feed. FeedReturnValue result = feedService.mutate(new FeedOperation[] { operation }); Feed savedFeed = result.value[0]; sitelinksData.FeedId = savedFeed.id; FeedAttribute[] savedAttributes = savedFeed.attributes; sitelinksData.LinkTextFeedAttributeId = savedAttributes[0].id; sitelinksData.LinkFinalUrlFeedAttributeId = savedAttributes[1].id; sitelinksData.Line2FeedAttributeId = savedAttributes[2].id; sitelinksData.Line3FeedAttributeId = savedAttributes[3].id; Console.WriteLine( "Feed with name {0} and ID {1} with linkTextAttributeId {2}, " + "linkFinalUrlAttributeId {3}, line2AttributeId {4} and line3AttributeId {5} " + "was created.", savedFeed.name, savedFeed.id, savedAttributes[0].id, savedAttributes[1].id, savedAttributes[2].id, savedAttributes[3].id); } } private static void CreateSitelinksFeedItems(AdWordsUser user, SitelinksDataHolder siteLinksData) { using (FeedItemService feedItemService = (FeedItemService) user.GetService(AdWordsService.v201809.FeedItemService)) { // Create operations to add FeedItems. FeedItemOperation home = NewSitelinkFeedItemAddOperation(siteLinksData, "Home", "http://www.example.com", "Home line 2", "Home line 3"); FeedItemOperation stores = NewSitelinkFeedItemAddOperation(siteLinksData, "Stores", "http://www.example.com/stores", "Stores line 2", "Stores line 3"); FeedItemOperation onSale = NewSitelinkFeedItemAddOperation(siteLinksData, "On Sale", "http://www.example.com/sale", "On Sale line 2", "On Sale line 3"); FeedItemOperation support = NewSitelinkFeedItemAddOperation(siteLinksData, "Support", "http://www.example.com/support", "Support line 2", "Support line 3"); FeedItemOperation products = NewSitelinkFeedItemAddOperation(siteLinksData, "Products", "http://www.example.com/prods", "Products line 2", "Products line 3"); // This site link is using geographical targeting to use LOCATION_OF_PRESENCE. FeedItemOperation aboutUs = NewSitelinkFeedItemAddOperation(siteLinksData, "About Us", "http://www.example.com/about", "About Us line 2", "About Us line 3", true); FeedItemOperation[] operations = new FeedItemOperation[] { home, stores, onSale, support, products, aboutUs }; FeedItemReturnValue result = feedItemService.mutate(operations); foreach (FeedItem item in result.value) { Console.WriteLine("FeedItem with feedItemId {0} was added.", item.feedItemId); siteLinksData.FeedItemIds.Add(item.feedItemId); } // Target the "aboutUs" sitelink to geographically target California. // See https://developers.google.com/adwords/api/docs/appendix/geotargeting for // location criteria for supported locations. RestrictFeedItemToGeoTarget(user, result.value[5], 21137); } } // See the Placeholder reference page for a list of all the placeholder types and fields. // https://developers.google.com/adwords/api/docs/appendix/placeholders.html private const int PLACEHOLDER_SITELINKS = 1; // See the Placeholder reference page for a list of all the placeholder types and fields. private const int PLACEHOLDER_FIELD_SITELINK_LINK_TEXT = 1; private const int PLACEHOLDER_FIELD_SITELINK_FINAL_URL = 5; private const int PLACEHOLDER_FIELD_LINE_2_TEXT = 3; private const int PLACEHOLDER_FIELD_LINE_3_TEXT = 4; private static void createSitelinksFeedMapping(AdWordsUser user, SitelinksDataHolder sitelinksData) { using (FeedMappingService feedMappingService = (FeedMappingService) user.GetService(AdWordsService.v201809.FeedMappingService)) { // Map the FeedAttributeIds to the fieldId constants. AttributeFieldMapping linkTextFieldMapping = new AttributeFieldMapping() { feedAttributeId = sitelinksData.LinkTextFeedAttributeId, fieldId = PLACEHOLDER_FIELD_SITELINK_LINK_TEXT }; AttributeFieldMapping linkFinalUrlFieldMapping = new AttributeFieldMapping() { feedAttributeId = sitelinksData.LinkFinalUrlFeedAttributeId, fieldId = PLACEHOLDER_FIELD_SITELINK_FINAL_URL }; AttributeFieldMapping line2FieldMapping = new AttributeFieldMapping() { feedAttributeId = sitelinksData.Line2FeedAttributeId, fieldId = PLACEHOLDER_FIELD_LINE_2_TEXT }; AttributeFieldMapping line3FieldMapping = new AttributeFieldMapping() { feedAttributeId = sitelinksData.Line3FeedAttributeId, fieldId = PLACEHOLDER_FIELD_LINE_3_TEXT }; // Create the FieldMapping and operation. FeedMappingOperation operation = new FeedMappingOperation() { operand = new FeedMapping() { placeholderType = PLACEHOLDER_SITELINKS, feedId = sitelinksData.FeedId, attributeFieldMappings = new AttributeFieldMapping[] { linkTextFieldMapping, linkFinalUrlFieldMapping, line2FieldMapping, line3FieldMapping } }, @operator = Operator.ADD }; // Save the field mapping. FeedMappingReturnValue result = feedMappingService.mutate(new FeedMappingOperation[] { operation }); foreach (FeedMapping savedFeedMapping in result.value) { Console.WriteLine( "Feed mapping with ID {0} and placeholderType {1} was saved for feed " + "with ID {2}.", savedFeedMapping.feedMappingId, savedFeedMapping.placeholderType, savedFeedMapping.feedId); } } } private static void CreateSitelinksCampaignFeed(AdWordsUser user, SitelinksDataHolder sitelinksData, long campaignId) { using (CampaignFeedService campaignFeedService = (CampaignFeedService) user.GetService(AdWordsService.v201809.CampaignFeedService)) { // Construct a matching function that associates the sitelink feeditems // to the campaign, and set the device preference to Mobile. See the // matching function guide at // https://developers.google.com/adwords/api/docs/guides/feed-matching-functions // for more details. string matchingFunctionString = string.Format(@" AND( IN(FEED_ITEM_ID, {{{0}}}), EQUALS(CONTEXT.DEVICE, 'Mobile') )", string.Join(",", sitelinksData.FeedItemIds)); CampaignFeed campaignFeed = new CampaignFeed() { feedId = sitelinksData.FeedId, campaignId = campaignId, matchingFunction = new Function() { functionString = matchingFunctionString }, // Specifying placeholder types on the CampaignFeed allows the same feed // to be used for different placeholders in different Campaigns. placeholderTypes = new int[] { PLACEHOLDER_SITELINKS } }; CampaignFeedOperation operation = new CampaignFeedOperation() { operand = campaignFeed, @operator = Operator.ADD }; CampaignFeedReturnValue result = campaignFeedService.mutate( new CampaignFeedOperation[] { operation }); foreach (CampaignFeed savedCampaignFeed in result.value) { Console.WriteLine("Campaign with ID {0} was associated with feed with ID {1}", savedCampaignFeed.campaignId, savedCampaignFeed.feedId); } } } private static FeedItemOperation NewSitelinkFeedItemAddOperation( SitelinksDataHolder sitelinksData, string text, string finalUrl, string line2, string line3) { return NewSitelinkFeedItemAddOperation(sitelinksData, text, finalUrl, line2, line3, false); } private static FeedItemOperation NewSitelinkFeedItemAddOperation( SitelinksDataHolder sitelinksData, string text, string finalUrl, string line2, string line3, bool restrictToLop) { // Create the FeedItemAttributeValues for our text values. FeedItemAttributeValue linkTextAttributeValue = new FeedItemAttributeValue() { feedAttributeId = sitelinksData.LinkTextFeedAttributeId, stringValue = text }; FeedItemAttributeValue linkFinalUrlAttributeValue = new FeedItemAttributeValue() { feedAttributeId = sitelinksData.LinkFinalUrlFeedAttributeId, stringValues = new string[] { finalUrl } }; FeedItemAttributeValue line2AttributeValue = new FeedItemAttributeValue() { feedAttributeId = sitelinksData.Line2FeedAttributeId, stringValue = line2 }; FeedItemAttributeValue line3AttributeValue = new FeedItemAttributeValue() { feedAttributeId = sitelinksData.Line3FeedAttributeId, stringValue = line3 }; // Create the feed item and operation. FeedItem item = new FeedItem() { feedId = sitelinksData.FeedId, attributeValues = new FeedItemAttributeValue[] { linkTextAttributeValue, linkFinalUrlAttributeValue, line2AttributeValue, line3AttributeValue } }; // OPTIONAL: Restrict targeting only to people physically within the location. if (restrictToLop) { item.geoTargetingRestriction = new FeedItemGeoRestriction() { geoRestriction = GeoRestriction.LOCATION_OF_PRESENCE }; } return new FeedItemOperation() { operand = item, @operator = Operator.ADD }; } } }