Dodaj moduł dostosowania reklam

Java

// 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.

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

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

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.v11.common.AdTextAsset;
import com.google.ads.googleads.v11.common.CustomizerValue;
import com.google.ads.googleads.v11.common.ResponsiveSearchAdInfo;
import com.google.ads.googleads.v11.enums.CustomizerAttributeTypeEnum.CustomizerAttributeType;
import com.google.ads.googleads.v11.enums.ServedAssetFieldTypeEnum.ServedAssetFieldType;
import com.google.ads.googleads.v11.errors.GoogleAdsError;
import com.google.ads.googleads.v11.errors.GoogleAdsException;
import com.google.ads.googleads.v11.resources.Ad;
import com.google.ads.googleads.v11.resources.AdGroupAd;
import com.google.ads.googleads.v11.resources.AdGroupCustomizer;
import com.google.ads.googleads.v11.resources.CustomizerAttribute;
import com.google.ads.googleads.v11.services.AdGroupAdOperation;
import com.google.ads.googleads.v11.services.AdGroupAdServiceClient;
import com.google.ads.googleads.v11.services.AdGroupCustomizerOperation;
import com.google.ads.googleads.v11.services.AdGroupCustomizerServiceClient;
import com.google.ads.googleads.v11.services.CustomizerAttributeOperation;
import com.google.ads.googleads.v11.services.CustomizerAttributeServiceClient;
import com.google.ads.googleads.v11.services.MutateAdGroupAdResult;
import com.google.ads.googleads.v11.services.MutateAdGroupAdsResponse;
import com.google.ads.googleads.v11.services.MutateAdGroupCustomizerResult;
import com.google.ads.googleads.v11.services.MutateAdGroupCustomizersResponse;
import com.google.ads.googleads.v11.services.MutateCustomizerAttributesResponse;
import com.google.ads.googleads.v11.utils.ResourceNames;
import com.google.common.collect.ImmutableList;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * This code example adds two ad customizer attributes and associates them with the ad group. Then
 * it adds an ad that uses the ad customizer attributes to populate dynamic data.
 */
public class AddAdCustomizer {

  // We're doing only searches by resource_name in this example, we can set page size = 1.
  private static class AddAdCustomizerParams extends CodeSampleParams {

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

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

  public static void main(String[] args) throws IOException {
    AddAdCustomizerParams params = new AddAdCustomizerParams();
    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.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 AddAdCustomizer().runExample(googleAdsClient, params.customerId, 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 ID of the customer.
   * @param adGroupId the ID of the adGroup to associate the customizers with.
   * @throws GoogleAdsException if an API request failed with one or more service errors.
   */
  private void runExample(GoogleAdsClient googleAdsClient, long customerId, long adGroupId) {
    String stringCustomizerName = "Planet_" + getShortPrintableDateTime();
    String priceCustomizerName = "Price_" + getShortPrintableDateTime();

    // Creates ad customizer attributes.
    String textCustomizerAttributeResourceName =
        createTextCustomizerAttribute(googleAdsClient, customerId, stringCustomizerName);
    String priceCustomizerAttributeResourceName =
        createPriceCustomizerAttribute(googleAdsClient, customerId, priceCustomizerName);

    // Links the customizer attributes.
    linkCustomizerAttributes(
        googleAdsClient,
        customerId,
        adGroupId,
        textCustomizerAttributeResourceName,
        priceCustomizerAttributeResourceName);

    // Creates an ad with the customizations provided by the ad customizer attributes.
    createAdWithCustomizations(
        googleAdsClient, customerId, adGroupId, stringCustomizerName, priceCustomizerName);
  }

  /**
   * Creates a text customizer attribute and returns its resource name.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the client customer ID.
   * @param customizerName the name of the customizer to create.
   * @return the attributes of the feed.
   */
  private String createTextCustomizerAttribute(
      GoogleAdsClient googleAdsClient, long customerId, String customizerName) {
    // Creates a text customizer attribute. The customizer attribute name is arbitrary and will be
    // used as a placeholder in the ad text fields.
    CustomizerAttribute textAttribute =
        CustomizerAttribute.newBuilder()
            .setName(customizerName)
            .setType(CustomizerAttributeType.TEXT)
            .build();

    CustomizerAttributeOperation operation =
        CustomizerAttributeOperation.newBuilder().setCreate(textAttribute).build();

    try (CustomizerAttributeServiceClient customizerAttributeServiceClient =
        googleAdsClient.getLatestVersion().createCustomizerAttributeServiceClient()) {
      MutateCustomizerAttributesResponse response =
          customizerAttributeServiceClient.mutateCustomizerAttributes(
              Long.toString(customerId), ImmutableList.of(operation));

      String customizerAttributeResourceName = response.getResults(0).getResourceName();
      System.out.printf(
          "Added text customizer attribute with resource name '%s'.%n",
          customizerAttributeResourceName);
      return customizerAttributeResourceName;
    }
  }

  /**
   * Creates a price customizer attribute and returns its resource name.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the client customer ID.
   * @param customizerName the name of the customizer to create.
   * @return the attributes of the feed.
   */
  private String createPriceCustomizerAttribute(
      GoogleAdsClient googleAdsClient, long customerId, String customizerName) {
    // Creates a price customizer attribute. The customizer attribute name is arbitrary and will be
    // used as a placeholder in the ad text fields.
    CustomizerAttribute priceAttribute =
        CustomizerAttribute.newBuilder()
            .setName(customizerName)
            .setType(CustomizerAttributeType.PRICE)
            .build();

    CustomizerAttributeOperation operation =
        CustomizerAttributeOperation.newBuilder().setCreate(priceAttribute).build();

    try (CustomizerAttributeServiceClient customizerAttributeServiceClient =
        googleAdsClient.getLatestVersion().createCustomizerAttributeServiceClient()) {
      MutateCustomizerAttributesResponse response =
          customizerAttributeServiceClient.mutateCustomizerAttributes(
              Long.toString(customerId), ImmutableList.of(operation));

      String customizerAttributeResourceName = response.getResults(0).getResourceName();
      System.out.printf(
          "Added price customizer attribute with resource name '%s'.%n",
          customizerAttributeResourceName);
      return customizerAttributeResourceName;
    }
  }


  /**
   * Restricts the ad customizer attributes to work only with a specific ad group; this prevents the
   * customizer attributes from being used elsewhere and makes sure they are used only for
   * customizing a specific ad group.
   *
   * @param googleAdsClient the Google Ads client.
   * @param customerId the client customer ID.
   * @param adGroupId the ad group ID to bind the customizer attributes to.
   * @param textCustomizerAttributeResourceName the resource name of the text customizer attribute.
   * @param priceCustomizerAttributeResourceName the resource name of the price customizer
   *     attribute.
   */
  private void linkCustomizerAttributes(
      GoogleAdsClient googleAdsClient,
      long customerId,
      long adGroupId,
      String textCustomizerAttributeResourceName,
      String priceCustomizerAttributeResourceName) {
    List<AdGroupCustomizerOperation> operations = new ArrayList<>();

    // Binds the text attribute customizer to a specific ad group to make sure it will only be used
    // to customize ads inside that ad group.
    AdGroupCustomizer marsCustomizer =
        AdGroupCustomizer.newBuilder()
            .setCustomizerAttribute(textCustomizerAttributeResourceName)
            .setValue(
                CustomizerValue.newBuilder()
                    .setType(CustomizerAttributeType.TEXT)
                    .setStringValue("Mars")
                    .build())
            .setAdGroup(ResourceNames.adGroup(customerId, adGroupId))
            .build();

    operations.add(AdGroupCustomizerOperation.newBuilder().setCreate(marsCustomizer).build());

    // Binds the price attribute customizer to a specific ad group to make sure it will only be used
    // to customize ads inside that ad group.
    AdGroupCustomizer priceCustomizer =
        AdGroupCustomizer.newBuilder()
            .setCustomizerAttribute(priceCustomizerAttributeResourceName)
            .setValue(
                CustomizerValue.newBuilder()
                    .setType(CustomizerAttributeType.PRICE)
                    .setStringValue("100.0€")
                    .build())
            .setAdGroup(ResourceNames.adGroup(customerId, adGroupId))
            .build();

    operations.add(AdGroupCustomizerOperation.newBuilder().setCreate(priceCustomizer).build());

    try (AdGroupCustomizerServiceClient adGroupCustomizerServiceClient =
        googleAdsClient.getLatestVersion().createAdGroupCustomizerServiceClient()) {
      MutateAdGroupCustomizersResponse response =
          adGroupCustomizerServiceClient.mutateAdGroupCustomizers(
              Long.toString(customerId), operations);
      for (MutateAdGroupCustomizerResult result : response.getResultsList()) {
        System.out.printf(
            "Added an ad group customizer with resource name '%s'.%n", result.getResourceName());
      }
    }
  }

  /**
   * Creates a responsive search ad that uses the ad customizer attributes to populate the
   * placeholders.
   *
   * @param googleAdsClient the Google Ads API client.
   * @param customerId the client customer ID.
   * @param stringCustomizerName name of the string customizer.
   * @param priceCustomizerName Name of the price customizer.
   */
  private void createAdWithCustomizations(
      GoogleAdsClient googleAdsClient,
      long customerId,
      long adGroupId,
      String stringCustomizerName,
      String priceCustomizerName) {

    // Creates a responsive search ad using the attribute customizer names as placeholders and
    // default values to be used in case there are no attribute customizer values.
    ResponsiveSearchAdInfo responsiveSearchAdInfo =
        ResponsiveSearchAdInfo.newBuilder()
            .addAllHeadlines(
                ImmutableList.of(
                    AdTextAsset.newBuilder()
                        .setText(
                            String.format(
                                "Luxury cruise to {CUSTOMIZER.%s:Venus}", stringCustomizerName))
                        .setPinnedField(ServedAssetFieldType.HEADLINE_1)
                        .build(),
                    AdTextAsset.newBuilder()
                        .setText(
                            String.format("Only {CUSTOMIZER.%s:10.0€}", priceCustomizerName))
                        .build(),
                    AdTextAsset.newBuilder()
                        .setText(
                            String.format(
                                "Cruise to {CUSTOMIZER.%s:Venus} for {CUSTOMIZER.%s:10.0€}",
                                stringCustomizerName, priceCustomizerName))
                        .build()))
            .addAllDescriptions(
                ImmutableList.of(
                    AdTextAsset.newBuilder()
                        .setText(
                            String.format(
                                "Tickets are only {CUSTOMIZER.%s:10.0€}!", priceCustomizerName))
                        .build(),
                    AdTextAsset.newBuilder()
                        .setText(
                            String.format(
                                "Buy your tickets to {CUSTOMIZER.%s:Venus} now!",
                                stringCustomizerName))
                        .build()))
            .build();

    Ad ad =
        Ad.newBuilder()
            .setResponsiveSearchAd(responsiveSearchAdInfo)
            .addFinalUrls("https://www.example.com")
            .build();

    List<AdGroupAdOperation> adGroupAdOperations = new ArrayList<>();

    AdGroupAd adGroupAd =
        AdGroupAd.newBuilder()
            .setAd(ad)
            .setAdGroup(ResourceNames.adGroup(customerId, adGroupId))
            .build();

    AdGroupAdOperation adGroupAdOperation =
        AdGroupAdOperation.newBuilder().setCreate(adGroupAd).build();

    adGroupAdOperations.add(adGroupAdOperation);

    try (AdGroupAdServiceClient adGroupAdServiceClient =
        googleAdsClient.getLatestVersion().createAdGroupAdServiceClient()) {

      MutateAdGroupAdsResponse response =
          adGroupAdServiceClient.mutateAdGroupAds(Long.toString(customerId), adGroupAdOperations);

      System.out.printf("Added %d ads:%n", response.getResultsCount());
      for (MutateAdGroupAdResult result : response.getResultsList()) {
        System.out.printf("Added an ad with resource name '%s'.%n", result.getResourceName());
      }
    }
  }
}

      

C#

// 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
//
//     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.Gax.Examples;
using Google.Ads.GoogleAds.Lib;
using Google.Ads.GoogleAds.V11.Common;
using Google.Ads.GoogleAds.V11.Errors;
using Google.Ads.GoogleAds.V11.Resources;
using Google.Ads.GoogleAds.V11.Services;
using System;
using System.Collections.Generic;
using Google.Ads.GoogleAds.V11.Enums;
using static Google.Ads.GoogleAds.V11.Enums.CustomizerAttributeTypeEnum.Types;

namespace Google.Ads.GoogleAds.Examples.V11
{
    /// <summary>
    /// This code example adds two ad customizer attributes and associates
    /// them with the ad group.
    /// Then it adds an ad that uses the ad customizer attributes to populate
    /// dynamic data.
    /// </summary>
    public class AddAdCustomizer : ExampleBase
    {
        /// <summary>
        /// Command line options for running the <see cref="AddAdCustomizer"/> 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 ad group to which ad customizers are added.
            /// </summary>
            [Option("adGroupId", Required = true, HelpText =
                "ID of the ad group to which ad customizers 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 = ExampleUtilities.ParseCommandLine<Options>(args);

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

        /// <summary>
        /// Returns a description about the code example.
        /// </summary>
        public override string Description =>
            "This code example adds two ad customizer attributes and associates them with the ad group. " +
            "Then it adds an ad that uses the customizer attributes to populate dynamic data.";

        /// <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="adGroupId">ID of the ad group to which ad customizers are added.</param>
        public void Run(GoogleAdsClient client, long customerId, long adGroupId)
        {            
            // Get the AdGroupBidModifierService.
            AdGroupBidModifierServiceClient adGroupBidModifierService =
                client.GetService(Services.V11.AdGroupBidModifierService);

            string stringCustomizerName = "Planet_" + ExampleUtilities.GetShortRandomString();
            string priceCustomizerName = "Price_" + ExampleUtilities.GetShortRandomString();

            try
            {
                // Create ad customizer attributes.
                string textCustomizerAttributeResourceName =
                    CreateTextCustomizerAttribute(client, customerId, stringCustomizerName);
                string priceCustomizerAttributeResourceName =
                    CreatePriceCustomizerAttribute(client, customerId, priceCustomizerName);

                // Link the customizer attributes to the ad group.
                LinkCustomizerAttributes(client, customerId, adGroupId,
                    textCustomizerAttributeResourceName, priceCustomizerAttributeResourceName);

                // Create an ad with the customizations provided by the ad customizer attributes.
                CreateAdWithCustomizations(client, customerId, adGroupId,
                    stringCustomizerName, priceCustomizerName);
            }
            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 a text customizer attribute and returns its resource name.
        /// </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="customizerName">The name of the customizer to create.</param>
        private string CreateTextCustomizerAttribute(GoogleAdsClient client, long customerId,
            string customizerName)
        {
            // Get the customizer attribute service.
            CustomizerAttributeServiceClient customizerAttributeService = 
                client.GetService(Services.V11.CustomizerAttributeService);

            // Creates a text customizer attribute. The customizer attribute name is
            // arbitrary and will be used as a placeholder in the ad text fields.
            CustomizerAttribute textAttribute = new CustomizerAttribute()
            {
                Name = customizerName,
                Type = CustomizerAttributeType.Text
            };

            CustomizerAttributeOperation textAttributeOperation = new CustomizerAttributeOperation(){
                Create = textAttribute
            };

            MutateCustomizerAttributesResponse response =
                customizerAttributeService.MutateCustomizerAttributes(customerId.ToString(),
                    new[] {textAttributeOperation});

            string customizerAttributeResourceName = response.Results[0].ResourceName; 
            Console.WriteLine($"Added text customizer attribute with resource name" +
                $" '{customizerAttributeResourceName}'.");

            return customizerAttributeResourceName;
        }

        /// <summary>
        /// Creates a price customizer attribute ad returns its resource name.
        /// </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="customizerName">The name of the customizer to create.</param>
        private string CreatePriceCustomizerAttribute(GoogleAdsClient client, long customerId,
            string customizerName)
        {
            // Get the customizer attribute service.
            CustomizerAttributeServiceClient customizerAttributeService = 
                client.GetService(Services.V11.CustomizerAttributeService);

            // Creates a price customizer attribute. The customizer attribute name is
            // arbitrary and will be used as a placeholder in the ad text fields.
            CustomizerAttribute priceAttribute = new CustomizerAttribute()
            {
                Name = customizerName,
                Type = CustomizerAttributeType.Price
            };

            CustomizerAttributeOperation priceAttributeOperation = new CustomizerAttributeOperation(){
                Create = priceAttribute
            };

            MutateCustomizerAttributesResponse response =
                customizerAttributeService.MutateCustomizerAttributes(customerId.ToString(),
                    new[] {priceAttributeOperation});

            string customizerAttributeResourceName = response.Results[0].ResourceName; 
            Console.WriteLine($"Added price customizer attribute with resource name" +
                $" '{customizerAttributeResourceName}'.");

            return customizerAttributeResourceName;
        }

        /// <summary>
        /// Restricts the ad customizer attributes to work only with a specific ad group; this prevents
        /// the customizer attributes from being used elsewhere and makes sure they are used only for
        /// customizing a specific ad group.
        /// </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="adGroupId">The ad group ID to bind the customizer attributes to.</param>
        /// <param name="textCustomizerAttributeResourceName">The resource name of the text customizer attribute.</param>
        /// <param name="priceCustomizerAttributeResourceName">The resource name of the price customizer attribute.</param>
        private void LinkCustomizerAttributes(GoogleAdsClient client,
            long customerId, long adGroupId,
            string textCustomizerAttributeResourceName,
            string priceCustomizerAttributeResourceName)
        {
            // Get the ad group customizer service.
            AdGroupCustomizerServiceClient adGroupCustomizerService =
                client.GetService(Services.V11.AdGroupCustomizerService);

            List<AdGroupCustomizerOperation> adGroupCustomizerOperations =
                new List<AdGroupCustomizerOperation>();

            // Binds the text attribute customizer to a specific ad group to
            // make sure it will only be used to customize ads inside that ad
            // group.
            AdGroupCustomizer marsCustomizer = new AdGroupCustomizer(){
                CustomizerAttribute = textCustomizerAttributeResourceName,
                Value = new CustomizerValue(){
                    Type = CustomizerAttributeType.Text,
                    StringValue = "Mars"
                },
                AdGroup = ResourceNames.AdGroup(customerId, adGroupId)
            };

            adGroupCustomizerOperations.Add(new AdGroupCustomizerOperation(){
                Create = marsCustomizer
            });

            // Binds the price attribute customizer to a specific ad group to
            // make sure it will only be used to customize ads inside that ad
            // group.
            AdGroupCustomizer priceCustomizer = new AdGroupCustomizer(){
                CustomizerAttribute = priceCustomizerAttributeResourceName,
                Value = new CustomizerValue(){
                    Type = CustomizerAttributeType.Price,
                    StringValue = "100.0€"
                },
                AdGroup = ResourceNames.AdGroup(customerId, adGroupId)
            };

            adGroupCustomizerOperations.Add(new AdGroupCustomizerOperation(){
                Create = priceCustomizer
            });                        

            MutateAdGroupCustomizersResponse response =                
                adGroupCustomizerService.MutateAdGroupCustomizers(customerId.ToString(),
                    adGroupCustomizerOperations);

            foreach (MutateAdGroupCustomizerResult result in response.Results)
            {
                Console.WriteLine($"Added an ad group customizer with resource name '{result.ResourceName}'.");
            }
        }

        /// <summary>
        /// Creates a responsive search ad that uses the ad customizer attributes to populate the placeholders.
        /// </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="adGroupId">The ad group IDs in which to create the ads.</param>
        /// <param name="stringCustomizerName">Name of the string customizer.</param>
        /// <param name="priceCustomizerName">Name of the price customizer.</param>
        private void CreateAdWithCustomizations(GoogleAdsClient client, long customerId,
            long adGroupId, string stringCustomizerName, string priceCustomizerName)
        {
            // Get the AdGroupAdServiceClient.
            AdGroupAdServiceClient adGroupAdService =
                client.GetService(Services.V11.AdGroupAdService);

            // Creates a responsive search ad using the attribute customizer names as
            // placeholders and default values to be used in case there are no attribute
            // customizer values.
            Ad ad = new Ad()
            {
                ResponsiveSearchAd = new ResponsiveSearchAdInfo()
                {
                    Headlines =
                    {
                        new AdTextAsset()
                        {
                            Text = $"Luxury cruise to {{CUSTOMIZER.{stringCustomizerName}:Venus}}",
                            PinnedField = ServedAssetFieldTypeEnum.Types.ServedAssetFieldType.Headline1
                        },
                        new AdTextAsset() { Text = $"Only {{CUSTOMIZER.{priceCustomizerName}:10.0€}}" },
                        new AdTextAsset()
                        {
                            Text = $"Cruise to {{CUSTOMIZER.{stringCustomizerName}:Venus}} for {{CUSTOMIZER.{priceCustomizerName}:10.0€}}"
                        }
                    },
                    Descriptions =
                    {
                        new AdTextAsset() { Text = $"Tickets are only {{CUSTOMIZER.{priceCustomizerName}:10.0€}}!" },
                        new AdTextAsset() { Text = $"Buy your tickets to {{CUSTOMIZER.{stringCustomizerName}:Venus}} now!" }
                    }
                },
                FinalUrls = { "https://www.example.com" }
            };

            AdGroupAd adGroupAd = new AdGroupAd()
            {
                Ad = ad,
                AdGroup = ResourceNames.AdGroup(customerId, adGroupId)
            };

            AdGroupAdOperation adGroupAdOperation = new AdGroupAdOperation(){ Create = adGroupAd };

            MutateAdGroupAdsResponse response =
                adGroupAdService.MutateAdGroupAds(customerId.ToString(), 
                new[] { adGroupAdOperation });

            foreach (MutateAdGroupAdResult result in response.Results)
            {
                Console.WriteLine($"Added an ad 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\V11\GoogleAdsClient;
use Google\Ads\GoogleAds\Lib\V11\GoogleAdsClientBuilder;
use Google\Ads\GoogleAds\Lib\V11\GoogleAdsException;
use Google\Ads\GoogleAds\Util\V11\ResourceNames;
use Google\Ads\GoogleAds\V11\Common\AdTextAsset;
use Google\Ads\GoogleAds\V11\Common\CustomizerValue;
use Google\Ads\GoogleAds\V11\Common\ResponsiveSearchAdInfo;
use Google\Ads\GoogleAds\V11\Enums\CustomizerAttributeTypeEnum\CustomizerAttributeType;
use Google\Ads\GoogleAds\V11\Enums\ServedAssetFieldTypeEnum\ServedAssetFieldType;
use Google\Ads\GoogleAds\V11\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V11\Resources\Ad;
use Google\Ads\GoogleAds\V11\Resources\AdGroupAd;
use Google\Ads\GoogleAds\V11\Resources\AdGroupCustomizer;
use Google\Ads\GoogleAds\V11\Resources\CustomizerAttribute;
use Google\Ads\GoogleAds\V11\Services\AdGroupAdOperation;
use Google\Ads\GoogleAds\V11\Services\AdGroupCustomizerOperation;
use Google\Ads\GoogleAds\V11\Services\CustomizerAttributeOperation;
use Google\ApiCore\ApiException;

/**
 * Adds ad customizer attributes and associates them with the ad group. Then it adds an ad that
 * uses the customizer attributes to populate dynamic data.
 */
class AddAdCustomizer
{
    private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE';
    private const AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE';

    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::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::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 $adGroupId the ad group ID
     */
    public static function runExample(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        int $adGroupId
    ) {
        $stringCustomizerName = 'Planet_' . Helper::getShortPrintableDatetime();
        $priceCustomizerName = 'Price_' . Helper::getShortPrintableDatetime();

        // Creates ad customizer attributes.
        $textCustomizerAttributeResourceName = self::createTextCustomizerAttribute(
            $googleAdsClient,
            $customerId,
            $stringCustomizerName
        );
        $priceCustomizerAttributeResourceName = self::createPriceCustomizerAttribute(
            $googleAdsClient,
            $customerId,
            $priceCustomizerName
        );

        // Link the customer attributes to the ad group.
        self::linkCustomizerAttributes(
            $googleAdsClient,
            $customerId,
            $adGroupId,
            $textCustomizerAttributeResourceName,
            $priceCustomizerAttributeResourceName
        );

        // Creates an ad with the customizations provided by the ad customizer attributes.
        self::createAdsWithCustomizations(
            $googleAdsClient,
            $customerId,
            $adGroupId,
            $stringCustomizerName,
            $priceCustomizerName
        );
    }

   /**
    * Creates a text customizer attribute and returns its resource name.
    *
    * @param GoogleAdsClient $googleAdsClient the Google Ads API client
    * @param int $customerId the customer ID
    * @param string $customizerName the name of the customizer to create
    * @return string the resource name of the newly created text customizer attribute
    */
    private static function createTextCustomizerAttribute(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        string $customizerName
    ) {
        // Creates a text customizer attribute. The customizer attribute name is
        // arbitrary and will be used as a placeholder in the ad text fields.
        $textAttribute = new CustomizerAttribute([
            'name' => $customizerName,
            'type' => CustomizerAttributeType::TEXT
        ]);

        // Creates a customizer attribute operation for creating a customizer attribute.
        $customizerAttributeOperation = new CustomizerAttributeOperation();
        $customizerAttributeOperation->setCreate($textAttribute);

        // Issues a mutate request to add the customizer attribute.
        $customizerAttributeServiceClient = $googleAdsClient->getCustomizerAttributeServiceClient();
        $response = $customizerAttributeServiceClient->mutateCustomizerAttributes(
            $customerId,
            [$customizerAttributeOperation]
        );

        $customizerAttributeResourceName = $response->getResults()[0]->getResourceName();
        printf(
            "Added text customizer attribute with resource name '%s'.%s",
            $customizerAttributeResourceName,
            PHP_EOL
        );

        return $customizerAttributeResourceName;
    }

    /**
     * Creates a price customizer attribute and returns its resource name.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param string $customizerName the name of the customizer to create
     * @return string the resource name of the newly created price customizer attribute
     */
    private static function createPriceCustomizerAttribute(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        string $customizerName
    ) {
        // Creates a price customizer attribute. The customizer attribute name is
        // arbitrary and will be used as a placeholder in the ad text fields.
        $priceAttribute = new CustomizerAttribute([
            'name' => $customizerName,
            'type' => CustomizerAttributeType::PRICE
        ]);

        // Creates a customizer attribute operation for creating a customizer attribute.
        $customizerAttributeOperation = new CustomizerAttributeOperation();
        $customizerAttributeOperation->setCreate($priceAttribute);

        // Issues a mutate request to add the customizer attribute.
        $customizerAttributeServiceClient = $googleAdsClient->getCustomizerAttributeServiceClient();
        $response = $customizerAttributeServiceClient->mutateCustomizerAttributes(
            $customerId,
            [$customizerAttributeOperation]
        );

        $customizerAttributeResourceName = $response->getResults()[0]->getResourceName();
        printf(
            "Added price customizer attribute with resource name '%s'.%s",
            $customizerAttributeResourceName,
            PHP_EOL
        );

        return $customizerAttributeResourceName;
    }

    /**
     * Restricts the ad customizer attributes to work only with a specific ad group; this prevents
     * the customizer attributes from being used elsewhere and makes sure they are used only for
     * customizing a specific ad group.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param int $adGroupId the ad group ID to bind the customizer attribute to
     * @param string $textCustomizerAttributeResourceName the resource name of the text customizer
     *     attribute
     * @param string $priceCustomizerAttributeResourceName the resource name of the price
     *     customizer attribute
     */
    private static function linkCustomizerAttributes(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        int $adGroupId,
        string $textCustomizerAttributeResourceName,
        string $priceCustomizerAttributeResourceName
    ) {
        $operations = [];

        // Binds the text attribute customizer to a specific ad group to
        // make sure it will only be used to customize ads inside that ad
        // group.
        $textAdGroupCustomizer = new AdGroupCustomizer([
            'customizer_attribute' => $textCustomizerAttributeResourceName,
            'value' => new CustomizerValue([
                'type' => CustomizerAttributeType::TEXT,
                'string_value' => 'Mars'
            ]),
            'ad_group' => ResourceNames::forAdGroup($customerId, $adGroupId)
        ]);

        // Creates an operation for the text attribute ad group customizer.
        $textAdGroupCustomizerOperation = new AdGroupCustomizerOperation();
        $textAdGroupCustomizerOperation->setCreate($textAdGroupCustomizer);
        $operations[] = $textAdGroupCustomizerOperation;

        // Binds the price attribute customizer to a specific ad group to
        // make sure it will only be used to customize ads inside that ad
        // group.
        $priceAdGroupCustomizer = new AdGroupCustomizer([
            'customizer_attribute' => $priceCustomizerAttributeResourceName,
            'value' => new CustomizerValue([
                'type' => CustomizerAttributeType::PRICE,
                'string_value' => '100.0€'
            ]),
            'ad_group' => ResourceNames::forAdGroup($customerId, $adGroupId)
        ]);

        // Creates an operation for the price attribute ad group customizer.
        $priceAdGroupCustomizerOperation = new AdGroupCustomizerOperation();
        $priceAdGroupCustomizerOperation->setCreate($priceAdGroupCustomizer);
        $operations[] = $priceAdGroupCustomizerOperation;

        // Issues a mutate request to add ad group customizers.
        $adGroupCustomizerServiceClient = $googleAdsClient->getAdGroupCustomizerServiceClient();
        $response =
            $adGroupCustomizerServiceClient->mutateAdGroupCustomizers($customerId, $operations);

        // Displays the results.
        foreach ($response->getResults() as $result) {
            printf(
                "Added an ad group customizer with resource name '%s'.%s",
                $result->getResourceName(),
                PHP_EOL
            );
        }
    }

    /**
     * Creates a responsive search ad that uses the ad customizer attributes to populate the
     * placeholders.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param int $adGroupId the ad group ID in which to create the ad
     * @param string $stringCustomizerName the name of the string customizer
     * @param string $priceCustomizerName the name of the price customizer
     */
    private static function createAdsWithCustomizations(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        int $adGroupId,
        string $stringCustomizerName,
        string $priceCustomizerName
    ) {
        // Creates a responsive search ad using the attribute customizer names as
        // placeholders and default values to be used in case there are no attribute
        // customizer values.
        $responsiveSearchAdInfo = new ResponsiveSearchAdInfo([
            'headlines' => [
                new AdTextAsset([
                    'text' => "Luxury cruise to {CUSTOMIZER.$stringCustomizerName:Venus}",
                    'pinned_field' => ServedAssetFieldType::HEADLINE_1
                ]),
                new AdTextAsset(['text' => "Only {CUSTOMIZER.$priceCustomizerName:10.0€}"]),
                new AdTextAsset([
                    'text' => "Cruise to {CUSTOMIZER.$stringCustomizerName:Venus} for "
                        . "{CUSTOMIZER.$priceCustomizerName:10.0€}"
                ])
            ],
            'descriptions' => [
                new AdTextAsset([
                    'text' => "Tickets are only {CUSTOMIZER.$priceCustomizerName:10.0€}!"]),
                new AdTextAsset([
                    'text' => "Buy your tickets to {CUSTOMIZER.$stringCustomizerName:Venus} now!"])
            ]
        ]);

        // Creates an ad group ad and its operation.
        $adGroupAd = new AdGroupAd([
            'ad' => new Ad([
                'responsive_search_ad' => $responsiveSearchAdInfo,
                'final_urls' => ['https://www.example.com']
            ]),
            'ad_group' => ResourceNames::forAdGroup($customerId, $adGroupId)
        ]);
        $adGroupAdOperation = new AdGroupAdOperation();
        $adGroupAdOperation->setCreate($adGroupAd);

        // Issues a mutate request to add the ad.
        $adGroupAdServiceClient = $googleAdsClient->getAdGroupAdServiceClient();
        $adGroupAdResponse = $adGroupAdServiceClient->mutateAdGroupAds(
            $customerId,
            [$adGroupAdOperation]
        );

        $adGroupAdResourceName = $adGroupAdResponse->getResults()[0]->getResourceName();
        printf("Added an ad with resource name '%s'.%s", $adGroupAdResourceName, PHP_EOL);
    }
}

AddAdCustomizer::main();

      

Python

#!/usr/bin/env python
# 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.
"""This code example adds two ad customizer attributes.

It then associates them with the given ad group and adds an ad that uses the ad
customizer attributes to populate dynamic data.
"""


import argparse
from datetime import datetime
import sys
from uuid import uuid4

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


def main(client, customer_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.
        ad_group_id: an ad group ID.
    """
    text_customizer_name = f"Planet_{uuid4().hex[:8]}"
    price_customizer_name = f"Price_{uuid4().hex[:8]}"

    text_customizer_resource_name = create_text_customizer_attribute(
        client, customer_id, text_customizer_name
    )
    price_customizer_resource_name = create_price_customizer_attribute(
        client, customer_id, price_customizer_name
    )
    link_customizer_attributes(
        client,
        customer_id,
        ad_group_id,
        text_customizer_resource_name,
        price_customizer_resource_name,
    )
    create_ad_with_customizations(
        client,
        customer_id,
        ad_group_id,
        text_customizer_name,
        price_customizer_name,
    )


def create_text_customizer_attribute(client, customer_id, customizer_name):
    """Creates a text customizer attribute and returns its resource name.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID.
        customizer_name: the name of the customizer to create.

    Returns:
        a resource name for a text customizer attribute.
    """
    customizer_attribute_service = client.get_service(
        "CustomizerAttributeService"
    )

    # Creates a text customizer attribute. The customizer attribute name is
    # arbitrary and will be used as a placeholder in the ad text fields.
    operation = client.get_type("CustomizerAttributeOperation")
    text_attribute = operation.create
    text_attribute.name = customizer_name
    text_attribute.type_ = client.enums.CustomizerAttributeTypeEnum.TEXT

    response = customizer_attribute_service.mutate_customizer_attributes(
        customer_id=customer_id, operations=[operation]
    )

    resource_name = response.results[0].resource_name
    print(
        f"Added text customizer attribute with resource name '{resource_name}'"
    )
    return resource_name


def create_price_customizer_attribute(client, customer_id, customizer_name):
    """Creates a price customizer attribute and returns its resource name.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID.
        customizer_name: the name of the customizer to create.

    Returns:
        a resource name for a text customizer attribute.
    """
    customizer_attribute_service = client.get_service(
        "CustomizerAttributeService"
    )

    # Creates a price customizer attribute. The customizer attribute name is
    # arbitrary and will be used as a placeholder in the ad text fields.
    operation = client.get_type("CustomizerAttributeOperation")
    price_attribute = operation.create
    price_attribute.name = customizer_name
    price_attribute.type_ = client.enums.CustomizerAttributeTypeEnum.PRICE

    response = customizer_attribute_service.mutate_customizer_attributes(
        customer_id=customer_id, operations=[operation]
    )

    resource_name = response.results[0].resource_name
    print(
        f"Added price customizer attribute with resource name '{resource_name}'"
    )
    return resource_name


def link_customizer_attributes(
    client,
    customer_id,
    ad_group_id,
    text_customizer_resource_name,
    price_customizer_resource_name,
):
    """Restricts the ad customizer attributes to work with a specific ad group.

    This prevents the customizer attributes from being used elsewhere and makes
    sure they are used only for customizing a specific ad group.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID.
        ad_group_id: the ad group ID to bind the customizer attributes to.
        text_customizer_resource_name: the resource name of the text customizer attribute.
        price_customizer_resource_name: the resource name of the price customizer attribute.
    """
    googleads_service = client.get_service("GoogleAdsService")
    ad_group_customizer_service = client.get_service("AdGroupCustomizerService")

    # Binds the text attribute customizer to a specific ad group to make sure
    # it will only be used to customize ads inside that ad group.
    mars_operation = client.get_type("AdGroupCustomizerOperation")
    mars_customizer = mars_operation.create
    mars_customizer.customizer_attribute = text_customizer_resource_name
    mars_customizer.value.type_ = client.enums.CustomizerAttributeTypeEnum.TEXT
    mars_customizer.value.string_value = "Mars"
    mars_customizer.ad_group = googleads_service.ad_group_path(
        customer_id, ad_group_id
    )

    # Binds the price attribute customizer to a specific ad group to make sure
    # it will only be used to customize ads inside that ad group.
    price_operation = client.get_type("AdGroupCustomizerOperation")
    price_customizer = price_operation.create
    price_customizer.customizer_attribute = price_customizer_resource_name
    price_customizer.value.type_ = (
        client.enums.CustomizerAttributeTypeEnum.PRICE
    )
    price_customizer.value.string_value = "100.0€"
    price_customizer.ad_group = googleads_service.ad_group_path(
        customer_id, ad_group_id
    )

    response = ad_group_customizer_service.mutate_ad_group_customizers(
        customer_id=customer_id, operations=[mars_operation, price_operation]
    )

    for result in response.results:
        print(
            "Added an ad group customizer with resource name "
            f"'{result.resource_name}'"
        )


def create_ad_with_customizations(
    client,
    customer_id,
    ad_group_id,
    text_customizer_name,
    price_customizer_name,
):
    """Creates a responsive search ad (RSA).

    The RSA uses the ad customizer attributes to populate the placeholders.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID.
        ad_group_id: the ad group ID to bind the customizer attributes to.
        text_customizer_name: name of the text customizer.
        price_customizer_name: name of the price customizer.
    """
    googleads_service = client.get_service("GoogleAdsService")
    ad_group_ad_service = client.get_service("AdGroupAdService")

    # Creates a responsive search ad using the attribute customizer names as
    # placeholders and default values to be used in case there are no attribute
    # customizer values.
    operation = client.get_type("AdGroupAdOperation")
    ad_group_ad = operation.create
    ad_group_ad.ad.final_urls.append("https://www.example.com")
    ad_group_ad.ad_group = googleads_service.ad_group_path(
        customer_id, ad_group_id
    )

    headline_1 = client.get_type("AdTextAsset")
    headline_1.text = (
        f"Luxury cruise to {{CUSTOMIZER.{text_customizer_name}:Venus}}"
    )
    headline_1.pinned_field = client.enums.ServedAssetFieldTypeEnum.HEADLINE_1

    headline_2 = client.get_type("AdTextAsset")
    headline_2.text = f"Only {{CUSTOMIZER.{price_customizer_name}:10.0€}}"

    headline_3 = client.get_type("AdTextAsset")
    headline_3.text = f"Cruise to {{CUSTOMIZER.{text_customizer_name}:Venus}} for {{CUSTOMIZER.{price_customizer_name}:10.0€}}"

    ad_group_ad.ad.responsive_search_ad.headlines.extend(
        [headline_1, headline_2, headline_3]
    )

    description_1 = client.get_type("AdTextAsset")
    description_1.text = (
        f"Tickets are only {{CUSTOMIZER.{price_customizer_name}:10.0€}}!"
    )

    description_2 = client.get_type("AdTextAsset")
    description_2.text = (
        f"Buy your tickets to {{CUSTOMIZER.{text_customizer_name}:Venus}} now!"
    )

    ad_group_ad.ad.responsive_search_ad.descriptions.extend(
        [description_1, description_2]
    )

    response = ad_group_ad_service.mutate_ad_group_ads(
        customer_id=customer_id, operations=[operation]
    )
    resource_name = response.results[0].resource_name
    print(f"Added an ad 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="v11")

    parser = argparse.ArgumentParser(
        description=(
            "This code example adds two ad customizer attributes and "
            "associates them with the ad group. Then it adds an ad that uses "
            "the customizer attributes to populate dynamic data."
        )
    )
    # 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(
        "-a", "--ad_group_id", type=str, required=True, help="An ad group ID.",
    )
    args = parser.parse_args()

    try:
        main(googleads_client, args.customer_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'Error 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 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.
#
# Adds an ad customizer feed and associates it with the customer. Then it adds
# an ad that uses the feed to populate dynamic data.

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

def add_ad_customizer(customer_id, ad_group_ids)
  # GoogleAdsClient will read a config file from
  # ENV['HOME']/google_ads_config.rb when called without parameters
  client = Google::Ads::GoogleAds::GoogleAdsClient.new

  if ad_group_ids.size != NUMBER_OF_AD_GROUPS
    raise "Please pass exactly #{NUMBER_OF_AD_GROUPS} ad group IDs in the " \
      "ad_group_ids parameter."
  end

  feed_name = "Ad Customizer example feed #{(Time.new.to_f * 1000).to_i}"

  # Create a feed to be used for ad customization
  ad_customizer_feed_resource_name = create_ad_customizer_feed(
    client, customer_id, feed_name)

  # Retrieve the attributes of the feed.
  ad_customizer_feed_attributes = get_feed_attributes(
    client, customer_id, ad_customizer_feed_resource_name)

  # Map the feed to the ad customizer placeholder fields.
  create_ad_customizer_mapping(
    client,
    customer_id,
    ad_customizer_feed_resource_name,
    ad_customizer_feed_attributes,
  )

  # Create feed items to be used to customize ads.
  feed_item_resource_names = create_feed_items(
    client,
    customer_id,
    ad_customizer_feed_resource_name,
    ad_customizer_feed_attributes,
  )

  # Set the feed to be used only with the specified ad groups.
  create_feed_item_targets(
    client,
    customer_id,
    ad_group_ids,
    feed_item_resource_names,
  )

  # Create ads that use the feed for customization.
  create_ads_with_customizations(
    client,
    customer_id,
    ad_group_ids,
    feed_name,
  )
end

# Creates a feed to be used for ad customization.
def create_ad_customizer_feed(
  client, customer_id, feed_name)
  # Creates a feed operation for creating a feed.
  operation = client.operation.create_resource.feed do |feed|
    feed.name = feed_name
    # Creates three feed attributes: a name, a price and a date. The attribute
    # names are arbitrary choices and will be used as placeholders in the ad
    # text fields.
    feed.attributes << client.resource.feed_attribute do |a|
      a.type = :STRING
      a.name = "Name"
    end
    feed.attributes << client.resource.feed_attribute do |a|
      a.type = :STRING
      a.name = "Price"
    end
    feed.attributes << client.resource.feed_attribute do |a|
      a.type = :DATE_TIME
      a.name = "Date"
    end
    feed.origin = :USER
  end

  # Issues a mutate request to add the feed.
  feed_response = client.service.feed.mutate_feeds(
    customer_id: customer_id,
    operations: [operation],
  )

  feed_resource_name = feed_response.results.first.resource_name
  puts "Added a feed with resource name #{feed_resource_name}."

  feed_resource_name
end

# Retrieves attributes for a feed.
def get_feed_attributes(
  client, customer_id, ad_customizer_feed_resource_name)
  query = <<~QUERY
    SELECT feed.attributes, feed.name
    FROM feed
    WHERE feed.resource_name = "#{ad_customizer_feed_resource_name}"
  QUERY

  response = client.service.google_ads.search(
    customer_id: customer_id,
    query: query,
    page_size: PAGE_SIZE,
  )

  feed = response.first.feed
  feed_details = {}
  puts "Found the following attributes for feed with name #{feed.name}:"
  feed.attributes.each do |a|
    feed_details[a.name.to_sym] = a.id
    puts "\t#{a.name} with id #{a.id} and type #{a.type}"
  end

  feed_details
end

# Creates a feed mapping for a given feed.
def create_ad_customizer_mapping(
  client,
  customer_id,
  ad_customizer_feed_resource_name,
  ad_customizer_feed_attributes)
  # Creates the operation.
  operation = client.operation.create_resource.feed_mapping do |fm|
    fm.placeholder_type = :AD_CUSTOMIZER
    fm.feed = ad_customizer_feed_resource_name
    # Maps the feed attribute IDs to the field ID constants.
    fm.attribute_field_mappings << client.resource.attribute_field_mapping do |af|
      af.feed_attribute_id = ad_customizer_feed_attributes[:Name]
      af.ad_customizer_field = :STRING
    end
    fm.attribute_field_mappings << client.resource.attribute_field_mapping do |af|
      af.feed_attribute_id = ad_customizer_feed_attributes[:Price]
      af.ad_customizer_field = :PRICE
    end
    fm.attribute_field_mappings << client.resource.attribute_field_mapping do |af|
      af.feed_attribute_id = ad_customizer_feed_attributes[:Date]
      af.ad_customizer_field = :DATE
    end
  end

  # Issues a mutate request to add the feed mapping.
  response = client.service.feed_mapping.mutate_feed_mappings(
    customer_id: customer_id,
    operations: [operation],
  )

  # Displays the results.
  response.results.each do |result|
    puts "Created feed mapping with resource name: #{result.resource_name}"
  end
end

# Creates two different feed items to enable two different ad customizations.
def create_feed_items(
  client,
  customer_id,
  ad_customizer_feed_resource_name,
  ad_customizer_feed_attributes)
  feed_item_operations = []

  feed_item_operations << create_feed_item_operation(
    client,
    "Mars",
    "$1234.56",
    # Set the date to the 1st of the current month.
    DateTime.new(Date.today.year, Date.today.month, 1, 0, 0, 0).strftime("%Y%m%d %H%M%S"),
    ad_customizer_feed_resource_name,
    ad_customizer_feed_attributes,
  )

  feed_item_operations << create_feed_item_operation(
    client,
    "Venus",
    "$6543.21",
    # Set the date to the 15th of the current month.
    DateTime.new(Date.today.year, Date.today.month, 15, 0, 0, 0).strftime("%Y%m%d %H%M%S"),
    ad_customizer_feed_resource_name,
    ad_customizer_feed_attributes,
  )

  # Adds the feed items.
  response = client.service.feed_item.mutate_feed_items(
    customer_id: customer_id,
    operations: feed_item_operations,
  )

  feed_item_resource_names = []
  response.results.each do |result|
    puts "Created feed item with resource name #{result.resource_name}"
    feed_item_resource_names << result.resource_name
  end

  feed_item_resource_names
end

# Creates a FeedItemOperation.
def create_feed_item_operation(
  client,
  name,
  price,
  date,
  ad_customizer_feed_resource_name,
  ad_customizer_feed_attributes)
  client.operation.create_resource.feed_item do |item|
    item.feed = ad_customizer_feed_resource_name
    item.attribute_values << client.resource.feed_item_attribute_value do |v|
      v.feed_attribute_id = ad_customizer_feed_attributes[:Name]
      v.string_value = name
    end
    item.attribute_values << client.resource.feed_item_attribute_value do |v|
      v.feed_attribute_id = ad_customizer_feed_attributes[:Price]
      v.string_value = price
    end
    item.attribute_values << client.resource.feed_item_attribute_value do |v|
      v.feed_attribute_id = ad_customizer_feed_attributes[:Date]
      v.string_value = date
    end
  end
end

# Restricts the feed items to work only with a specific ad group; this prevents
# the feed items from being used elsewhere and makes sure they are used only for
# customizing a specific ad group.
def create_feed_item_targets(
  client,
  customer_id,
  ad_group_ids,
  feed_item_resource_names)
  # Bind each feed item to a specific ad group to make sure it will only be
  # used to customize ads inside that ad group; using the feed item elsewhere
  # will result in an error.
  feed_item_resource_names.size.times do |i|
    feed_item_resource_name = feed_item_resource_names[i]
    ad_group_id = ad_group_ids[i]

    # Creates the operation.
    operation = client.operation.create_resource.feed_item_target do |t|
      t.feed_item = feed_item_resource_name
      t.ad_group = client.path.ad_group(customer_id, ad_group_id)
    end

    # Issues a mutate request to add the feed item target.
    response = client.service.feed_item_target.mutate_feed_item_targets(
      customer_id: customer_id,
      operations: [operation],
    )

    puts "Added feed item target with resource name #{response.results.first.resource_name}."
  end
end

# Creates expanded text ads that use the ad customizer feed to populate the
# placeholders.
def create_ads_with_customizations(
  client,
  customer_id,
  ad_group_ids,
  feed_name)
  operations = []

  ad_group_ids.each do |ad_group_id|
    operations << client.operation.create_resource.ad_group_ad do |aga|
      aga.ad = client.resource.ad do |ad|
        ad.expanded_text_ad = client.resource.expanded_text_ad_info do |eta|
          eta.headline_part1 = "Luxury cruise to {=#{feed_name}.Name}"
          eta.headline_part2 = "Only {=#{feed_name}.Price}"
          eta.description = "Offer ends in {=countdown(#{feed_name}.Date)}!"
        end
        ad.final_urls << "http://www.example.com"
      end
      aga.ad_group = client.path.ad_group(customer_id, ad_group_id)
    end
  end

  # Issues a mutate request to add the ads.
  response = client.service.ad_group_ad.mutate_ad_group_ads(
    customer_id: customer_id,
    operations: operations,
  )

  puts "Added #{response.results.size} ads:"
  response.results.each do |result|
    puts "Added an ad with resource name #{result.resource_name}."
  end
end

if __FILE__ == $0
  # We're creating two different ad groups to be dynamically populated by
  # the same feed.
  NUMBER_OF_AD_GROUPS = 2

  # We're doing only searches by resource_name in this example,
  # we can set page size = 1.
  PAGE_SIZE = 1;

  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[:ad_group_ids] = [
    'INSERT_AD_GROUP_ID_1_HERE',
    'INSERT_AD_GORUP_ID_2_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('-A', '--ad-group-ids AD-GROUP-IDS', String, "#{NUMBER_OF_AD_GROUPS} AdGroup IDs (comma-separated)") do |v|
      options[:ad_group_ids] = v.split(',')
    end

    opts.on('-B', '--bid-modifier-value BID-MODIFIER-VALUE', String,
        'Bid Modifier Value') do |v|
      options[:bid_modifier_value] = v
    end

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

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

  begin
    add_ad_customizer(
      options.fetch(:customer_id).tr("-", ""),
      options[:ad_group_ids],
    )
  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 code example adds two ad customizer attributes and associates them with the ad group.
# Then it adds an ad that uses the ad customizer attributes to populate dynamic data.

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::V11::Resources::AttributeFieldMapping;
use Google::Ads::GoogleAds::V11::Resources::Ad;
use Google::Ads::GoogleAds::V11::Resources::AdGroupAd;
use Google::Ads::GoogleAds::V11::Resources::AdGroupCustomizer;
use Google::Ads::GoogleAds::V11::Resources::CustomizerAttribute;
use Google::Ads::GoogleAds::V11::Common::AdTextAsset;
use Google::Ads::GoogleAds::V11::Common::CustomizerValue;
use Google::Ads::GoogleAds::V11::Common::ResponsiveSearchAdInfo;
use Google::Ads::GoogleAds::V11::Enums::CustomizerAttributeTypeEnum
  qw(TEXT PRICE);
use Google::Ads::GoogleAds::V11::Enums::ServedAssetFieldTypeEnum qw(HEADLINE_1);
use Google::Ads::GoogleAds::V11::Services::AdGroupAdService::AdGroupAdOperation;
use
  Google::Ads::GoogleAds::V11::Services::AdGroupCustomizerService::AdGroupCustomizerOperation;
use
  Google::Ads::GoogleAds::V11::Services::CustomizerAttributeService::CustomizerAttributeOperation;
use Google::Ads::GoogleAds::V11::Utils::ResourceNames;

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

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

  my $string_customizer_name = "Planet_" . uniqid();
  my $price_customizer_name  = "Price_" . uniqid();

  my $text_customizer_attribute_resource_name =
    create_text_customizer_attribute($api_client, $customer_id,
    $string_customizer_name);
  my $price_customizer_attribute_resource_name =
    create_price_customizer_attribute($api_client, $customer_id,
    $price_customizer_name);

  # Link the customizer attributes to the ad group.
  link_customizer_attributes(
    $api_client, $customer_id, $ad_group_id,
    $text_customizer_attribute_resource_name,
    $price_customizer_attribute_resource_name
  );

  # Create an ad with the customizations provided by the ad customizer attributes.
  create_ad_with_customizations($api_client, $customer_id, $ad_group_id,
    $string_customizer_name, $price_customizer_name);

  return 1;
}

# Creates a text customizer attribute and returns its resource name.
sub create_text_customizer_attribute {
  my ($api_client, $customer_id, $customizer_name) = @_;

  # Creates a text customizer attribute. The customizer attribute name is
  # arbitrary and will be used as a placeholder in the ad text fields.
  my $text_attribute =
    Google::Ads::GoogleAds::V11::Resources::CustomizerAttribute->new({
      name => $customizer_name,
      type => TEXT
    });

  # Create a customizer attribute operation for creating a customizer attribute.
  my $text_attribute_operation =
    Google::Ads::GoogleAds::V11::Services::CustomizerAttributeService::CustomizerAttributeOperation
    ->new({
      create => $text_attribute
    });

  # Issue a mutate request to add the customizer attribute.
  my $response = $api_client->CustomizerAttributeService()->mutate({
      customerId => $customer_id,
      operations => [$text_attribute_operation]});

  my $customizer_attribute_resource_name =
    $response->{results}[0]{resourceName};
  printf "Added text customizer attribute with resource name '%s'.\n",
    $customizer_attribute_resource_name;

  return $customizer_attribute_resource_name;
}

# Creates a price customizer attribute and returns its resource name.
sub create_price_customizer_attribute {
  my ($api_client, $customer_id, $customizer_name) = @_;

  # Creates a price customizer attribute. The customizer attribute name is
  # arbitrary and will be used as a placeholder in the ad text fields.
  my $price_attribute =
    Google::Ads::GoogleAds::V11::Resources::CustomizerAttribute->new({
      name => $customizer_name,
      type => PRICE
    });

  # Create a customizer attribute operation for creating a customizer attribute.
  my $price_attribute_operation =
    Google::Ads::GoogleAds::V11::Services::CustomizerAttributeService::CustomizerAttributeOperation
    ->new({
      create => $price_attribute
    });

  # Issue a mutate request to add the customizer attribute.
  my $response = $api_client->CustomizerAttributeService()->mutate({
      customerId => $customer_id,
      operations => [$price_attribute_operation]});

  my $customizer_attribute_resource_name =
    $response->{results}[0]{resourceName};
  printf "Added price customizer attribute with resource name '%s'.\n",
    $customizer_attribute_resource_name;

  return $customizer_attribute_resource_name;
}

# Restricts the ad customizer attributes to work only with a specific ad group;
# this prevents the customizer attributes from being used elsewhere and makes sure
# they are used only for customizing a specific ad group.
sub link_customizer_attributes {
  my (
    $api_client, $customer_id, $ad_group_id,
    $text_customizer_attribute_resource_name,
    $price_customizer_attribute_resource_name
  ) = @_;

  my $ad_group_customizer_operations = [];

  # Binds the text attribute customizer to a specific ad group to
  # make sure it will only be used to customizer ads inside that ad group.
  my $marsCustomizer =
    Google::Ads::GoogleAds::V11::Resources::AdGroupCustomizer->new({
      customizerAttribute => $text_customizer_attribute_resource_name,
      value => Google::Ads::GoogleAds::V11::Common::CustomizerValue->new({
          type        => TEXT,
          stringValue => "Mars"
        }
      ),
      adGroup => Google::Ads::GoogleAds::V11::Utils::ResourceNames::ad_group(
        $customer_id, $ad_group_id
      )});

  push @$ad_group_customizer_operations,
    Google::Ads::GoogleAds::V11::Services::AdGroupCustomizerService::AdGroupCustomizerOperation
    ->new({
      create => $marsCustomizer
    });

  # Binds the price attribute customizer to a specific ad group to
  # make sure it will only be used to customizer ads inside that ad group.
  my $priceCustomizer =
    Google::Ads::GoogleAds::V11::Resources::AdGroupCustomizer->new({
      customizerAttribute => $price_customizer_attribute_resource_name,
      value => Google::Ads::GoogleAds::V11::Common::CustomizerValue->new({
          type        => PRICE,
          stringValue => "100.0€"
        }
      ),
      adGroup => Google::Ads::GoogleAds::V11::Utils::ResourceNames::ad_group(
        $customer_id, $ad_group_id
      )});

  push @$ad_group_customizer_operations,
    Google::Ads::GoogleAds::V11::Services::AdGroupCustomizerService::AdGroupCustomizerOperation
    ->new({
      create => $priceCustomizer
    });

  # Issue a mutate request to link the customizers to the ad group.
  my $mutate_ad_group_customizers_response =
    $api_client->AdGroupCustomizerService()->mutate({
      customerId => $customer_id,
      operations => $ad_group_customizer_operations
    });

  # Display the results.
  foreach my $result (@{$mutate_ad_group_customizers_response->{results}}) {
    printf "Added an ad group customizer with resource name '%s'.\n",
      $result->{resourceName};
  }
}

# Creates a responsive search ad that uses the ad customizer attributes to populate the placeholders.
sub create_ad_with_customizations {
  my ($api_client, $customer_id, $ad_group_id, $string_customizer_name,
    $price_customizer_name)
    = @_;

  # Creates a responsive search ad using the attribute customizer names as
  # placeholders and default values to be used in case there are no attribute
  # customizer values.
  my $responsive_search_ad_info =
    Google::Ads::GoogleAds::V11::Common::ResponsiveSearchAdInfo->new({
      headlines => [
        Google::Ads::GoogleAds::V11::Common::AdTextAsset->new({
            text =>
              "Luxury cruise to {CUSTOMIZER.$string_customizer_name:Venus}",
            pinnedField => HEADLINE_1
          }
        ),
        Google::Ads::GoogleAds::V11::Common::AdTextAsset->new({
            text => "Only {CUSTOMIZER.$price_customizer_name:10.0€}",
          }
        ),
        Google::Ads::GoogleAds::V11::Common::AdTextAsset->new({
            text =>
"Cruise to {CUSTOMIZER.$string_customizer_name:Venus} for {CUSTOMIZER.$price_customizer_name:10.0€}",
          })
      ],
      descriptions => [
        Google::Ads::GoogleAds::V11::Common::AdTextAsset->new({
            text =>
              "Tickets are only {CUSTOMIZER.$price_customizer_name:10.0€}!",
          }
        ),
        Google::Ads::GoogleAds::V11::Common::AdTextAsset->new({
            text =>
"Buy your tickets to {CUSTOMIZER.$string_customizer_name:Venus} now!"
          })]});

  my $ad = Google::Ads::GoogleAds::V11::Resources::Ad->new({
      responsiveSearchAd => $responsive_search_ad_info,
      finalUrls          => ["https://www.example.com"]});

  my $ad_group_ad = Google::Ads::GoogleAds::V11::Resources::AdGroupAd->new({
      ad      => $ad,
      adGroup => Google::Ads::GoogleAds::V11::Utils::ResourceNames::ad_group(
        $customer_id, $ad_group_id
      )});

  my $ad_group_ad_operation =
    Google::Ads::GoogleAds::V11::Services::AdGroupAdService::AdGroupAdOperation
    ->new({
      create => $ad_group_ad
    });

  # Issue a mutate request to add the ads.
  my $response = $api_client->AdGroupAdService()->mutate({
      customerId => $customer_id,
      operations => [$ad_group_ad_operation]});

  my $ad_group_ad_resource_name = $response->{results}[0]{resourceName};
  printf "Added an ad with resource name '%s'.\n", $ad_group_ad_resource_name;
}

# 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);

my $customer_id = undef;
my $ad_group_id = undef;

# Parameters passed on the command line will override any parameters set in code.
GetOptions(
  "customer_id=s" => \$customer_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, $ad_group_id);

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

=pod

=head1 NAME

add_ad_customizer

=head1 DESCRIPTION

This code example adds two ad customizer attributes and associates them with the ad group.
Then it adds an ad that uses the ad customizer attributes to populate dynamic data.

=head1 SYNOPSIS

add_ad_customizer.pl [options]

    -help                       Show the help message.
    -customer_id                The Google Ads customer ID.
    -ad_group_id                The ad group ID to add the ad customizers to.

=cut