Advanced Operations Samples

The code samples below provide examples of common advanced operations using the AdWords API. Client Library.

Add an ad customizer

#!/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 an ad customizer feed, and then adds an ad in two different
# ad groups that uses the feed to populate dynamic data.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::AdCustomizerFeed;
use Google::Ads::AdWords::v201708::AdCustomizerFeedAttribute;
use Google::Ads::AdWords::v201708::AdCustomizerFeedOperation;
use Google::Ads::AdWords::v201708::AdGroupAd;
use Google::Ads::AdWords::v201708::AdGroupAdOperation;
use Google::Ads::AdWords::v201708::ConstantOperand;
use Google::Ads::AdWords::v201708::ExpandedTextAd;
use Google::Ads::AdWords::v201708::Feed;
use Google::Ads::AdWords::v201708::FeedAttribute;
use Google::Ads::AdWords::v201708::FeedItem;
use Google::Ads::AdWords::v201708::FeedItemAdGroupTargeting;
use Google::Ads::AdWords::v201708::FeedItemAttributeValue;
use Google::Ads::AdWords::v201708::FeedItemOperation;
use Google::Ads::AdWords::v201708::Function;
use Google::Ads::AdWords::v201708::FunctionOperand;
use Google::Ads::AdWords::v201708::RequestContextOperand;

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

# Replace with valid values of your account.
my $ad_group_ids = ["INSERT_ADGROUP_ID_HERE", "INSERT_ADGROUP_ID_HERE"];
my $feed_name = "INSERT_FEED_NAME_HERE";

# Example main subroutine.
sub add_ad_customizers {
  my $client = shift;

  my $ad_group_ids = shift;

  my $feed_name = shift;

  # Create a customizer feed. One feed per account can be used for all ads.
  my $ad_customizer_feed = create_customizer_feed($client, $feed_name);

  # Add feed items containing the values we'd like to place in ads.
  create_customizer_feed_items($client, $ad_customizer_feed, $ad_group_ids);

  # All set! We can now create ads with customizations.
  create_ads_with_customizations($client, $ad_group_ids, $feed_name);

  return 1;
}

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

  my $name_attribute =
    Google::Ads::AdWords::v201708::AdCustomizerFeedAttribute->new({
      type => "STRING",
      name => "Name"
    });
  my $price_attribute =
    Google::Ads::AdWords::v201708::AdCustomizerFeedAttribute->new({
      type => "STRING",
      name => "Price"
    });
  my $date_attribute =
    Google::Ads::AdWords::v201708::AdCustomizerFeedAttribute->new({
      type => "DATE_TIME",
      name => "Date"
    });
  my $ad_customizer_feed = Google::Ads::AdWords::v201708::AdCustomizerFeed->new(
    {
      feedName       => $feed_name,
      feedAttributes => [$name_attribute, $price_attribute, $date_attribute]});

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

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

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

  printf(
    "Ad customizer feed with ID %d and name '%s'.\n",
    $saved_feed->get_feedId(),
    $saved_feed->get_feedName(),
  );

  return $saved_feed;
}

sub create_customizer_feed_items {
  my ($client, $ad_customizer_feed, $ad_group_ids) = @_;

  my @operations = ();

  push @operations,
    create_feed_item_add_operation($ad_customizer_feed,
    "Mars", "\$1234.56", "20140601 000000",
    $ad_group_ids->[0]);
  push @operations,
    create_feed_item_add_operation($ad_customizer_feed,
    "Venus", "\$1450.00", "20140615 120000",
    $ad_group_ids->[1]);

  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();
  }
}

sub create_feed_item_add_operation {
  my ($ad_customizer_feed, $name, $price, $date, $ad_group_id) = @_;

  my $name_attribute_value =
    Google::Ads::AdWords::v201708::FeedItemAttributeValue->new({
      feedAttributeId =>
        $ad_customizer_feed->get_feedAttributes()->[0]->get_id(),
      stringValue => $name
    });
  my $price_attribute_value =
    Google::Ads::AdWords::v201708::FeedItemAttributeValue->new({
      feedAttributeId =>
        $ad_customizer_feed->get_feedAttributes()->[1]->get_id(),
      stringValue => $price
    });
  my $date_attribute_value =
    Google::Ads::AdWords::v201708::FeedItemAttributeValue->new({
      feedAttributeId =>
        $ad_customizer_feed->get_feedAttributes()->[2]->get_id(),
      stringValue => $date
    });

  my $feed_item = Google::Ads::AdWords::v201708::FeedItem->new({
      feedId => $ad_customizer_feed->get_feedId(),
      attributeValues =>
        [$name_attribute_value, $price_attribute_value, $date_attribute_value],
      adGroupTargeting =>
        Google::Ads::AdWords::v201708::FeedItemAdGroupTargeting->new(
        {TargetingAdGroupId => $ad_group_id})});

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

  return $operation;
}

sub create_ads_with_customizations {
  my ($client, $ad_group_ids, $feed_name) = @_;

  my $text_ad = Google::Ads::AdWords::v201708::ExpandedTextAd->new({
      headlinePart1 => sprintf("Luxury Cruise to {=%s.Name}", $feed_name),
      headlinePart2 => sprintf("Only {=%s.Price}",            $feed_name),
      description =>
        sprintf("Offer ends in {=countdown(%s.Date)}!", $feed_name),
      finalUrls  => ['http://www.example.com']
  });

  # We add the same ad to both ad groups. When they serve, they will show
  # different values, since they match different feed items.
  my @operations = ();

  foreach my $ad_group_id (@{$ad_group_ids}) {
    push @operations,
      Google::Ads::AdWords::v201708::AdGroupAdOperation->new({
        operator => "ADD",
        operand  => Google::Ads::AdWords::v201708::AdGroupAd->new({
            adGroupId => $ad_group_id,
            ad        => $text_ad
          })});
  }

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

  foreach my $ad_group_ad (@{$result->get_value()}) {
    printf "Created an ad with ID %d, type '%s', and status '%s'.\n",
      $ad_group_ad->get_ad()->get_id(), $ad_group_ad->get_ad()->get_Ad__Type(),
      $ad_group_ad->get_status();
  }
}

# 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_ad_customizers($client, $ad_group_ids, $feed_name);

Add an ad group bid modifier

#!/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 multiple keywords to an ad group. To get ad groups run
# basic_operations/get_ad_groups.pl.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::AdGroupBidModifierOperation;
use Google::Ads::AdWords::v201708::AdGroupBidModifier;
use Google::Ads::AdWords::v201708::Platform;

use Cwd qw(abs_path);

use constant BID_MODIFIER => 1.5;

# Replace with valid values of your account.
my $ad_group_id = "INSERT_AD_GROUP_ID_HERE";

# Example main subroutine.
sub add_ad_group_bid_modifier {
  my $client      = shift;
  my $ad_group_id = shift;

  # Create mobile platform. The ID can be found in the documentation.
  # https://developers.google.com/adwords/api/docs/appendix/platforms
  my $mobile = Google::Ads::AdWords::v201708::Platform->new({id => 30001});

  # Create the bid modifier.
  my $modifier = Google::Ads::AdWords::v201708::AdGroupBidModifier->new({
      adGroupId   => $ad_group_id,
      criterion   => $mobile,
      bidModifier => BID_MODIFIER
  });

  # Create ADD operation.
  my $operation =
    Google::Ads::AdWords::v201708::AdGroupBidModifierOperation->new({
      operator => "ADD",
      operand  => $modifier
    });

  # Update campaign criteria.
  my $result =
    $client->AdGroupBidModifierService()->mutate({operations => [$operation]});

  # Display campaign criteria.
  if ($result->get_value()) {
    foreach my $modifier (@{$result->get_value()}) {
      printf "Ad Group ID '%s', criterion ID '%s', " .
        "and type '%s' was modified with bid %.2f.\n",
        $modifier->get_adGroupId(),
        $modifier->get_criterion()->get_id(),
        $modifier->get_criterion()->get_type(),
        $modifier->get_bidModifier();
    }
  } else {
    print "No ad group bid modifier was added.\n";
  }

  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_ad_group_bid_modifier($client, $ad_group_id);

Add a click-to-download ad

#!/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 code example adds a click to download ad to a given ad group.
# To get ad groups, run basic_operations/get_ad_groups.pl.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::Common::MediaUtils;
use Google::Ads::AdWords::v201708::AdGroupAd;
use Google::Ads::AdWords::v201708::AdGroupAdOperation;
use Google::Ads::AdWords::v201708::Image;
use Google::Ads::AdWords::v201708::TemplateAd;
use Google::Ads::AdWords::v201708::TemplateElementField;
use Google::Ads::Common::MediaUtils;

use Cwd qw(abs_path);

# Replace with valid values of your account.
my $ad_group_id = "INSERT_AD_GROUP_ID_HERE";

# Example main subroutine.
sub add_click_to_download_ad {
  my $client      = shift;
  my $ad_group_id = shift;

  my @operations = ();

  # Create the template ad.
  my $click_to_download_ad = Google::Ads::AdWords::v201708::TemplateAd->new({
    name       => "Ad for demo game",
    templateId => 353,
    finalUrls =>
      ["http://play.google.com/store/apps/details?id=com.example.demogame"],
    displayUrl => "play.google.com"
  });

  # Create the template elements for the ad. You can refer to
  # https://developers.google.com/adwords/api/docs/appendix/templateads
  # for the list of avaliable template fields.
  my $headline = Google::Ads::AdWords::v201708::TemplateElementField->new({
    name      => "headline",
    fieldText => "Enjoy your drive in Mars",
    type      => "TEXT"
  });

  my $description1 = Google::Ads::AdWords::v201708::TemplateElementField->new({
    name      => "description1",
    fieldText => "Realistic physics simulation",
    type      => "TEXT"
  });

  my $description2 = Google::Ads::AdWords::v201708::TemplateElementField->new({
    name      => "description2",
    fieldText => "Race against players online",
    type      => "TEXT"
  });

  my $appId = Google::Ads::AdWords::v201708::TemplateElementField->new({
    name      => "appId",
    fieldText => "com.example.demogame",
    type      => "TEXT"
  });

  my $appStore = Google::Ads::AdWords::v201708::TemplateElementField->new({
    name      => "appStore",
    fieldText => "2",
    type      => "ENUM"
  });

  # Optionally specify a landscape image. The image needs to be in a BASE64
  # encoded form. Here we download a demo image and encode it for this ad.
  my $image_data = Google::Ads::Common::MediaUtils::get_base64_data_from_url(
    "http://goo.gl/9JmyKk");
  my $image = Google::Ads::AdWords::v201708::Image->new({
    data => $image_data,
    type => "IMAGE"
  });
  my $landscapeImage = Google::Ads::AdWords::v201708::TemplateElementField->new(
    {
      name       => "landscapeImage",
      fieldMedia => $image,
      type       => "IMAGE"
    });

  my $adData = Google::Ads::AdWords::v201708::TemplateElement->new({
      uniqueName => "adData",
      fields     => [
        $headline, $description1, $description2,
        $appId,    $appStore,     $landscapeImage
      ]});

  $click_to_download_ad->set_templateElements([$adData]);

  # Create the AdGroupAd.
  my $click_to_download_ad_group_ad =
    Google::Ads::AdWords::v201708::AdGroupAd->new({
      adGroupId => $ad_group_id,
      ad        => $click_to_download_ad,
      # Additional properties (non-required).
      status => "PAUSED"
    });
  my $text_ad_group_ad_operation =
    Google::Ads::AdWords::v201708::AdGroupAdOperation->new({
      operator => "ADD",
      operand  => $click_to_download_ad_group_ad
    });

  push @operations, $text_ad_group_ad_operation;

  # Add text ads.
  my $result =
    $client->AdGroupAdService()->mutate({operations => \@operations});

  # Display results.
  if ($result->get_value()) {
    foreach my $ad_group_ad (@{$result->get_value()}) {
      printf "New click-to-download ad with id \"%d\" and display url " .
        "\"%s\" was added.\n",
        $ad_group_ad->get_ad()->get_id(),
        $ad_group_ad->get_ad()->get_displayUrl();
    }
  } else {
    print "No click-to-download ads were added.\n";
  }

  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_click_to_download_ad($client, $ad_group_id);

Add a page feed specifying URLs for a DSA 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 code example adds a page feed to specify precisely which URLs to use
# with your Dynamic Search Ads campaign. To create a Dynamic Search Ads
# campaign, run add_dynamic_search_ads_campaign.pl. To get campaigns, run
# get_campaigns.pl.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::Utilities::PageProcessor;
use Google::Ads::AdWords::v201708::AdGroupCriterionOperation;
use Google::Ads::AdWords::v201708::AttributeFieldMapping;
use Google::Ads::AdWords::v201708::BiddableAdGroupCriterion;
use Google::Ads::AdWords::v201708::Campaign;
use Google::Ads::AdWords::v201708::CampaignFeed;
use Google::Ads::AdWords::v201708::CampaignFeedOperation;
use Google::Ads::AdWords::v201708::CampaignOperation;
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 Google::Ads::AdWords::v201708::PageFeed;
use Google::Ads::AdWords::v201708::Paging;
use Google::Ads::AdWords::v201708::Predicate;
use Google::Ads::AdWords::v201708::Selector;
use Google::Ads::AdWords::v201708::Webpage;
use Google::Ads::AdWords::v201708::WebpageCondition;
use Google::Ads::AdWords::v201708::WebpageParameter;

use Cwd qw(abs_path);
use Data::Uniqid qw(uniqid);
use constant PAGE_SIZE => 500;
# The criterion type to be used for DSA page feeds. DSA page feeds use the
# criterionType field instead of the placeholderType field unlike most other
# feed types.
use constant DSA_PAGE_FEED_CRITERION_TYPE => 61;
# ID that corresponds to the page URLs.
use constant DSA_PAGE_URLS_FIELD_ID => 1;
# ID that corresponds to the labels.
use constant DSA_LABEL_FIELD_ID => 2;

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

# Example main subroutine.
sub add_dynamic_page_feed {
  my ($client, $campaign_id, $ad_group_id) = @_;
  my $dsa_page_url_label = "discounts";

  # Get the page feed details. This code example creates a new feed, but you can
  # fetch and re-use an existing feed.
  my $feed_details = _create_feed($client);
  _create_feed_mapping($client, $feed_details);
  _create_feed_items($client, $feed_details, $dsa_page_url_label);

  # Associate the page feed with the campaign.
  _update_campaign_dsa_setting($client, $campaign_id, $feed_details);

  # Optional: Target web pages matching the feed's label in the ad group.
  _add_dsa_targeting($client, $ad_group_id, $dsa_page_url_label);

  printf("Dynamic page feed setup is complete for campaign ID %s.\n",
    $campaign_id);

  return 1;
}

sub _create_feed {
  my ($client) = @_;

  #  Create attributes.
  my $url_attribute = Google::Ads::AdWords::v201708::FeedAttribute->new({
    type => "URL_LIST",
    name => "Page URL"
  });

  my $label_attribute = Google::Ads::AdWords::v201708::FeedAttribute->new({
    type => "STRING_LIST",
    name => "Label"
  });

  # Create the feed.
  my $dsa_page_feed = Google::Ads::AdWords::v201708::Feed->new({
    name       => sprintf("DSA Feed #%s", uniqid()),
    attributes => [$url_attribute,        $label_attribute],
    origin     => "USER"
  });

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

  # Add the feed.
  my $feed_result =
    $client->FeedService()->mutate({operations => [$operation]});
  my $new_feed = $feed_result->get_value(0);

  my $feed_details = {
    "feedId"           => $new_feed->get_id(),
    "urlAttributeId"   => $new_feed->get_attributes()->[0]->get_id(),
    "labelAttributeId" => $new_feed->get_attributes()->[1]->get_id()};

  printf(
    "Feed with name '%s' and ID %d with urlAttributeId %d " .
      " and labelAttributeId %d was created.\n",
    $new_feed->get_name(),             $feed_details->{"feedId"},
    $feed_details->{"urlAttributeId"}, $feed_details->{"labelAttributeId"});

  return $feed_details;
}

# Creates the feed mapping for the DSA page feeds.
sub _create_feed_mapping {
  my ($client, $feed_details) = @_;

  # Map the FeedAttributeIds to the fieldId constants.
  my $url_field_mapping =
    Google::Ads::AdWords::v201708::AttributeFieldMapping->new({
      feedAttributeId => $feed_details->{"urlAttributeId"},
      fieldId         => DSA_PAGE_URLS_FIELD_ID
    });

  my $label_field_mapping =
    Google::Ads::AdWords::v201708::AttributeFieldMapping->new({
      feedAttributeId => $feed_details->{"labelAttributeId"},
      fieldId         => DSA_LABEL_FIELD_ID
    });

  # Create the FeedMapping and operation.
  my $feed_mapping = Google::Ads::AdWords::v201708::FeedMapping->new({
      criterionType          => DSA_PAGE_FEED_CRITERION_TYPE,
      feedId                 => $feed_details->{"feedId"},
      attributeFieldMappings => [$url_field_mapping, $label_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]});
  my $new_feed_mapping = $result->get_value()->[0];
  printf "Feed mapping with ID %d and criterionType %d was saved for " .
    "feed with ID %d.\n", $new_feed_mapping->get_feedMappingId(),
    $new_feed_mapping->get_criterionType(),
    $new_feed_mapping->get_feedId();
}

sub _create_feed_items {
  my ($client, $feed_details, $label_name) = @_;

  # Create operations to add FeedItems.
  my @operations = ();
  push @operations,
    _create_dsa_url_add_operation($feed_details,
    "http://www.example.com/discounts/rental-cars", $label_name);
  push @operations,
    _create_dsa_url_add_operation($feed_details,
    "http://www.example.com/discounts/hotel-deals", $label_name);
  push @operations,
    _create_dsa_url_add_operation($feed_details,
    "http://www.example.com/discounts/flight-deals", $label_name);

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

  foreach my $feed_item (@{$result->get_value()}) {
    printf "Feed item with feed item ID %d was added.\n",
      $feed_item->get_feedItemId();
  }
}

# Creates a {@link FeedItemOperation} to add the DSA URL.
sub _create_dsa_url_add_operation {
  my ($feed_details, $url, $label_name) = @_;

  # Create the FeedItemAttributeValues for the URL and label.
  my $url_attribute_value =
    Google::Ads::AdWords::v201708::FeedItemAttributeValue->new({
      feedAttributeId => $feed_details->{"urlAttributeId"},
      # Optional: Add the {feeditem} valuetrack parameter to track which page
      # feed items lead to each click.
      stringValues => sprintf("%s?id={feeditem}", $url)});

  my $label_attribute_value =
    Google::Ads::AdWords::v201708::FeedItemAttributeValue->new({
      feedAttributeId => $feed_details->{"labelAttributeId"},
      stringValues    => $label_name
    });

  # Create the feed item and operation.
  my $feed_item = Google::Ads::AdWords::v201708::FeedItem->new({
      feedId          => $feed_details->{"feedId"},
      attributeValues => [$url_attribute_value, $label_attribute_value]});

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

  return $operation;
}

# Update the campaign DSA setting to add DSA pagefeeds.
sub _update_campaign_dsa_setting {
  my ($client, $campaign_id, $feed_details) = @_;

  my $paging = Google::Ads::AdWords::v201708::Paging->new({
    startIndex    => 0,
    numberResults => PAGE_SIZE
  });
  my $selector = Google::Ads::AdWords::v201708::Selector->new({
      fields     => ["Id", "Settings"],
      predicates => [
        Google::Ads::AdWords::v201708::Predicate->new({
            field    => "CampaignId",
            operator => "EQUALS",
            values   => [$campaign_id]})
      ],
      paging => $paging
    });

  my $dsa_setting = undef;
  Google::Ads::AdWords::Utilities::PageProcessor->new({
      client   => $client,
      service  => $client->CampaignService(),
      selector => $selector
    }
    )->process_entries(
    sub {
      my ($campaign) = @_;
      if ($campaign->get_settings()) {
        foreach my $setting (@{$campaign->get_settings()}) {
          if (
            $setting->isa(
              "Google::Ads::AdWords::v201708::DynamicSearchAdsSetting"))
          {
            $dsa_setting = $setting;
            last;
          }
        }
      }
    });

  if (!$dsa_setting) {
    die sprintf("Campaign with ID %s is not a DSA campaign.", $campaign_id);
  }

  # Use a page feed to specify precisely which URLs to use with your
  # Dynamic Search Ads.
  my $page_feed = Google::Ads::AdWords::v201708::PageFeed->new({
      feedIds => [$feed_details->{"feedId"}]});
  $dsa_setting->set_pageFeed($page_feed);

  # Optional: Specify whether only the supplied URLs should be used with your
  # Dynamic Search Ads.
  $dsa_setting->set_useSuppliedUrlsOnly(1);

  my $updated_campaign = Google::Ads::AdWords::v201708::Campaign->new({
      id       => $campaign_id,
      settings => [$dsa_setting]});

  my $operation = Google::Ads::AdWords::v201708::CampaignOperation->new({
    operand  => $updated_campaign,
    operator => "SET"
  });

  $client->CampaignService()->mutate({operations => [$operation]});
  printf(
    "DSA page feed for campaign ID %d was updated with feed ID %d.\n",
    $updated_campaign->get_id(),
    $feed_details->{"feedId"});
}

# Sets custom targeting for the page feed URLs based on a list of labels.
sub _add_dsa_targeting {
  my ($client, $ad_group_id, $dsa_page_url_label) = @_;

  # Create a webpage criterion.
  # Add a condition for label=specified_label_name.
  my $condition = Google::Ads::AdWords::v201708::WebpageCondition->new({
    operand  => "CUSTOM_LABEL",
    argument => $dsa_page_url_label
  });

  # Create a webpage criterion for special offers.
  my $parameter = Google::Ads::AdWords::v201708::WebpageParameter->new({
      criterionName => "Test criterion",
      conditions    => [$condition]});

  my $webpage = Google::Ads::AdWords::v201708::Webpage->new({
    parameter => $parameter
  });

  # Create biddable ad group criterion.
  my $biddable_ad_group_criterion =
    Google::Ads::AdWords::v201708::BiddableAdGroupCriterion->new({
      adGroupId => $ad_group_id,
      criterion => $webpage,
      # Set a custom bid for this criterion.
      biddingStrategyConfiguration =>
        Google::Ads::AdWords::v201708::BiddingStrategyConfiguration->new({
          bids => [
            Google::Ads::AdWords::v201708::CpcBid->new({
                bid => Google::Ads::AdWords::v201708::Money->new(
                  {microAmount => 1500000}
                ),
              }
            ),
          ]})});

  # Create operation.
  my $operation =
    Google::Ads::AdWords::v201708::AdGroupCriterionOperation->new({
      operator => "ADD",
      operand  => $biddable_ad_group_criterion
    });

  # Create the criterion.
  my $result =
    $client->AdGroupCriterionService()->mutate({operations => [$operation]});
  my $new_ad_group_criterion = $result->get_value()->[0];
  printf "Web page criterion with ID %d and status '%s' was created.\n",
    $new_ad_group_criterion->get_criterion()->get_id(),
    $new_ad_group_criterion->get_userStatus();
}

# 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_dynamic_page_feed($client, $campaign_id, $ad_group_id);

Add a DSA 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 code example adds a Dynamic Search Ads campaign. To get campaigns, run
# get_campaigns.pl.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::AdGroup;
use Google::Ads::AdWords::v201708::AdGroupOperation;
use Google::Ads::AdWords::v201708::AdGroupAd;
use Google::Ads::AdWords::v201708::AdGroupAdOperation;
use Google::Ads::AdWords::v201708::AdGroupCriterionOperation;
use Google::Ads::AdWords::v201708::BiddableAdGroupCriterion;
use Google::Ads::AdWords::v201708::BiddingStrategyConfiguration;
use Google::Ads::AdWords::v201708::Budget;
use Google::Ads::AdWords::v201708::BudgetOperation;
use Google::Ads::AdWords::v201708::Campaign;
use Google::Ads::AdWords::v201708::CampaignCriterion;
use Google::Ads::AdWords::v201708::CampaignCriterionOperation;
use Google::Ads::AdWords::v201708::CampaignOperation;
use Google::Ads::AdWords::v201708::CpcBid;
use Google::Ads::AdWords::v201708::DynamicSearchAdsSetting;
use Google::Ads::AdWords::v201708::ExpandedDynamicSearchAd;
use Google::Ads::AdWords::v201708::Money;
use Google::Ads::AdWords::v201708::Webpage;
use Google::Ads::AdWords::v201708::WebpageCondition;
use Google::Ads::AdWords::v201708::WebpageParameter;

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

# Example main subroutine.
sub add_dynamic_search_ads_campaign {
  my $client = shift;

  my $budget   = _create_budget($client);
  my $campaign = _create_campaign($client, $budget);
  my $ad_group = _create_ad_group($client, $campaign);
  _create_expanded_DSA($client, $ad_group);
  _add_web_page_criteria($client, $ad_group);

  return 1;
}

# Create the budget.
sub _create_budget() {
  my ($client) = @_;

  # Create a budget, which can be shared by multiple campaigns.
  my $shared_budget = Google::Ads::AdWords::v201708::Budget->new({
    name => sprintf("Interplanetary Cruise #%s", uniqid()),
    amount =>
      Google::Ads::AdWords::v201708::Money->new({microAmount => 5000000}),
    deliveryMethod => "STANDARD"
  });

  my $budget_operation = Google::Ads::AdWords::v201708::BudgetOperation->new({
    operator => "ADD",
    operand  => $shared_budget
  });

  # Add budget.
  my $budget =
    $client->BudgetService()->mutate({operations => ($budget_operation)})
    ->get_value()->[0];
  return $budget;
}

# Creates the campaign.
sub _create_campaign {
  my ($client, $budget) = @_;

  # Required: Set the campaign's Dynamic Search Ads settings.
  my $dynamic_search_ads_setting =
    Google::Ads::AdWords::v201708::DynamicSearchAdsSetting->new({
      # Required: Set the domain name and language.
      domainName   => "example.com",
      languageCode => "en"
    });

  # Calculating a start date of today and an end date 1 year from now.
  my (undef, undef, undef, $mday, $mon, $year) = localtime(time + 60 * 60 * 24);
  my $start_date = sprintf("%d%02d%02d", ($year + 1900), ($mon + 1), $mday);
  (undef, undef, undef, $mday, $mon, $year) =
    localtime(time + 60 * 60 * 24 * 365);
  my $end_date = sprintf("%d%02d%02d", ($year + 1900), ($mon + 1), $mday);

  my $campaign = Google::Ads::AdWords::v201708::Campaign->new({
      name => sprintf("Interplanetary Cruise #%s", uniqid()),
      biddingStrategyConfiguration =>
        Google::Ads::AdWords::v201708::BiddingStrategyConfiguration->new({
          biddingStrategyType => "MANUAL_CPC"
        }
        ),
      # Only the budgetId should be sent, all other fields will be ignored by
      # CampaignService.
      budget => Google::Ads::AdWords::v201708::Budget->new(
        {budgetId => $budget->get_budgetId()}
      ),
      advertisingChannelType => "SEARCH",
      settings               => [$dynamic_search_ads_setting],
      # Additional properties (non-required).
      startDate => $start_date,
      endDate   => $end_date,
      # Recommendation: Set the campaign to PAUSED when creating it to stop
      # the ads from immediately serving. Set to ENABLED once you've added
      # targeting and the ads are ready to serve.
      status => "PAUSED"
    });

  # Create operation.
  my $campaign_operation =
    Google::Ads::AdWords::v201708::CampaignOperation->new({
      operator => "ADD",
      operand  => $campaign
    });

  # Add campaigns.
  my $result =
    $client->CampaignService()->mutate({operations => [$campaign_operation]});

  # Display campaigns.
  my $new_campaign = $result->get_value()->[0];
  printf "Campaign with name '%s' and ID %d was added.\n",
    $new_campaign->get_name(),
    $new_campaign->get_id();
  return $new_campaign;
}

# Creates the ad group.
sub _create_ad_group {
  my ($client, $campaign) = @_;

  my $ad_group = Google::Ads::AdWords::v201708::AdGroup->new({
      name       => sprintf("Earth to Mars Cruises #%s", uniqid()),
      campaignId => $campaign->get_id(),
      # Required: Set the ad group's type to Dynamic Search Ads.
      adGroupType => "SEARCH_DYNAMIC_ADS",
      status      => "PAUSED",
      # Recommended: Set a tracking URL template for your ad group if you want
      # to use URL tracking software.
      trackingUrlTemplate =>
        "http://tracker.example.com/traveltracker/{escapedlpurl}",
      biddingStrategyConfiguration =>
        Google::Ads::AdWords::v201708::BiddingStrategyConfiguration->new({
          bids => [
            Google::Ads::AdWords::v201708::CpcBid->new({
                bid => Google::Ads::AdWords::v201708::Money->new(
                  {microAmount => 3000000}
                ),
              }
            ),
          ]})});

  # Create operation.
  my $ad_group_operation =
    Google::Ads::AdWords::v201708::AdGroupOperation->new({
      operator => "ADD",
      operand  => $ad_group
    });

  my $result =
    $client->AdGroupService()->mutate({operations => [$ad_group_operation]});
  my $new_ad_group = $result->get_value()->[0];
  printf "Ad group with name '%s' and ID %d was added.\n",
    $new_ad_group->get_name(), $new_ad_group->get_id();
  return $new_ad_group;
}

# Creates the expanded Dynamic Search Ad.
sub _create_expanded_DSA {
  my ($client, $ad_group) = @_;
  # Create the expanded Dynamic Search Ad. This ad will have its headline and
  # final URL auto-generated at serving time according to domain name specific
  # information provided by DynamicSearchAdsSetting at the campaign level.
  my $expanded_DSA =
    Google::Ads::AdWords::v201708::ExpandedDynamicSearchAd->new({
      # Set the ad description.
      description => "Buy your tickets now!",
    });

  # Create the ad group ad.
  my $ad_group_ad = Google::Ads::AdWords::v201708::AdGroupAd->new({
    adGroupId => $ad_group->get_id(),
    ad        => $expanded_DSA,
    # Optional: Set the status.
    status => "PAUSED"
  });

  # Create operation.
  my $operation = Google::Ads::AdWords::v201708::AdGroupAdOperation->new({
    operator => "ADD",
    operand  => $ad_group_ad
  });

  my $result =
    $client->AdGroupAdService()->mutate({operations => [$operation]});
  my $new_ad_group_ad = $result->get_value()->[0];
  my $new_expanded_dsa = $new_ad_group_ad->get_ad();
  printf
    "Expanded Dynamic Search Ad with ID %d and description '%s' was added.\n",
    $new_expanded_dsa->get_id(), $new_expanded_dsa->get_description();
}

# Adds a web page criteria to target Dynamic Search Ads.
sub _add_web_page_criteria {
  my ($client, $ad_group) = @_;

  my $url_condition = Google::Ads::AdWords::v201708::WebpageCondition->new({
    operand  => "URL",
    argument => "/specialoffers"
  });

  my $title_condition = Google::Ads::AdWords::v201708::WebpageCondition->new({
    operand  => "PAGE_TITLE",
    argument => "Special Offer"
  });

  # Create a webpage criterion for special offers.
  my $param = Google::Ads::AdWords::v201708::WebpageParameter->new({
      criterionName => "Special offers",
      conditions    => [$url_condition, $title_condition]});

  my $webpage = Google::Ads::AdWords::v201708::Webpage->new({
    parameter => $param
  });

  # Create biddable ad group criterion.
  my $biddable_ad_group_criterion =
    Google::Ads::AdWords::v201708::BiddableAdGroupCriterion->new({
      adGroupId  => $ad_group->get_id(),
      criterion  => $webpage,
      userStatus => "PAUSED",
      # Optional: set a custom bid.
      biddingStrategyConfiguration =>
        Google::Ads::AdWords::v201708::BiddingStrategyConfiguration->new({
          bids => [
            Google::Ads::AdWords::v201708::CpcBid->new({
                bid => Google::Ads::AdWords::v201708::Money->new(
                  {microAmount => 1000000}
                ),
              }
            ),
          ]})});

  # Create operation.
  my $operation =
    Google::Ads::AdWords::v201708::AdGroupCriterionOperation->new({
      operator => "ADD",
      operand  => $biddable_ad_group_criterion
    });

  # Create the criterion.
  my $result =
    $client->AdGroupCriterionService()->mutate({operations => [$operation]});
  my $new_ad_group_criterion = $result->get_value()->[0];
  printf "Webpage criterion with ID %d was added to ad group ID %d.\n",
    $new_ad_group_criterion->get_criterion()->get_id(),
    $new_ad_group_criterion->get_adGroupId();
}

# 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_dynamic_search_ads_campaign($client);

Add an expanded text ad with Upgraded URLs

#!/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 text ad that uses advanced features of upgraded URLs.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::AdGroupAd;
use Google::Ads::AdWords::v201708::AdGroupAdOperation;
use Google::Ads::AdWords::v201708::CustomParameter;
use Google::Ads::AdWords::v201708::CustomParameters;
use Google::Ads::AdWords::v201708::ExpandedTextAd;
use Google::Ads::AdWords::v201708::Image;
use Google::Ads::AdWords::v201708::ImageAd;
use Google::Ads::AdWords::v201708::TemplateAd;
use Google::Ads::AdWords::v201708::Video;
use Google::Ads::Common::MediaUtils;

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

# Replace with valid values of your account.
my $ad_group_id = "INSERT_AD_GROUP_ID_HERE";

# Example main subroutine.
sub add_text_ad_with_upgraded_urls {
  my $client      = shift;
  my $ad_group_id = shift;

  # Create text ad.
  my $text_ad = Google::Ads::AdWords::v201708::ExpandedTextAd->new({
      headlinePart1 => "Cruise to Mars #" . substr(uniqid(), 0, 8),
      headlinePart2 => "Visit the Red Planet in style.",
      description   => "Buy your tickets now!"
  });

  # Specify a tracking url for 3rd party tracking provider. You may
  # specify one at customer, campaign, ad group, ad, criterion or
  # feed item levels.
  $text_ad->set_trackingUrlTemplate(
    "http://tracker.example.com/?season={_season}&promocode={_promocode}&" .
      "u={lpurl}");

  # Since your tracking url has two custom parameters, provide their
  # values too. This can be provided at campaign, ad group, ad, criterion
  # or feed item levels.
  my $season_parameter = Google::Ads::AdWords::v201708::CustomParameter->new({
      key   => "season",
      value => "christmas"
  });
  my $promo_code_parameter =
    Google::Ads::AdWords::v201708::CustomParameter->new({
      key   => "promocode",
      value => "NYC123"
    });
  my $tracking_url_parameters =
    Google::Ads::AdWords::v201708::CustomParameters->new(
    {parameters => [$season_parameter, $promo_code_parameter]});

  $text_ad->set_urlCustomParameters($tracking_url_parameters);

  # Specify a list of final urls. This field cannot be set if url field is
  # set. This may be specified at ad, criterion, and feed item levels.
  $text_ad->set_finalUrls([
      "http://www.example.com/cruise/space/",
      "http://www.example.com/locations/mars/"
  ]);
  # Specify a list of final mobile urls. This field cannot be set if url field
  # is set or finalUrls is not set. This may be specified at ad, criterion, and
  # feed item levels.
  $text_ad->set_finalMobileUrls([
      "http://mobile.example.com/cruise/space/",
      "http://mobile.example.com/locations/mars/"
  ]);

  # Create ad group ad for the expanded text ad.
  my $text_ad_group_ad = Google::Ads::AdWords::v201708::AdGroupAd->new({
      adGroupId => $ad_group_id,
      ad        => $text_ad,
      # Additional properties (non-required).
      status => "PAUSED"
  });

  # Create operation.
  my $text_ad_group_ad_operation =
    Google::Ads::AdWords::v201708::AdGroupAdOperation->new({
      operator => "ADD",
      operand  => $text_ad_group_ad
    });

  # Add expanded text ads.
  my $result =
    $client->AdGroupAdService()
    ->mutate({operations => [$text_ad_group_ad_operation]});

  # Display results.
  if ($result->get_value()) {
    foreach my $ad_group_ad (@{$result->get_value()}) {
      printf "New expanded text ad with id \"%d\" was added.\n",
        $ad_group_ad->get_ad()->get_id();
    }
  } else {
    print "No expanded text ads were added.\n";
  }

  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_text_ad_with_upgraded_urls($client, $ad_group_id);


Add an HTML 5 ad to an ad group

#!/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 code example adds an HTML5 ad to a given ad group.
# To get ad groups, run basic_operations/get_ad_groups.pl.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::AdGroupAd;
use Google::Ads::AdWords::v201708::AdGroupAdOperation;
use Google::Ads::AdWords::v201708::Dimensions;
use Google::Ads::AdWords::v201708::MediaBundle;
use Google::Ads::AdWords::v201708::TemplateAd;
use Google::Ads::AdWords::v201708::TemplateElementField;
use Google::Ads::Common::MediaUtils;

use Cwd qw(abs_path);

# Replace with valid values of your account.
my $ad_group_id = "INSERT_ADGROUP_ID_HERE";

# Example main subroutine.
sub add_html5_ad {
  my $client      = shift;
  my $ad_group_id = shift;

  my @operations = ();

  # Create the template ad.
  my $html5_ad = Google::Ads::AdWords::v201708::TemplateAd->new({
      name       => "Ad for HTML5",
      templateId => 419,
      finalUrls  => ["http://example.com/html5"],
      displayUrl => "www.example.com/html5",
      dimensions => Google::Ads::AdWords::v201708::Dimensions->new({
          width  => 300,
          height => 250
        })});

  # The HTML5 zip file contains all the HTML, CSS, and images needed for the
  # HTML5 ad. For help on creating an HTML5 zip file, check out Google Web
  # Designer (https://www.google.com/webdesigner/).
  my $html5_zip = Google::Ads::Common::MediaUtils::get_base64_data_from_url(
    "https://goo.gl/9Y7qI2");

  # Create a media bundle containing the zip file with all the HTML5 components.
  # NOTE: You may also upload an HTML5 zip using MediaService.upload()
  # and simply set the mediaId field below. See upload_media_bundle.pl
  # for an example.
  my $media_bundle = Google::Ads::AdWords::v201708::MediaBundle->new({
      data       => $html5_zip,
      entryPoint => "carousel/index.html",
      type       => "MEDIA_BUNDLE"
  });

  # Create the template elements for the ad. You can refer to
  # https://developers.google.com/adwords/api/docs/appendix/templateads
  # for the list of available template fields.
  my $media = Google::Ads::AdWords::v201708::TemplateElementField->new({
      name       => "Custom_layout",
      fieldMedia => $media_bundle,
      type       => "MEDIA_BUNDLE"
  });
  my $layout = Google::Ads::AdWords::v201708::TemplateElementField->new({
      name      => "layout",
      fieldText => "Custom",
      type      => "ENUM"
  });

  my $adData = Google::Ads::AdWords::v201708::TemplateElement->new({
      uniqueName => "adData",
      fields     => [$media, $layout]});

  $html5_ad->set_templateElements([$adData]);

  # Create the AdGroupAd.
  my $html5_ad_group_ad = Google::Ads::AdWords::v201708::AdGroupAd->new({
      adGroupId => $ad_group_id,
      ad        => $html5_ad,
      # Additional properties (non-required).
      status => "PAUSED"
  });
  my $ad_group_ad_operation =
    Google::Ads::AdWords::v201708::AdGroupAdOperation->new({
      operator => "ADD",
      operand  => $html5_ad_group_ad
    });

  push @operations, $ad_group_ad_operation;

  # Add HTML5 ad.
  my $result =
    $client->AdGroupAdService()->mutate({operations => \@operations});

  # Display results.
  if ($result->get_value()) {
    foreach my $ad_group_ad (@{$result->get_value()}) {
      printf "New HTML5 ad with id \"%d\" and display url " .
        "\"%s\" was added.\n",
        $ad_group_ad->get_ad()->get_id(),
        $ad_group_ad->get_ad()->get_displayUrl();
    }
  } else {
    print "No HTML5 ads were added.\n";
  }

  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_html5_ad($client, $ad_group_id);

Add responsive ads

#!/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 code example adds an image representing the ad using the MediaService and
# then adds a responsive display ad to a given ad group.
# To get ad groups, run basic_operations/get_ad_groups.pl.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::Common::MediaUtils;
use Google::Ads::AdWords::v201708::AdGroupAd;
use Google::Ads::AdWords::v201708::AdGroupAdOperation;
use Google::Ads::AdWords::v201708::DisplayAdFormatSetting;
use Google::Ads::AdWords::v201708::DynamicSettings;
use Google::Ads::AdWords::v201708::ResponsiveDisplayAd;

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

# Replace with valid values of your account.
my $ad_group_id = "INSERT_AD_GROUP_ID_HERE";

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

  # This ad format does not allow the creation of an image using the
  # Image.data field. An image must first be created using the MediaService,
  # and Image.mediaId must be populated when creating the ad.
  my $ad_image = _upload_image($client, "http://goo.gl/3b9Wfh");
  my $marketing_image = Google::Ads::AdWords::v201708::Image->new(
    {mediaId => $ad_image->get_mediaId()});

  # Create the responsive display ad.
  my $responsive_display_ad =
    Google::Ads::AdWords::v201708::ResponsiveDisplayAd->new({
      marketingImage => $marketing_image,
      shortHeadline  => "Travel",
      longHeadline   => "Travel the World",
      description    => "Take to the air!",
      businessName   => "Interplanetary Cruises",
      finalUrls      => ["http://www.example.com/"],
    });

  # Optional: Create a square marketing image using MediaService, and set it
  # to the ad.
  my $square_image = _upload_image($client, "https://goo.gl/mtt54n");
  my $square_marketing_image = Google::Ads::AdWords::v201708::Image->new(
    {mediaId => $square_image->get_mediaId()});
  $responsive_display_ad->set_squareMarketingImage($square_marketing_image);

  # Optional: Set call to action text.
  $responsive_display_ad->set_callToActionText("Shop Now");

  # Optional: Set dynamic display ad settings, composed of landscape logo
  # image, promotion text, and price prefix.
  my $dynamic_settings = _create_dynamic_display_ad_settings($client);
  $responsive_display_ad->set_dynamicDisplayAdSettings($dynamic_settings);

  # Whitelisted accounts only: Set color settings using hexadecimal values.
  # Set allowFlexibleColor to false if you want your ads to render by always
  # using your colors strictly.
  # $responsiveDisplayAd->set_mainColor("#0000ff");
  # $responsiveDisplayAd->set_accentColor("#ffff00");
  # $responsiveDisplayAd->set_allowFlexibleColor(0);

  # Whitelisted accounts only: Set the format setting that the ad will be
  # served in.
  # $responsiveDisplayAd->set_formatSetting("NON_NATIVE");

  # Create ad group ad for the responsive display ad.
  my $responsive_display_ad_group_ad =
    Google::Ads::AdWords::v201708::AdGroupAd->new({
      adGroupId => $ad_group_id,
      ad        => $responsive_display_ad,
      # Additional properties (non-required).
      status => "PAUSED"
    });

  # Create operation.
  my $responsive_display_ad_group_ad_operation =
    Google::Ads::AdWords::v201708::AdGroupAdOperation->new({
      operator => "ADD",
      operand  => $responsive_display_ad_group_ad
    });

  # Add responsive display ad.
  my $result =
    $client->AdGroupAdService()
    ->mutate({operations => [$responsive_display_ad_group_ad_operation]});

  # Display results.
  if ($result->get_value()) {
    foreach my $ad_group_ad (@{$result->get_value()}) {
      printf "New responsive display ad with id \"%d\" and " .
        "short headline \"%s\" was added.\n",
        $ad_group_ad->get_ad()->get_id(),
        $ad_group_ad->get_ad()->get_shortHeadline();
    }
  } else {
    print "No responsive display ads were added.\n";
  }

  return 1;
}

sub _upload_image {
  my ($client, $url) = @_;

  # Creates an image and upload it to the server.
  my $image_data = Google::Ads::Common::MediaUtils::get_base64_data_from_url(
    $url);
  my $image = Google::Ads::AdWords::v201708::Image->new({
      data => $image_data,
      type => "IMAGE"
  });

  return $client->MediaService()->upload({media => [$image]});
}

sub _create_dynamic_display_ad_settings {
  my ($client) = @_;

  my $logo_image = _upload_image($client, 'https://goo.gl/dEvQeF');
  my $logo = Google::Ads::AdWords::v201708::Image->new({
      mediaId => $logo_image->get_mediaId(),
  });

  my $dynamic_settings = Google::Ads::AdWords::v201708::DynamicSettings->new({
    landscapeLogoImage => $logo,
    pricePrefix => "as low as",
    promoText => "Free shipping!"
  });

  return $dynamic_settings;
}

# 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_responsive_display_ad($client, $ad_group_id);


Add a universal app 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 universal app campaign. To get campaigns, run
# get_campaigns.pl. To upload image assets for this campaign, run
# upload_image.pl.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::BiddingStrategyConfiguration;
use Google::Ads::AdWords::v201708::Budget;
use Google::Ads::AdWords::v201708::BudgetOperation;
use Google::Ads::AdWords::v201708::Campaign;
use Google::Ads::AdWords::v201708::CampaignCriterion;
use Google::Ads::AdWords::v201708::CampaignCriterionOperation;
use Google::Ads::AdWords::v201708::CampaignOperation;
use Google::Ads::AdWords::v201708::GeoTargetTypeSetting;
use Google::Ads::AdWords::v201708::Language;
use Google::Ads::AdWords::v201708::Location;
use Google::Ads::AdWords::v201708::Money;
use Google::Ads::AdWords::v201708::NetworkSetting;
use Google::Ads::AdWords::v201708::TargetCpaBiddingScheme;
use Google::Ads::AdWords::v201708::UniversalAppCampaignSetting;

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

# Example main subroutine.
sub add_universal_app_campaign {
  my $client = shift;

  # Set the campaign's assets and ad text ideas. These values will be used to
  # generate ads.
  my $universalAppSetting =
    Google::Ads::AdWords::v201708::UniversalAppCampaignSetting->new({
      appId        => "com.labpixies.colordrips",
      description1 => "A cool puzzle game",
      description2 => "Remove connected blocks",
      description3 => "3 difficulty levels",
      description4 => "4 colorful fun skins"
    });

  # Optional: You can set up to 10 image assets for your campaign.
  # See upload_image.pl for an example on how to upload images.
  # universalAppSetting->set_imageMediaIds([INSERT_IMAGE_MEDIA_ID_HERE]);

  # Optimize this campaign for getting new users for your app.
  $universalAppSetting->set_universalAppBiddingStrategyGoalType(
    "OPTIMIZE_FOR_INSTALL_CONVERSION_VOLUME");

  # If you select the OPTIMIZE_FOR_IN_APP_CONVERSION_VOLUME goal type, then also
  # specify your in-app conversion types so AdWords can focus your campaign on
  # people who are most likely to complete the corresponding in-app actions.
  # Conversion type IDs can be retrieved using ConversionTrackerService.get.

  # my $selectiveOptimization =
  # Google::Ads::AdWords::v201708::SelectiveOptimization->new({
  #  conversionTypeIds =>
  #    [INSERT_CONVERSION_TYPE_ID_1_HERE, INSERT_CONVERSION_TYPE_ID_2_HERE]
  # });
  # $campaign->set_selectiveOptimization($selectiveOptimization);

  # Optional: Set the campaign settings for advanced location options.
  my $geoSetting = Google::Ads::AdWords::v201708::GeoTargetTypeSetting->new({
    positiveGeoTargetType => "LOCATION_OF_PRESENCE",
    negativeGeoTargetType => "DONT_CARE"
  });

  my (undef, undef, undef, $mday, $mon, $year) = localtime(time + 60 * 60 * 24);
  my $start_date = sprintf("%d%02d%02d", ($year + 1900), ($mon + 1), $mday);
  (undef, undef, undef, $mday, $mon, $year) =
    localtime(time + 60 * 60 * 24 * 365);
  my $end_date = sprintf("%d%02d%02d", ($year + 1900), ($mon + 1), $mday);

  my $budgetId = create_budget($client);

  my $campaign = Google::Ads::AdWords::v201708::Campaign->new({
      name => "Interplanetary Cruise App #" . uniqid(),
      # Bidding strategy (required).
      # Set the campaign's bidding strategy. Universal app campaigns
      # only support TARGET_CPA bidding strategy.
      biddingStrategyConfiguration =>
        Google::Ads::AdWords::v201708::BiddingStrategyConfiguration->new({
          biddingStrategyType => "TARGET_CPA",
          # Set the target CPA to $1 / app install.
          biddingScheme =>
            Google::Ads::AdWords::v201708::TargetCpaBiddingScheme->new({
              targetCpa => Google::Ads::AdWords::v201708::Money->new(
                {microAmount => 1000000})})}
        ),
      # Budget (required) - note only the budgetId is required.
      budget =>
        Google::Ads::AdWords::v201708::Budget->new({budgetId => $budgetId}),
      # Advertising channel type (required).
      # Set the advertising channel and subchannel types for universal
      # app campaigns.
      advertisingChannelType    => "MULTI_CHANNEL",
      advertisingChannelSubType => "UNIVERSAL_APP_CAMPAIGN",
      settings                  => [$universalAppSetting, $geoSetting],
      # Additional properties (non-required).
      startDate => $start_date,
      endDate   => $end_date,
      # Recommendation: Set the campaign to PAUSED when creating it to stop
      # the ads from immediately serving. Set to ENABLED once you've added
      # targeting and the ads are ready to serve.
      status    => "PAUSED"
    });

  # Create operation.
  my $campaign_operation =
    Google::Ads::AdWords::v201708::CampaignOperation->new({
      operator => "ADD",
      operand  => $campaign
    });

  # Add campaigns.
  my $result =
    $client->CampaignService()->mutate({operations => [$campaign_operation]});

  # Display campaigns.
  foreach my $new_campaign (@{$result->get_value()}) {
    printf "Universal app campaign with name \"%s\" and ID %s was added.\n",
      $new_campaign->get_name(), $new_campaign->get_id();
    # Optional: Set the campaign's location and language targeting. No other
    # targeting criteria can be used for universal app campaigns.
    set_campaign_targeting_criteria($client, $new_campaign->get_id());
  }

  return 1;
}

# Create the budget.
sub create_budget() {
  my ($client) = @_;

  # Create the campaign budget.
  my $budget = Google::Ads::AdWords::v201708::Budget->new({
    # Required attributes.
    name => "Interplanetary Cruise App Budget #" . uniqid(),
    amount =>
      Google::Ads::AdWords::v201708::Money->new({microAmount => 5000000}),
    deliveryMethod => "STANDARD",
    # Universal app campaigns don't support shared budgets.
    isExplicitlyShared => 0
  });

  my $budget_operation = Google::Ads::AdWords::v201708::BudgetOperation->new({
    operator => "ADD",
    operand  => $budget
  });

  # Add budget.
  my $addedBudget =
    $client->BudgetService()->mutate({operations => ($budget_operation)})
    ->get_value();
  printf
    "Budget with name '%s' and ID %d was created.\n",
    $addedBudget->get_name(), $addedBudget->get_budgetId()->get_value();
  my $budget_id = $addedBudget->get_budgetId()->get_value();
  return $budget_id;
}

# Set the campaign targeting criteria.
sub set_campaign_targeting_criteria() {
  my ($client, $campaign_id) = @_;
  my @criteria = ();

  # Create locations. The IDs can be found in the documentation or retrieved
  # with the LocationCriterionService.
  my $california = Google::Ads::AdWords::v201708::Location->new({id => 21137});
  push @criteria, $california;
  my $mexico = Google::Ads::AdWords::v201708::Location->new({id => 2484});
  push @criteria, $mexico;

  # Create languages. The IDs can be found in the documentation or retrieved
  # with the ConstantDataService.
  my $english = Google::Ads::AdWords::v201708::Language->new({id => 1000});
  push @criteria, $english;
  my $spanish = Google::Ads::AdWords::v201708::Language->new({id => 1003});
  push @criteria, $spanish;

  # Create operations.
  my @operations = ();
  foreach my $criterion (@criteria) {
    my $operation =
      Google::Ads::AdWords::v201708::CampaignCriterionOperation->new({
        operator => "ADD",
        operand  => Google::Ads::AdWords::v201708::CampaignCriterion->new({
            campaignId => $campaign_id,
            criterion  => $criterion
          })});
    push @operations, $operation;
  }

  # Set campaign criteria.
  my $result =
    $client->CampaignCriterionService()->mutate({operations => \@operations});

  # Display campaign criteria.
  if ($result->get_value()) {
    foreach my $campaign_criterion (@{$result->get_value()}) {
      printf "Campaign criterion of type '%s' and ID %s was added.\n",
        $campaign_criterion->get_criterion()->get_type(),
        $campaign_criterion->get_criterion()->get_id();
    }
  }
}

# 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_universal_app_campaign($client);

Create and attach a shared keyword set

#!/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 creates a shared list of negative broad match keywords, then
# attaches them to a campaign.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::CampaignSharedSet;
use Google::Ads::AdWords::v201708::CampaignSharedSetOperation;
use Google::Ads::AdWords::v201708::Keyword;
use Google::Ads::AdWords::v201708::SharedCriterion;
use Google::Ads::AdWords::v201708::SharedCriterionOperation;
use Google::Ads::AdWords::v201708::SharedSet;
use Google::Ads::AdWords::v201708::SharedSetOperation;

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 create_and_attach_shared_keyword_set {
  my $client      = shift;
  my $campaign_id = shift;

  # Keywords to include in the shared set.
  my @keywords = ('mars cruise', 'mars hotels');

  # Create the shared negative keyword set.
  my $shared_set = Google::Ads::AdWords::v201708::SharedSet->new({
      name => 'Negative keyword list #' . uniqid(),
      type => 'NEGATIVE_KEYWORDS'
  });

  # Add the shared set.
  my $shared_set_result = $client->SharedSetService()->mutate({
      operations => [
        Google::Ads::AdWords::v201708::SharedSetOperation->new({
            operator => 'ADD',
            operand  => $shared_set
          })]});

  $shared_set = $shared_set_result->get_value(0);

  printf "Shared set with ID %d and name '%s' was successfully added.\n",
    $shared_set->get_sharedSetId(),
    $shared_set->get_name();

  # Add negative keywords to the shared set.
  my @shared_criterion_operations = ();
  foreach my $keyword (@keywords) {
    my $keyword_criterion = Google::Ads::AdWords::v201708::Keyword->new({
        text      => $keyword,
        matchType => 'BROAD'
    });

    my $shared_criterion = Google::Ads::AdWords::v201708::SharedCriterion->new({
        criterion   => $keyword_criterion,
        negative    => 1,
        sharedSetId => $shared_set->get_sharedSetId()});

    my $shared_criterion_operation =
      Google::Ads::AdWords::v201708::SharedCriterionOperation->new({
        operator => 'ADD',
        operand  => $shared_criterion
      });

    push @shared_criterion_operations, $shared_criterion_operation;
  }

  my $shared_criterion_result =
    $client->SharedCriterionService()
    ->mutate({operations => \@shared_criterion_operations});

  foreach my $shared_criterion (@{$shared_criterion_result->get_value()}) {
    printf "Added shared criterion ID %d '%s' to shared set with ID %d.\n",
      $shared_criterion->get_criterion()->get_id(),
      $shared_criterion->get_criterion()->get_text(),
      $shared_criterion->get_sharedSetId();
  }

  # Attach the negative keyword shared set to the campaign.
  my $campaign_shared_set =
    Google::Ads::AdWords::v201708::CampaignSharedSet->new({
      campaignId  => $campaign_id,
      sharedSetId => $shared_set->get_sharedSetId()});

  my $campaign_shared_set_result = $client->CampaignSharedSetService->mutate({
      operations => [
        Google::Ads::AdWords::v201708::CampaignSharedSetOperation->new({
            operator => 'ADD',
            operand  => $campaign_shared_set
          })]});

  $campaign_shared_set = $campaign_shared_set_result->get_value(0);

  printf "Shared set ID %d was attached to campaign ID %d.\n",
    $campaign_shared_set->get_sharedSetId(),
    $campaign_shared_set->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
create_and_attach_shared_keyword_set($client, $campaign_id);

Find and remove criteria from a shared set

#!/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 demonstrates how to find and remove shared sets and shared set
# criteria.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::CampaignSharedSet;
use Google::Ads::AdWords::v201708::CampaignSharedSetOperation;
use Google::Ads::AdWords::v201708::Criterion;
use Google::Ads::AdWords::v201708::Keyword;
use Google::Ads::AdWords::v201708::OrderBy;
use Google::Ads::AdWords::v201708::Paging;
use Google::Ads::AdWords::v201708::Placement;
use Google::Ads::AdWords::v201708::Predicate;
use Google::Ads::AdWords::v201708::Selector;
use Google::Ads::AdWords::v201708::SharedCriterion;
use Google::Ads::AdWords::v201708::SharedCriterionOperation;
use Google::Ads::AdWords::v201708::SharedSet;
use Google::Ads::AdWords::v201708::SharedSetOperation;
use Google::Ads::AdWords::Utilities::PageProcessor;

use constant PAGE_SIZE => 500;

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 find_and_remove_criteria_from_shared_set {
  my $client      = shift;
  my $campaign_id = shift;

  # First, retrieve all shared sets associated with the campaign.
  my $paging = Google::Ads::AdWords::v201708::Paging->new({
      startIndex    => 0,
      numberResults => PAGE_SIZE
  });
  my $selector = Google::Ads::AdWords::v201708::Selector->new({
      fields => ["SharedSetId", "CampaignId", "SharedSetName", "SharedSetType"],
      predicates => [
        Google::Ads::AdWords::v201708::Predicate->new({
            field    => "CampaignId",
            operator => "EQUALS",
            values   => [$campaign_id]})
      ],
      paging => $paging
    });

  # Paginate through results and collect the shared set IDs.
  # The subroutine will be executed for each shared set.
  my @shared_set_ids = Google::Ads::AdWords::Utilities::PageProcessor->new({
      client   => $client,
      service  => $client->CampaignSharedSetService(),
      selector => $selector
    }
    )->process_entries(
    sub {
      my ($campaign_shared_set) = @_;
      printf "Campaign shared set ID %d and name '%s' found for " .
        " campaign ID %d.\n",
        $campaign_shared_set->get_sharedSetId(),
        $campaign_shared_set->get_sharedSetName(),
        $campaign_shared_set->get_campaignId();
      return $campaign_shared_set->get_sharedSetId()->get_value();
    });

  if (!@shared_set_ids) {
    printf "No shared sets found for campaign ID %d.\n", $campaign_id;
    return 1;
  }

  # Next, retrieve criterion IDs for all found shared sets.
  $paging = Google::Ads::AdWords::v201708::Paging->new({
      startIndex    => 0,
      numberResults => PAGE_SIZE
  });
  $selector = Google::Ads::AdWords::v201708::Selector->new({
      fields => [
        "SharedSetId", "Id", "KeywordText", "KeywordMatchType", "PlacementUrl"
      ],
      predicates => [
        Google::Ads::AdWords::v201708::Predicate->new({
            field    => "SharedSetId",
            operator => "IN",
            values   => \@shared_set_ids
          })
      ],
      paging => $paging
    });

  my @remove_criterion_operations =
    Google::Ads::AdWords::Utilities::PageProcessor->new({
      client   => $client,
      service  => $client->SharedCriterionService(),
      selector => $selector
    }
    )->process_entries(
    sub {
      my ($shared_criterion) = @_;
      my $criterion = $shared_criterion->get_criterion();
      if ($criterion->isa("Google::Ads::AdWords::v201708::Keyword")) {
        printf "Shared negative keyword with ID %d and text '%s' was " .
          "found.\n",
          $criterion->get_id(),
          $criterion->get_text();
      } elsif ($criterion->isa("Google::Ads::AdWords::v201708::Placement")) {
        printf "Shared negative placement with ID %d and URL '%s' was " .
          "found.\n",
          $criterion->get_id(),
          $criterion->get_url();
      } else {
        printf "Shared criterion with ID %d was found.\n", $criterion->get_id();
      }

      # Create an operation to remove this criterion.
      my $shared_criterion_operation =
        Google::Ads::AdWords::v201708::SharedCriterionOperation->new({
          operator => 'REMOVE',
          operand  => Google::Ads::AdWords::v201708::SharedCriterion->new({
              criterion => Google::Ads::AdWords::v201708::Criterion->new(
                {id => $criterion->get_id()}
              ),
              sharedSetId => $shared_criterion->get_sharedSetId()})});
      return $shared_criterion_operation;
    });

  # Finally, remove the criteria.
  if (@remove_criterion_operations) {
    my $remove_criteria_result =
      $client->SharedCriterionService()
      ->mutate({operations => \@remove_criterion_operations});
    foreach my $removed_criterion (@{$remove_criteria_result->get_value()}) {
      printf "Shared criterion ID %d was successfully removed from shared " .
        "set ID %d.\n",
        $removed_criterion->get_criterion()->get_id(),
        $removed_criterion->get_sharedSetId();
    }
  } else {
    printf "No shared criteria to remove.\n";
  }

  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
find_and_remove_criteria_from_shared_set($client, $campaign_id);

Get ad group bid modifiers

#!/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.
#
# Retrieves all the ad group level bid modifiers of the account.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::OrderBy;
use Google::Ads::AdWords::v201708::Paging;
use Google::Ads::AdWords::v201708::Predicate;
use Google::Ads::AdWords::v201708::Selector;
use Google::Ads::AdWords::Utilities::PageProcessor;

use Cwd qw(abs_path);

use constant PAGE_SIZE => 500;

# Example main subroutine.
sub get_ad_group_bid_modifier {
  my $client = shift;

  # Create selector.
  my $paging = Google::Ads::AdWords::v201708::Paging->new({
      startIndex    => 0,
      numberResults => PAGE_SIZE
  });
  my $selector = Google::Ads::AdWords::v201708::Selector->new({
      fields => ["CampaignId", "AdGroupId", "BidModifier", "Id"],
      paging => $paging
  });

  # Paginate through results.
  Google::Ads::AdWords::Utilities::PageProcessor->new({
      client   => $client,
      service  => $client->AdGroupBidModifierService(),
      selector => $selector
    }
    )->process_entries(
    sub {
      my ($modifier) = @_;
      my $modifier_value = $modifier->get_bidModifier() || "unset";
      printf "Campaign ID %s, AdGroup ID %s, Criterion ID %s has ad group " .
        "level modifier: %s\n", $modifier->get_campaignId(),
        $modifier->get_adGroupId(), $modifier->get_criterion()->get_id(),
        $modifier_value;
    });

  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
get_ad_group_bid_modifier($client);

Upload offline conversions

#!/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 code example imports offline conversion values for specific clicks to
# your account. To get Google Click ID for a click, run
# CLICK_PERFORMANCE_REPORT. To set up a conversion tracker, run the
# add_conversion_trackers.pl example.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::UploadConversion;
use Google::Ads::AdWords::v201708::ConversionTrackerOperation;
use Google::Ads::AdWords::v201708::OfflineConversionFeed;
use Google::Ads::AdWords::v201708::OfflineConversionFeedOperation;

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

# Replace with valid values of your account.
my $conversion_name             = "INSERT_CONVERSION_NAME_HERE";
my $gclid                       = "INSERT_GCLID_HERE";
my $conversion_time             = "INSERT_CONVERSION_TIME_HERE";
my $conversion_value            = "INSERT_CONVERSION_VALUE_HERE";

# Example main subroutine.
sub upload_offline_conversions {
  my $client                      = shift;
  my $conversion_name             = shift;
  my $gclid                       = shift;
  my $conversion_time             = shift;
  my $conversion_value            = shift;

  my @conversion_tracker_operations = ();
  my @offline_conversion_operations = ();

  # Create an upload conversion. Once created, this entry will be visible
  # under Tools and Analysis->Conversion and will have Source = Import.
  my $upload_conversion = Google::Ads::AdWords::v201708::UploadConversion->new({
    category                  => 'PAGE_VIEW',
    name                      => $conversion_name,
    viewthroughLookbackWindow => 30,
    ctcLookbackWindow         => 90
  });

  my $upload_operation =
    Google::Ads::AdWords::v201708::ConversionTrackerOperation->new({
      operator => "ADD",
      operand  => $upload_conversion
    });

  push @conversion_tracker_operations, $upload_operation;

  # Add the upload conversion.
  my $tracker_result =
    $client->ConversionTrackerService()
    ->mutate({operations => \@conversion_tracker_operations});

  # Display results.
  if ($tracker_result->get_value()) {
    foreach my $conversion_tracker (@{$tracker_result->get_value()}) {
      printf "New upload conversion type with name \"%s\" and ID \"%d\" " .
        "was created.\n",
        $conversion_tracker->get_name(),
        $conversion_tracker->get_id();
    }
  } else {
    print "No upload conversions were added.\n";
    return;
  }

  # Associate offline conversions with the upload conversion we created.
  my $feed = Google::Ads::AdWords::v201708::OfflineConversionFeed->new({
    conversionName            => $conversion_name,
    conversionTime            => $conversion_time,
    conversionValue           => $conversion_value,
    googleClickId             => $gclid,
    # Optional: To upload fractional conversion credits, set the external
    # attribution model and credit. To use this feature, your conversion tracker
    # should be marked as externally attributed. See
    # https://developers.google.com/adwords/api/docs/guides/conversion-tracking#importing_externally_attributed_conversions
    # to learn more about importing externally attributed conversions.
    # externalAttributionModel => "Linear";
    # externalAttributionCredit => 0.3;
  });

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

  push @offline_conversion_operations, $offline_conversion_operation;

  # Add the upload conversion.
  my $feed_result =
    $client->OfflineConversionFeedService()
    ->mutate({operations => \@offline_conversion_operations});

  # Display results.
  if ($feed_result->get_value()) {
    foreach my $oc_feed (@{$feed_result->get_value()}) {
      printf "Uploaded offline conversion value of \"%s\" for Google Click " .
        "ID \"%s\" was created.\n",
        $oc_feed->get_conversionName(),
        $oc_feed->get_googleClickId();
    }
  } else {
    print "No offline conversion were added.\n";
    return;
  }

  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
upload_offline_conversions($client, $conversion_name, $gclid, $conversion_time,
  $conversion_value);

Use hashes

#!/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 demonstrates how to use hashes instead of objects to do a request
# to the API. In general hashes can be used to call and read data from any
# of the API services.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;

use Cwd qw(abs_path);

use constant PAGE_SIZE => 500;

# Example main subroutine.
sub use_hashes {
  my $client = shift;

  # Get all campaigns.
  my $paging = {
    startIndex    => 0,
    numberResults => PAGE_SIZE
  };

  # Paginate through results.
  my $page;
  my $start_index = 0;
  do {
    my $paging = {
      startIndex    => $start_index,
      numberResults => PAGE_SIZE
    };
    # Get a page of campaigns.
    $page = $client->CampaignService()->get({
        serviceSelector => {
          fields     => ["Id", "Name"],
          predicates => [{
              field    => "Status",
              operator => "IN",
              values   => ["ENABLED"]
            }
          ],
          ordering => {
            field     => "Id",
            sortOrder => "ASCENDING"
          },
          paging => $paging
        }
      }
    );

    # Display campaigns.
    if ($page->{entries}) {
      foreach my $campaign (@{$page->{entries}}) {
        printf "Campaign with name \"%s\" and id \"%d\" was found.\n",
          $campaign->{name}, $campaign->{id};
      }
    }
    $start_index = $start_index + PAGE_SIZE;
  } while ($start_index < $page->{totalNumEntries});

  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
use_hashes($client);

Use OAuth2

#!/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 demonstrates how to authenticate using OAuth.  This example
# is meant to be run from the command line and requires user input.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::OrderBy;
use Google::Ads::AdWords::v201708::Predicate;
use Google::Ads::AdWords::v201708::Selector;

use Cwd qw(abs_path);

# Replace with valid values, see
# https://developers.google.com/accounts/docs/OAuth2WebServer for more
# information.
my $client_id     = "ENTER_YOUR_CLIENT_ID_HERE";
my $client_secret = "ENTER_YOUR_CLIENT_SECRET_HERE";

# Example main subroutine.
sub use_oauth2 {
  my ($client, $oauth2_client_id, $oauth2_client_secret) = @_;

  my $auth_handler = $client->get_oauth_2_handler();

  $auth_handler->set_client_id($oauth2_client_id);
  $auth_handler->set_client_secret($oauth2_client_secret);

  # Open a browser and point it to the authorization URL, authorize the access
  # and then enter the generated verification code.
  print "Log in to your AdWords account and open the following URL: ",
    $auth_handler->get_authorization_url(), "\n";
  print "Grant access to the applications and enter the authorization code " .
    "display in the page then hit ENTER.\n";
  my $code = <STDIN>;
  # Trimming the value.
  $code =~ s/^\s*(.*)\s*$/$1/;

  # Requesting the access token using the authorization code, so it can be used
  # to access the API.
  if (my $error = $auth_handler->issue_access_token($code)) {
    die($error);
  }

  # After the access token is generated, you should store the
  # access and refresh token and re-use them for future calls, by either
  # changing your adwords.properties file or setting them in the authorization
  # handler as follows:
  # $client->get_oauth_2_handler()->set_access_token($access_token);
  # $client->get_oauth_2_handler()->set_refresh_token($refresh_token);
  print "OAuth2 Access Token: ", $auth_handler->get_access_token(), "\n",
    "OAuth2 Refresh Token: ", $auth_handler->get_refresh_token(), "\n\n";

  # Create selector.
  my $selector = Google::Ads::AdWords::v201708::Selector->new({
      fields   => ["Id", "Name"],
      ordering => [
        Google::Ads::AdWords::v201708::OrderBy->new({
            field     => "Name",
            sortOrder => "ASCENDING"
          })]});

  # Get all campaigns.
  my $page = $client->CampaignService()->get({serviceSelector => $selector});

  # Display campaigns.
  if ($page->get_entries()) {
    foreach my $campaign (@{$page->get_entries()}) {
      print "Campaign with name '", $campaign->get_name(), "' and id '",
        $campaign->get_id(), "' was found.\n";
    }
  } else {
    print "No campaigns were found.\n";
  }

  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
use_oauth2($client, $client_id, $client_secret);

f

Use a portfolio bidding strategy

#!/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 portfolio bidding strategy and uses it to
# construct a campaign.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::SharedBiddingStrategy;
use Google::Ads::AdWords::v201708::TargetSpendBiddingScheme;
use Google::Ads::AdWords::v201708::Money;
use Google::Ads::AdWords::v201708::BiddingStrategyOperation;
use Google::Ads::AdWords::v201708::BudgetOperation;
use Google::Ads::AdWords::v201708::NetworkSetting;
use Google::Ads::AdWords::v201708::CampaignOperation;

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

# Replace with valid values of your account.
my $budget_id = 0;

# Example main subroutine.
sub use_portfolio_bidding_strategy {
  my $client    = shift;
  my $budget_id = shift;

  my $biddingStrategy = create_bidding_strategy($client);
  if (!$biddingStrategy) {
    return 0;
  }

  if (!$budget_id) {
    my $budget = create_shared_budget($client);
    if (!$budget) {
      return 0;
    }
    $budget_id = $budget->get_budgetId();
  }

  create_campaign_with_bidding_strategy($client, $biddingStrategy->get_id(),
    $budget_id);

  return 1;
}

# Creates the bidding strategy object.
sub create_bidding_strategy {
  my $client = shift;

  my @operations = ();

  # Create a portfolio bidding strategy.
  my $bidding_strategy =
    Google::Ads::AdWords::v201708::SharedBiddingStrategy->new({
      name => "Maximize Clicks " . uniqid(),
      type => "TARGET_SPEND",

      # Create the bidding scheme.
      biddingScheme =>
        Google::Ads::AdWords::v201708::TargetSpendBiddingScheme->new({
          # Optionally set additional bidding scheme parameters.
          bidCeiling => Google::Ads::AdWords::v201708::Money->new(
            {microAmount => 2000000,}
          ),
          spendTarget => Google::Ads::AdWords::v201708::Money->new(
            {microAmount => 20000000,})})});

  # Create operation.
  my $operation = Google::Ads::AdWords::v201708::BiddingStrategyOperation->new({
      operator => "ADD",
      operand  => $bidding_strategy
  });

  push @operations, $operation;

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

  if ($result->get_value()) {
    my $strategy = $result->get_value()->[0];
    printf "Portfolio bidding strategy with name \"%s\" and ID %d of type %s " .
      "was created.\n", $strategy->get_name(), $strategy->get_id(),
      $strategy->get_biddingScheme()->get_BiddingScheme__Type();
    return $strategy;
  } else {
    print "No portfolio bidding strategies were added.\n";
    return 0;
  }
}

# Creates an explicit budget to be used only to create the campaign.
sub create_shared_budget {
  my $client = shift;

  my @operations = ();

  # Create a shared budget operation.
  my $operation = Google::Ads::AdWords::v201708::BudgetOperation->new({
      operator => 'ADD',
      operand  => Google::Ads::AdWords::v201708::Budget->new({
          amount => Google::Ads::AdWords::v201708::Money->new(
            {microAmount => 50000000}
          ),
          deliveryMethod     => 'STANDARD',
          isExplicitlyShared => 0
        })});

  push @operations, $operation;

  # Make the mutate request.
  my $result = $client->BudgetService()->mutate({operations => \@operations});

  if ($result->get_value()) {
    return $result->get_value()->[0];
  } else {
    print "No budgets were added.\n";
    return 0;
  }
}

# Create a campaign with a portfolio bidding strategy.
sub create_campaign_with_bidding_strategy {
  my $client              = shift;
  my $bidding_strategy_id = shift;
  my $budget_id           = shift;

  my @operations = ();

  # Create campaign.
  my $campaign = Google::Ads::AdWords::v201708::Campaign->new({
      name => 'Interplanetary Cruise #' . uniqid(),
      budget =>
        Google::Ads::AdWords::v201708::Budget->new({budgetId => $budget_id}),
      # Set bidding strategy (required).
      biddingStrategyConfiguration =>
        Google::Ads::AdWords::v201708::BiddingStrategyConfiguration->new(
        {biddingStrategyId => $bidding_strategy_id}
        ),
      # Set advertising channel type (required).
      advertisingChannelType => 'SEARCH',
      # Network targeting (recommended).
      networkSetting => Google::Ads::AdWords::v201708::NetworkSetting->new({
          targetGoogleSearch   => 1,
          targetSearchNetwork  => 1,
          targetContentNetwork => 1
        }),
      # Recommendation: Set the campaign to PAUSED when creating it to stop
      # the ads from immediately serving. Set to ENABLED once you've added
      # targeting and the ads are ready to serve.
      status => "PAUSED"
  });

  # Create operation.
  my $operation = Google::Ads::AdWords::v201708::CampaignOperation->new({
      operator => 'ADD',
      operand  => $campaign
  });

  push @operations, $operation;

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

  if ($result->get_value()) {
    my $new_campaign = $result->get_value()->[0];
    printf "Campaign with name \"%s\", ID %d and bidding strategy ID %d was " .
      "created.\n", $new_campaign->get_name(), $new_campaign->get_id(),
      $new_campaign->get_biddingStrategyConfiguration()
      ->get_biddingStrategyId();
    return $new_campaign;
  } else {
    print "No campaigns were added.\n";
    return 0;
  }
}

# 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
use_portfolio_bidding_strategy($client, $budget_id);

Use XPath

#!/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 shows the use of an XPath expression to gather all campaign
# budget objects from an API response. In general any object returned from a
# service call is able to accept XPath queries.

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

use Google::Ads::AdWords::Client;
use Google::Ads::AdWords::Logging;
use Google::Ads::AdWords::v201708::OrderBy;
use Google::Ads::AdWords::v201708::Selector;
use Google::Ads::AdWords::v201708::Paging;

use Cwd qw(abs_path);

use constant PAGE_SIZE => 500;

# Example main subroutine.
sub use_xpath {
  my $client = shift;

  # Create selector.
  my $paging = Google::Ads::AdWords::v201708::Paging->new({
      startIndex    => 0,
      numberResults => PAGE_SIZE
  });
  my $selector = Google::Ads::AdWords::v201708::Selector->new({
      fields => ["Amount", "DeliveryMethod"],
      paging => $paging
  });

  # Paginate through results.
  my $page;
  do {
    # Get a page of campaigns.
    $page = $client->CampaignService()->get({serviceSelector => $selector});

    # Get all campaigns and then find all associated budgets.
    my $budgets =
      $client->CampaignService()->get({serviceSelector => $selector})
      ->find('//entries/budget');

    # Display budgets.
    foreach my $budget (@{$budgets}) {
      printf "Budget with amount \"%s\" and delivery method " .
        "\"%s\" was found.\n",
        $budget->get_amount()->get_microAmount(),
        $budget->get_deliveryMethod();
    }
    $paging->set_startIndex($paging->get_startIndex() + PAGE_SIZE);
  } while ($paging->get_startIndex() < $page->get_totalNumEntries());

  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
use_xpath($client);

Send feedback about...

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