If you're still on v201609, please migrate to a newer version before October 2, 2017.

Extensions Samples

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

Add Google My Business location extensions

#!/usr/bin/perl -w
#
# Copyright 2017, Google Inc. All Rights Reserved.
#
# 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.
#
# This example adds a feed that syncs feed items from a Google
# My Business (GMB) account and associates the feed with a customer.

use strict;
use lib "../../../lib";

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Constants;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::ConstantOperand;
use Google::Ads::AdWords::v201708::CustomerFeed;
use Google::Ads::AdWords::v201708::CustomerFeedOperation;
use Google::Ads::AdWords::v201708::Feed;
use Google::Ads::AdWords::v201708::FeedOperation;
use Google::Ads::AdWords::v201708::Function;
use Google::Ads::AdWords::v201708::PlacesLocationFeedData;
use Google::Ads::AdWords::v201708::OAuthInfo;

use Cwd qw(abs_path);
use Data::Uniqid qw(uniqid);

# See the Placeholder reference page for a list of all the placeholder types and
# fields.
# https://developers.google.com/adwords/api/docs/appendix/placeholders
use constant PLACEHOLDER_LOCATION => 7;

# The maximum number of CustomerFeed ADD operation attempts to make before
# throwing an exception.
use constant MAX_CUSTOMER_FEED_ADD_ATTEMPTS => 10;

# The email address of either an owner or a manager of the GMB account.
my $gmb_email_address = 'INSERT_GMB_EMAIL_ADDRESS_HERE';

# 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
# generate_offline_credentials example. Make sure you are logged in as the
# same user as gmbEmailAddress above when you follow the link provided by the
# example, then capture the credential's access token. Copy and paste the value
# into the assignment below.
my $gmb_access_token;

# If the gmb_email_address 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.
my $business_account_identifier = undef;

# Example main subroutine.
sub add_gmb_location_extensions {
  my ($client, $gmb_email_address, $gmb_access_token,
    $business_account_identifier)
    = @_;

  # Create a feed that will sync to the Google My Business account specified
  # by gmb_email_address. Do not add FeedAttributes to this object,
  # as AdWords will add them automatically because this will be a
  # system generated feed.
  my $gmb_feed = Google::Ads::AdWords::v201708::Feed->new({
      name => "Google My Business feed " . uniqid(),
      # Since this feed's feed items will be managed by AdWords,
      # you must set its origin to ADWORDS.
      origin => "ADWORDS"
  });

  my $oauth_info = Google::Ads::AdWords::v201708::OAuthInfo->new({
      httpMethod     => "GET",
      httpRequestUrl => Google::Ads::AdWords::Constants::DEFAULT_OAUTH_SCOPE,
      httpAuthorizationHeader => "Bearer ${gmb_access_token}"
  });
  my $feed_data = Google::Ads::AdWords::v201708::PlacesLocationFeedData->new({
      emailAddress => $gmb_email_address,
      oAuthInfo    => $oauth_info,
      # 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 => ["Stores in New York City"]
  });

  if ($business_account_identifier) {
    $feed_data->set_businessAccountIdentifier($business_account_identifier);
  }

  $gmb_feed->set_systemFeedGenerationData($feed_data);

  # Create an operation to add the feed.
  my $feed_operation = Google::Ads::AdWords::v201708::FeedOperation->new({
      operand  => $gmb_feed,
      operator => "ADD"
  });

  # 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.
  my $feed_result = $client->FeedService()->mutate({
      operations => [
        Google::Ads::AdWords::v201708::FeedOperation->new({
            operator => "ADD",
            operand  => $gmb_feed
          })]});

  my $added_feed = $feed_result->get_value(0);

  printf "Added GMB feed with ID %d\n", $added_feed->get_id();

  # Add a CustomerFeed that associates the feed with this customer for
  # the LOCATION placeholder type.
  my $customer_feed = Google::Ads::AdWords::v201708::CustomerFeed->new({
      feedId           => $added_feed->get_id(),
      placeholderTypes => [PLACEHOLDER_LOCATION]});

  # Create a matching function that will always evaluate to true.
  my $customer_matching_function = Google::Ads::AdWords::v201708::Function->new(
    {
      lhsOperand => [
        Google::Ads::AdWords::v201708::ConstantOperand->new({
            type         => "BOOLEAN",
            booleanValue => 1
          })
      ],
      operator => "IDENTITY"
    });

  $customer_feed->set_matchingFunction($customer_matching_function);

  # Create an operation to add the customer feed.
  my $customer_feed_operation =
    Google::Ads::AdWords::v201708::CustomerFeedOperation->new({
      operand  => $customer_feed,
      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.
  my $added_customer_feed = undef;
  my $number_of_attempts  = 0;
  # Disable die on faults for this section because we want to retry failed
  # attempts to add the customer feed.
  $client->set_die_on_faults(0);
  do {
    $number_of_attempts++;
    my $customer_feed_result =
      $client->CustomerFeedService()
      ->mutate({operations => [$customer_feed_operation]});

    if ($customer_feed_result->isa("SOAP::WSDL::SOAP::Typelib::Fault11")) {
      # Wait using exponential backoff policy
      my $sleep_seconds = 5 * (2**$number_of_attempts);
      printf "Attempt #%d to add the CustomerFeed was not successful. " .
        "Waiting %d seconds before trying again.\n", $number_of_attempts,
        $sleep_seconds;
      sleep $sleep_seconds;
    } else {
      $added_customer_feed = $customer_feed_result->get_value(0);
      printf "Attempt #%d to add the CustomerFeed was successful.\n",
        $number_of_attempts;
    }
    } while ($number_of_attempts < MAX_CUSTOMER_FEED_ADD_ATTEMPTS
    and !$added_customer_feed);

  # Restore the previous setting of die on faults now that we are done retrying
  # requests.
  $client->set_die_on_faults(1);

  if (!$added_customer_feed) {
    die "Could not create the CustomerFeed after " .
      MAX_CUSTOMER_FEED_ADD_ATTEMPTS . " attempts. Please retry " .
      "the CustomerFeed ADD operation later.";
  }

  printf "Added CustomerFeed for feed ID %d and placeholder type %d\n",
    $added_customer_feed->get_feedId(),
    PLACEHOLDER_LOCATION;

  return 1;
}

# Don't run the example if the file is being included.
if (abs_path($0) ne abs_path(__FILE__)) {
  return 1;
}

# Log SOAP XML request, response and API errors.
Google::Ads::AdWords::Logging::enable_all_logging();

# Get AdWords Client, credentials will be read from ~/adwords.properties.
my $client = Google::Ads::AdWords::Client->new({version => "v201708"});

# By default examples are set to die on any server returned fault.
$client->set_die_on_faults(1);

# If the access token has not been set, then retrieve the access token.
my $auth_handler = $client->get_oauth_2_handler();
if (!$gmb_access_token) {
  $gmb_access_token = $auth_handler->get_access_token();
}

# Call the example
add_gmb_location_extensions($client, $gmb_email_address,
  $gmb_access_token, $business_account_identifier);

Add prices

#!/usr/bin/perl -w
#
# Copyright 2017, Google Inc. All Rights Reserved.
#
# 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.
#
# This example adds a prices feed and associates it with a campaign.

use strict;
use lib "../../../lib";
use utf8;

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::CustomerExtensionSetting;
use Google::Ads::AdWords::v201708::CustomerExtensionSettingOperation;
use Google::Ads::AdWords::v201708::FeedItemCampaignTargeting;
use Google::Ads::AdWords::v201708::FeedItemSchedule;
use Google::Ads::AdWords::v201708::FeedItemScheduling;
use Google::Ads::AdWords::v201708::Keyword;
use Google::Ads::AdWords::v201708::Location;
use Google::Ads::AdWords::v201708::Money;
use Google::Ads::AdWords::v201708::MoneyWithCurrency;
use Google::Ads::AdWords::v201708::PriceFeedItem;
use Google::Ads::AdWords::v201708::PriceTableRow;
use Google::Ads::AdWords::v201708::UrlList;

use Cwd qw(abs_path);
use Data::Uniqid qw(uniqid);

# Replace with valid values of your account.
my $campaign_id = "INSERT_CAMPAIGN_ID_HERE";

# Example main subroutine.
sub add_prices {
  my ($client, $campaign_id) = @_;

  # Create the price extension feed item.
  my $price_feed_item = Google::Ads::AdWords::v201708::PriceFeedItem->new({
      priceExtensionType => "SERVICES",
      # Price qualifer is optional.
      priceQualifier      => "FROM",
      trackingUrlTemplate => "http://tracker.example.com/?u={lpurl}",
      language            => 'en',
      campaignTargeting =>
        Google::Ads::AdWords::v201708::FeedItemCampaignTargeting->new({
          TargetingCampaignId => $campaign_id
        }
        ),
      scheduling => Google::Ads::AdWords::v201708::FeedItemScheduling->new({
          feedItemSchedules => [
            Google::Ads::AdWords::v201708::FeedItemSchedule->new({
                dayOfWeek   => "SUNDAY",
                startHour   => "10",
                startMinute => "ZERO",
                endHour     => "18",
                endMinute   => "ZERO"
              }
            ),
            Google::Ads::AdWords::v201708::FeedItemSchedule->new({
                dayOfWeek   => "SATURDAY",
                startHour   => "10",
                startMinute => "ZERO",
                endHour     => "22",
                endMinute   => "ZERO"
              })]})});

  # To create a price extension, at least three table rows are needed.
  my @table_rows = ();
  push @table_rows, create_price_table_row(
    "Scrubs",
    "Body Scrub, Salt Scrub",
    "http://www.example.com/scrubs",
    "http://m.example.com/scrubs",
    60000000,    # 60 USD
    "USD",
    "PER_HOUR"
  );
  push @table_rows, create_price_table_row(
    "Hair Cuts",
    "Once a month",
    "http://www.example.com/haircuts",
    "http://m.example.com/haircuts",
    75000000,    # 75 USD
    "USD",
    "PER_MONTH"
  );
  push @table_rows, create_price_table_row(
    "Skin Care Package",
    "Four times a month",
    "http://www.example.com/skincarepackage",
    undef,
    250000000,    # 250 USD
    "USD",
    "PER_MONTH"
  );
  $price_feed_item->set_tableRows(\@table_rows);

  # Create your customer extension settings. This associates the price
  # extension to your account.
  my $customer_extension_setting =
    Google::Ads::AdWords::v201708::CustomerExtensionSetting->new({
      extensionType    => 'PRICE',
      extensionSetting => Google::Ads::AdWords::v201708::ExtensionSetting->new({
          extensions => [$price_feed_item]})});

  my $mutate_result = $client->CustomerExtensionSettingService()->mutate({
      operations => [
        Google::Ads::AdWords::v201708::CustomerExtensionSettingOperation->new({
            operand  => $customer_extension_setting,
            operator => 'ADD'
          })]});

  my $new_extension_setting = $mutate_result->get_value(0);

  printf "Extension setting with type '%s' was added to your account.\n",
    $new_extension_setting->get_extensionType();
  return 1;
}

# Creates a new price table row with the specified attributes.
sub create_price_table_row {
  my ($header, $description, $final_url, $final_mobile_url, $price_in_micros,
    $currency_code, $price_unit)
    = @_;
  my $price_table_row = Google::Ads::AdWords::v201708::PriceTableRow->new({
      header      => $header,
      description => $description,
      finalUrls =>
        [Google::Ads::AdWords::v201708::UrlList->new({urls => [$final_url]})],
      price => Google::Ads::AdWords::v201708::MoneyWithCurrency->new({
          money => Google::Ads::AdWords::v201708::Money->new({
              microAmount => $price_in_micros
            }
          ),
          currencyCode => $currency_code
        }
      ),
      priceUnit => $price_unit
    });

  # Optional: set the mobile final URLs.
  if ($final_mobile_url) {
    $price_table_row->set_finalMobileUrls([
        Google::Ads::AdWords::v201708::UrlList->new(
          {urls => [$final_mobile_url]})]);
  }

  return $price_table_row;
}

# Don't run the example if the file is being included.
if (abs_path($0) ne abs_path(__FILE__)) {
  return 1;
}

# Log SOAP XML request, response and API errors.
Google::Ads::AdWords::Logging::enable_all_logging();

# Get AdWords Client, credentials will be read from ~/adwords.properties.
my $client = Google::Ads::AdWords::Client->new({version => "v201708"});

# By default examples are set to die on any server returned fault.
$client->set_die_on_faults(1);

# Call the example
add_prices($client, $campaign_id);


Add sitelinks to a campaign

#!/usr/bin/perl -w
#
# Copyright 2017, Google Inc. All Rights Reserved.
#
# 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.
#
# This example adds a sitelinks feed and associates it with a campaign.

use strict;
use lib "../../../lib";

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::CampaignExtensionSetting;
use Google::Ads::AdWords::v201708::CampaignExtensionSettingOperation;
use Google::Ads::AdWords::v201708::FeedItemGeoRestriction;
use Google::Ads::AdWords::v201708::Keyword;
use Google::Ads::AdWords::v201708::Location;
use Google::Ads::AdWords::v201708::SitelinkFeedItem;

use Cwd qw(abs_path);
use Data::Uniqid qw(uniqid);

# Replace with valid values of your account.
my $campaign_id = "INSERT_CAMPAIGN_ID_HERE";

# Example main subroutine.
sub add_site_links {
  my ($client, $campaign_id) = @_;

  my $customer           = $client->CustomerService()->getCustomers()->[0];
  my $customer_time_zone = $customer->get_dateTimeZone();
  printf(
    "Found customer ID %d with time zone %s.\n",
    $customer->get_customerId(),
    $customer_time_zone
  );

  # Create the site links.
  my $site_link_1 = Google::Ads::AdWords::v201708::SitelinkFeedItem->new({
      sitelinkText      => 'Store Hours',
      sitelinkFinalUrls => Google::Ads::AdWords::v201708::UrlList->new(
        {urls => ['http://www.example.com/storehours']})});

  # Set the startTime and endTime to show the Thanksgiving specials link only
  # from 20 - 27 Nov.
  my $site_link_2 = Google::Ads::AdWords::v201708::SitelinkFeedItem->new({
      sitelinkText      => 'Thanksgiving Specials',
      sitelinkFinalUrls => Google::Ads::AdWords::v201708::UrlList->new(
        {urls => ['http://www.example.com/thanksgiving']})});

  # The time zone of the start and end date/times must match the time zone of
  # the customer.
  my ($sec, $min, $hour, $mday, $mon, $year) = localtime(time - (60 * 60 * 24));
  my $start_time =
    sprintf("%d1120 000000 %s", ($year + 1900), $customer_time_zone);
  my $end_time =
    sprintf("%d1127 235959 %s", ($year + 1900), $customer_time_zone);
  $site_link_2->set_startTime($start_time);
  $site_link_2->set_endTime($end_time);

  # Target this sitelink for United States only. See
  # https://developers.google.com/adwords/api/docs/appendix/geotargeting
  # for valid geolocation codes.
  my $location = Google::Ads::AdWords::v201708::Location->new({
    id => 2840    # United States
  });
  $site_link_2->set_geoTargeting($location);

  # 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.
  my $geo_targeting_restriction =
    Google::Ads::AdWords::v201708::FeedItemGeoRestriction->new({
      geoRestriction => "LOCATION_OF_PRESENCE"
    });
  $site_link_2->set_geoTargetingRestriction($geo_targeting_restriction);

  # Set the devicePreference to show the wifi details primarily for high end
  # mobile users.
  # Target this sitelink for the keyword "free wifi".
  my $keyword = Google::Ads::AdWords::v201708::Keyword->new({
    text      => "free wifi",
    matchType => "BROAD"
  });
  my $site_link_3 = Google::Ads::AdWords::v201708::SitelinkFeedItem->new({
      sitelinkText      => 'Wifi available',
      keywordTargeting  => $keyword,
      sitelinkFinalUrls => Google::Ads::AdWords::v201708::UrlList->new(
        {urls => ['http://www.example.com/mobile/wifi']}
      ),
      devicePreference =>
        Google::Ads::AdWords::v201708::FeedItemDevicePreference->new({
          # See https://developers.google.com/adwords/api/docs/appendix/platforms
          # for device criteria IDs.
          devicePreference => '30001'
        })});

  # Set the feedItemSchedules to show the happy hours link only during Mon - Fri
  # 6PM to 9PM.
  my $site_link_4 = Google::Ads::AdWords::v201708::SitelinkFeedItem->new({
      sitelinkText      => 'Happy hours',
      sitelinkFinalUrls => Google::Ads::AdWords::v201708::UrlList->new(
        {urls => ['http://www.example.com/mobile/happyhours']}
      ),
    });

  my @schedules = ();
  foreach my $day_name ('MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY')
  {
    push @schedules,
      Google::Ads::AdWords::v201708::FeedItemSchedule->new({
        'dayOfWeek'   => $day_name,
        'startHour'   => 18,
        'startMinute' => 'ZERO',
        'endHour'     => 21,
        'endMinute'   => 'ZERO',
      });
  }
  $site_link_4->set_scheduling(
    Google::Ads::AdWords::v201708::FeedItemScheduling->new(
      {feedItemSchedules => \@schedules}));

  my $campaign_extension_setting =
    Google::Ads::AdWords::v201708::CampaignExtensionSetting->new({
      campaignId       => $campaign_id,
      extensionType    => 'SITELINK',
      extensionSetting => Google::Ads::AdWords::v201708::ExtensionSetting->new({
          extensions => [$site_link_1, $site_link_2, $site_link_3, $site_link_4]
        })});

  my $mutate_result = $client->CampaignExtensionSettingService()->mutate({
      operations => [
        Google::Ads::AdWords::v201708::CampaignExtensionSettingOperation->new({
            operand  => $campaign_extension_setting,
            operator => 'ADD'
          })]});

  my $added_extension_setting = $mutate_result->get_value(0);

  printf "Extension setting with type = %s was added to campaign ID %d.\n",
    $added_extension_setting->get_extensionType(),
    $added_extension_setting->get_campaignId();
  return 1;
}

# Don't run the example if the file is being included.
if (abs_path($0) ne abs_path(__FILE__)) {
  return 1;
}

# Log SOAP XML request, response and API errors.
Google::Ads::AdWords::Logging::enable_all_logging();

# Get AdWords Client, credentials will be read from ~/adwords.properties.
my $client = Google::Ads::AdWords::Client->new({version => "v201708"});

# By default examples are set to die on any server returned fault.
$client->set_die_on_faults(1);

# Call the example
add_site_links($client, $campaign_id);


Add sitelinks to a campaign using feeds

#!/usr/bin/perl -w
#
# Copyright 2017, Google Inc. All Rights Reserved.
#
# 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.
#
# This example adds a sitelinks feed and associates it with a campaign. To
# create a campaign, run add_campaigns.pl. To add sitelinks using the simpler
# ExtensionSetting services, see add_site_links.pl.

use strict;
use lib "../../../lib";

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::AttributeFieldMapping;
use Google::Ads::AdWords::v201708::CampaignFeed;
use Google::Ads::AdWords::v201708::CampaignFeedOperation;
use Google::Ads::AdWords::v201708::Feed;
use Google::Ads::AdWords::v201708::FeedAttribute;
use Google::Ads::AdWords::v201708::FeedItem;
use Google::Ads::AdWords::v201708::FeedItemAttributeValue;
use Google::Ads::AdWords::v201708::FeedItemGeoRestriction;
use Google::Ads::AdWords::v201708::FeedItemOperation;
use Google::Ads::AdWords::v201708::FeedMapping;
use Google::Ads::AdWords::v201708::FeedMappingOperation;
use Google::Ads::AdWords::v201708::FeedOperation;
use Google::Ads::AdWords::v201708::Function;
use Google::Ads::AdWords::v201708::Location;

use Cwd qw(abs_path);

# See the Placeholder reference page for a list of all the placeholder types and
# fields.
# https://developers.google.com/adwords/api/docs/appendix/placeholders
use constant PLACEHOLDER_SITELINKS                  => 1;
use constant PLACEHOLDER_FIELD_SITELINK_LINK_TEXT   => 1;
use constant PLACEHOLDER_FIELD_SITELINK_FINAL_URLS  => 5;
use constant PLACEHOLDER_FIELD_SITELINK_LINE_2_TEXT => 3;
use constant PLACEHOLDER_FIELD_SITELINK_LINE_3_TEXT => 4;

# Replace with valid values of your account.
my $campaign_id = "INSERT_CAMPAIGN_ID_HERE";
my $feed_name   = "INSERT_FEED_NAME_HERE";

# Example main subroutine.
sub add_site_links_using_feeds {
  my ($client, $campaign_id, $feed_name) = @_;

  my $site_links_data = {
    "siteLinksFeedId"             => 0,
    "linkTextFeedAttributeId"     => 0,
    "linkFinalUrlFeedAttributeId" => 0,
    "line2FeedAttributeId"        => 0,
    "line3FeedAttributeId"        => 0,
    "feedItemIds"                 => []};

  create_site_links_feed($client, $site_links_data, $feed_name);
  create_site_links_feed_items($client, $site_links_data);
  create_site_links_feed_mapping($client, $site_links_data);
  create_site_links_campaign_feed($client, $site_links_data, $campaign_id);

  return 1;
}

sub create_site_links_feed {
  my ($client, $site_links_data, $feed_name) = @_;

  my $text_attribute = Google::Ads::AdWords::v201708::FeedAttribute->new({
    type => "STRING",
    name => "Link Text"
  });
  my $final_url_attribute = Google::Ads::AdWords::v201708::FeedAttribute->new({
    type => "URL_LIST",
    name => "Link Final URLs"
  });
  my $line_2_attribute = Google::Ads::AdWords::v201708::FeedAttribute->new({
    type => "STRING",
    name => "Line 2"
  });
  my $line_3_attribute = Google::Ads::AdWords::v201708::FeedAttribute->new({
    type => "STRING",
    name => "Line 3"
  });
  my $feed = Google::Ads::AdWords::v201708::Feed->new({
      name       => $feed_name,
      attributes => [
        $text_attribute,   $final_url_attribute,
        $line_2_attribute, $line_3_attribute
      ],
      origin => "USER"
    });

  my $operation = Google::Ads::AdWords::v201708::FeedOperation->new({
    operator => "ADD",
    operand  => $feed
  });

  my $feed_result =
    $client->FeedService()->mutate({operations => [$operation]});

  my $saved_feed = $feed_result->get_value(0);

  $site_links_data->{"siteLinksFeedId"} = $saved_feed->get_id();

  my $saved_attributes = $saved_feed->get_attributes();

  $site_links_data->{"linkTextFeedAttributeId"} =
    $saved_attributes->[0]->get_id();
  $site_links_data->{"linkFinalUrlFeedAttributeId"} =
    $saved_attributes->[1]->get_id();
  $site_links_data->{"line2FeedAttributeId"} = $saved_attributes->[2]->get_id();
  $site_links_data->{"line3FeedAttributeId"} = $saved_attributes->[3]->get_id();
  printf(
    "Feed with name '%s' and ID %d with linkTextAttributeId %d" .
      " and linkFinalUrlAttributeId %d and line2AttributeId %d" .
      " and line3AttributeId %d was created.\n",
    $saved_feed->get_name(),          $saved_feed->get_id(),
    $saved_attributes->[0]->get_id(), $saved_attributes->[1]->get_id(),
    $saved_attributes->[2]->get_id(), $saved_attributes->[3]->get_id());
}

sub create_site_links_feed_items {
  my ($client, $site_links_data) = @_;

  my @operations = ();

  push @operations,
    create_feed_item_add_operation($site_links_data,
    "Home", "http://www.example.com", "Home line 2", "Home line 3");
  push @operations,
    create_feed_item_add_operation(
    $site_links_data, "Stores",
    "http://www.example.com/stores",
    "Stores line 2",
    "Stores line 3"
    );
  push @operations,
    create_feed_item_add_operation(
    $site_links_data, "On Sale", "http://www.example.com/sale",
    "On Sale line 2",
    "On Sale line 3"
    );
  push @operations,
    create_feed_item_add_operation(
    $site_links_data, "Support",
    "http://www.example.com/support",
    "Support line 2",
    "Support line 3"
    );
  push @operations,
    create_feed_item_add_operation(
    $site_links_data, "Products",
    "http://www.example.com/prods",
    "Products line 2",
    "Products line 3"
    );
  # This site link is using geographical targeting by specifying the criterion
  # ID for California.
  push @operations,
    create_feed_item_add_operation(
    $site_links_data, "About Us",
    "http://www.example.com/about",
    "About Us line 2",
    "About Us line 3", "21137"
    );

  my $result = $client->FeedItemService()->mutate({operations => \@operations});

  foreach my $feed_item (@{$result->get_value()}) {
    printf "FeedItem with feedItemId %d was added.\n",
      $feed_item->get_feedItemId();
    push $site_links_data->{"feedItemIds"}, $feed_item->get_feedItemId();
  }
}

sub create_feed_item_add_operation {
  my ($site_links_data, $text, $final_url, $line_2, $line_3, $location_id) = @_;

  my $text_attribute_value =
    Google::Ads::AdWords::v201708::FeedItemAttributeValue->new({
      feedAttributeId => $site_links_data->{"linkTextFeedAttributeId"},
      stringValue     => $text
    });
  my $final_url_attribute_value =
    Google::Ads::AdWords::v201708::FeedItemAttributeValue->new({
      feedAttributeId => $site_links_data->{"linkFinalUrlFeedAttributeId"},
      stringValues    => [$final_url]});
  my $line_2_attribute_value =
    Google::Ads::AdWords::v201708::FeedItemAttributeValue->new({
      feedAttributeId => $site_links_data->{"line2FeedAttributeId"},
      stringValue     => $line_2
    });
  my $line_3_attribute_value =
    Google::Ads::AdWords::v201708::FeedItemAttributeValue->new({
      feedAttributeId => $site_links_data->{"line3FeedAttributeId"},
      stringValue     => $line_3
    });

  my $feed_item = Google::Ads::AdWords::v201708::FeedItem->new({
      feedId          => $site_links_data->{"siteLinksFeedId"},
      attributeValues => [
        $text_attribute_value,   $final_url_attribute_value,
        $line_2_attribute_value, $line_3_attribute_value
      ]});

  # OPTIONAL: Use geographical targeting on a feed.
  # The IDs can be found in the documentation or retrieved with the
  # LocationCriterionService.
  if ($location_id) {
    my $location =
      Google::Ads::AdWords::v201708::Location->new({id => $location_id});
    $feed_item->set_geoTargeting($location);
    # OPTIONAL: Restrict targeting only to people physically within
    # the location.
    my $geo_targeting_restriction =
      Google::Ads::AdWords::v201708::FeedItemGeoRestriction->new({
        geoRestriction => "LOCATION_OF_PRESENCE"
      });
    $feed_item->set_geoTargetingRestriction($geo_targeting_restriction);
  }

  my $operation = Google::Ads::AdWords::v201708::FeedItemOperation->new({
    operand  => $feed_item,
    operator => "ADD"
  });

  return $operation;
}

sub create_site_links_feed_mapping {
  my ($client, $site_links_data) = @_;

  # Map the FeedAttributeIds to the fieldId constants.
  my $text_field_mapping =
    Google::Ads::AdWords::v201708::AttributeFieldMapping->new({
      feedAttributeId => $site_links_data->{"linkTextFeedAttributeId"},
      fieldId         => PLACEHOLDER_FIELD_SITELINK_LINK_TEXT
    });
  my $final_url_field_mapping =
    Google::Ads::AdWords::v201708::AttributeFieldMapping->new({
      feedAttributeId => $site_links_data->{"linkFinalUrlFeedAttributeId"},
      fieldId         => PLACEHOLDER_FIELD_SITELINK_FINAL_URLS
    });
  my $line_2_field_mapping =
    Google::Ads::AdWords::v201708::AttributeFieldMapping->new({
      feedAttributeId => $site_links_data->{"line2FeedAttributeId"},
      fieldId         => PLACEHOLDER_FIELD_SITELINK_LINE_2_TEXT
    });
  my $line_3_field_mapping =
    Google::Ads::AdWords::v201708::AttributeFieldMapping->new({
      feedAttributeId => $site_links_data->{"line3FeedAttributeId"},
      fieldId         => PLACEHOLDER_FIELD_SITELINK_LINE_3_TEXT
    });

  # Create the FeedMapping and operation.
  my $feed_mapping = Google::Ads::AdWords::v201708::FeedMapping->new({
      placeholderType        => PLACEHOLDER_SITELINKS,
      feedId                 => $site_links_data->{"siteLinksFeedId"},
      attributeFieldMappings => [
        $text_field_mapping,   $final_url_field_mapping,
        $line_2_field_mapping, $line_3_field_mapping
      ]});

  my $operation = Google::Ads::AdWords::v201708::FeedMappingOperation->new({
    operand  => $feed_mapping,
    operator => "ADD"
  });

  # Save the feed mapping.
  my $result =
    $client->FeedMappingService()->mutate({operations => [$operation]});

  foreach my $saved_feed_mapping (@{$result->get_value()}) {
    printf "Feed mapping with ID %d and placeholderType %d was saved for " .
      "feed with ID %d.\n", $saved_feed_mapping->get_feedMappingId(),
      $saved_feed_mapping->get_placeholderType(),
      $saved_feed_mapping->get_feedId();
  }
}

sub create_site_links_campaign_feed {
  my ($client, $site_links_data, $campaign_id) = @_;

  # Construct a matching function that assoicates the sitelink feed items
  # to the campaign, and sets 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.
  my $matching_function_string =
    sprintf("AND( IN(FEED_ITEM_ID, {%s}), EQUALS(CONTEXT.DEVICE, 'Mobile') )",
    (join ' ,', @{$site_links_data->{"feedItemIds"}}));

  my $matching_function = Google::Ads::AdWords::v201708::Function->new(
    {functionString => $matching_function_string});

  my $campaign_feed = Google::Ads::AdWords::v201708::CampaignFeed->new({
      feedId           => $site_links_data->{"siteLinksFeedId"},
      campaignId       => $campaign_id,
      matchingFunction => $matching_function,
      # Specifying placeholder types on the CampaignFeed allows the same feed
      # to be used for different placeholders in different Campaigns.
      placeholderTypes => [PLACEHOLDER_SITELINKS]});

  my $result = $client->CampaignFeedService()->mutate({
      operations => [
        Google::Ads::AdWords::v201708::CampaignFeedOperation->new({
            operand  => $campaign_feed,
            operator => "ADD"
          })]});

  $campaign_feed = $result->get_value(0);

  printf "Campaign with ID %d was associated with feed with ID %d.\n",
    $campaign_feed->get_campaignId(), $campaign_feed->get_feedId();
}

# Don't run the example if the file is being included.
if (abs_path($0) ne abs_path(__FILE__)) {
  return 1;
}

# Log SOAP XML request, response and API errors.
Google::Ads::AdWords::Logging::enable_all_logging();

# Get AdWords Client, credentials will be read from ~/adwords.properties.
my $client = Google::Ads::AdWords::Client->new({version => "v201708"});

# By default examples are set to die on any server returned fault.
$client->set_die_on_faults(1);

# Call the example
add_site_links_using_feeds($client, $campaign_id, $feed_name);

Send feedback about...

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