Extensions Samples

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.v201806;
using Google.Api.Ads.Common.Lib;

using System;

namespace Google.Api.Ads.AdWords.Examples.CSharp.v201806
{
    /// <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.v201806.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.v201806.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.v201806;

using System;
using System.Collections.Generic;

using DayOfWeek = Google.Api.Ads.AdWords.v201806.DayOfWeek;

namespace Google.Api.Ads.AdWords.Examples.CSharp.v201806
{
    /// <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.v201806
                    .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.v201806;

using System;
using System.Collections.Generic;

using DayOfWeek = Google.Api.Ads.AdWords.v201806.DayOfWeek;

namespace Google.Api.Ads.AdWords.Examples.CSharp.v201806
{
    /// <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.v201806
                    .CampaignExtensionSettingService))
            {
                Customer customer = null;
                using (CustomerService customerService =
                    (CustomerService) user.GetService(AdWordsService.v201806.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.v201806;

using System;
using System.Collections.Generic;

namespace Google.Api.Ads.AdWords.Examples.CSharp.v201806
{
    /// <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.v201802.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.v201806.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.v201806.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.v201806.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.v201806.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.v201806.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
            };
        }
    }
}

Send feedback about...

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