Add Dynamic Page Feed

Java

// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://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.

package com.google.ads.googleads.examples.advancedoperations;

import static com.google.ads.googleads.examples.utils.CodeSampleHelper.getPrintableDateTime;

import com.beust.jcommander.Parameter;
import com.google.ads.googleads.examples.utils.ArgumentNames;
import com.google.ads.googleads.examples.utils.CodeSampleParams;
import com.google.ads.googleads.lib.GoogleAdsClient;
import com.google.ads.googleads.lib.utils.FieldMasks;
import com.google.ads.googleads.v9.common.WebpageConditionInfo;
import com.google.ads.googleads.v9.common.WebpageInfo;
import com.google.ads.googleads.v9.enums.DsaPageFeedCriterionFieldEnum.DsaPageFeedCriterionField;
import com.google.ads.googleads.v9.enums.FeedAttributeTypeEnum.FeedAttributeType;
import com.google.ads.googleads.v9.enums.FeedMappingCriterionTypeEnum.FeedMappingCriterionType;
import com.google.ads.googleads.v9.enums.WebpageConditionOperandEnum.WebpageConditionOperand;
import com.google.ads.googleads.v9.errors.GoogleAdsError;
import com.google.ads.googleads.v9.errors.GoogleAdsException;
import com.google.ads.googleads.v9.resources.AdGroupCriterion;
import com.google.ads.googleads.v9.resources.AttributeFieldMapping;
import com.google.ads.googleads.v9.resources.Campaign;
import com.google.ads.googleads.v9.resources.Campaign.DynamicSearchAdsSetting;
import com.google.ads.googleads.v9.resources.Feed;
import com.google.ads.googleads.v9.resources.FeedAttribute;
import com.google.ads.googleads.v9.resources.FeedItem;
import com.google.ads.googleads.v9.resources.FeedItemAttributeValue;
import com.google.ads.googleads.v9.resources.FeedMapping;
import com.google.ads.googleads.v9.services.AdGroupCriterionOperation;
import com.google.ads.googleads.v9.services.AdGroupCriterionServiceClient;
import com.google.ads.googleads.v9.services.CampaignOperation;
import com.google.ads.googleads.v9.services.CampaignServiceClient;
import com.google.ads.googleads.v9.services.FeedItemOperation;
import com.google.ads.googleads.v9.services.FeedItemServiceClient;
import com.google.ads.googleads.v9.services.FeedMappingOperation;
import com.google.ads.googleads.v9.services.FeedMappingServiceClient;
import com.google.ads.googleads.v9.services.FeedOperation;
import com.google.ads.googleads.v9.services.FeedServiceClient;
import com.google.ads.googleads.v9.services.GoogleAdsRow;
import com.google.ads.googleads.v9.services.GoogleAdsServiceClient;
import com.google.ads.googleads.v9.services.GoogleAdsServiceClient.SearchPagedResponse;
import com.google.ads.googleads.v9.services.MutateAdGroupCriteriaResponse;
import com.google.ads.googleads.v9.services.MutateCampaignsResponse;
import com.google.ads.googleads.v9.services.MutateFeedItemResult;
import com.google.ads.googleads.v9.services.MutateFeedItemsResponse;
import com.google.ads.googleads.v9.services.MutateFeedMappingsResponse;
import com.google.ads.googleads.v9.services.MutateFeedsResponse;
import com.google.ads.googleads.v9.services.SearchGoogleAdsRequest;
import com.google.ads.googleads.v9.utils.ResourceNames;
import com.google.common.collect.ImmutableList;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Adds a page feed with URLs for a Dynamic Search Ads Campaign.
 */
// DEPRECATION WARNING!
// Feed-services based DSA page feeds are deprecated and being replaced with assets. See
// AddDynamicPageFeedAsset.java.
public class AddDynamicPageFeed {

  private static final int PAGE_SIZE = 1_000;

  private static class AddDynamicPageFeedParams extends CodeSampleParams {

    @Parameter(names = ArgumentNames.CUSTOMER_ID, required = true)
    private Long customerId;

    @Parameter(names = ArgumentNames.CAMPAIGN_ID, required = true)
    private Long campaignId;

    @Parameter(names = ArgumentNames.AD_GROUP_ID, required = true)
    private Long adGroupId;
  }

  public static void main(String[] args) {
    AddDynamicPageFeedParams params = new AddDynamicPageFeedParams();
    if (!params.parseArguments(args)) {

      // Either pass the required parameters for this example on the command line, or insert them
      // into the code here. See the parameter class definition above for descriptions.
      params.customerId = Long.parseLong("INSERT_CUSTOMER_ID_HERE");
      params.campaignId = Long.parseLong("INSERT_CAMPAIGN_ID_HERE");
      params.adGroupId = Long.parseLong("INSERT_AD_GROUP_ID_HERE");
    }

    GoogleAdsClient googleAdsClient = null;
    try {
      googleAdsClient = GoogleAdsClient.newBuilder().fromPropertiesFile().build();
    } catch (FileNotFoundException fnfe) {
      System.err.printf(
          "Failed to load GoogleAdsClient configuration from file. Exception: %s%n", fnfe);
      System.exit(1);
    } catch (IOException ioe) {
      System.err.printf("Failed to create GoogleAdsClient. Exception: %s%n", ioe);
      System.exit(1);
    }

    try {
      new AddDynamicPageFeed()
          .runExample(googleAdsClient, params.customerId, params.campaignId, params.adGroupId);
    } catch (GoogleAdsException gae) {
      // GoogleAdsException is the base class for most exceptions thrown by an API request.
      // Instances of this exception have a message and a GoogleAdsFailure that contains a
      // collection of GoogleAdsErrors that indicate the underlying causes of the
      // GoogleAdsException.
      System.err.printf(
          "Request ID %s failed due to GoogleAdsException. Underlying errors:%n",
          gae.getRequestId());
      int i = 0;
      for (GoogleAdsError googleAdsError : gae.getGoogleAdsFailure().getErrorsList()) {
        System.err.printf("  Error %d: %s%n", i++, googleAdsError);
      }
      System.exit(1);
    }
  }

  /**
   * Runs the example.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the client customer ID.
   * @param campaignId the campaign ID.
   * @param adGroupId the ad group ID.
   * @throws GoogleAdsException if an API request failed with one or more service errors.
   */
  private void runExample(
      GoogleAdsClient googleAdsClient, long customerId, long campaignId, long adGroupId) {
    // The label for the DSA page URLs.
    String dsaPageUrlLabel = "discounts";

    // Creates the page feed details. This code example creates a new feed, but you can
    // fetch and re-use an existing feed.
    String feedResourceName = createFeed(googleAdsClient, customerId);
    Map<String, Long> feedDetails = getFeed(googleAdsClient, customerId, feedResourceName);
    createFeedMapping(googleAdsClient, customerId, feedDetails, feedResourceName);
    createFeedItems(googleAdsClient, customerId, feedDetails, feedResourceName, dsaPageUrlLabel);

    // Associates the page feed with the campaign.
    updateCampaignDsaSetting(googleAdsClient, customerId, feedResourceName, campaignId);

    // Optional: Targets web pages matching the feed's label in the ad group.
    addDsaTarget(googleAdsClient, customerId, adGroupId, dsaPageUrlLabel);

    System.out.printf("Dynamic page feed setup is complete for campaign with ID %d.%n", campaignId);
  }

  /**
   * Creates a feed.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the customer ID in which to create the feed.
   * @return the resource name of the newly created feed.
   */
  private static String createFeed(GoogleAdsClient googleAdsClient, long customerId) {
    // Creates a URL attribute.
    FeedAttribute urlAttribute =
        FeedAttribute.newBuilder().setType(FeedAttributeType.URL_LIST).setName("Page URL").build();

    // Creates a label attribute.
    FeedAttribute labelAttribute =
        FeedAttribute.newBuilder().setType(FeedAttributeType.STRING_LIST).setName("Label").build();

    // Creates the feed.
    Feed feed =
        Feed.newBuilder()
            .setName("DSA Feed #" + getPrintableDateTime())
            .addAllAttributes(ImmutableList.of(urlAttribute, labelAttribute))
            .build();

    // Creates a feed operation for creating a feed.
    FeedOperation feedOperation = FeedOperation.newBuilder().setCreate(feed).build();

    // Creates a feed service client.
    try (FeedServiceClient feedServiceClient =
        googleAdsClient.getLatestVersion().createFeedServiceClient()) {
      // Adds the feed.
      MutateFeedsResponse feedResponse =
          feedServiceClient.mutateFeeds(Long.toString(customerId), ImmutableList.of(feedOperation));
      String feedResourceName = feedResponse.getResults(0).getResourceName();
      System.out.printf("Added feed named '%s'.%n", feedResourceName);

      return feedResourceName;
    }
  }

  /**
   * Retrieves details about a feed.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the customer ID.
   * @param feedResourceName the resource name of the feed.
   * @return a map of the names and IDs of feed attributes.
   */
  private static Map<String, Long> getFeed(
      GoogleAdsClient googleAdsClient, long customerId, String feedResourceName) {
    String query =
        String.format(
            "SELECT feed.attributes FROM feed WHERE feed.resource_name = '%s'", feedResourceName);

    // Creates the request.
    SearchGoogleAdsRequest request =
        SearchGoogleAdsRequest.newBuilder()
            .setCustomerId(Long.toString(customerId))
            .setPageSize(PAGE_SIZE)
            .setQuery(query)
            .build();

    // Creates the service client.
    try (GoogleAdsServiceClient googleAdsServiceClient =
        googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
      // Issues the search request.
      SearchPagedResponse response = googleAdsServiceClient.search(request);
      // Gets the first result because we only need the single feed item we created previously.
      GoogleAdsRow googleAdsRow = response.getPage().getResponse().getResults(0);
      // Gets the attributes list from the feed and creates a map with keys of each attribute and
      // values of each corresponding ID.
      List<FeedAttribute> feedAttributes = googleAdsRow.getFeed().getAttributesList();
      // Creates a map to return.
      Map<String, Long> feedDetails = new HashMap<>();
      // Adds each of the feed attributes and IDs to the map.
      for (FeedAttribute feedAttribute : feedAttributes) {
        feedDetails.put(feedAttribute.getName(), feedAttribute.getId());
      }

      return feedDetails;
    }
  }

  /**
   * Creates a feed mapping for a given feed.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the customer ID.
   * @param feedDetails a map of the names and IDs of feed attributes.
   * @param feedResourceName the resource name of the feed.
   */
  private static void createFeedMapping(
      GoogleAdsClient googleAdsClient,
      long customerId,
      Map<String, Long> feedDetails,
      String feedResourceName) {
    // Maps the feed attribute IDs to the field ID constants.
    AttributeFieldMapping urlFieldMapping =
        AttributeFieldMapping.newBuilder()
            .setFeedAttributeId(feedDetails.get("Page URL"))
            .setDsaPageFeedField(DsaPageFeedCriterionField.PAGE_URL)
            .build();

    AttributeFieldMapping labelFieldMapping =
        AttributeFieldMapping.newBuilder()
            .setFeedAttributeId(feedDetails.get("Label"))
            .setDsaPageFeedField(DsaPageFeedCriterionField.LABEL)
            .build();

    // Creates the feed mapping.
    FeedMapping feedMapping =
        FeedMapping.newBuilder()
            .setCriterionType(FeedMappingCriterionType.DSA_PAGE_FEED)
            .setFeed(feedResourceName)
            .addAllAttributeFieldMappings(ImmutableList.of(urlFieldMapping, labelFieldMapping))
            .build();

    // Creates the operation.
    FeedMappingOperation operation =
        FeedMappingOperation.newBuilder().setCreate(feedMapping).build();

    // Creates the service client.
    try (FeedMappingServiceClient feedMappingServiceClient =
        googleAdsClient.getLatestVersion().createFeedMappingServiceClient()) {
      // Adds the feed mapping.
      MutateFeedMappingsResponse response =
          feedMappingServiceClient.mutateFeedMappings(
              Long.toString(customerId), ImmutableList.of(operation));
      // Displays the results.
      System.out.printf(
          "Created feed maping with resource name '%s'.%n",
          response.getResults(0).getResourceName());
    }
  }

  /**
   * Creates feed items for a given feed.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the customer ID.
   * @param feedDetails a map of the names and IDs of feed attributes.
   * @param feedResourceName the resource name of the feed.
   * @param dsaPageUrlLabel the label for the DSA page URLs.
   */
  private static void createFeedItems(
      GoogleAdsClient googleAdsClient,
      long customerId,
      Map<String, Long> feedDetails,
      String feedResourceName,
      String dsaPageUrlLabel) {
    List<String> urls =
        ImmutableList.of(
            "http://www.example.com/discounts/rental-cars",
            "http://www.example.com/discounts/hotel-deals",
            "http://www.example.com/discounts/flight-deals");

    // Creates a value for the label attribute.
    FeedItemAttributeValue labelAttributeValue =
        FeedItemAttributeValue.newBuilder()
            .setFeedAttributeId(feedDetails.get("Label"))
            .addAllStringValues(ImmutableList.of(dsaPageUrlLabel))
            .build();

    // Creates one operation per URL.
    List<FeedItemOperation> feedItemOperations = new ArrayList<>();
    for (String url : urls) {
      // Creates a url attribute.
      FeedItemAttributeValue urlAttributeValue =
          FeedItemAttributeValue.newBuilder()
              .setFeedAttributeId(feedDetails.get("Page URL"))
              .addAllStringValues(ImmutableList.of(url))
              .build();

      // Creates a feed item.
      FeedItem feedItem =
          FeedItem.newBuilder()
              .setFeed(feedResourceName)
              .addAllAttributeValues(ImmutableList.of(urlAttributeValue, labelAttributeValue))
              .build();

      // Creates an operation and adds it to the list of operations.
      FeedItemOperation feedItemOperation =
          FeedItemOperation.newBuilder().setCreate(feedItem).build();
      feedItemOperations.add(feedItemOperation);
    }

    // Creates the service client.
    try (FeedItemServiceClient feedItemServiceClient =
        googleAdsClient.getLatestVersion().createFeedItemServiceClient()) {
      // Adds the feed items.
      MutateFeedItemsResponse response =
          feedItemServiceClient.mutateFeedItems(Long.toString(customerId), feedItemOperations);

      // Displays the results.
      for (MutateFeedItemResult result : response.getResultsList()) {
        System.out.printf("Created feed item with resource name '%s'.%n", result.getResourceName());
      }
    }
  }

  /**
   * Updates a campaign to set the DSA feed.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the customer ID.
   * @param feedResourceName the resource name of the feed.
   * @param campaignId the campaign ID of the campaign to update.
   */
  private static void updateCampaignDsaSetting(
      GoogleAdsClient googleAdsClient, long customerId, String feedResourceName, long campaignId) {
    // Retrieves the existing dynamic search ads settings for the campaign.
    DynamicSearchAdsSetting dsaSetting = getDsaSetting(googleAdsClient, customerId, campaignId);
    dsaSetting.toBuilder().addAllFeeds(ImmutableList.of(feedResourceName)).build();

    // Creates the campaign object to update.
    Campaign campaign =
        Campaign.newBuilder()
            .setResourceName(ResourceNames.campaign(customerId, campaignId))
            .setDynamicSearchAdsSetting(dsaSetting)
            .build();

    // Creates the update operation and sets the update mask.
    CampaignOperation operation =
        CampaignOperation.newBuilder()
            .setUpdate(campaign)
            .setUpdateMask(FieldMasks.allSetFieldsOf(campaign))
            .build();

    // Creates the service client.
    try (CampaignServiceClient campaignServiceClient =
        googleAdsClient.getLatestVersion().createCampaignServiceClient()) {
      // Updates the campaign.
      MutateCampaignsResponse response =
          campaignServiceClient.mutateCampaigns(
              Long.toString(customerId), ImmutableList.of(operation));

      // Displays the results.
      System.out.printf(
          "Updated campaign with resource name '%s'.%n", response.getResults(0).getResourceName());
    }
  }

  /**
   * Returns the DSA settings for a campaign. Throws an error if the campaign does not exist or is
   * not a DSA campaign.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the customer ID.
   * @param campaignId the campaign ID of the campaign to update.
   * @return the DSA settings for the campaign.
   */
  private static DynamicSearchAdsSetting getDsaSetting(
      GoogleAdsClient googleAdsClient, long customerId, long campaignId) {
    // Creates the query.
    String query =
        String.format(
            "SELECT campaign.id, "
                + " campaign.name, "
                + " campaign.dynamic_search_ads_setting.use_supplied_urls_only "
                + "FROM campaign "
                + "WHERE campaign.id = '%s'",
            campaignId);

    // Creates the request.
    SearchGoogleAdsRequest request =
        SearchGoogleAdsRequest.newBuilder()
            .setCustomerId(Long.toString(customerId))
            .setPageSize(PAGE_SIZE)
            .setQuery(query)
            .build();

    // Creates the service client.
    try (GoogleAdsServiceClient googleAdsServiceClient =
        googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
      // Issues the search request.
      SearchPagedResponse response = googleAdsServiceClient.search(request);

      // Throws an exception if the campaign is not a DSA campaign.
      // The server will return an error when trying to update the campaign with the DSA feed in
      // the following step if the campaign is not a DSA campaign. However, this
      // exception is easier to interpret.
      if (!response
          .getPage()
          .getResponse()
          .getResults(0)
          .getCampaign()
          .hasDynamicSearchAdsSetting()) {
        throw new IllegalArgumentException("Campaign with ID '%s' is not a DSA campaign.");
      }

      // Retrieves and returns the DSA setting.
      return response
          .getPage()
          .getResponse()
          .getResults(0)
          .getCampaign()
          .getDynamicSearchAdsSetting();
    }
  }

  /**
   * Creates an ad group criterion targeting the DSA label.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the customer ID.
   * @param adGroupId the ad group ID.
   * @param dsaPageUrlLabel the label for the DSA page URLs.
   */
  private static void addDsaTarget(
      GoogleAdsClient googleAdsClient, long customerId, long adGroupId, String dsaPageUrlLabel) {
    String adGroupResourceName = ResourceNames.adGroup(customerId, adGroupId);

    // Creates the webpage condition info that targets an advertiser's webpages based on the
    // custom label specified by the dsaPageUrlLabel (e.g. "discounts").
    WebpageConditionInfo webpageConditionInfo =
        WebpageConditionInfo.newBuilder()
            .setOperand(WebpageConditionOperand.CUSTOM_LABEL)
            .setArgument(dsaPageUrlLabel)
            .build();

    // Creates the webpage info, or criterion for targeting webpages of an advertiser's website.
    WebpageInfo webpageInfo =
        WebpageInfo.newBuilder()
            .setCriterionName("Test Criterion")
            .addAllConditions(ImmutableList.of(webpageConditionInfo))
            .build();

    // Creates the ad group criterion.
    AdGroupCriterion adGroupCriterion =
        AdGroupCriterion.newBuilder()
            .setAdGroup(adGroupResourceName)
            .setWebpage(webpageInfo)
            .setCpcBidMicros(1_500_000)
            .build();

    // Creates the operation.
    AdGroupCriterionOperation operation =
        AdGroupCriterionOperation.newBuilder().setCreate(adGroupCriterion).build();

    // Creates the service client.
    try (AdGroupCriterionServiceClient adGroupCriterionServiceClient =
        googleAdsClient.getLatestVersion().createAdGroupCriterionServiceClient()) {
      // Adds the ad group criterion.
      MutateAdGroupCriteriaResponse response =
          adGroupCriterionServiceClient.mutateAdGroupCriteria(
              Long.toString(customerId), ImmutableList.of(operation));

      // Displays the results.
      System.out.printf(
          "Created ad group criterion with resource name '%s'.%n",
          response.getResults(0).getResourceName());
    }
  }
}

      

C#

// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using CommandLine;
using Google.Ads.GoogleAds.Lib;
using Google.Ads.GoogleAds.Util;
using Google.Ads.GoogleAds.V9.Common;
using Google.Ads.GoogleAds.V9.Errors;
using Google.Ads.GoogleAds.V9.Resources;
using Google.Ads.GoogleAds.V9.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using static Google.Ads.GoogleAds.V9.Enums.DsaPageFeedCriterionFieldEnum.Types;
using static Google.Ads.GoogleAds.V9.Enums.FeedAttributeTypeEnum.Types;
using static Google.Ads.GoogleAds.V9.Enums.FeedMappingCriterionTypeEnum.Types;
using static Google.Ads.GoogleAds.V9.Enums.WebpageConditionOperandEnum.Types;
using static Google.Ads.GoogleAds.V9.Resources.Campaign.Types;

namespace Google.Ads.GoogleAds.Examples.V9
{
    /// <summary>
    /// This code example adds a page feed to specify precisely which URLs to use with your
    /// Dynamic Search Ads.
    /// </summary>
    public class AddDynamicPageFeed : ExampleBase
    {
        /// <summary>
        /// Command line options for running the <see cref="AddDynamicPageFeed"/> example.
        /// </summary>
        public class Options : OptionsBase
        {
            /// <summary>
            /// The Google Ads customer ID for which the call is made.
            /// </summary>
            [Option("customerId", Required = true, HelpText =
                "The Google Ads customer ID for which the call is made.")]
            public long CustomerId { get; set; }

            /// <summary>
            /// ID of the campaign for which dynamic page feeds are added.
            /// </summary>
            [Option("campaignId", Required = true, HelpText =
                "ID of the campaign for which dynamic page feeds are added.")]
            public long CampaignId { get; set; }

            /// <summary>
            /// ID of the ad group for which dynamic page feeds are added.
            /// </summary>
            [Option("adGroupId", Required = true, HelpText =
                "ID of the ad group for which dynamic page feeds are added.")]
            public long AdGroupId { get; set; }
        }

        /// <summary>
        /// Main method, to run this code example as a standalone application.
        /// </summary>
        /// <param name="args">The command line arguments.</param>
        public static void Main(string[] args)
        {
            Options options = new Options();
            CommandLine.Parser.Default.ParseArguments<Options>(args).MapResult(
                delegate (Options o)
                {
                    options = o;
                    return 0;
                }, delegate (IEnumerable<Error> errors)
                {
                    // The Google Ads customer ID for which the call is made.
                    options.CustomerId = long.Parse("INSERT_CUSTOMER_ID_HERE");

                    // ID of the campaign for which dynamic page feeds are added.
                    options.CampaignId = long.Parse("INSERT_CAMPAIGN_ID_HERE");

                    // ID of the ad group for which dynamic page feeds are added.
                    options.AdGroupId = long.Parse("INSERT_AD_GROUP_ID_HERE");

                    return 0;
                });

            AddDynamicPageFeed codeExample = new AddDynamicPageFeed();
            Console.WriteLine(codeExample.Description);
            codeExample.Run(new GoogleAdsClient(), options.CustomerId, options.CampaignId,
                options.AdGroupId);
        }

        /// <summary>
        /// Returns a description about the code example.
        /// </summary>
        public override string Description =>
            "This code example adds a page feed to specify precisely which URLs to use with " +
            "your Dynamic Search Ads.";

        /// <summary>
        /// Runs the code example.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
        /// <param name="campaignId">ID of the campaign for which dynamic page feeds are added.
        /// </param>
        /// <param name="adGroupId">ID of the ad group for which dynamic page feeds are added.
        /// </param>
        public void Run(GoogleAdsClient client, long customerId, long campaignId, long adGroupId)
        {
            try
            {
                string dsaPageUrlLabel = "discounts";

                // Get the page feed details. This code example creates a new feed, but you can
                // fetch and re-use an existing feed.
                string feedResourceName = CreateFeed(client, customerId);
                Dictionary<DsaPageFeedCriterionField, FeedAttribute> feedAttributes =
                    GetFeed(client, customerId, feedResourceName);
                CreateFeedMapping(client, customerId, feedResourceName, feedAttributes);
                CreateFeedItems(client, customerId, feedResourceName, feedAttributes,
                    dsaPageUrlLabel);

                // Associates the page feed with the campaign.
                UpdateCampaignDsaSetting(client, customerId, feedResourceName, campaignId);

                // Optional: Targets web pages matching the feed's label in the ad group.
                AddDsaTarget(client, customerId, adGroupId, dsaPageUrlLabel);

                Console.WriteLine($"Dynamic page feed setup is complete for campaign " +
                    $"ID {campaignId}");
            }
            catch (GoogleAdsException e)
            {
                Console.WriteLine("Failure:");
                Console.WriteLine($"Message: {e.Message}");
                Console.WriteLine($"Failure: {e.Failure}");
                Console.WriteLine($"Request ID: {e.RequestId}");
                throw;
            }
        }

        /// <summary>
        /// Creates the feed.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
        /// <returns>The resource name of the newly created feed.</returns>
        private string CreateFeed(GoogleAdsClient client, long customerId)
        {
            // Get the FeedService.
            FeedServiceClient feedService = client.GetService(Services.V9.FeedService);

            // Create a URL attribute.
            FeedAttribute urlAttribute = new FeedAttribute()
            {
                Type = FeedAttributeType.UrlList,
                Name = "Page URL"
            };

            // Create a label attribute.
            FeedAttribute labelAttribute = new FeedAttribute()
            {
                Type = FeedAttributeType.StringList,
                Name = "Label"
            };

            // Create the feed.
            Feed feed = new Feed()
            {
                Name = "DSA Feed #" + ExampleUtilities.GetRandomString(),
                Attributes = { urlAttribute, labelAttribute }
            };

            // Create the operation.
            FeedOperation operation = new FeedOperation()
            {
                Create = feed
            };

            // Add the feed.
            MutateFeedsResponse response =
                feedService.MutateFeeds(customerId.ToString(), new[] { operation });

            string feedResourceName = response.Results[0].ResourceName;

            // Display the result.
            Console.WriteLine($"Feed with resource name '{feedResourceName}' was created.");

            return feedResourceName;
        }

        /// <summary>
        /// Retrieves details about a feed.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
        /// <param name="feedResourceName">The feed resource name.</param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private Dictionary<DsaPageFeedCriterionField, FeedAttribute> GetFeed(
            GoogleAdsClient client, long customerId, string feedResourceName)
        {
            // Get the GoogleAdsService.
            GoogleAdsServiceClient googleAdsService = client.GetService(
                Services.V9.GoogleAdsService);

            // Construct the query.
            String query = $"SELECT feed.attributes FROM feed WHERE feed.resource_name" +
                $" = '{feedResourceName}'";

            // Construct the request.
            SearchGoogleAdsRequest request = new SearchGoogleAdsRequest()
            {
                CustomerId = customerId.ToString(),
                Query = query
            };

            // Issue the search request.
            Feed feed = googleAdsService.Search(customerId.ToString(), query).First().Feed;

            Dictionary<DsaPageFeedCriterionField, FeedAttribute> retval =
                new Dictionary<DsaPageFeedCriterionField, FeedAttribute>();

            foreach (FeedAttribute attribute in feed.Attributes)
            {
                DsaPageFeedCriterionField key;
                switch (attribute.Name)
                {
                    case "Page URL":
                        key = DsaPageFeedCriterionField.PageUrl;
                        break;

                    case "Label":
                        key = DsaPageFeedCriterionField.Label;
                        break;

                    default:
                        throw new Exception("Unable to map attribute name to DSA page feed" +
                            " criterion.");
                }
                retval[key] = attribute;
            }

            return retval;
        }

        /// <summary>
        /// Creates a feed mapping for a given feed.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
        /// <param name="feedResourceName">The feed resource for which feed mapping is created.
        /// </param>
        /// <param name="feedAttributes">The feed attributes.</param>
        private void CreateFeedMapping(GoogleAdsClient client, long customerId,
            string feedResourceName,
             Dictionary<DsaPageFeedCriterionField, FeedAttribute> feedAttributes)
        {
            // Get the FeedMappingService.
            FeedMappingServiceClient feedMappingService = client.GetService(
                Services.V9.FeedMappingService);

            FeedMapping feedMapping = new FeedMapping()
            {
                CriterionType = FeedMappingCriterionType.DsaPageFeed,
                Feed = feedResourceName,

                // Map the FeedAttributeId to the fieldId constants.
                AttributeFieldMappings =
                {
                    new AttributeFieldMapping()
                    {
                        FeedAttributeId = feedAttributes[DsaPageFeedCriterionField.PageUrl].Id,
                        DsaPageFeedField = DsaPageFeedCriterionField.PageUrl
                    },

                    new AttributeFieldMapping()
                    {
                        FeedAttributeId = feedAttributes[DsaPageFeedCriterionField.Label].Id,
                        DsaPageFeedField = DsaPageFeedCriterionField.Label
                    }
                }
            };

            // Create the operation.
            FeedMappingOperation operation = new FeedMappingOperation()
            {
                Create = feedMapping
            };

            // Add the FeedMapping.
            MutateFeedMappingsResponse response =
                feedMappingService.MutateFeedMappings(customerId.ToString(), new[] { operation });

            // Display the results.
            foreach (MutateFeedMappingResult result in response.Results)
            {
                Console.WriteLine($"Created feed mapping with resource name" +
                    $" '{result.ResourceName}'");
            }
        }

        /// <summary>
        /// Creates feed items for a given feed.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
        /// <param name="feedResourceName">The feed resource for which feed items are created.
        /// </param>
        /// <param name="feedAttributes">The feed attributes.</param>
        /// <param name="dsaPageUrlLabel">The DSA page URL label.</param>
        private void CreateFeedItems(GoogleAdsClient client, long customerId,
            string feedResourceName,
            Dictionary<DsaPageFeedCriterionField, FeedAttribute> feedAttributes,
            string dsaPageUrlLabel)
        {
            // Get the FeedItemService.
            FeedItemServiceClient feedItemService = client.GetService(
                Services.V9.FeedItemService);

            List<string> urls = new List<string>
            {
                "http://www.example.com/discounts/rental-cars",
                "http://www.example.com/discounts/hotel-deals",
                "http://www.example.com/discounts/flight-deals"
            };

            List<FeedItemOperation> operations = new List<FeedItemOperation>();

            foreach (string url in urls)
            {
                // Create a feed item.
                FeedItem feedItem = new FeedItem()
                {
                    Feed = feedResourceName,
                    AttributeValues =
                    {
                        // Create a url attribute.
                        new FeedItemAttributeValue()
                        {
                            FeedAttributeId = feedAttributes[DsaPageFeedCriterionField.PageUrl].Id,
                            StringValue = url
                        },

                        // Creates a label attribute.
                        new FeedItemAttributeValue()
                        {
                            FeedAttributeId = feedAttributes[DsaPageFeedCriterionField.Label].Id,
                            StringValue = dsaPageUrlLabel
                        }
                    }
                };

                operations.Add(new FeedItemOperation()
                {
                    Create = feedItem
                });
            }

            // Add the feed items.
            MutateFeedItemsResponse response =
                feedItemService.MutateFeedItems(customerId.ToString(), operations);
            // Display the results.
            foreach (MutateFeedItemResult result in response.Results)
            {
                Console.WriteLine($"Created feed items with resource " +
                    $"name '{result.ResourceName}'.");
            }
        }

        /// <summary>
        /// Updates a campaign to set the DSA feed.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
        /// <param name="feedResourceName">The DSA feed resource name</param>
        /// <param name="campaignId">ID of the campaign for which DSA settings are updated.</param>
        private void UpdateCampaignDsaSetting(GoogleAdsClient client, long customerId,
            string feedResourceName, long campaignId)
        {
            // Get the CampaignService.
            CampaignServiceClient campaignService = client.GetService(
                Services.V9.CampaignService);

            DynamicSearchAdsSetting dsaSetting = GetDsaSetting(client, customerId, campaignId);
            dsaSetting.Feeds.Add(feedResourceName);

            // Create the campaign.
            Campaign campaign = new Campaign()
            {
                ResourceName = ResourceNames.Campaign(customerId, campaignId),
                DynamicSearchAdsSetting = dsaSetting
            };

            // Create the operation.
            CampaignOperation operation = new CampaignOperation()
            {
                Update = campaign,
                UpdateMask = FieldMasks.AllSetFieldsOf(campaign)
            };

            // Update the campaign.
            MutateCampaignsResponse response =
                campaignService.MutateCampaigns(customerId.ToString(), new[] { operation });
            // Display the results.
            foreach (MutateCampaignResult mutateCampaignResult in response.Results)
            {
                Console.WriteLine($"Updated campaign with resourceName: " +
                    $"'{mutateCampaignResult.ResourceName}'.");
            }
        }

        /// <summary>
        /// Returns the DSA settings for a campaign. Throws an error if the campaign does not
        /// exist or is not a DSA campaign.
        /// </summary>
        /// <param name="client">The Google Ads client.</param>
        /// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
        /// <param name="campaignId">ID of the campaign for which DSA settings are fetched.</param>
        /// <returns>The DSA settings.</returns>
        private DynamicSearchAdsSetting GetDsaSetting(GoogleAdsClient client, long customerId,
            long campaignId)
        {
            // Get the GoogleAdsService.
            GoogleAdsServiceClient googleAdsService = client.GetService(
                Services.V9.GoogleAdsService);

            // Creates the query.
            // You must request all DSA fields in order to update the DSA settings in the
            // following step.
            string query =
                $@"SELECT
                      campaign.id,
                      campaign.name,
                      campaign.dynamic_search_ads_setting.use_supplied_urls_only
                  FROM
                      campaign
                  WHERE
                      campaign.id = {campaignId}";

            GoogleAdsRow result = googleAdsService.Search(
                customerId.ToString(), query).FirstOrDefault();

            if (result == null)
            {
                throw new Exception("No campaign found with ID: " + campaignId);
            }

            // Gets the DSA settings.
            DynamicSearchAdsSetting dynamicSearchAdsSetting =
                result.Campaign.DynamicSearchAdsSetting;

            // Throws an exception if the campaign is not a DSA campaign.
            if (dynamicSearchAdsSetting == null)
            {
                throw new Exception($"Campaign with ID {campaignId} is not a DSA campaign.");
            }

            return dynamicSearchAdsSetting;
        }

        private void AddDsaTarget(GoogleAdsClient client, long customerId, long adGroupId,
            string dsaPageUrlLabel)
        {
            // Get the AdGroupCriterionService.
            AdGroupCriterionServiceClient adGroupCriterionService = client.GetService(
                Services.V9.AdGroupCriterionService);

            // Create the webpage condition info.
            WebpageConditionInfo webpageConditionInfo = new WebpageConditionInfo()
            {
                Operand = WebpageConditionOperand.CustomLabel,
                Argument = dsaPageUrlLabel,
            };

            // Creates the webpage info.
            WebpageInfo webpageInfo = new WebpageInfo()
            {
                CriterionName = "Test Criterion",
                Conditions = { webpageConditionInfo }
            };

            // Creates the ad group criterion.
            AdGroupCriterion adGroupCriterion = new AdGroupCriterion()
            {
                AdGroup = ResourceNames.AdGroup(customerId, adGroupId),
                Webpage = webpageInfo,
                CpcBidMicros = 1_500_000
            };

            // Create the operation.
            AdGroupCriterionOperation operation = new AdGroupCriterionOperation()
            {
                Create = adGroupCriterion
            };

            // Add the ad group criterion.
            MutateAdGroupCriteriaResponse mutateAdGroupCriteriaResponse =
                adGroupCriterionService.MutateAdGroupCriteria(customerId.ToString(),
                    new[] { operation });

            // Display the results.
            foreach (MutateAdGroupCriterionResult result in mutateAdGroupCriteriaResponse.Results)
            {
                Console.WriteLine($"Created ad group criterion with resource name " +
                    $"'{result.ResourceName}'.");
            }
        }
    }
}

      

PHP

<?php

/**
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://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.
 */

namespace Google\Ads\GoogleAds\Examples\AdvancedOperations;

require __DIR__ . '/../../vendor/autoload.php';

use GetOpt\GetOpt;
use Google\Ads\GoogleAds\Examples\Utils\ArgumentNames;
use Google\Ads\GoogleAds\Examples\Utils\ArgumentParser;
use Google\Ads\GoogleAds\Examples\Utils\Helper;
use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder;
use Google\Ads\GoogleAds\Lib\V9\GoogleAdsClient;
use Google\Ads\GoogleAds\Lib\V9\GoogleAdsClientBuilder;
use Google\Ads\GoogleAds\Lib\V9\GoogleAdsException;
use Google\Ads\GoogleAds\Util\FieldMasks;
use Google\Ads\GoogleAds\Util\V9\ResourceNames;
use Google\Ads\GoogleAds\V9\Common\WebpageConditionInfo;
use Google\Ads\GoogleAds\V9\Common\WebpageInfo;
use Google\Ads\GoogleAds\V9\Enums\DsaPageFeedCriterionFieldEnum\DsaPageFeedCriterionField;
use Google\Ads\GoogleAds\V9\Enums\FeedAttributeTypeEnum\FeedAttributeType;
use Google\Ads\GoogleAds\V9\Enums\FeedMappingCriterionTypeEnum\FeedMappingCriterionType;
use Google\Ads\GoogleAds\V9\Enums\FeedOriginEnum\FeedOrigin;
use Google\Ads\GoogleAds\V9\Enums\WebpageConditionOperandEnum\WebpageConditionOperand;
use Google\Ads\GoogleAds\V9\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V9\Resources\AdGroupCriterion;
use Google\Ads\GoogleAds\V9\Resources\AttributeFieldMapping;
use Google\Ads\GoogleAds\V9\Resources\Campaign;
use Google\Ads\GoogleAds\V9\Resources\Campaign\DynamicSearchAdsSetting;
use Google\Ads\GoogleAds\V9\Resources\Feed;
use Google\Ads\GoogleAds\V9\Resources\FeedAttribute;
use Google\Ads\GoogleAds\V9\Resources\FeedItem;
use Google\Ads\GoogleAds\V9\Resources\FeedItemAttributeValue;
use Google\Ads\GoogleAds\V9\Resources\FeedMapping;
use Google\Ads\GoogleAds\V9\Services\AdGroupCriterionOperation;
use Google\Ads\GoogleAds\V9\Services\CampaignOperation;
use Google\Ads\GoogleAds\V9\Services\FeedItemOperation;
use Google\Ads\GoogleAds\V9\Services\FeedMappingOperation;
use Google\Ads\GoogleAds\V9\Services\FeedOperation;
use Google\ApiCore\ApiException;

/**
 * This code example adds a page feed to specify precisely which URLs to use with your Dynamic
 * Search Ads campaign.
 */
class AddDynamicPageFeed
{
    private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE';
    private const CAMPAIGN_ID = 'INSERT_CAMPAIGN_ID_HERE';
    private const AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE';

    private const PAGE_SIZE = 1000;

    public static function main()
    {
        // Either pass the required parameters for this example on the command line, or insert them
        // into the constants above.
        $options = (new ArgumentParser())->parseCommandArguments([
            ArgumentNames::CUSTOMER_ID => GetOpt::REQUIRED_ARGUMENT,
            ArgumentNames::CAMPAIGN_ID => GetOpt::REQUIRED_ARGUMENT,
            ArgumentNames::AD_GROUP_ID => GetOpt::REQUIRED_ARGUMENT
        ]);

        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct a Google Ads client configured from a properties file and the
        // OAuth2 credentials above.
        $googleAdsClient = (new GoogleAdsClientBuilder())->fromFile()
            ->withOAuth2Credential($oAuth2Credential)
            ->build();

        try {
            self::runExample(
                $googleAdsClient,
                $options[ArgumentNames::CUSTOMER_ID] ?: self::CUSTOMER_ID,
                $options[ArgumentNames::CAMPAIGN_ID] ?: self::CAMPAIGN_ID,
                $options[ArgumentNames::AD_GROUP_ID] ?: self::AD_GROUP_ID
            );
        } catch (GoogleAdsException $googleAdsException) {
            printf(
                "Request with ID '%s' has failed.%sGoogle Ads failure details:%s",
                $googleAdsException->getRequestId(),
                PHP_EOL,
                PHP_EOL
            );
            foreach ($googleAdsException->getGoogleAdsFailure()->getErrors() as $error) {
                /** @var GoogleAdsError $error */
                printf(
                    "\t%s: %s%s",
                    $error->getErrorCode()->getErrorCode(),
                    $error->getMessage(),
                    PHP_EOL
                );
            }
            exit(1);
        } catch (ApiException $apiException) {
            printf(
                "ApiException was thrown with message '%s'.%s",
                $apiException->getMessage(),
                PHP_EOL
            );
            exit(1);
        }
    }

    /**
     * Runs the example.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param int $campaignId the campaign ID
     * @param int $adGroupId the ad group ID
     */
    public static function runExample(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        int $campaignId,
        int $adGroupId
    ) {
        $dsaPageUrlLabel = 'discounts';

        // Creates the page feed details. This code example creates a new feed, but you can
        // fetch and re-use an existing feed.
        $feedDetails = self::createFeed($googleAdsClient, $customerId);
        self::createFeedMapping($googleAdsClient, $customerId, $feedDetails);
        self::createFeedItems($googleAdsClient, $customerId, $feedDetails, $dsaPageUrlLabel);

        // Associates the page feed with the campaign.
        self::updateCampaignDsaSetting($googleAdsClient, $customerId, $feedDetails, $campaignId);

        // Optional: Targets web pages matching the feed's label in the ad group.
        self::addDsaTarget($googleAdsClient, $customerId, $adGroupId, $dsaPageUrlLabel);

        printf("Dynamic page feed setup is complete for campaign ID %d.%s", $campaignId, PHP_EOL);
    }

   /**
    * Creates a feed.
    *
    * @param GoogleAdsClient $googleAdsClient the Google Ads API client
    * @param int $customerId the customer ID in which to create the feed
    * @return array the names and IDs of feed attributes
    */
    private static function createFeed(
        GoogleAdsClient $googleAdsClient,
        int $customerId
    ) {
        // Creates a URL attribute.
        $urlAttribute = new FeedAttribute([
            'type' => FeedAttributeType::URL_LIST,
            'name' => 'Page URL'
        ]);

        // Creates a label attribute.
        $labelAttribute = new FeedAttribute([
            'type' => FeedAttributeType::STRING_LIST,
            'name' => 'Label'
        ]);

        // Creates the feed.
        $feed = new Feed([
            'name' => 'DSA Feed #' . Helper::getPrintableDatetime(),
            'attributes' => [$urlAttribute, $labelAttribute],
            'origin' => FeedOrigin::USER
        ]);

        // Creates a feed operation for creating a feed.
        $feedOperation = new FeedOperation();
        $feedOperation->setCreate($feed);

        // Issues a mutate request to add the feed.
        $feedServiceClient = $googleAdsClient->getFeedServiceClient();
        $feedResponse = $feedServiceClient->mutateFeeds($customerId, [$feedOperation]);

        $feedResourceName = $feedResponse->getResults()[0]->getResourceName();
        printf("Added feed named '%s'.%s", $feedResourceName, PHP_EOL);

        return self::getFeed($googleAdsClient, $customerId, $feedResourceName);
    }

    /**
     * Retrieves details about a feed.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param string $feedResourceName the resource name of the feed
     * @return array the feed details containing the feed's resource name and the feed attributes'
     *     names and values
     */
    private static function getFeed(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        string $feedResourceName
    ) {
        $query = "SELECT feed.attributes FROM feed WHERE feed.resource_name = '$feedResourceName'";

        $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
        $response =
            $googleAdsServiceClient->search($customerId, $query, ['pageSize' => self::PAGE_SIZE]);

        $feedAttributes = $response->getIterator()->current()->getFeed()->getAttributes();
        $feedDetails = ['resource_name' => $feedResourceName];
        foreach ($feedAttributes as $feedAttribute) {
            /** @var FeedAttribute $feedAttribute */
            $feedDetails[$feedAttribute->getName()] = $feedAttribute->getId();
        }
        return $feedDetails;
    }

    /**
     * Creates a feed mapping for a given feed.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param array $feedDetails the names and IDs of feed attributes
     */
    private static function createFeedMapping(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        array $feedDetails
    ) {
        // Maps the feed attribute IDs to the field ID constants.
        $urlFieldMapping = new AttributeFieldMapping([
            'feed_attribute_id' => $feedDetails['Page URL'],
            'dsa_page_feed_field' => DsaPageFeedCriterionField::PAGE_URL
        ]);

        $labelFieldMapping = new AttributeFieldMapping([
            'feed_attribute_id' => $feedDetails['Label'],
            'dsa_page_feed_field' => DsaPageFeedCriterionField::LABEL
        ]);

        // Creates the feed mapping.
        $feedMapping = new FeedMapping([
            'criterion_type' => FeedMappingCriterionType::DSA_PAGE_FEED,
            'feed' => $feedDetails['resource_name'],
            'attribute_field_mappings' => [$urlFieldMapping, $labelFieldMapping]
        ]);

        // Creates the operation.
        $feedMappingOperation = new FeedMappingOperation();
        $feedMappingOperation->setCreate($feedMapping);

        // Issues a mutate request to add the feed mapping.
        $feedMappingServiceClient = $googleAdsClient->getFeedMappingServiceClient();
        $response = $feedMappingServiceClient->mutateFeedMappings(
            $customerId,
            [$feedMappingOperation]
        );

        // Displays the results.
        foreach ($response->getResults() as $result) {
            printf(
                "Created feed mapping with resource name '%s'.%s",
                $result->getResourceName(),
                PHP_EOL
            );
        }
    }

    /**
     * Creates feed items for a given feed.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param array $feedDetails the names and IDs of feed attributes
     * @param string $dsaPageUrlLabel the label for the DSA page URLs
     */
    private static function createFeedItems(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        array $feedDetails,
        string $dsaPageUrlLabel
    ) {
        $urls = [
            'http://www.example.com/discounts/rental-cars',
            'http://www.example.com/discounts/hotel-deals',
            'http://www.example.com/discounts/flight-deals'
        ];

        // Creates a label attribute.
        $labelAttributeValue = new FeedItemAttributeValue([
            'feed_attribute_id' => $feedDetails['Label'],
            'string_values' => [$dsaPageUrlLabel]
        ]);

        // Creates one operation per URL.
        $feedItemOperations = [];
        foreach ($urls as $url) {
            // Creates a url attribute.
            $urlAttributeValue = new FeedItemAttributeValue([
                'feed_attribute_id' => $feedDetails['Page URL'],
                'string_values' => [$url]
            ]);

            // Creates a feed item.
            $feedItem = new FeedItem([
                'feed' => $feedDetails['resource_name'],
                'attribute_values' => [$urlAttributeValue, $labelAttributeValue]
            ]);

            // Creates an operation and adds it to the list of operations.
            $feedItemOperation = new FeedItemOperation();
            $feedItemOperation->setCreate($feedItem);
            $feedItemOperations[] = $feedItemOperation;
        }

        // Adds the feed items.
        $feedItemServiceClient = $googleAdsClient->getFeedItemServiceClient();
        $response = $feedItemServiceClient->mutateFeedItems($customerId, $feedItemOperations);

        // Displays the results.
        foreach ($response->getResults() as $result) {
            printf(
                "Created feed item with resource name '%s'.%s",
                $result->getResourceName(),
                PHP_EOL
            );
        }
    }

    /**
     * Updates a campaign to set the DSA feed.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param array $feedDetails the names and IDs of feed attributes
     * @param int $campaignId the campaign ID of the campaign to update
     */
    private static function updateCampaignDsaSetting(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        array $feedDetails,
        int $campaignId
    ) {
        // Retrieves the existing dynamic search ads settings for the campaign.
        $dsaSetting = self::getDsaSetting(
            $googleAdsClient,
            $customerId,
            $campaignId
        );

        $dsaSetting->setFeeds([$feedDetails['resource_name']]);

        // Creates the campaign object to be updated.
        $campaign = new Campaign([
            'resource_name' => ResourceNames::forCampaign($customerId, $campaignId),
            'dynamic_search_ads_setting' => $dsaSetting
        ]);

        // Creates the update operation and sets the update mask.
        $campaignOperation = new CampaignOperation();
        $campaignOperation->setUpdate($campaign);
        $campaignOperation->setUpdateMask(FieldMasks::allSetFieldsOf($campaign));

        // Updates the campaign.
        $campaignServiceClient = $googleAdsClient->getCampaignServiceClient();
        $response = $campaignServiceClient->mutateCampaigns(
            $customerId,
            [$campaignOperation]
        );

        // Displays the results.
        $campaignResourceName = $response->getResults()[0]->getResourceName();
        printf(
            "Updated campaign with resourceName: '%s'.%s",
            $campaignResourceName,
            PHP_EOL
        );
    }

    /**
     * Returns the DSA settings for a campaign. Throws an error if the campaign does not exist or
     * is not a DSA campaign.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param int $campaignId the campaign ID of the campaign to update
     * @return DynamicSearchAdsSetting the DSA settings for the campaign
     */
    private static function getDsaSetting(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        int $campaignId
    ) {
        // Creates the query.
        $query = "SELECT campaign.id, campaign.name, " .
        "campaign.dynamic_search_ads_setting.use_supplied_urls_only " .
        "FROM campaign where campaign.id = $campaignId";

        $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
        $response = $googleAdsServiceClient->search(
            $customerId,
            $query,
            ['pageSize' => self::PAGE_SIZE, 'returnTotalResultsCount' => true]
        );

        // Throws an exception if a campaign with the provided ID does not exist.
        if ($response->getPage()->getResponseObject()->getTotalResultsCount() === 0) {
            throw new \InvalidArgumentException("No campaign found with ID $campaignId");
        }

        /** @var Campaign $campaign */
        $campaign = $response->getPage()->getResponseObject()->getResults()[0]->getCampaign();
        $dynamicSearchAdsSetting = $campaign->getDynamicSearchAdsSetting();

        // Throws an exception if the campaign is not a DSA campaign.
        if (is_null($dynamicSearchAdsSetting)) {
            throw new \InvalidArgumentException(
                "Campaign with ID $campaignId is not a DSA campaign."
            );
        }

        return $dynamicSearchAdsSetting;
    }

    /**
     * Creates an ad group criterion targeting the DSA label.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param int $adGroupId the ad group ID
     * @param string $dsaPageUrlLabel the label for the DSA page URLs
     */
    public static function addDsaTarget(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        int $adGroupId,
        string $dsaPageUrlLabel
    ) {
        // Creates the webpage condition info.
        $webPageConditionInfo = new WebpageConditionInfo([
            'operand' => WebpageConditionOperand::CUSTOM_LABEL,
            'argument' => $dsaPageUrlLabel
        ]);

        // Creates the webpage info.
        $webPageInfo = new WebpageInfo([
            'criterion_name' => 'Test Criterion',
            'conditions' => [$webPageConditionInfo]
        ]);

        // Creates the ad group criterion.
        $adGroupCriterion = new AdGroupCriterion([
            'ad_group' => ResourceNames::forAdGroup($customerId, $adGroupId),
            'webpage' => $webPageInfo,
            'cpc_bid_micros' => 1500000
        ]);

        // Creates the operation.
        $adGroupCriterionOperation = new AdGroupCriterionOperation();
        $adGroupCriterionOperation->setCreate($adGroupCriterion);

        $adGroupCriterionServiceClient = $googleAdsClient->getAdGroupCriterionServiceClient();
        $response = $adGroupCriterionServiceClient->mutateAdGroupCriteria(
            $customerId,
            [$adGroupCriterionOperation]
        );

        $adGroupCriterionResourceName = $response->getResults()[0]->getResourceName();
        printf(
            "Created ad group criterion with resource name '%s'.%s",
            $adGroupCriterionResourceName,
            PHP_EOL
        );
    }
}

AddDynamicPageFeed::main();

      

Python

#!/usr/bin/env python
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://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 page feed with URLs for a Dynamic Search Ads Campaign.

The page feed specifies precisely which URLs to use with the campaign. To use
a Dynamic Search Ads Campaign run add_dynamic_search_ads_campaign.py. To get
campaigns run basic_operations/get_campaigns.py.
"""


import argparse
import sys
import uuid

from google.api_core import protobuf_helpers

from google.ads.googleads.client import GoogleAdsClient
from google.ads.googleads.errors import GoogleAdsException


# Class to keep track of page feed details.
class FeedDetails(object):
    def __init__(self, resource_name, url_attribute_id, label_attribute_id):
        self.resource_name = resource_name
        self.url_attribute_id = url_attribute_id
        self.label_attribute_id = label_attribute_id


def main(client, customer_id, campaign_id, ad_group_id):
    """The main method that creates all necessary entities for the example.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID str.
        campaign_id: a campaign ID str.
        ad_group_id: an ad group ID str.
    """
    dsa_page_url_label = "discounts"

    # Get the page feed resource name. This code example creates a new feed,
    # but you can fetch and re-use an existing feed.
    feed_resource_name = _create_feed(client, customer_id)

    # We need to look up the attribute name and ID for the feed we just
    # created so that we can give them back to the API for construction of
    # feed mappings in the next function.
    feed_details = _get_feed_details(client, customer_id, feed_resource_name)
    _create_feed_mapping(client, customer_id, feed_details)
    _create_feed_items(client, customer_id, feed_details, dsa_page_url_label)

    # Associate the page feed with the campaign.
    _update_campaign_dsa_setting(client, customer_id, campaign_id, feed_details)
    ad_group_service = client.get_service("AdGroupService")
    ad_group_resource_name = ad_group_service.ad_group_path(
        customer_id, ad_group_id
    )

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


def _create_feed(client, customer_id):
    """Creates a page feed with URLs

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID str.

    Returns:
        A FeedDetails instance with information about the newly created feed.
    """
    # Retrieve a new feed operation object.
    feed_operation = client.get_type("FeedOperation")
    # Create a new feed.
    feed = feed_operation.create
    feed.name = f"DSA Feed #{uuid.uuid4()}"
    feed.origin = client.enums.FeedOriginEnum.USER

    feed_attribute_type_enum = client.enums.FeedAttributeTypeEnum

    # Create the feed's attributes.
    feed_attribute_url = client.get_type("FeedAttribute")
    feed_attribute_url.type_ = feed_attribute_type_enum.URL_LIST
    feed_attribute_url.name = "Page URL"

    feed_attribute_label = client.get_type("FeedAttribute")
    feed_attribute_label.type_ = feed_attribute_type_enum.STRING_LIST
    feed_attribute_label.name = "Label"

    feed.attributes.extend([feed_attribute_url, feed_attribute_label])

    # Retrieve the feed service.
    feed_service = client.get_service("FeedService")
    # Send the feed operation and add the feed.
    response = feed_service.mutate_feeds(
        customer_id=customer_id, operations=[feed_operation]
    )

    return response.results[0].resource_name


def _get_feed_details(client, customer_id, resource_name):
    """Makes a search request to retrieve the attributes of a single feed.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID str.
        resource_name: the str resource_name of a feed.

    Returns:
        A FeedDetails instance with information about the feed that was
        retrieved in the search request.
    """
    query = f"""
        SELECT
            feed.attributes
        FROM
            feed
        WHERE
            feed.resource_name = "{resource_name}"
        LIMIT 1
    """

    ga_service = client.get_service("GoogleAdsService")
    search_request = client.get_type("SearchGoogleAdsRequest")
    search_request.customer_id = customer_id
    search_request.query = query

    response = ga_service.search(request=search_request)

    # Maps specific fields in each row in the response to a dict. This would
    # overwrite the same fields in the dict for each row, but we know we'll
    # only one row will be returned.
    for row in response:
        attribute_lookup = {
            attribute.name: attribute.id for attribute in row.feed.attributes
        }

    return FeedDetails(
        resource_name, attribute_lookup["Page URL"], attribute_lookup["Label"]
    )


def _create_feed_mapping(client, customer_id, feed_details):
    """Creates feed mapping using the given feed details

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID str.
        feed_details: a FeedDetails instance with feed attribute information
    """
    # Retrieve a new feed mapping operation object.
    feed_mapping_operation = client.get_type("FeedMappingOperation")
    # Create a new feed mapping.
    feed_mapping = feed_mapping_operation.create
    feed_mapping.criterion_type = (
        client.enums.FeedMappingCriterionTypeEnum.DSA_PAGE_FEED
    )
    feed_mapping.feed = feed_details.resource_name
    dsa_page_feed_field_enum = client.enums.DsaPageFeedCriterionFieldEnum

    url_field_mapping = client.get_type("AttributeFieldMapping")
    url_field_mapping.feed_attribute_id = feed_details.url_attribute_id
    url_field_mapping.dsa_page_feed_field = dsa_page_feed_field_enum.PAGE_URL
    feed_mapping.attribute_field_mappings.append(url_field_mapping)

    label_field_mapping = client.get_type("AttributeFieldMapping")
    label_field_mapping.feed_attribute_id = feed_details.label_attribute_id
    label_field_mapping.dsa_page_feed_field = dsa_page_feed_field_enum.LABEL
    feed_mapping.attribute_field_mappings.append(label_field_mapping)

    # Retrieve the feed mapping service.
    feed_mapping_service = client.get_service("FeedMappingService")
    # Submit the feed mapping operation and add the feed mapping.
    response = feed_mapping_service.mutate_feed_mappings(
        customer_id=customer_id, operations=[feed_mapping_operation]
    )
    resource_name = response.results[0].resource_name

    # Display the results.
    print(f"Feed mapping created with resource_name: '{resource_name}'")


def _create_feed_items(client, customer_id, feed_details, label):
    """Creates feed items with the given feed_details and label

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID str.
        feed_details: a FeedDetails instance with feed attribute information
        label: a Dynamic Search Ad URL label str.
    """
    # See https://support.google.com/google-ads/answer/7166527 for page feed URL
    # recommendations and rules.
    urls = [
        "http://www.example.com/discounts/rental-cars",
        "http://www.example.com/discounts/hotel-deals",
        "http://www.example.com/discounts/flight-deals",
    ]

    def map_feed_urls(url):
        feed_item_operation = client.get_type("FeedItemOperation")
        feed_item = feed_item_operation.create
        feed_item.feed = feed_details.resource_name

        url_attribute_value = client.get_type("FeedItemAttributeValue")
        url_attribute_value.feed_attribute_id = feed_details.url_attribute_id
        label_attribute_value = client.get_type("FeedItemAttributeValue")
        label_attribute_value.feed_attribute_id = (
            feed_details.label_attribute_id
        )
        feed_item.attribute_values.extend(
            [url_attribute_value, label_attribute_value]
        )
        url_attribute_value.string_values.append(url)
        label_attribute_value.string_values.append(label)

        return feed_item_operation

    # Create a new feed item operation for each of the URLs in the url list.
    feed_item_operations = list(map(map_feed_urls, urls))

    # Retrieve the feed item service.
    feed_item_service = client.get_service("FeedItemService")
    # Submit the feed item operations and add the feed items.
    response = feed_item_service.mutate_feed_items(
        customer_id=customer_id, operations=feed_item_operations
    )

    # Display the results.
    for feed_item in response.results:
        print(
            f"Created feed item with resource_name: '{feed_item.resource_name}'"
        )


def _update_campaign_dsa_setting(
    client, customer_id, campaign_id, feed_details
):
    """Updates the given campaign with the given feed details.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID str.
        campaign_id: a campaign ID str;
        feed_details: a FeedDetails instance with feed attribute information.
    """
    query = f"""
        SELECT
            campaign.id,
            campaign.name,
            campaign.dynamic_search_ads_setting.use_supplied_urls_only
        FROM
            campaign
        WHERE
            campaign.id = {campaign_id}
        LIMIT 1
    """

    ga_service = client.get_service("GoogleAdsService")
    search_request = client.get_type("SearchGoogleAdsRequest")
    search_request.customer_id = customer_id
    search_request.query = query

    results = ga_service.search(request=search_request)

    campaign = None
    for row in results:
        campaign = row.campaign

    if not campaign:
        raise ValueError(f"Campaign with id #{campaign_id} not found")

    # Retrieve a new campaign operation
    campaign_operation = client.get_type("CampaignOperation")
    # Copy the retrieved campaign onto the new campaign operation.
    client.copy_from(campaign_operation.update, campaign)
    updated_campaign = campaign_operation.update
    # Use a page feed to specify precisely which URLs to use with your Dynamic
    # Search ads.
    updated_campaign.dynamic_search_ads_setting.feeds.append(
        feed_details.resource_name
    )
    client.copy_from(
        campaign_operation.update_mask,
        protobuf_helpers.field_mask(campaign._pb, updated_campaign._pb),
    )

    # Retrieve the campaign service.
    campaign_service = client.get_service("CampaignService")
    # Submit the campaign operation and update the campaign.
    response = campaign_service.mutate_campaigns(
        customer_id=customer_id, operations=[campaign_operation]
    )
    resource_name = response.results[0].resource_name

    # Display the results.
    print(f"Updated campaign #{resource_name}")


def _add_dsa_targeting(client, customer_id, ad_group_resource_name, label):
    """Adds Dynamic Search Ad targeting criteria to the given ad group.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID str.
        ad_group_resource_name: a resource_name str for an Ad Group.
        label: a Dynamic Search Ad URL label str.
    """
    # Retrieve a new ad group criterion operation object.
    ad_group_criterion_operation = client.get_type("AdGroupCriterionOperation")
    # Create a new ad group criterion.
    ad_group_criterion = ad_group_criterion_operation.create
    ad_group_criterion.ad_group = ad_group_resource_name
    # Set the custom bid for this criterion.
    ad_group_criterion.cpc_bid_micros = 1500000
    ad_group_criterion.webpage.criterion_name = "Test criterion"
    # Add a condition for label=specified_label_name
    webpage_criterion_info = client.get_type(
        "WebpageConditionInfo"
    )  # ad_group_criterion.webpage.conditions.add()
    webpage_criterion_info.argument = label
    webpage_criterion_info.operand = (
        client.enums.WebpageConditionOperandEnum.CUSTOM_LABEL
    )
    ad_group_criterion.webpage.conditions.append(webpage_criterion_info)

    # Retrieve the ad group criterion service.
    ad_group_criterion_service = client.get_service("AdGroupCriterionService")
    response = ad_group_criterion_service.mutate_ad_group_criteria(
        customer_id=customer_id, operations=[ad_group_criterion_operation]
    )
    resource_name = response.results[0].resource_name

    # Display the results.
    print(f"Created ad group criterion with resource_name: '{resource_name}'")


if __name__ == "__main__":
    # GoogleAdsClient will read the google-ads.yaml configuration file in the
    # home directory if none is specified.
    googleads_client = GoogleAdsClient.load_from_storage(version="v9")

    parser = argparse.ArgumentParser(
        description=(
            "Adds a page feed with URLs for a Dynamic Search Ads Campaign."
        )
    )
    # The following argument(s) should be provided to run the example.
    parser.add_argument(
        "-c",
        "--customer_id",
        type=str,
        required=True,
        help="The Google Ads customer ID.",
    )
    parser.add_argument(
        "-i", "--campaign_id", type=str, required=True, help="The campaign ID."
    )
    parser.add_argument(
        "-a", "--ad_group_id", type=str, required=True, help="The ad group ID."
    )
    args = parser.parse_args()

    try:
        main(
            googleads_client,
            args.customer_id,
            args.campaign_id,
            args.ad_group_id,
        )
    except GoogleAdsException as ex:
        print(
            f'Request with ID "{ex.request_id}" failed with status '
            f'"{ex.error.code().name}" and includes the following errors:'
        )
        for error in ex.failure.errors:
            print(f'\tError with message "{error.message}".')
            if error.location:
                for field_path_element in error.location.field_path_elements:
                    print(f"\t\tOn field: {field_path_element.field_name}")
        sys.exit(1)

      

Ruby

#!/usr/bin/env ruby
# Encoding: utf-8
#
# Copyright:: Copyright 2019, Google Inc. All Rights Reserved.
#
# License:: 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 use a Dynamic Search Ads campaign, run
# add_dynamic_search_ads_campaign.rb. To get campaigns, run get_campaigns.rb.

require 'optparse'
require 'google/ads/google_ads'

FeedDetails = Struct.new(
  :resource_name,
  :url_attribute_id,
  :label_attribute_id
)

def add_dynamic_page_feed(customer_id, campaign_id, ad_group_id)
  client = Google::Ads::GoogleAds::GoogleAdsClient.new

  dsa_page_url_label = "discounts"

  feed_details = create_feed(client, customer_id)
  create_feed_mapping(client, customer_id, feed_details)
  create_feed_items(client, customer_id, feed_details, dsa_page_url_label)

  update_campaign_dsa_setting(client, customer_id, campaign_id, feed_details)
  ad_group_resource_name = client.path.ad_group(customer_id, ad_group_id)

  add_dsa_targeting(
    client,
    customer_id,
    ad_group_resource_name,
    dsa_page_url_label
  )
end

def create_feed(client, customer_id)
  feed_attribute_url = client.resource.feed_attribute do |a|
    a.type = :URL_LIST
    a.name = "Page URL"
  end

  feed_attribute_label = client.resource.feed_attribute do |a|
    a.type = :STRING_LIST
    a.name = "Label"
  end

  feed = client.resource.feed do |f|
    f.name = "DSA Feed #{(Time.now.to_f * 1000).to_i}"
    f.attributes << feed_attribute_url
    f.attributes << feed_attribute_label
    f.origin = :USER
  end

  operation = client.operation.create_resource.feed(feed)

  response = client.service.feed.mutate_feeds(
    customer_id: customer_id,
    operations: [operation],
  )
  feed_id = response.results.first.resource_name

  # We need to look up the attribute name and IDs for the feed we just created
  # so that we can give them back to the API for construction of feed mappings
  # in the next function.
  query = <<~EOD
  SELECT
    feed.attributes
  FROM
    feed
  WHERE
    feed.resource_name = '#{feed_id}'
  LIMIT
    100
  EOD
  response = client.service.google_ads.search(
    customer_id: customer_id,
    query: query,
  )

  # Hash.[] takes an aray of pairs and turns them in to a hash with keys
  # equal to the first item, and values equal to the second item, we get two
  # items back one with ["Page URL", id_for_url] and another with
  # ["Label", id_for_label], so this expression gives us a convenient way to
  # look them back up
  attribute_lookup = Hash[
    response.first.feed.attributes.map { |attribute|
      [attribute.name, attribute.id]
    }
  ]

  # Finally, construct a FeedDetails object so that we have a nice small
  # wrapper around the details we care about for the next phase.
  FeedDetails.new(
    feed_id,
    attribute_lookup.fetch("Page URL"),
    attribute_lookup.fetch("Label"),
  )
end

def create_feed_mapping(client, customer_id, feed_details)
  url_field_mapping = client.resource.attribute_field_mapping do |mapping|
    mapping.feed_attribute_id = feed_details.url_attribute_id
    mapping.dsa_page_feed_field = :PAGE_URL
  end

  label_field_mapping = client.resource.attribute_field_mapping do |mapping|
    mapping.feed_attribute_id = feed_details.label_attribute_id
    mapping.dsa_page_feed_field = :LABEL
  end

  feed_mapping = client.resource.feed_mapping do |mapping|
    mapping.criterion_type = :DSA_PAGE_FEED
    mapping.feed = feed_details.resource_name
    mapping.attribute_field_mappings << url_field_mapping
    mapping.attribute_field_mappings << label_field_mapping
  end

  operation = client.operation.create_resource.feed_mapping(feed_mapping)

  response = client.service.feed_mapping.mutate_feed_mappings(
    customer_id: customer_id,
    operations: [operation],
  )
  puts "Feed mapping created with id #{response.results.first.resource_name}"
end

def create_feed_items(client, customer_id, feed_details, label)
  urls = [
    "http://www.example.com/discounts/rental-cars",
    "http://www.example.com/discounts/hotel-deals",
    "http://www.example.com/discounts/flight-deals",
  ]

  feed_items = urls.map { |url|
    client.resource.feed_item do |fi|
      fi.feed = feed_details.resource_name
      fi.attribute_values << client.resource.feed_item_attribute_value do |val|
        val.feed_attribute_id = feed_details.url_attribute_id
        val.string_values << url
      end

      fi.attribute_values << client.resource.feed_item_attribute_value do |val|
        val.feed_attribute_id = feed_details.label_attribute_id
        val.string_values << label
      end
    end
  }

  ops = feed_items.map { |fi|
    client.operation.create_resource.feed_item(fi)
  }

  response = client.service.feed_item.mutate_feed_items(
    customer_id: customer_id,
    operations: ops,
  )

  response.results.each do |result|
    puts "Created feed item with id #{result.resource_name}"
  end
end

def update_campaign_dsa_setting(client, customer_id, campaign_id, feed_details)
  query = <<~EOD
    SELECT
      campaign.id,
      campaign.name,
      campaign.dynamic_search_ads_setting.feeds
    FROM
      campaign
    WHERE
      campaign.id = #{campaign_id}
    LIMIT 1000
  EOD
  response = client.service.google_ads.search(
    customer_id: customer_id,
    query: query,
  )

  result = response.first
  if result.nil?
    raise "Campaign with id #{id} not found"
  end

  campaign = result.campaign

  op = client.operation.update_resource.campaign(campaign) do
    campaign.dynamic_search_ads_setting.feeds << feed_details.resource_name
  end

  response = client.service.campaign.mutate_campaigns(
    customer_id: customer_id,
    operations: [op],
  )
  puts "Updated campaign #{response.results.first.resource_name}"
end

def add_dsa_targeting(client, customer_id, ad_group_resource_name, label)
  webpage_condition_info = client.resource.webpage_condition_info do |wci|
    wci.operand = :CUSTOM_LABEL
    wci.argument = label
  end

  webpage_criterion = client.resource.webpage_info do |wi|
    wi.criterion_name = "Test criterion"
    wi.conditions << webpage_condition_info
  end

  ad_group_criterion = client.resource.ad_group_criterion do |agc|
    agc.ad_group = ad_group_resource_name
    agc.webpage = webpage_criterion
    agc.cpc_bid_micros = 1_500_000
  end

  op = client.operation.create_resource.ad_group_criterion(ad_group_criterion)

  response = client.service.ad_group_criterion.mutate_ad_group_criteria(
    customer_id: customer_id,
    operations: [op],
  )

  puts "Created ad group criterion with id: #{response.results.first.resource_name}"
end

if __FILE__ == $0
  options = {}
  # The following parameter(s) should be provided to run the example. You can
  # either specify these by changing the INSERT_XXX_ID_HERE values below, or on
  # the command line.
  #
  # Parameters passed on the command line will override any parameters set in
  # code.
  #
  # Running the example with -h will print the command line usage.
  options[:customer_id] = 'INSERT_CUSTOMER_ID_HERE'
  options[:campaign_id] = 'INSERT_CAMPAIGN_ID_HERE'
  options[:ad_group_id] = 'INSERT_AD_GROUP_ID_HERE'

  OptionParser.new do |opts|
    opts.banner = sprintf('Usage: %s [options]', File.basename(__FILE__))

    opts.separator ''
    opts.separator 'Options:'

    opts.on('-C', '--customer-id CUSTOMER-ID', String, 'Customer ID') do |v|
      options[:customer_id] = v
    end

    opts.on('-c', '--campaign-id CAMPAIGN-ID', String, 'Campaign ID') do |v|
      options[:campaign_id] = v
    end

    opts.on('-A', '--ad-group-id AD-GROUP-ID', String, 'Ad Group ID') do |v|
      options[:ad_group_id] = v
    end

    opts.separator ''
    opts.separator 'Help:'

    opts.on_tail('-h', '--help', 'Show this message') do
      puts opts
      exit
    end
  end.parse!

  begin
    add_dynamic_page_feed(
      options.fetch(:customer_id).tr("-", ""),
      options.fetch(:campaign_id),
      options.fetch(:ad_group_id),
    )
  rescue Google::Ads::GoogleAds::Errors::GoogleAdsError => e
    e.failure.errors.each do |error|
      STDERR.printf("Error with message: %s\n", error.message)
      if error.location
        error.location.field_path_elements.each do |field_path_element|
          STDERR.printf("\tOn field: %s\n", field_path_element.field_name)
        end
      end
      error.error_code.to_h.each do |k, v|
        next if v == :UNSPECIFIED
        STDERR.printf("\tType: %s\n\tCode: %s\n", k, v)
      end
    end
    raise
  end
end

      

Perl

#!/usr/bin/perl -w
#
# Copyright 2019, Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This example adds a page feed to specify precisely which URLs to use with your
# dynamic search ads campaign.

use strict;
use warnings;
use utf8;

use FindBin qw($Bin);
use lib "$Bin/../../lib";
use Google::Ads::GoogleAds::Client;
use Google::Ads::GoogleAds::Utils::GoogleAdsHelper;
use Google::Ads::GoogleAds::Utils::FieldMasks;
use Google::Ads::GoogleAds::V9::Resources::FeedAttribute;
use Google::Ads::GoogleAds::V9::Resources::Feed;
use Google::Ads::GoogleAds::V9::Resources::AttributeFieldMapping;
use Google::Ads::GoogleAds::V9::Resources::FeedMapping;
use Google::Ads::GoogleAds::V9::Resources::FeedItemAttributeValue;
use Google::Ads::GoogleAds::V9::Resources::FeedItem;
use Google::Ads::GoogleAds::V9::Resources::Campaign;
use Google::Ads::GoogleAds::V9::Resources::AdGroupCriterion;
use Google::Ads::GoogleAds::V9::Common::WebpageConditionInfo;
use Google::Ads::GoogleAds::V9::Common::WebpageInfo;
use Google::Ads::GoogleAds::V9::Enums::FeedAttributeTypeEnum
  qw(URL_LIST STRING_LIST);
use Google::Ads::GoogleAds::V9::Enums::FeedOriginEnum qw(USER);
use Google::Ads::GoogleAds::V9::Enums::DsaPageFeedCriterionFieldEnum
  qw(PAGE_URL LABEL);
use Google::Ads::GoogleAds::V9::Enums::FeedMappingCriterionTypeEnum
  qw(DSA_PAGE_FEED);
use Google::Ads::GoogleAds::V9::Enums::WebpageConditionOperandEnum
  qw(CUSTOM_LABEL);
use Google::Ads::GoogleAds::V9::Services::FeedService::FeedOperation;
use
  Google::Ads::GoogleAds::V9::Services::FeedMappingService::FeedMappingOperation;
use Google::Ads::GoogleAds::V9::Services::FeedItemService::FeedItemOperation;
use Google::Ads::GoogleAds::V9::Services::CampaignService::CampaignOperation;
use
  Google::Ads::GoogleAds::V9::Services::AdGroupCriterionService::AdGroupCriterionOperation;
use
  Google::Ads::GoogleAds::V9::Services::GoogleAdsService::SearchGoogleAdsRequest;
use Google::Ads::GoogleAds::V9::Utils::ResourceNames;

use Getopt::Long qw(:config auto_help);
use Pod::Usage;
use Cwd qw(abs_path);
use Data::Uniqid qw(uniqid);

use constant PAGE_SIZE => 1000;

# The following parameter(s) should be provided to run the example. You can
# either specify these by changing the INSERT_XXX_ID_HERE values below, or on
# the command line.
#
# Parameters passed on the command line will override any parameters set in
# code.
#
# Running the example with -h will print the command line usage.
my $customer_id = "INSERT_CUSTOMER_ID_HERE";
my $campaign_id = "INSERT_CAMPAIGN_ID_HERE";
my $ad_group_id = "INSERT_AD_GROUP_ID_HERE";

sub add_dynamic_page_feed {
  my ($api_client, $customer_id, $campaign_id, $ad_group_id) = @_;

  my $dsa_page_url_label = "discounts";

  # Create the page feed details. This example creates a new feed, but you can
  # fetch and re-use an existing feed.
  my $feed_details = create_feed($api_client, $customer_id);
  create_feed_mapping($api_client, $customer_id, $feed_details);
  create_feed_items($api_client, $customer_id, $feed_details,
    $dsa_page_url_label);

  # Associate the page feed with the campaign.
  update_campaign_dsa_setting($api_client, $customer_id, $feed_details,
    $campaign_id);

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

  print "Dynamic page feed setup is complete for campaign ID $campaign_id.\n";

  return 1;
}

# Creates a feed.
sub create_feed {
  my ($api_client, $customer_id) = @_;

  # Create a URL attribute.
  my $url_attribute = Google::Ads::GoogleAds::V9::Resources::FeedAttribute->new(
    {
      type => URL_LIST,
      name => "Page URL"
    });

  # Create a label attribute.
  my $label_attribute =
    Google::Ads::GoogleAds::V9::Resources::FeedAttribute->new({
      type => STRING_LIST,
      name => "Label"
    });

  # Create the feed.
  my $feed = Google::Ads::GoogleAds::V9::Resources::Feed->new({
    name       => "DSA Feed #" . uniqid(),
    attributes => [$url_attribute, $label_attribute],
    origin     => USER
  });

  # Create a feed operation for creating a feed.
  my $feed_operation =
    Google::Ads::GoogleAds::V9::Services::FeedService::FeedOperation->new(
    {create => $feed});

  # Add the feed.
  my $feeds_response = $api_client->FeedService()->mutate({
      customerId => $customer_id,
      operations => [$feed_operation]});

  my $feed_resource_name = $feeds_response->{results}[0]{resourceName};

  printf "Created feed with resource name: '%s'.\n", $feed_resource_name;

  return get_feed($api_client, $customer_id, $feed_resource_name);
}

# Retrieves details about a feed.
sub get_feed {
  my ($api_client, $customer_id, $feed_resource_name) = @_;

  my $search_query =
    sprintf "SELECT feed.attributes FROM feed WHERE feed.resource_name = '%s'",
    $feed_resource_name;

  my $search_response = $api_client->GoogleAdsService()->search({
    customerId => $customer_id,
    query      => $search_query,
    pageSize   => PAGE_SIZE
  });

  my $feed_attributes = $search_response->{results}[0]{feed}{attributes};
  my $feed_details    = {resourceName => $feed_resource_name};
  foreach my $feed_attribute (@$feed_attributes) {
    $feed_details->{$feed_attribute->{name}} = $feed_attribute->{id};
  }

  return $feed_details;
}

# Creates a feed mapping for a given feed.
sub create_feed_mapping {
  my ($api_client, $customer_id, $feed_details) = @_;

  # Map the feed attribute IDs to the field ID constants.
  my $url_field_mapping =
    Google::Ads::GoogleAds::V9::Resources::AttributeFieldMapping->new({
      feedAttributeId  => $feed_details->{'Page URL'},
      dsaPageFeedField => PAGE_URL
    });

  my $label_field_mapping =
    Google::Ads::GoogleAds::V9::Resources::AttributeFieldMapping->new({
      feedAttributeId  => $feed_details->{Label},
      dsaPageFeedField => LABEL
    });

  # Create the feed mapping.
  my $feed_mapping = Google::Ads::GoogleAds::V9::Resources::FeedMapping->new({
      criterionType          => DSA_PAGE_FEED,
      feed                   => $feed_details->{resourceName},
      attributeFieldMappings => [$url_field_mapping, $label_field_mapping]});

  # Create the feed mapping operation.
  my $feed_mapping_operation =
    Google::Ads::GoogleAds::V9::Services::FeedMappingService::FeedMappingOperation
    ->new({
      create => $feed_mapping
    });

  my $feed_mappings_response = $api_client->FeedMappingService()->mutate({
      customerId => $customer_id,
      operations => [$feed_mapping_operation]});

  printf "Created feed mapping with resource name: '%s'.\n",
    $feed_mappings_response->{results}[0]{resourceName};
}

# Creates feed items for a given feed.
sub create_feed_items {
  my ($api_client, $customer_id, $feed_details, $dsa_page_url_label) = @_;

  my $urls = [
    "http://www.example.com/discounts/rental-cars",
    "http://www.example.com/discounts/hotel-deals",
    "http://www.example.com/discounts/flight-deals"
  ];

  # Create a label attribute.
  my $label_attribute_value =
    Google::Ads::GoogleAds::V9::Resources::FeedItemAttributeValue->new({
      feedAttributeId => $feed_details->{Label},
      stringValue     => $dsa_page_url_label
    });

  # Create one operation per URL.
  my $feed_item_operations = [];
  foreach my $url (@$urls) {
    # Create a url attribute.
    my $url_attribute_value =
      Google::Ads::GoogleAds::V9::Resources::FeedItemAttributeValue->new({
        feedAttributeId => $feed_details->{'Page URL'},
        stringValue     => $url
      });

    # Create a feed item.
    my $feed_item = Google::Ads::GoogleAds::V9::Resources::FeedItem->new({
        feed            => $feed_details->{resourceName},
        attributeValues => [$url_attribute_value, $label_attribute_value]});

    push @$feed_item_operations,
      Google::Ads::GoogleAds::V9::Services::FeedItemService::FeedItemOperation
      ->new({
        create => $feed_item
      });
  }

  # Add the feed items.
  my $feed_items_response = $api_client->FeedItemService()->mutate({
    customerId => $customer_id,
    operations => $feed_item_operations
  });

  foreach my $feed_item_result (@{$feed_items_response->{results}}) {
    printf "Created feed item with resource name: '%s'.\n",
      $feed_item_result->{resourceName};
  }
}

# Updates a campaign to set the DSA feed.
sub update_campaign_dsa_setting {
  my ($api_client, $customer_id, $feed_details, $campaign_id) = @_;

  # Retrieve the existing dynamic search ads settings for the campaign.
  my $dsa_setting = get_dsa_setting($api_client, $customer_id, $campaign_id);

  my $feed_resource_name = $feed_details->{resourceName};
  $dsa_setting->{feeds} = [$feed_resource_name];

  # Create the campaign object to be updated.
  my $campaign = Google::Ads::GoogleAds::V9::Resources::Campaign->new({
      resourceName =>
        Google::Ads::GoogleAds::V9::Utils::ResourceNames::campaign(
        $customer_id, $campaign_id
        ),
      dynamicSearchAdsSetting => $dsa_setting
    });

  # Create the update operation and set the update mask.
  my $campaign_operation =
    Google::Ads::GoogleAds::V9::Services::CampaignService::CampaignOperation->
    new({
      update     => $campaign,
      updateMask =>
        Google::Ads::GoogleAds::Utils::FieldMasks::all_set_fields_of($campaign)}
    );

  # Update the campaign.
  my $campaigns_response = $api_client->CampaignService()->mutate({
      customerId => $customer_id,
      operations => [$campaign_operation]});

  printf "Updated campaign with resource name: '%s'.\n",
    $campaigns_response->{results}[0]{resourceName};
}

# Returns the DSA settings for a campaign. Dies if the campaign does not
# exist or is not a DSA campaign.
sub get_dsa_setting {
  my ($api_client, $customer_id, $campaign_id) = @_;

  # Create the query.
  # You must request all DSA fields in order to update the DSA settings in the
  # following step.
  my $search_query =
    "SELECT campaign.id, campaign.name, " .
    "campaign.dynamic_search_ads_setting.use_supplied_urls_only " .
    "FROM campaign where campaign.id = $campaign_id";

  my $search_response = $api_client->GoogleAdsService()->search({
    customerId => $customer_id,
    query      => $search_query,
    pageSize   => PAGE_SIZE
  });

  # Die if a campaign with the provided ID does not exist.
  die "No campaign found with ID $campaign_id.\n"
    if scalar @{$search_response->{results}} == 0;

  my $dynamic_search_ads_setting =
    $search_response->{results}[0]{campaign}{dynamicSearchAdsSetting};

  # Die if the campaign is not a DSA campaign.
  die "Campaign with ID $campaign_id is not a DSA campaign.\n"
    if not $dynamic_search_ads_setting;

  return $dynamic_search_ads_setting;
}

# Creates an ad group criterion targeting the DSA label.
sub add_dsa_target {
  my ($api_client, $customer_id, $ad_group_id, $dsa_page_url_label) = @_;

  my $ad_group_resource_name =
    Google::Ads::GoogleAds::V9::Utils::ResourceNames::ad_group($customer_id,
    $ad_group_id);

  # Create the webpage condition info.
  my $web_page_condition_info =
    Google::Ads::GoogleAds::V9::Common::WebpageConditionInfo->new({
      operand  => CUSTOM_LABEL,
      argument => $dsa_page_url_label
    });

  # Create the webpage info.
  my $web_page_info = Google::Ads::GoogleAds::V9::Common::WebpageInfo->new({
      criterionName => "Test Criterion",
      conditions    => [$web_page_condition_info]});

  # Create the ad group criterion.
  my $ad_group_criterion =
    Google::Ads::GoogleAds::V9::Resources::AdGroupCriterion->new({
      adGroup      => $ad_group_resource_name,
      webpage      => $web_page_info,
      cpcBidMicros => 1500000
    });

  # Create the operation.
  my $ad_group_criterion_operation =
    Google::Ads::GoogleAds::V9::Services::AdGroupCriterionService::AdGroupCriterionOperation
    ->new({
      create => $ad_group_criterion
    });

  my $ad_group_criteria_response =
    $api_client->AdGroupCriterionService()->mutate({
      customerId => $customer_id,
      operations => [$ad_group_criterion_operation]});

  printf "Created ad group criterion with resource name: '%s'.\n",
    $ad_group_criteria_response->{results}[0]{resourceName};
}

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

# Get Google Ads Client, credentials will be read from ~/googleads.properties.
my $api_client = Google::Ads::GoogleAds::Client->new();

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

# Parameters passed on the command line will override any parameters set in code.
GetOptions(
  "customer_id=s" => \$customer_id,
  "campaign_id=i" => \$campaign_id,
  "ad_group_id=i" => \$ad_group_id
);

# Print the help message if the parameters are not initialized in the code nor
# in the command line.
pod2usage(2) if not check_params($customer_id, $campaign_id, $ad_group_id);

# Call the example.
add_dynamic_page_feed($api_client, $customer_id =~ s/-//gr,
  $campaign_id, $ad_group_id);

=pod

=head1 NAME

add_dynamic_page_feed

=head1 DESCRIPTION

This example adds a page feed to specify precisely which URLs to use with your
dynamic search ads campaign.

=head1 SYNOPSIS

add_dynamic_page_feed.pl [options]

    -help                       Show the help message.
    -customer_id                The Google Ads customer ID.
    -campaign_id                The campaign ID.
    -ad_group_id                The ad group ID.

=cut