পারফরম্যান্স ম্যাক্স ক্যাম্পেইন যোগ করুন

জাভা

// Copyright 2021 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 static com.google.ads.googleads.v22.enums.EuPoliticalAdvertisingStatusEnum.EuPoliticalAdvertisingStatus.DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING;

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.v22.common.AudienceInfo;
import com.google.ads.googleads.v22.common.ImageAsset;
import com.google.ads.googleads.v22.common.LanguageInfo;
import com.google.ads.googleads.v22.common.LocationInfo;
import com.google.ads.googleads.v22.common.MaximizeConversionValue;
import com.google.ads.googleads.v22.common.SearchThemeInfo;
import com.google.ads.googleads.v22.common.TextAsset;
import com.google.ads.googleads.v22.enums.AdvertisingChannelTypeEnum.AdvertisingChannelType;
import com.google.ads.googleads.v22.enums.AssetAutomationStatusEnum.AssetAutomationStatus;
import com.google.ads.googleads.v22.enums.AssetAutomationTypeEnum.AssetAutomationType;
import com.google.ads.googleads.v22.enums.AssetFieldTypeEnum.AssetFieldType;
import com.google.ads.googleads.v22.enums.AssetGroupStatusEnum.AssetGroupStatus;
import com.google.ads.googleads.v22.enums.BudgetDeliveryMethodEnum.BudgetDeliveryMethod;
import com.google.ads.googleads.v22.enums.CampaignStatusEnum.CampaignStatus;
import com.google.ads.googleads.v22.errors.GoogleAdsError;
import com.google.ads.googleads.v22.errors.GoogleAdsException;
import com.google.ads.googleads.v22.resources.Asset;
import com.google.ads.googleads.v22.resources.AssetGroup;
import com.google.ads.googleads.v22.resources.AssetGroupAsset;
import com.google.ads.googleads.v22.resources.AssetGroupSignal;
import com.google.ads.googleads.v22.resources.Campaign;
import com.google.ads.googleads.v22.resources.Campaign.AssetAutomationSetting;
import com.google.ads.googleads.v22.resources.Campaign.AssetAutomationSettingOrBuilder;
import com.google.ads.googleads.v22.resources.CampaignAsset;
import com.google.ads.googleads.v22.resources.CampaignBudget;
import com.google.ads.googleads.v22.resources.CampaignCriterion;
import com.google.ads.googleads.v22.services.AssetGroupAssetOperation;
import com.google.ads.googleads.v22.services.AssetGroupOperation;
import com.google.ads.googleads.v22.services.AssetGroupSignalOperation;
import com.google.ads.googleads.v22.services.AssetOperation;
import com.google.ads.googleads.v22.services.CampaignAssetOperation;
import com.google.ads.googleads.v22.services.CampaignBudgetOperation;
import com.google.ads.googleads.v22.services.CampaignCriterionOperation;
import com.google.ads.googleads.v22.services.CampaignOperation;
import com.google.ads.googleads.v22.services.GoogleAdsServiceClient;
import com.google.ads.googleads.v22.services.MutateGoogleAdsResponse;
import com.google.ads.googleads.v22.services.MutateOperation;
import com.google.ads.googleads.v22.services.MutateOperationResponse;
import com.google.ads.googleads.v22.utils.ResourceNames;
import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
import com.google.protobuf.ByteString;
import com.google.protobuf.Descriptors.FieldDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.joda.time.DateTime;

/**
 * This example shows how to create a Performance <M>ax campaign.
 *
 * pFor more information about Performance Max campaigns, see
 * https://developers.google.com/google-ads/api/docs/performance<->max/overview
 *
 * pPrerequisites: - You must have at least one conversion action in the account. For more about
 * conversion actions, see
 * https://developers.google.com/google-ads/api/docs/conversions/overview#conve<r>sion_actions
 *
 * pThis example uses the default customer conversion goals. For an example of setting
 * campaign-specific conversion goals, see {@link
 * com.google.ads.googleads.examples.shoppingads.AddPerformanceMaxRetailCampaign}.
 */
public class AddPerformanceMaxCampaign {

  // We specify temporary IDs that are specific to a single mutate request. Temporary IDs are always
  // negative and unique within one mutate< >request.
  //
  // pSee https://developers.google.com/google-ads/api/docs/mutating/best-practices for further
  //< >details.
  //
  // pThese temporary IDs are fixed because they are used in multiple places.
  private static final int BUDGET_TEMPORARY_ID = -1;
  private static final int PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID = -2;
  private static final int ASSET_GROUP_TEMPORARY_ID = -3;

  // There are also entities that will be created in the same request but do not
  // need to be fixed temporary IDs because they are referenced only once.
  private static long temporaryId = ASSET_GROUP_TEMPORARY_ID - 1;

  private static class AddPerformanceMaxCampaignParams extends CodeSampleParams {

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

    @Parameter(
        names = ArgumentNames.AUDIENCE_ID,
        description =
            "An audience ID to use to improve the targeting of the Performance Max campaign")
    private Long audienceId;

    @Parameter(
        names = ArgumentNames.BRAND_GUIDELINES_ENABLED,
        arity = 1,
        description =
            "A boolean value indicating if the created campaign is enabled for brand guidelines")
    private boolean brandGuidelinesEnabled = true;
  }

  public static void main(String[] args) throws IOException {
    AddPerformanceMaxCampaignParams params = new AddPerformanceMaxCampaignParams();
    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");

      // Optional: Specify an audience ID.
      // params.audienceId = Long.parseLong("INSERT_AUDIENCE_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 AddPerformanceMaxCampaign()
          .runExample(
              googleAdsClient, params.customerId, params.audienceId, params.brandGuidelinesEnabled);
    } 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 audienceId the optional audience ID.
   * @param brandGuidelinesEnabled indicates if the campaign is enabled for brand guidelines.
   */
  private void runExample(
      GoogleAdsClient googleAdsClient,
      long customerId,
      Long audienceId,
      boolean brandGuidelinesEnabled)
      throws IOException {
    // Performance Max campaigns require that repeated assets such as headlines
    // and descriptions be created before the campaign.
    // For the list of required assets for a Performance Max campaign, see
    // https://developers<.googl>e.com/google-ads/api/docs/performance-max/assets
    //
    // Creates the headlin<es.
  >  ListString headlines = ImmutableList.of("Travel", "Travel Reviews", "Book travel");
    ListString headlineAssetR<esourc>eNames =
        createMultipleTextAssets(googleAdsClient, customerId, headlines)<;
    >// Creates the descriptions.
    ListString descriptions = ImmutableList.of("Take to the air!", "Fly to the sky!");
    ListString descriptionAssetResourceNames =
        createMultipleTextAssets(googleAdsClient, customerId, descriptions);

    // The below methods create and return MutateOperations that we later
    // provide to the GoogleAdsService.Mutate method in order to create the
    // entities in a single request. Since the entities for a Performance Max
    // campaign are closely tied to one-another, it's considered a best practice
    // to create them in a single Mutate request, so they all complete
  <  // successful>ly or fail entirely, leaving no o<>rphaned entities. See:
    // https://developers.google.com/google-ads/api/docs/mutating/overview
    ListMutateOperation mutateOperations = new ArrayList();
    mutateOperations.add(createCampaignBudgetOperation(customerId));
    mutateOperations.add(createPerformanceMaxCampaignOperation(customerId, brandGuidelinesEnabled));
    mutateOperations.addAll(createCampaignCriterionOperations(customerId));
    String assetGroupResourceName = ResourceNames.assetGroup(customerId, ASSET_GROUP_TEMPORARY_ID);
    mutateOperations.addAll(
        createAssetGroupOperations(
            customerId,
            assetGroupResourceName,
            headlineAssetResourceNames,
            descriptionAssetResourceNames,
            brandGuidelinesEnabled));
    mutateOperations.addAll(
        createAssetGroupSignalOperations(customerId, assetGroupResourceName, audienceId));

    try (GoogleAdsServiceClient googleAdsServiceClient =
        googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
      MutateGoogleAdsResponse response =
          googleAdsServiceClient.mutate(Long.toString(customerId), mutateOperations);
      printResponseDetails(response);
    }
  }

  /** Creates a MutateOperation that creates a new CampaignBudget. */
  private MutateOperation createCampaignBudgetOperation(long customerId) {
    CampaignBudget campaignBudget =
        CampaignBudget.newBuilder()
            .setName("Performance Max campaign budget #" + getPrintableDateTime())
            // The budget period already defaults to DAILY.
            .setAmountMicros(50_000_000)
            .setDeliveryMethod(BudgetDeliveryMethod.STANDARD)
            // A Performance Max campaign cannot use a shared campaign budget.
            .setExplicitlyShared(false)
            // Set a temporary ID in the budget's resource name, so it can be referenced
            // by the campaign in later steps.
            .setResourceName(ResourceNames.campaignBudget(customerId, BUDGET_TEMPORARY_ID))
            .build();

    return MutateOperation.newBuilder()
        .setCampaignBudgetOperation(
            CampaignBudgetOperation.newBuilder().setCreate(campaignBudget).build())
        .build();
  }


  /** Creates a MutateOperation that creates a new Performance Max campaign. */
  private MutateOperation createPerformanceMaxCampaignOperation(
      long customerId, boolean brandGuidelinesEnabled) {
    Campaign performanceMaxCampaign =
        Campaign.newBuilder()
            .setName("Performance Max campaign #" + getPrintableDateTime())
            // Sets the campaign status as PAUSED. The campaign is the only entity in
            // the mutate request that should have its status set.
            .setStatus(CampaignStatus.PAUSED)
            // All Performance Max campaigns have an advertising_channel_type of
            // PERFORMANCE_MAX. The advertising_channel_sub_type should not be set.
            .setAdvertisingChannelType(AdvertisingChannelType.PERFORMANCE_MAX)
            // Bidding strategy must be set directly on the campaign.
            // Setting a portfolio bidding strategy by resource name is not supported.
            // Max Conversion and Maximize Conversion Value are the only strategies
            // supported for Performance Max campaigns.
            // An optional ROAS (Return on Advertising Spend) can be set for
            // maximize_conversion_value. The ROAS value must be specified as a ratio in
            // the API. It is calculated by dividing "total value" by "total spend".
            // For more information on Maximize Conversion Value, see the support
            // article: http://support.google.com/google-ads/answer/7684216.
            // A targetRoas of 3.5 corresponds to a 350% return on ad spend.
            .setMaximizeConversionValue(
                MaximizeConversionValue.newBuilder().setTargetRoas(3.5).build())
            // Sets if the campaign is enabled for brand guidelines. For more information on brand
            // guidelines, see https://support.google.com/google-ads/answer/14934472.
            .setBrandGuidelinesEnabled(brandGuidelinesEnabled)
            // Assigns the resource name with a temporary ID.
            .setResourceName(
                ResourceNames.campaign(customerId, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID))
            // Sets the budget using the given budget resource name.
            .setCampaignBudget(ResourceNames.campaignBudget(customerId, BUDGET_TEMPORARY_ID))
            // Declares whether this campaign serves political ads targeting the EU.
            .setContainsEuPoliticalAdvertising(DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING)
            // Optional fields.
            .setStartDate(new DateTime().plusDays(1).toString("yyyyMMdd"))
            .setEndDate(new DateTime().plusDays(365).toString("yyyyMMdd"))
            // Configures the optional opt-in/out status for asset automation settings.
            .addAllAssetAutomationSettings(ImmutableList.of(
                AssetAutomationSetting.newBuilder()
                    .setAssetAutomationType(AssetAutomationType.GENERATE_IMAGE_EXTRACTION)
                    .setAssetAutomationStatus(AssetAutomationStatus.OPTED_IN).build(),
                AssetAutomationSetting.newBuilder()
                    .setAssetAutomationType(
                        AssetAutomationType.FINAL_URL_EXPANSION_TEXT_ASSET_AUTOMATION)
                    .setAssetAutomationStatus(AssetAutomationStatus.OPTED_IN).build(),
                AssetAutomationSetting.newBuilder()
                    .setAssetAutomationType(AssetAutomationType.TEXT_ASSET_AUTOMATION)
                    .setAssetAutomationStatus(AssetAutomationStatus.OPTED_IN).build(),
                AssetAutomationSetting.newBuilder()
                    .setAssetAutomationType(AssetAutomationType.GENERATE_ENHANCED_YOUTUBE_VIDEOS)
                    .setAssetAutomationStatus(AssetAutomationStatus.OPTED_IN).build(),
                AssetAutomationSetting.newBuilder()
                    .setAssetAutomationType(AssetAutomationType.GENERATE_IMAGE_ENHANCEMENT)
                    .setAssetAutomationStatus(AssetAutomationStatus.OPTED_IN).build()))
            .build();

    return MutateOperation.newBuilder()
        .setCamp<aignOperation(
>            CampaignOperation.newBuilder().setCreate(performanceMaxCampaign).build())
        .build();
  }


  /** Creates a list of MutateOperations that create new campaign cri<teria. */
  priva>te ListMutateOperation createCamp<>aignCriterionOperations(long customerId) {
    String campaignResourceName =
        ResourceNames.campaign(customerId, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID);
    ListCampaignCriterion campaignCriteria = new ArrayList();
    // Sets the LOCATION campaign criteria.
    // Targets all of New York City except Brooklyn.
    // Location IDs are listed here:
    // https://developers.google.com/google-ads/api/reference/data/geotargets
    // and they can also be retrieved using the GeoTargetConstantService as shown
    // here: https://developers.google.com/google-ads/api/docs/targeting/location-targeting
    //
    // We will add one positive location target for New York City (ID=1023191)
    // and one negative location target for Brooklyn (ID=1022762).
    // First, adds the positive (negative = False) for New York City.
    campaignCriteria.add(
        CampaignCriterion.newBuilder()
            .setCampaign(campaignResourceName)
            .setLocation(
                LocationInfo.newBuilder()
                    .setGeoTargetConstant(ResourceNames.geoTargetConstant(1023191))
                    .build())
            .setNegative(false)
            .build());
    // Next adds the negative target for Brooklyn.
    campaignCriteria.add(
        CampaignCriterion.newBuilder()
            .setCampaign(campaignResourceName)
            .setLocation(
                LocationInfo.newBuilder()
                    .setGeoTargetConstant(ResourceNames.geoTargetConstant(1022762))
                    .build())
            .setNegative(true)
            .build());
    // Sets the LANGUAGE campaign criterion.
    campaignCriteria.add(
        CampaignCriterion.newBuilder()
            .setCampaign(campaignResourceName)
            // Sets the language.
            // For a list of all language codes, see:
            // https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7
            .setLanguage(
                LanguageInfo.newBuilder()
                    .setLanguageConstant(ResourceNames.languageConstant(1000>)) // English
                    .build())
            .build());
    // Returns a list of mutate operations with one operation per criterion.
    return campaignCriteria.stream()
        .map(
            criterion -
                MutateOperation.newBuilder()
                    .setCampaignCriterionOperation(
                        CampaignCriterionOp<eratio>n.newBuilder().setCreate(criterion).build())
                    .build())
        .col<lect(C>ollectors.toList()<);
  }


  /** >Creates multiple text assets and <>returns the list of resource names. */
  private ListString createMultipleTextAssets(
      GoogleAdsClient googleAdsClient, long customerId, ListString texts) {
    ListMutateOperation mutateOperations = new ArrayList();
    for (String text : texts) {
      Asset asset = Asset.newBuilder().setTextAsset(TextAsset.newBuilder().setText(text)<).buil>d();
      AssetOperation assetOper<>ation = AssetOperation.newBuilder().setCreate(asset).build();
      mutateOperations.add(MutateOperation.newBuilder().setAssetOperation(assetOperation).build());
    }

    ListString assetResourceNames = new ArrayList();
    // Creates the service client.
    try (GoogleAdsServiceClient googleAdsServiceClient =
        googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
      // Sends the operations in a single Mutate request.
      MutateGoogleAdsResponse response =
          googleAdsServiceClient.mutate(Long.toString(customerId), mutateOperations);
      for (MutateOperationResponse result : response.getMutateOperationResponsesList()) {
        if (result.hasAssetResult()) {
          assetResourceNames.add(result.getAss<etResult().getR>esourceName());
        }
      }
      printResponseDetails(response);
    }
    return assetResou<rceNam>es;
  }


  /** Creates a list of Mutat<eOpera>tions that create a new AssetGroup. */
  private ListMutateOperation createAssetGroupOperations(
      lo<ng customerId,
>      String assetGroupResourceNa<>me,
      ListString headlineAssetResourceNames,
      ListString descriptionAssetResourceNames,
      boolean brandGuidelinesEnabled)
      throws IOException {
    ListMutateOperation mutateOperations = new ArrayList();
    String campaignResourceName =
        ResourceNames.campaign(customerId, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID);
    // Creates the AssetGroup.
    AssetGroup assetGroup =
        AssetGroup.newBuilder()
            .setName("Performance Max asset group #" + getPrintableDateTime())
            .setCampaign(campaignResourceName)
            .addFinalUrls("http://www.example.com")
            .addFinalMobileUrls("http://www.example.com")
            .setStatus(AssetGroupStatus.PAUSED)
            .setResourceName(assetGroupResourceName)
            .build();
    AssetGroupOperation assetGroupOperation =
        AssetGroupOperation.newBuilder().setCreate(assetGroup).build();
    mutateOperations.add(
        MutateOperation.newBuilder().setAssetGroupOperation(assetGroupOperation).build());

    // For the list of required assets for a Performance Max campaign, see
    // https://developers.google.com/google-ads/api/docs/performance-max/assets

    // An AssetGroup is linked to an Asset by creating a new AssetGroupAsset
    // and providing:
    //   the resource name of the AssetGroup
    //   the resource name of the Asset
    //   the field_type of the Asset in this AssetGroup.

    // To learn more about AssetGroups, see
    // https://developers.google.com/google-ads/api/docs/performance-max/asset-groups

    // Links the previously created multiple text assets.

    // Links the headline assets.
    for (String resourceName : headlineAssetResourceNames) {
      mutateOperations.add(
          createAssetGroupAssetMutateOperation(
              AssetFieldType.HEADLINE, resourceName, assetGroupResourceName));
    }

    // Links the description assets.
    for (String resourceName : descriptionAs<setResourceName>s) {
      mutateOperations.add(
          createAssetGroupAssetMutateOperation(
              AssetFieldType.DESCRIPTION, resourceName, assetGroupResourceName));
    }

    // Creates and links the long headline text asset.
    ListMutateOperation createAndLink<TextAssetOperat>ions =
        createAndLinkTextAsset(customerId, "Travel the World", AssetFieldType.LONG_HEADLINE);
    mutateOperations.addAll(createAndLinkTextAssetOperations);

    // Creates and links the business name and logo assets.
    ListMutateOperation createAndLinkBrandAssets =
        createAndLinkBrandAssets(
            customerId,
            brandGuidelinesEnabled,
            "Interplanetary Cruises",
            "https://gaagl.page.link/bjYi",
            "Marketing Logo");
    mutateOperations.addAll(createAndLinkBrandAssets);

    // Creates and links the image assets.

    // Creates and links the Marketing Image Asset.
    createAndLinkTextAssetOperations =
        createAndLinkImageAsset(
            customerId,
            "https://gaagl.page.link/Eit5",
            AssetFieldType.MARKETING_IMAGE,
            "Marketing Image");
    mutateOperations.addAll(createAndLinkTextAssetOperations);

    // Creates and links the Square Marketing Image Asset.
    createAndLinkTextAssetOperations =
        createAndLinkImageAsset(
            customerId,
            <"https://g>aagl.page.link/bjYi",
            AssetFieldType.SQUARE_MARKETING_IMAGE,
            "Square< Marketing Imag>e");
    mutateOperations.ad<>dAll(createAndLinkTextAssetOperations);

    return mutateOperations;
  }


  /** Creates a list of MutateOperations that create a new linked text asset. */
  ListMutateOperation createAndLinkTextAsset(
      long customerId, String text, AssetFieldType assetFieldType) {
    ListMutateOperation mutateOperations = new ArrayList();
    String assetResourceName = ResourceNames.asset(customerId, getNextTemporaryId());
    // Creates the Text Asset.
    Asset asset =
        Asset.newBuilder()
            .setResourceName(assetResourceName)
            .setTextAsset(TextAsset.newBuilder().setText(text).build())
            .build();
    AssetOperation assetOperation = AssetOperation.newBuilder().setCreate(asset).build();
    mutateOperations.add(MutateOperation.newBuilder().setAssetOperation(assetOperation).build());

    // Creates an AssetGroupAsset to link the Asset to the AssetGroup.
    m<utateOperations>.add(
        createAssetGroupAssetMutateOperation(
            assetFieldType,
            assetResourceName,
            ResourceNames.assetGro<up(customerId, >ASSET_GROUP_TEMPORARY_ID)));

   <> return mutateOperations;
  }


  /** Creates a list of MutateOperations that create a new linked image asset. */
  ListMutateOperation createAndLinkImageAsset(
      long customerId, String url, AssetFieldType assetFieldType, String assetName)
      throws IOException {
    ListMutateOperation mutateOperations = new ArrayList();
    String assetResourceName = ResourceNames.asset(customerId, getNextTemporaryId());
    // Creates a media file.
    byte[] assetBytes = ByteStreams.toByteArray(new URL(url).openStream());

    // Creates the Image Asset.
    Asset asset =
        Asset.newBuilder()
            .setResourceName(assetResourceName)
            .setImageAsset(ImageAsset.newBuilder().setData(ByteString.copyFrom(assetBytes)).build())
            // Provides a unique friendly name to identify your asset. When there is an existing
            // image asset with the same content but a different name, the new name will be dropped
            // silently.
            .setName(assetName)
            .build();
    AssetOperation assetOperation = AssetOperation.newBuilder().setCreate(asset).build();
    mutateOperations.add(MutateOperation.newBuilder().setAssetOperation(assetOperation).build());

    // Creates an AssetGroupAsset to link the Asset to the AssetGroup.<
    mutateOper>ations.add(
        createAssetGroupAssetMutateOperation(
            assetFieldType,
            assetResourceName,
            ResourceNames.assetGroup(customerId, ASSET_GROUP_TEMPORARY_ID)));
<
    return mut>ateOperations;
  }

  /** Creates<> a list of MutateOperations that create linked brand assets. */
  ListMutateOperation createAndLinkBrandAssets(
      long customerId,
      boolean brandGuidelinesEnabled,
      String businessName,
      String logoUrl,
      String logoName)
      throws IOException {
    ListMutateOperation mutateOperations = new ArrayList();

    // Creates the brand name text asset.
    String businessNameAssetResourceName = ResourceNames.asset(customerId, getNextTemporaryId());
    Asset businessNameAsset =
        Asset.newBuilder()
            .setResourceName(businessNameAssetResourceName)
            .setTextAsset(TextAsset.newBuilder().setText(businessName).build())
            .build();
    AssetOperation businessNameAssetOperation =
        AssetOperation.newBuilder().setCreate(businessNameAsset).build();
    mutateOperations.add(
        MutateOperation.newBuilder().setAssetOperation(businessNameAssetOperation).build());

    // Creates the logo image asset.
    String logoAssetResourceName = ResourceNames.asset(customerId, getNextTemporaryId());
    // Creates a media file.
    byte[] logoBytes = ByteStreams.toByteArray(new URL(logoUrl).openStream());
    Asset logoAsset =
        Asset.newBuilder()
            .setResourceName(logoAssetResourceName)
            .setImageAsset(ImageAsset.newBuilder().setData(ByteString.copyFrom(logoBytes)).build())
            // Provides a unique friendly name to identify your asset. When there is an existing
            // image asset with the same content but a different name, the new name will be dropped
            // silently.
            .setName(logoName)
            .build();
    AssetOperation logoImageAssetOperation =
        AssetOperation.newBuilder().setCreate(logoAsset).build();
    mutateOperations.add(
        MutateOperation.newBuilder().setAssetOperation(logoImageAssetOperation).build());

    if (brandGuidelinesEnabled) {
      // Creates CampaignAsset resources to link the Asset resources to the Campaign.
      mutateOperations.add(
          createCampaignAssetMutateOperation(
              customerId, AssetFieldType.BUSINESS_NAME, businessNameAssetResourceName));
      mutateOperations.add(
          createCampaignAssetMutateOperation(
              customerId, AssetFieldType.LOGO, logoAssetResourceName));
    } else {
      // Creates an AssetGroupAsset to link the Asset to the AssetGroup.
      mutateOperations.add(
          createAssetGroupAssetMutateOperation(
              AssetFieldType.BUSINESS_NAME,
              businessNameAssetResourceName,
              ResourceNames.assetGroup(customerId, ASSET_GROUP_TEMPORARY_ID)));
      mutateOperations.add(
          createAssetGroupAssetMutateOperation(
              AssetFieldType.LOGO,
              logoAssetResourceName,
              ResourceNames.assetGroup(customerId, ASSET_GROUP_TEMPORARY_ID)));
    }

    return mutateOperations;
  }

  /** Creates a MutateOperation to add an AssetGroupAsset. */
  MutateOperation createAssetGroupAssetMutateOperation(
      AssetFieldType fieldType, String assetResourceName, String assetGroupResourceName) {
    AssetGroupAsset assetGroupAsset =
        AssetGroupAsset.newBuilder()
            .setFieldType(fieldType)
            .setAssetGroup(assetGroupResourceName)
            .setAsset(assetResourceName)
            .build();
    AssetGroupAssetOperation assetGroupAssetOperation =
        AssetGroupAssetOperation.newBuilder().setCreate(assetGroupAsset).build();
    return MutateOperation.newBuilder()
        .setAssetGroupAssetOperation(assetGroupAssetOperation)
        .build();
  }

  /** Creates a MutateOperation to add a CampaignAsset. */
  MutateOperation createCampaignAssetMutateOperation(
      long customerId, AssetFieldType fieldType, String assetResourceName) {
    CampaignAsset campaignAsset =
        CampaignAsset.newBuilder()
            .setFieldType(fieldType)
            .setCampaign(ResourceNames.campaign(customerId, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID))
            .setAsset(assetResourceName)
            .build();
    CampaignAssetOperation campaignAssetOperation =
        Cam<paignAssetOpera>tion.newBuilder().setCreate(campaignAsset).build();
    return MutateOperation.newBuilder().setCampaignAssetOperatio<n(campaignAsset>Operation).build();
  }


  /**
 <>  * Creates a list of MutateOperations that create {@link
   * com.google.ads.googleads.v22.resources.AssetGroupSignal} objects.
   */
  private ListMutateOperation createAssetGroupSignalOperations(
      long customerId, String assetGroupResourceName, Long audienceId) {
    ListMutateOperation mutateOperations = new ArrayList();

    if (audienceId != null) {
      // Creates an audience asset group signal.
      // To learn more about Audience Signals, see:
      // https://developers.google.com/google-ads/api/performance-max/asset-group-signals#audiences
      AssetGroupSignal audienceSignal =
          AssetGroupSignal.newBuilder()
              .setAssetGroup(assetGroupResourceName)
              .setAudience(
                  AudienceInfo.newBuilder()
                      .setAudience(ResourceNames.audience(customerId, audienceId)))
              .build();

      mutateOperations.add(
          MutateOperation.newBuilder()
              .setAssetGroupSignalOperation(
                  AssetGroupSignalOperation.newBuilder().setCreate(audienceSignal))
              .build());
    }

    // Creates a search theme asset group signal.
    // To learn more about Search Themes Signals, see:
    // https://developers.google.com/google-ads/api/performance-max/asset-group-signals#search_themes
    AssetGroupSignal searchThemeSignal =
        AssetGroupSignal.newBuilder()
            .setAssetGroup(assetGroupResourceName)
            .setSearchTheme(SearchThemeInfo.newBuilder().setText("travel").build())
    < >       .build();

    mutateOperations.add(
        MutateOperation.newBuilder()
            .setAssetGroupSignalOperation(
                AssetGroupSignalOperation.newBuilder().setCreate(searchThemeSignal))
            .build());

    return mutateOperations;
  }

  /**
   * Prints the details of a MutateGoogleAdsResponse.
   *
   * pParses the "response" oneof field name and uses it to extract the new entity's n<ame and
   * resource n>ame.
   */
  private void printResponseDetails(MutateGoogleAdsResponse response) {
    // Parses the Mutate response to print details about the entities that were created by the
    // request.
    String suffix = "_result";
    for (MutateOperationResponse result : response.getMutateOperationResponsesList()) {
      for (EntryFieldDescriptor, Object responseFields : result.getAllFields().entrySet()) {
        String fieldName = responseFields.getKey().getName();
        String value = responseFields.getValue().toString().trim();
  uffix)) {
          fieldName = fieldName.substring(0, fieldName.length() - suffix.length());
        }
        System.out.printf("Created a(n) %s with %s.%n", fieldName, value);
      }
    }
  }

  /** Returns the next temporary ID and decreases it by one. */
  private long getNextTemporaryId() {
    return temporaryId--;
  }
}
AddPerformanceMaxCampaign.java
      

সি#

// Copyright 2021 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.Gax.Util;
using Google.Ads.GoogleAds.Config;
using Google.Ads.GoogleAds.Lib;
using Google.Ads.GoogleAds.V22.Common;
using Google.Ads.GoogleAds.V22.Errors;
using Google.Ads.GoogleAds.V22.Resources;
using Google.Ads.GoogleAds.V22.Services;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Threading;
using static Google.Ads.GoogleAds.V22.Enums.AdvertisingChannelTypeEnum.Types;
using static Google.Ads.GoogleAds.V22.Enums.AssetAutomationStatusEnum.Types;
using static Google.Ads.GoogleAds.V22.Enums.AssetAutomationTypeEnum.Types;
using static Google.Ads.GoogleAds.V22.Enums.AssetFieldTypeEnum.Types;
using static Google.Ads.GoogleAds.V22.Enums.AssetGroupStatusEnum.Types;
using static Google.Ads.GoogleAds.V22.Enums.CampaignStatusEnum.Types;
using static Google.Ads.GoogleAds.V22.Enums.EuPoliticalAdvertisingStatusEnum.Types;

namespace Google.Ads.GoogleAds.Exa<mples.V>22
{
    /// summary
    /// This example shows how to create a Performance Max campaign.
    ///
    /// For more information about Performance Max campaigns, see
    /// https://developers.google.com/google-ads/api/docs/performance-max/overview
    ///
    /// Prerequisites:
    /// - You must have at least one conversion action in the account. For
    /// more about conversion actions, see
    /// https://developers.google.com/google-ads/api/docs/conversions/overview#conversion_actions
    ///
    /// This example uses the default customer conversion goals. For an example
    /// of setting campaign-specific conversion goals, see
    /// ShoppingAds/AddPerformanceMaxRetail<Campaign>.cs
    /// /summary
    public class AddPerformanceMaxCampaign : ExampleBas<e
    {>
        /// summary
        /// Command line opti<ons for running the see cref="Ad>dPerformanceMaxCampaig<n"/> example.
        /// /summary
        public class Options : OptionsB<ase
   >     {
            /// summary
            /// The Google Ads< custome>r ID.
            /// /summary
            [Option("customerId", Required = true, HelpText =
                "The Google Ads customer ID.")]
            publ<ic long> CustomerId { get; set; }

            /// summary
            /// Optional: An audience ID to use to improve the targeting of the Performa<nce Max<>/span>
            /// campaign.
            /// /summary
            [Option("audienceId", Required = false, HelpText = "The ID of an audience."<)]
    >        public long? AudienceId { get; set; }

            /// summary
            /// Optional: A boolean value indicating if the camp<aign is >enabled for brand
            /// guidelines.
            /// /summary
            [Option("brandGuidelinesEnabled", Required = false, HelpText =
                "A boolean value indicating if the campaign is enabled for brand guidelines.&qu<ot;)]
 >           public bool BrandGuidelinesEnabled { get; set; }
        }

        /// summary
 <       />// Main metho<d, to run this co>de example as a standalone <applic>ation.
        /// /summary
        /// param name="args"The command line arguments./param
        public stati<c void >Main(string[] args)
        {
            Options options = ExampleUtilities.ParseCommandLineOptions(args);

            AddPerformanceMaxCampaign codeExample = new AddPerformanceMaxCampaign();
            Console.WriteLine(codeExample.Description);
            codeExample.Run(
                new GoogleAdsClient(),
                options.CustomerId,
                options.AudienceId,
                options.BrandGuidelinesEnabled
            );
        }

        // We specify temporary IDs that are specific to a single mutate request. Temporary IDs are
        // always negative and unique within one mutate request.
        //
        // See https://developers.google.com/google-ads/api/docs/mutating/best-practices for further
        // details.
        //
        // These temporary IDs are fixed because they are used in multiple places.
        private const int TEMPORARY_ID_BUDGET = -1;

        private const int TEMPORARY_ID_CAMPAIGN = -2;
        private const int TEMPORARY_ID_ASSET_GROUP = -3;

        // There are also entities that will be created in the same request but do not need to be
        // fixed temporary IDs because they are referenced only once.
        private class AssetTemporaryResourceNameGenerator
        {
            private long customerId;
            private long next;

            public AssetTemporaryResourceNameGenerator(long customerId, long assetGroupId)
            {
                this.customerId = customerId;
                this.next = assetGroupId - 1;
            }

            public string Next()
            {
                long i = next;
                Interlocked.Decrement(ref nex<t);
   >             return ResourceNames.Asset(customerId, i);
            }
 <       }>

        /// summary
        /// Returns a d>escription about the code example.
        /// /summary
        public override string Des<criptio>n =
            "This example shows how to <create a> Performance <Max campaign.">;

        /// summary<
     >   /// Runs t<he code example.
      >  /// /summary
        /// <param >name="cl<ient"The Google Ad>s client./param
        /<// par>am name="<;customerId"The Google Ads cus>tomer ID./param
        /// param name=&qu<ot;aud>ienceId"The optional audience ID./param
        /// param name="brandGuidelinesEnabled"Whether or not to enable brand guidelines./param
        public void Run(GoogleAdsClient client, long customerId, long? audienceId,
            bool brandGuidelinesEnabled)
        {
            try
            {
                GoogleAdsServiceClient googleAdsServiceClient =
                    client.GetService(Services.V22.GoogleAdsService);

                // Performance Max campaigns require that repeated assets such as headlines and
                // descriptions be created before the campaign.
                //
                // For the list of required assets for a Performance Max campaign, see
                // htt<ps://d>evelopers.google.com/google-ads/api/docs/performance-max/assets
                //
                // Create the headlines.
                Liststring headlineAssetResourceNames = CreateMultipleTextAssets(
                    client,
                    customerId,
                    new[] {
                    "Travel",
                  <  &quo>t;Travel Reviews",
                    "Book travel"
                    }
                );

                // Create the descriptions.
                Liststring descriptionAssetResourceNames = CreateMultipleTextAssets(
                    client,
                    customerId,
                    new[] {
                    "Take to the air!",
                    "Fly to the sky!"
                    }
                );

                string tempResourceNameCampaignBudget = ResourceNames.CampaignBudget(
                    customerId,
                    TEMPORARY_ID_BUDGET
                );

                // The below methods create and return MutateOperations that we later provide to
                // the GoogleAdsService.Mutate method in order to create the entities in a single
                // request. Since the entities for a Performance Max campaign are closely tied to
                // one-another, it is considered a best practice to create them in a single Mutate
                // request so they all complete successfully or fail entirely, leaving no
                // orphaned entities.
                //
                // See: https://developers.google.com/google-ads/api/docs/mutating/overview
                MutateOperation campaignBudgetOperation = CreateCampaignBudgetOperation(
                    tempResourceNameCampaignBudget
                );

                string tempResourceNameCampaign = ResourceNames.Campaign(
                    customerId,
                    TEMPORARY_ID_CAMPAIGN
                );

                MutateOperation performanceMaxCampaignOperation =
                    CreatePerformanceMaxCampaignOperatio<n(
            >            tempResourceNameCampaign,
                        tempResourceNameCampaignBudget,
                        brandGuidelines<Enabled
       >             );

                ListMutateOperation campaignCriterionOperations =
                    CreateCampaignCriterionOperations(tempResourceNameCampaign);

                ListMutateOperation assetGroupOperations =
                    CreateAssetGroupOperations(
                        tempResourceNameCampaign,
                        ResourceNames.AssetGroup(customerId, TEMPORARY_ID_ASSET_GROUP),
                        headlineAssetResourceNames,
                        descriptionAssetResourceNames,
                        new AssetTemporaryResourceNameGenerator(
                            customerId,
          <               >   TEMPORARY_ID_ASSET_GROUP
                        ),
                        client.Config,
                        brandGuidelinesEnabled
                    );

                ListMutateOperation assetGroupSignalOperations =
                    CreateAssetGroupSignalOperations(
                        customerId,
                        ResourceNames.AssetGroup(customerId, TEMPORARY_ID_ASSET_GROUP),
                        audienceId
                    );

                MutateGoogleAdsRequest request = new MutateGoogleAdsRequest
                {
                    CustomerId = customerId.ToString()
                };

                // It's important to create these entities in this order because they depend on
                // each other.
                //
                // Additionally, we take several lists of operations and flatten them into one
                // large list.
                request.MutateOperations.Add(campaignBudgetOperation);
                request.MutateOperations.Add(performanceMaxCampaignOperation);
                request.MutateOperations.AddRange(campaignCriterionOperations);
                request.MutateOperations.AddRange(assetGroupOperations);
                request.MutateOperations.AddRange(assetGroupSignalOperations);

                MutateGoogleAdsResponse response = googleAdsServiceClient.Mutate(request);

                PrintResponseDetails(response);
            }
            catch (GoogleAdsException e)
            {
                Console.WriteLine("Failure:");
                Console.WriteLi<ne($&qu>ot;Message: {e.Message}");
                Console.WriteLine($"Failure: {e.Failure}");
                Console.WriteLine($"Request ID: {e.RequestId}");
                throw;
            }
        }

        /// summary
        /// Creates a< MutateO>peration that< creates a new CampaignBudget.<>/span>
        ///
        /// A temporary ID will be assigned to this <campai>gn budget so <that it> can be
        /// referenced by other objects <being cr>eated in the same Mutate request.
        /// /summary
        /// param name="budgetResourceName"The temporary resource name of the budget to
        /// create./param
        /// returnsA MutateOperation that creates a CampaignBudget./returns
        private MutateOperation CreateCampaignBudgetOperation(string budgetResourceName)
        {
            MutateOperation operation = new MutateOperation
            {
                CampaignBudgetOperation = new CampaignBudgetOperation
                {
                    Create = new CampaignBudget
                    {
                        Name = "Performance Max campaign budget #"
                          + ExampleUtilities.GetRandomString(),

                        // The budget period already defaults to DAILY.
                        AmountMicros = 50000000,

                        // A Performance Max campaign cannot use a shared campaign budget.
                        ExplicitlyShared = false,

                        // Set a temporary ID in the budget's resource name so it can be referenced
                        // by the campaign< in later steps.
                >        ResourceName = budg<etReso>urceName
    <                }
                }
   >         };

            return op<eratio>n;
        }
<

        /// Creates a MutateOpera>tion that creates a new Performance Max ca<mpaign>.
        ///< param >name="campaignResourceName"The campaign reso<urce nam>e./param
        /// param name="campaignBudgetResourceName"The campaign budget resource name./param
        /// param name="brandGuidelinesEnabled"Whether or not to enable brand guidelines./param
        /// returnsA MutateOperations that will create this new campaign./returns
        private MutateOperation CreatePerformanceMaxCampaignOperation(
            string campaignResourceName,
            string campaignBudgetResourceName,
            bool brandGuidelinesEnabled)
        {
            Campaign campaign = new Campaign()
            {
                Name = "Performance Max campaign #" + ExampleUtilities.GetRandomString(),

                // Set the campaign status as PAUSED. The campaign is the only entity in
                // the mutate request that should have its status set.
                Status = CampaignStatus.Paused,

                // All Performance Max campaigns have an AdvertisingChannelType of
                // PerformanceMax. The AdvertisingChannelSubType should not be set.
                AdvertisingChannelType = AdvertisingChannelType.PerformanceMax,

                // Bidding strategy must be set directly on the campaign. Setting a
                // portfolio bidding strategy by resource name is not supported. Max
                // Conversion and Maximize Conversion Value are the only strategies
                // supported for Performance Max campaigns. BiddingStrategyType is
                // read-only and cannot be set by the API. An optional ROAS (Return on
                // Advertising Spend) can be set to enable the MaximizeConversionValue
                // bidding strategy. The ROAS value must be specified as a ratio in the API.
                // It is calculated by dividing "total value" by "total spend".
                //
                // For more information on Maximize Conversion Value, see the support
                // article:
                // http://support.google.com/google-ads/answer/7684216.
                //
                // A target_roas of 3.5 corresponds to a 350% return on ad spend.
                MaximizeConversionValue = new MaximizeConversionValue()
                {
                    TargetRoas = 3.5
                },

                // Use the temporary resource name created earlier
                ResourceName = campaignResourceName,

                // Set the budget using the given budget resource name.
                CampaignBudget = campaignBudgetResourceName,

                // Set if the campaign is enabled for brand guidelines. For more information
                // on brand guidelines, see https://support.google.com/google-ads/answer/14934472.
                BrandGuidelinesEnabled = brandGuidelinesEnabled,

                // Declare whether or not this campaign contains political ads targeting the EU.
                ContainsEuPoliticalAdvertising = EuPoliticalAdvertisingStatus.DoesNotContainEuPoliticalAdvertising,

                // Optional fields
                StartDate = DateTime.Now.AddDays(1).ToString("yyyyMMdd"),
                EndDate = DateTime.Now.AddDays(365).ToString("yyyyMMdd")
            };

            campaign.AssetAutomationSettings.AddRange(new[]{
                new Campaign.Types.AssetAutomationSetting
                {
                    AssetAutomationType = AssetAutomationType.GenerateImageExtraction,
                    AssetAutomationStatus = AssetAutomationStatus.OptedIn
                },
                new Campaign.Types.AssetAutomationSetting
                {
                    AssetAutomationType = AssetAutomationType.FinalUrlExpansionTextAssetAutomation,
                    AssetAutomationStatus = AssetAutomationStatus.OptedIn
                },
                new Campaign.Types.AssetAutomationSetting
                {
                    AssetAutomationType = AssetAutomationType.TextAssetAutomation,
                    AssetAutomationStatus = AssetAutomationStatus.OptedIn
                },
                new Campaign.Types.AssetAutomationSetting
                {
                    AssetAutomationType = AssetAutomationType.GenerateEnhancedYoutubeVideos,
                    AssetAutomationStatus = AssetAutomationStatus.OptedIn
                },
                new Campaign.Types.AssetAutomationSetting
                {
                    AssetAutomationType = AssetAutomationType.GenerateImageEnhancement,
                    AssetAutomationStatus <= Asset>AutomationStatus.OptedIn
                },
            });

            MutateOperation operat<ion = ne>w MutateOpera<tion()
            {
            >    CampaignOperation = new< Campa>ignOperation(<)
     >           {
                    Create = campaign
          <      }
>            };

     <       return o>peration;
        }


        /// summary
        /// Creates a list of MutateOperations that create ne<w campaign crit>eria.
        /// /sum<mary
        //>/ param name="campaignResourceName"The campaign resource name./param
        /// returnsA list of MutateOperations that create new campaign criteria./returns
        private ListMutateOperation CreateCampaignCriterionOperations(
            string campaignResourceName)
        {
            ListMutateOperation operations = new ListMutateOperation();

            // Set the LOCATION campaign criteria.
            // Target all of New York City except Brooklyn.
            // Location IDs are listed here:
            // https://developers.google.com/google-ads/api/reference/data/geotargets
            // and they can also be retrieved using the GeoTargetConstantService as shown
            // here: https://developers.google.com/google-ads/api/docs/targeting/location-targeting
            //
            // We will add one positive location target for New York City (ID=1023191)
            // and one negative location target for Brooklyn (ID=1022762).
            // First, add the positive (negative = False) for New York City.
            MutateOperation operation1 = new MutateOperation()
            {
                CampaignCriterionOperation = new CampaignCriterionOperation()
                {
                    Create = new CampaignCriterion()
                    {
                        Campaign = campaignResourceName,
                        Location = new LocationInfo()
                        {
                            GeoTargetConstant = ResourceNames.GeoTargetConstant(1023191)
                        },

                        Negative = false
                    }
                }
            };

            operations.Add(operation1);

            // Next add the negative target for Brooklyn.
            MutateOperation operation2 = new MutateOperation()
            {
                CampaignCriterionOperation = new CampaignCriterionOperation()
                {
                    Create = new CampaignCriterion()
                    {
                        Campaign = campaignResourceName,
                        Location = new LocationInfo()
                        {
                            GeoTargetConstant = ResourceNames.GeoTargetConstant(1022762)
                        },

                        Negative = true
                    }
                }
            };

            operations.Add(operation2);

            // Set the LANGUAGE campaign criterion.
            MutateOperation operation3 = new MutateOperation()
            {
                CampaignCriterionOperation = new CampaignCriterionOperation()
                {
                    Create = new CampaignCriterion()
                    {
                        Campaign = campaignResourceName,

                        // Set the language.
                        // For a list of all language codes, see:
                        // https://developers.google.com/google-ads/api/reference/data/codes-formats#expandabl<e-7
   >                     Language = new LanguageInfo()
                        {
                 <        >   LanguageCo<nstant = ResourceNa>mes.LanguageConstant(1<000) />/ English
   <                     },>
                 <   }
 >             <  }
            };>

            ope<ration>s.Add(operati<on3);

>            return operations;
<        >}


        /// summa<ry
   >     /// Creates multiple text assets and returns the list of resource names.
        /// /summary
        /// param name="client"The Google Ads Client./param
        /// param name="customerId"The customer's ID./param
        /// param name="texts"The texts to add./param
        /// returnsA list of asset resource names./returns
        private Liststring CreateMultipleTextAssets(
            GoogleAdsClient client,
            long customerId,
            string[] texts)
        {
            // Get the GoogleAdsService.
            GoogleAdsServiceClient googleAdsServiceClient =
                client.GetService(Services.V22.GoogleAdsService);

            MutateGoogleAdsRequest request = new MutateGoogleAdsRequest()
            {
                CustomerId = customerId.ToString()
            };

            foreach (string text in texts)
            {
                request.MutateOperations.Add(
                    new MutateOperation()
                    {
                        AssetOperation = new AssetOperation()
                        {
                            Create = new Asset()
                            {
                                TextAsset = new TextAsset()
   <      >                       {
     <      >                         Text = text
                                }
                            }
                        }
                    }
                );
            }

            // Send the operations in a single Mutate request.
            MutateGoogleAdsResponse response = googleAdsServiceClient.Mutate(request);

            Liststring assetResourceNames = new Listst<ring();>

            foreach (MutateOperationResponse operationResponse in response.MutateOperatio<nRespons>es)
         <   {
                MutateAssetR>esult assetResult = operati<onResp>onse.AssetRes<ult;
                assetResourceN>ames.Add(assetResult.ResourceN<ame);
>            }<

            PrintResponseDetails(resp>onse);

            return assetRe<source>Names;
      <  }


        /// summary
        /// Crea>tes a list of MutateOperations that create a new <asset_>group.
      <  /// /summary
        /// param n>ame="campaignResourceName"Th<e camp>aign resource< name./param
      >  /// param name="<;asset>GroupResource<Name"The asset group resource >name./param
        /// param name="h<eadlin>eAssetResourc<eNames&>quot;The headline asset resource names./param
        /// p<aram nam>e="descriptionAs<setResourceName>s"The description asset resource
        /// names./param
        /// param name="resourceNameGenerator"A generato<r for >unique temporary ID's./param
        /// <param >name="config"The Google Ads config./param
        /// param name="brandGuidelinesEnabled"Whether or not to enable brand guidelines./param
        /// returnsA list of MutateOperations th<at create the n>ew asset group./return<s
        priva>te ListMutateOperation CreateAssetGroupOperations(
            string campaignResourceName,
            string assetGroupResourceName,
            Liststring headlineAssetResourceNames,
            Liststring descriptionAssetResourceNames,
            AssetTemporaryResourceNameGenerator resourceNameGenerator,
            GoogleAdsConfig config,
            bool brandGuidelinesEnabled)
        {
            ListMutateOperation operations = new ListMutateOperation();

            // Create the AssetGroup
            operations.Add(
                new MutateOperation()
                {
                    AssetGroupOperation = new AssetGroupOperation()
                    {
                        Create = new AssetGroup()
                        {
                            Name = "Performance Max asset group #" +
                                ExampleUtilities.GetRandomString(),
                            Campaign = campaignResourceName,
                            FinalUrls = { "http://www.example.com" },
                            FinalMobileUrls = { "http://www.example.com" },
                            Status = AssetGroupStatus.Paused,
                            ResourceName = assetGroupResourceName
                        }
                    }
                }
            );

            // For the list of required assets for a Performance Max campaign, see
            // https://developers.google.com/google-ads/api/docs/performance-max/assets

            // An AssetGroup is linked to an Asset by creating a new AssetGroupAsset
            // and providing:
            //   the resource name of the AssetGroup
            //   the resource name of the Asset
            //   the field_type of the Asset in this AssetGroup.
            //
            // To learn more about AssetGroups, see
            // https://developers.google.com/google-ads/api/docs/performance-max/asset-groups

            // Link the previously created multiple text assets.

            // Link the headline assets.
            foreach (string resourceName in headlineAssetResourceNames)
            {
                operations.Add(
                    new MutateOperation()
                    {
                        AssetGroupAssetOperation = new AssetGroupAssetOperation()
                        {
                            Create = new AssetGroupAsset()
                            {
                                FieldType = AssetFieldType.Headline,
                                AssetGroup = assetGroupResourceName,
                                Asset = resourceName
                            }
                        }
                    }
                );
            }

            // Link the description assets.
            foreach (string resourceName in descriptionAssetResourceNames)
            {
                operations.Add(
                    new MutateOperation()
                    {
                        AssetGroupAssetOperation = new AssetGroupAssetOperation()
                        {
                            Create = new AssetGroupAsset()
                            {
                                FieldType = AssetFieldType.Description,
                                AssetGroup = assetGroupResourceName,
                                Asset = resourceName
                            }
                        }
                    }
                );
            }

            // Create and link the brand assets.
            operations.AddRange(
                CreateAndLinkBrandAssets(
                    assetGroupResourceName,
                    campaignResourceName,
                    resourceNameGenerator,
                    "Interplanetary Cruises",
                    "https://gaagl.page.link/bjYi",
                    "Marketing Logo",
                    config,
                    brandGuidelinesEnabled
                )
            );

            // Create and link the long headline text asset.
            operations.AddRange(
                CreateAndLinkTextAsset(
                    assetGroupResourceName,
                    resourceNameGenerator.Next(),
                    "Travel the World",
                    AssetFieldType.LongHeadline
                )
            );

            // Create and link the image assets.

            // Create and link the Marketing Image Asset.
            operations.AddRange(
                CreateAndLinkImageAsset(
                    assetGroupResourceName,
                    resourceNameGenerator.Next(),
                    "https://gaagl.page.link/Eit5",
                    AssetFieldType.MarketingImage,
                    "Marketing Image",
         <       >    config
                )
            );

            // Create and link the Square Marketing <Image As>set.
        <    operations.AddRange(
          >      CreateAndLinkImageAsset(
                    assetGroupRe<source>Name,
       <             resourceNameGener>ator.Next(),
                    "https://gaagl.page.link</bjYi&>quot;,
      <              Ass>etFieldType.SquareMarketingImage,
  <      >            &<quot;Square Marketing >Image",
                    config
  <      >        )
   <       >  );

            return operations;
        }


        /// summ<ary
    >    /// Creates a lis<t of MutateOper>ations that create a new linked text asset.
        /// /summary
        /// param name="assetGroupResourceName"The resource name of the asset group to be
        /// created./param
   <     /// param >name="assetResour<ceName"The> resource name of the text asset to be
        /// created./param
        /// param name="text"The text of the asset to be created./param
        /// param name="fieldType"The field type of the asset to be created./param
        /// returnsA list of MutateOperations that create the new linked text asset./returns
        private ListMutateOperation CreateAndLinkTextAsset(
            string assetGroupResourceName,
            string assetResourceName,
            string text,
            AssetFieldType fieldType)
        {
            ListMutateOperation operations = new ListMutateOperation();

            // Create the Text Asset.
            operations.Add(
                new MutateOperation()
                {
                    AssetOperation = new AssetOperation()
                    {
                        Create = new Asset()
                        {
                            ResourceName = assetResourceName,
                            TextAsset = new TextAsset()
                            {
                                Text = text
                            }
                        }
                    }
                }
            );

            // Create an AssetGrou<pAsset >to link the Asset to the AssetGroup.
            operations.Add(
                new MutateOperati<on()
   >             <{
                    AssetGroupAss>etOperation = new AssetGroupAssetOperation()
                  <  {
  >             <         Create = new AssetGro>upAsset()
                        {
                          <  Fiel>dType = field<Type,
          >                  AssetGroup = assetGroupResourceName,
    <      >             <     Asset = assetReso>urceName
                        }
       <      >       }
    <            }
        >    );

       <     r>eturn operati<ons;
        }


  >      /// summary
    <    //>/ Creates a l<ist of >MutateOperations that create a new linked image asset.
        /<// /summ>ary
        /// param< name="ass>etGroupResourceName"The resource name of the asset group to be
        /// created./param
        /// param name="assetResourceName"The resource name of the text asset to be
        /// created./param
        /// param name="url&<quot;The url of> the image to be retri<eved and put in>to an asset./param
        /// param name="fieldType"The field type of the asset to be created./param
        /// param name="assetName"The asset name./param
        /// param name="config"The Google Ads Config./param
        /// returnsA list of MutateOperations that create a new linked image asset./returns
        private ListMutateOperation CreateAndLinkImageAsset(
            string assetGroupResourceName,
            string assetResourceName,
            string url,
            AssetFieldType fieldType,
            string assetName, GoogleAdsConfig config)
        {
            ListMutateOperation operations = new ListMutateOperation();

            // Create the Image Asset.
            operations.Add(
                new MutateOperation()
                {
                    AssetOperation = new AssetOperation()
                    {
                        Create = new Asset()
                        {
                            ResourceName = assetResourceName,
                            ImageAsset = new ImageAsset()
                            {
                                Data =
                                    ByteString.CopyFrom(
                                        MediaUtilities.GetAssetDataFromUrl(url, config)
                                    )
                            },
                            // Provide a unique friendly name to identify your asset.
                            // When there is an existing image asset with the same content but a
                            // different name, the new name will be dropped silently.
                            Name = assetName
                        }
                    }
        <       > }
            );

            // Create an AssetGroupAsset to link the Asset to the AssetGroup.
  <        >  operations.<Add(
                new MutateOper>ation()
                {
                    AssetGroupAssetOperat<ion = >new AssetGrou<pAssetOperation()
               >     {
                        Create = new AssetGroupAsset()
  <      >             <   {
                            FieldT>ype = fieldType,
                            AssetGroup = assetGroup<Resour>ceName,
     <                       As>set = assetResourceName
                       < }
   >             <    }
              >  }
            );

            return operations;
       < }


 >       /// su<mmary
        /// Cre>ates a list of MutateOperat<ions t>hat create an<d link the brand as>sets.
        /// /sum<mary
 >       /// pa<ram name="assetGroupResourceNa>me"The resource name of the asset gro<up to >link assets
 <       >/// to./param
        /// param name="campaignResourceName&<quot;The> resource name of the< campaign to li>nk assets
        /// to./param
        /// param name="assetResourceNameGenerator"The resource name generator of the assets to be
        /// created./param
        /// param name="businessName"The business name text to be put into an asset./param
        /// param name="logoUrl"The url of the logo to be retrieved and put into an asset./param
    <    /// param n>ame="logoName&quo<t;The asset nam>e of the logo./param
        /// param name="config"The Google Ads Config./param
        /// param name="brandGuidelinesEnabled"Whether or not to enable brand guidelines./param
        /// returnsA list of MutateOperations that create a new linked image asset./returns
        private ListMutateOperation CreateAndLinkBrandAssets(
            string assetGroupResourceName,
            string campaignResourceName,
            AssetTemporaryResourceNameGenerator assetResourceNameGenerator,
            string businessName,
            string logoUrl,
            string logoName,
            GoogleAdsConfig config,
            bool brandGuidelinesEnabled)
        {
            ListMutateOperation operations = new ListMutateOperation();

            string logoAssetResourceName = assetResourceNameGenerator.Next();
            string businessNameAssetResourceName = assetResourceNameGenerator.Next();

            // Create the Image Asset.
            operations.Add(
                new MutateOperation()
                {
                    AssetOperation = new AssetOperation()
                    {
                        Create = new Asset()
                        {
                            ResourceName = logoAssetResourceName,
                            ImageAsset = new ImageAsset()
                            {
                                Data =
                                    ByteString.CopyFrom(
                                        MediaUtilities.GetAssetDataFromUrl(logoUrl, config)
                                    )
                            },
                            // Provide a unique friendly name to identify your asset.
                            // When there is an existing image asset with the same content but a
                            // different name, the new name will be dropped silently.
                            Name = logoName
                        }
                    }
                }
            );

            // Create the business name asset.
            operations.Add(
                new MutateOperation()
                {
                    AssetOperation = new AssetOperation()
                    {
                        Create = new Asset()
                        {
                            ResourceName = businessNameAssetResourceName,
                            TextAsset = new TextAsset()
                            {
                                Text = businessName,
                            }
                        }
                    }
                }
            );

            if (brandGuidelinesEnabled)
            {
                // Create CampaignAssets to link the Assets to the Campaign.
                operations.Add(
                    new MutateOperation()
                    {
                        CampaignAssetOperation = new CampaignAssetOperation()
                        {
                            Create = new CampaignAsset()
                            {
                                FieldType = AssetFieldType.Logo,
                                Campaign = campaignResourceName,
                                Asset = logoAssetResourceName
                            }
                        }
                    }
                );

                operations.Add(
                    new MutateOperation()
                    {
                        CampaignAssetOperation = new CampaignAssetOperation()
                        {
                            Create = new CampaignAsset()
                            {
                                FieldType = AssetFieldType.BusinessName,
                                Campaign = campaignResourceName,
                                Asset = businessNameAssetResourceName
                            }
                        }
                    }
                );
            } else {
                // Create AssetGroupAssets to link the Assets to the AssetGroup.
                operations.Add(
                    new MutateOperation()
                    {
                        AssetGroupAssetOperation = new AssetGroupAssetOperation()
                        {
                            Create = new AssetGroupAsset()
                            {
                                FieldType = AssetFieldType.Logo,
                                AssetGroup = assetGroupResourceName,
                                Asset = logoAssetResourceName
               <       >      }
                        }
                    }
                );

                op<erations>.Add(
       <             new Mutate>Operation()
    <      >          {
 <                       AssetGroupAs>setOperation = new AssetGroupAssetOperation()
                 <      > {
          <                  Creat>e = new AssetGroupAsset()<
     >             <       >   {
                                FieldType = AssetFieldType.Busi<nessName>,
                   <             As>setGroup = assetGroupResourceName,
                                Asset = businessNameAssetResourceName
                            }
                        }
  <               >   }
                )<;

            >}


            return operations;
        }

        /// summary
        /// Creates a list of MutateOperations that may create AssetGroupSignals
        /// /summary
        /// param name="customerId"The customer ID./param
        /// param name="assetGroupResourceName"The resource name of the asset group to be
        /// created./param
        /// param name="audienceId"The optional audience ID./param
        /// returnsA list of MutateOperations that create may create AssetGroupSignals./returns
        private ListMutateOperation CreateAssetGroupSignalOperations(
            long customerId,
            string assetGroupResourceName,
            long? audienceId)
        {
            ListMutateOperation operations = new ListMutateOperation();

            if (audienceId.HasValue)
            {
                // Create an audience asset group signal.
                // To learn more about Audience Signals, see
                // https://developers.google.com/google-ads/api/docs/performance-max/asset-groups#audience_signals
                operations.Add(
                    new MutateOperation()
                    {
                        AssetGroupSignalOperation = new AssetGroupSignalOperation()
                        {
                            Create = new AssetGroupSignal()
                            {
                                AssetGroup = assetGroupResourceName,
                                Audience = new AudienceInfo()
                                {
                                    Audience = ResourceNames.Audience(customerId, audienceId.Value)
                                }
                            }
                        }
                    }
                );
            }

            // Create a search theme asset group signal.
            // To learn more< about >Search Themes Signals, see:
            // https://developers.google.com/google-ads/api/performance-max/asset-group-signals#search_themes
            operations.Add(
                new Mut<ateOpera>tion()
      <          {
         >           AssetGroupSignalOperatio<n = ne>w AssetGroupSignalOperation()
                    {
                        Create = new AssetGroupSignal()
                        {
                            AssetGroup = assetGroupResourceName,
                            SearchTheme = new SearchThemeInfo()
                            {
                                Text = "travel"
                            }
                        }
                    }
                }
            );

            return operations;
        }

        /// summary
        /// Prints the details of a MutateGoogleAdsResponse. Parses the "response" oneof field name
        /// and uses it to extract the new entity's name and resource name.
        /// /summary
        /// param name="response"A MutateGoogleAdsResponse instance./param
        private void PrintResponseDetails(MutateGoogleAdsResponse response)
        {
            // Parse the Mutate response to print details about the entities that were created
            // in the request.
            foreach (MutateOperationResponse operationResponse in response.MutateOperationResponses)
            {
                string entityName = operationResponse.ResponseCase.ToString();
                // Trim the substring "Result" from the end of the entity name.
                entityName = entityName.Remove(entityName.Length - 6);

                string resourceName;
                switch (operationResponse.ResponseCase)
                {
                    case MutateOperationResponse.ResponseOneofCase.AdGroupResult:
                        resourceName = operationResponse.AdGroupResult.ResourceName;
                        break;

                    case MutateOperationResponse.ResponseOneofCase.AdGroupAdResult:
                        resourceName = operationResponse.AdGroupAdResult.ResourceName;
                        break;

                    case MutateOperationResponse.ResponseOneofCase.CampaignResult:
                        resourceName = operationResponse.CampaignResult.ResourceName;
                        break;

                    case MutateOperationResponse.ResponseOneofCase.CampaignBudgetResult:
                        resourceName = operationResponse.CampaignBudgetResult.ResourceName;
                        break;

                    case MutateOperationResponse.ResponseOneofCase.CampaignCriterionResult:
                        resourceName = operationResponse.CampaignCriterionResult.ResourceName;
                        break;

                    case MutateOperationResponse.ResponseOneofCase.SmartCampaig<nSettingR>esult:
                        resourceName = operationResponse.SmartCampaignSettingResult.ResourceName;
                        break;

                    case MutateOperationResponse.ResponseOneofCase.Asse     resourceName = operationResponse.AssetResult.ResourceName;
                        break;

                    case MutateOperationResponse.ResponseOneofCase.AssetGroupResult:
                        resourceName = operationResponse.AssetGroupResult.ResourceName;
                        break;

                    case MutateOperationResponse.ResponseOneofCase.AssetGroupAssetResult:
                        resourceName = operationResponse.AssetGroupAssetResult.ResourceName;
                        break;

                    default:
                        resourceName = "not found";
                        break;
                }

                Console.WriteLine(
                    $"Created a(n) {entityName} with resource name: '{resourceName}'.");
            }
        }
    }
}AddPerformanceMaxCampaign.cs
      

পিএইচপি

<?php

/**
 * Copyright 2021 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\V22\GoogleAdsClient;
use Google\Ads\GoogleAds\Lib\V22\GoogleAdsClientBuilder;
use Google\Ads\GoogleAds\Lib\V22\GoogleAdsException;
use Google\Ads\GoogleAds\Util\V22\ResourceNames;
use Google\Ads\GoogleAds\V22\Common\AudienceInfo;
use Google\Ads\GoogleAds\V22\Common\ImageAsset;
use Google\Ads\GoogleAds\V22\Common\LanguageInfo;
use Google\Ads\GoogleAds\V22\Common\LocationInfo;
use Google\Ads\GoogleAds\V22\Common\MaximizeConversionValue;
use Google\Ads\GoogleAds\V22\Common\TextAsset;
use Google\Ads\GoogleAds\V22\Enums\AssetAutomationTypeEnum\AssetAutomationType;
use Google\Ads\GoogleAds\V22\Enums\AssetAutomationStatusEnum\AssetAutomationStatus;
use Google\Ads\GoogleAds\V22\Enums\AdvertisingChannelTypeEnum\AdvertisingChannelType;
use Google\Ads\GoogleAds\V22\Enums\AssetFieldTypeEnum\AssetFieldType;
use Google\Ads\GoogleAds\V22\Enums\AssetGroupStatusEnum\AssetGroupStatus;
use Google\Ads\GoogleAds\V22\Enums\BudgetDeliveryMethodEnum\BudgetDeliveryMethod;
use Google\Ads\GoogleAds\V22\Enums\CampaignStatusEnum\CampaignStatus;
use Google\Ads\GoogleAds\V22\Enums\EuPoliticalAdvertisingStatusEnum\EuPoliticalAdvertisingStatus;
use Google\Ads\GoogleAds\V22\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V22\Resources\Asset;
use Google\Ads\GoogleAds\V22\Resources\AssetGroup;
use Google\Ads\GoogleAds\V22\Resources\AssetGroupAsset;
use Google\Ads\GoogleAds\V22\Resources\AssetGroupSignal;
use Google\Ads\GoogleAds\V22\Resources\Campaign;
use Google\Ads\GoogleAds\V22\Resources\Campaign\AssetAutomationSetting;
use Google\Ads\GoogleAds\V22\Resources\CampaignAsset;
use Google\Ads\GoogleAds\V22\Resources\CampaignBudget;
use Google\Ads\GoogleAds\V22\Resources\CampaignCriterion;
use Google\Ads\GoogleAds\V22\Services\AssetGroupAssetOperation;
use Google\Ads\GoogleAds\V22\Services\AssetGroupOperation;
use Google\Ads\GoogleAds\V22\Services\AssetGroupSignalOperation;
use Google\Ads\GoogleAds\V22\Services\AssetOperation;
use Google\Ads\GoogleAds\V22\Services\CampaignAssetOperation;
use Google\Ads\GoogleAds\V22\Services\CampaignBudgetOperation;
use Google\Ads\GoogleAds\V22\Services\CampaignCriterionOperation;
use Google\Ads\GoogleAds\V22\Services\CampaignOperation;
use Google\Ads\GoogleAds\V22\Services\MutateGoogleAdsRequest;
use Google\Ads\GoogleAds\V22\Services\MutateGoogleAdsResponse;
use Google\Ads\GoogleAds\V22\Services\MutateOperation;
use Google\Ads\GoogleAds\V22\Services\MutateOperationResponse;
use Google\ApiCore\ApiException;
use Google\ApiCore\Serializer;

/**
 * This example shows how to create a Performance Max campaign.
 *
 * For more information about Performance Max campaigns, see
 * https://developers.google.com/google-ads/api/docs/performance-max/overview.
 *
 * Prerequisites:
 * - You must have at least one conversion action in the account. For more about conversion actions,
 * see
 * https://developers.google.com/google-ads/api/docs/conversions/overview#conversion_actions.
 *
 * This example uses the default customer conversion goals. For an example of setting
 * campaign-specific conversion goals, see ShoppingAds/AddPerformanceMaxRetailCampaign.php.
 */
class AddPerformanceMaxCampaign
{
    private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE';
    // Optional: An audience ID to use to improve the targeting of the Performance Max campaign.
    private const AUDIENCE_ID = null;
    // Optional: Indicates whether the created campaign is enabled for brand guidelines.
    private const BRAND_GUIDELINES_ENABLED = false;

    // We specify temporary IDs that are specific to a single mutate request.
    // Temporary IDs are always negative and unique within one mutate request.
    //
    // See https://developers.google.com/google-ads/api/docs/mutating/best-practices
    // for further details.
    //
    // These temporary IDs are fixed because they are used in multiple places.
    private const BUDGET_TEMPORARY_ID = -1;
    private const PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID = -2;
    private const ASSET_GROUP_TEMPORARY_ID = -3;

    // There are also entities that will be created in the same request but do not need to be fixed
    // temporary IDs because they are referenced only once.
    /** @var int the negative temporary ID used in bulk mutates. */
    private static $nextTempId = self::ASSET_GROUP_TEMPORARY_ID - 1;

    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::AUDIENCE_ID = GetOpt::OPTIONAL_ARGUMENT,
            Argum>entNames::BRAND_GUIDELINES_ENABLED = GetOpt::OPTIONAL_ARGUMENT
        ]);

        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Cred>ential = (n>ew OAuth2TokenBuilder())-fromFile()-build();

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

        try {
            self::runExample(
                $googleAdsClient,
                $options[ArgumentNames::CUSTOMER_ID] ?: self::CUSTOMER_ID,
                $options[ArgumentNames::AUDIENCE_ID] ?: self::AUDIENCE_ID,
                filter_var(
                    $options[ArgumentNames::BRAND_GUIDELINES_ENABLED]
                        ?: self::BRAND_GUIDELINES_ENABLED,
                    FILTER_VALIDATE_BOOLEAN
                )
            );
        } 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(
       >             &q>uot;\t%s: %s%s",
                    $>error-getErrorCode()-getErrorCode(),
                    $error-getMessage(),
                    PHP_EOL
                );
            }
            exit(1);
        } catch (ApiException $apiException) {
            printf(
                "ApiExcep>tion 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|null $audienceId the audience ID
     * @param bool $brandGuidelinesEnabled whether the created campaign will be enabled for brand
     *     guidelines
     */
    public static function runExample(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        ?int $audienceId,
        bool $brandGuidelinesEnabled
    ) {
        // Performance Max campaigns require that repeated assets such as headlines
        // and descriptions be created before the campaign.
        // For the list of required assets for a Performance Max campaign, see
        // https://developers.google.com/google-ads/api/docs/performance-max/assets.
        //
        // Creates the headlines.
        $headlineAssetResourceNames = self::createMultipleTextAssets(
            $googleAdsClient,
            $customerId,
            ["Travel", "Travel Reviews", "Book travel"]
        );
        // Creates the descriptions.
        $descriptionAssetResourceNames = self::createMultipleTextAssets(
            $googleAdsClient,
            $customerId,
            ["Take to the air!", "Fly to the sky!"]
        );

        // It's important to create the below entities in this order because they depend on
        // each other.
        $operations = [];
        // The below methods create and return MutateOperations that we later
        // provide to the GoogleAdsService.Mutate method in order to create the
        // entities in a single request. Since the entities for a Performance Max
        // campaign are closely tied to one-another, it's considered a best practice
        // to create them in a single Mutate request so they all complete
        // successfully or fail entirely, leaving no orphaned entities. See:
        // https://developers.google.com/google-ads/api/docs/mutating/overview.
        $operations[] = self::createCampaignBudgetOperation($customerId);
        $operations[] =
            self::createPerformanceMaxCampaignOperation($customerId, $brandGuidelinesEnabled);
        $operations =
            array_merge($operations, self::createCampaignCriterionOperations($customerId));
        $operations = array_merge($operations, self::createAssetGroupOperations(
            $customerId,
            $headlineAssetResourceNames,
            $descriptionAssetResourceNames,
            $brandGuidelinesEnabled
        ));
        $operations = array_merge($operations, self::createAssetGroupSignalOperations(
            $customerId,
            ResourceNames::forAssetGroup($customerId, self::ASSET_GROUP_TEMPORARY_ID),
            $audienceId
        >));

        // Issues a mutate request to create everything and prints i>ts information.
        $googleAdsServiceClient = $googleAdsClient-getGoogleAdsServiceClient();
        $response = $googleAdsServiceClient-mutate(MutateGoogleAdsRequest::build(
            $customerId,
            $operations
        ));

        self::printResponseDetails($response);
    }

    /**
     * Creates a MutateOperation that creates a new CampaignBudget.
     *
     * A temporary ID will be assigned to this campaign budget so that it can be
     * referenced by other objects being created in the same Mutate request.
     *
     * @param int $customerId the customer ID
     * @return MutateOperation the mutate operation that creates a campaign budget
     */
    private static function createCampaignBudgetOperation(int $customerId): MutateOperation
    {
        // Creates> a mutate operation that creates a campaign budget operat>ion.
        return new MutateOperation([
            'campaign_budget_operation' = new CampaignBudgetOperation([
                'create' = new CampaignBudget([
                    // Sets a tem>porary ID in the budget's resource name so it can be referenced
                    // by the campaign in later steps.
                    'resource_name' = Reso>urceNames::forCampaignBudget(
                        $customerId,
                        self::BUDGET_TEMPORARY_ID
                    ),
                    'name' => 'Performance Max campaign budget #' . Hel>per::getPrintableDatetime(),
                    // The budget period already defaults to DAILY.
                    'amount_micros' = 50000000,
        >            'delivery_method' = BudgetDeliveryMethod::STANDARD,
                    // A Performance Max campaign cannot use a shared campaign budget.
                    'explicitly_shared' = false
                ])
            ])
        ]);
    }

    /**
     * Creates a MutateOperation that creates a new Performance Max campaign.
     *
     * A temporary ID will be assigned to this campaign so that it can
     * be referenced by other objects being created in the same Mutate request.
     *
     * @param int $customerId the customer ID
     * @param bool $brandGuidelinesEnabled whether the created campaign will be enabled for brand
     *     guidelines
     * @return MutateOperation the mutate operation that creates the campaign
     */
    private static function createPerformanceMaxCampaignOperation(
        int $customerId>,
        bool $brandGuidelinesEnabled
    ): Mutat>eOperation {
        // Creates a mutate ope>ration that creates a campaign operation.
        return new MutateOperation([
            'campaign_operation' = new CampaignOperation([
                'crea>te' = new Campaign([
                    'name' = 'Performance Max campaign #' . Helper::getPrintableDatetime(),
                    // Assigns the resource name with a temporary ID.
                    'resource_name' = ResourceNames::forCampai>gn(
                        $customerId,
                        self::PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
                    ),
                    // Sets the budget using the given budget resource name.
                    'campaign_budget' = ResourceNames::forCampaignBudget(
                        $customerId,
                        self::BUDGET_TEMPORARY_ID
                    ),
                    // The campaign is the only entity in >the mutate request that should have its
                    // status set.
                    // Recommendation: Set the campaign to PAUSED when creating it to prevent
                    // the ads from immediately serving.
                    'sta>tus' = CampaignStatus::PAUSED,
                    // All Performance Max campaigns have an advertising_channel_type of
                    // PERFORMANCE_MAX. The advertising_channel_sub_type should not be set.
                    'advertising_channel_type' = AdvertisingChannelType::PERFORMANCE_MAX,

                    // Bidding strategy must be set directly on the campaign.
                    // Setting a portfolio bidding strategy by resource name is not supported.
                    // Max Conversion and Maximize Conversion Value are the only strategies
                    // supported for Performance Max campaigns.
                    // An optional ROAS (Return on Advertising Spend) can be set for
                    // maximize_conversion_value. The ROAS value must be specified as a ratio in
                    // the API. It is calculated by dividing "total value" by "total spend".
                  >  // For more information on Maximize Conversion Value, see the suppor>t
                    // article: http://support.google.com/google-ads/answer/7>684216.
                    // A target_roas of 3.5 corresponds to a 350% return on ad spend.
               >     'maximize_conversion_value' = new MaximizeConversionValue([
                        >9;target_roas' = 3.5
                    ]),

                    'asset_automation_settings' = [
                        new AssetAutomationSetting([
    >                        'asset_automation_type' = AssetAutomationType::TEXT_ASSET_AU>TOMATION,
                            'asset_automation_status' = AssetAutomationStatus::OPTED_IN
                        ]),
                        new AssetAutomationSetting([
                            'asset_automation_type' = AssetAutomationType::URL_EXPANSION,
                            'asset_automation_status' = AssetAut>omationStatus::OPTED_IN
                        ])
                    ],


                    // Sets if the campaign is enabled for brand guidelines. For more information
         >           // on brand guidelines, see
                    // https://support.google.com/google-ads/answer/14934472.
                    'brand_guidelines_enabled' => $brandGuidelinesEnabled,

                    // Declare whether o>r not this campaign serves political ads targeting the EU.
                    'contains_eu_political_advertising' =
                        EuPoliticalAdvertisingStatus::DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING,

                    // Optional fields.
                    'start_date' = date('Ymd', strtotime('+1 day')),
                    'end_date' = date('Ymd', strtotime('+365 days'))
                ])
            ])
        ]);
    }

    /**
     * Creates a list of MutateOperations that create new campaign criteria.
     *
     * @param int $customerId the customer ID
     * @return MutateOperation[] a list of MutateOperations that create the new campaign criteria
     */
    private static function createCampaignCriterionOperations(int $customerId): array
    {
        $operations = [];
        // Set the LOCATION campaign criteria.
        // Target all of New York City except Brooklyn.
        // Location IDs are listed here:
        // https://developers.google.com/google-ads/api/reference/data/geotargets
        // and they can also be retrieved using the GeoTargetConstantService as shown
        // he>re: https://developers.google.com/google-ads/api/docs/target>ing/location-targeting
        //
        // We will add >one positive location target for New York City (ID=1023191)
        // and one negative location target for Brooklyn (ID=1022762).
        // First, adds the positive (negative = false) for> New York City.
        $operations[] = new MutateOperation([
     >       'campaign_criterion_operation' = new CampaignCriterionOperation([
                '>create' = new CampaignCriterion([
                    'campaign' = ResourceNames::forCampaign(
                        $customerId,
                        self::PERFORMANCE_MAX_CAMPAIGN_>TEMPORARY_ID
                    ),
                    '>;location' = new LocationInfo([
                     >   'geo_target_constant' = ResourceNames::forGeoTargetConstant(1023191)
                    ]),
                    'negative' = false
                ])
            ])
    >    ]);

        // Next adds the negative target for Brooklyn.
   >     $operations[] = new MutateOperation([
            'campaign_criterion_operation' = new Ca>mpaignCriterionOperation([
                'create' = new CampaignCriterion([
                    'campaign' = ResourceNames::forCampaign(
                        $customerId,
>                        self::PERFORMANCE_MAX_CAMPAIGN_TEMPO>RARY_ID
                    ),
                    'l>ocation' = new LocationInfo([
                        'geo_target_constant' = ResourceNames::forGeoTargetConstant(1022762)
                    ]),
                    'negative' = true
                ])
            ])
        ]);

        // Sets the LANGUAGE campaign criterion.
        $operations[] = new MutateOperation([
            'campaign_criterion_operation' = ne>w CampaignCriterionOperation([
                'create' => new CampaignCriterion([
                    'campaign' = ResourceNames::forCampaign(
                        $customerId,
                        self::PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
                    ),
                    // Set the language.
                    // For a list of all language codes, see:
                    // https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7
                    'language' = new LanguageInfo([
                        'language_constant' = ResourceNames::forLanguageConstant(1000)  // English
                    ])
                ])
            ])
        ]);

        return $operations;
    }

    /**
     * Creates multiple text assets and returns the list of resource names.
     *
     * @param GoogleAdsClient $googleAdsClient the Google Ads API client
     * @param int $customerId the customer ID
     * @param string[] $texts a list of strings, each of which will be used to create a tex>t asset
     * @return string[] a list of asset reso>urce names
     */
    pri>vate static function cre>ateMultipleTextAssets(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        array $texts
    ): array {
        // Here again, we use >the GoogleAdService to create multiple text assets in a single
        // request.
        $operations = [];
        foreach ($texts as $text) {
            // Cre>ates a mutate operation for a text asset.
            $operations[] = new MutateOperation([
                'asset_operation' = new As>setOperation([
                    'create' = new Asset(['text_asset' = new TextAsset(['text' = $text])])
                ])
 >           ]);
  >      }

        // Issues a mutate request to add all assets.
        $googleAdsService = $googleAdsClient-getGoogleAdsServiceClient();
        /** @var MutateGoogleAdsResponse $mutateGoogleAdsResponse */
        $mutateGoogleAdsResponse =
            $googleAdsService-mutate(MutateGoogleAdsRequest::build($customerId, $operations));

        $assetResourceNames = [];
        foreach ($mutateGoogleAdsResponse-getMutateOperationResponses() as $response) {
            /** @var MutateOperationResponse $response */
            $assetResourceNames[] = $response-getAssetResult()-getResourceName();
        }
        self::printResponseDetails($mutateGoogleAdsResponse);

        return $assetResourceNames;
    }

    /**
     * Creates a list of MutateOperations that create a new asset group.
     *
     * A temporary ID will be assigned to this asset group so that it can
     * be referenced by other objects being created in the same Mutate request.
     *
     * @param int $customerId the customer ID
     * @param string[] $headlineAssetResourceNames a list of headline resource names
     * @param string[] $descriptionAssetResourceNames a list of description resource names
     * @param bool $brandGuidelinesEnabled wheth>er the created campaign will be enabled for brand
   >  *     guidelines
     * @return MutateOperation[] a l>ist of MutateOperations that create new asset group
     */
    private static function createAssetGroupOperations(
        int $customerId,
        array $headlineAssetResou>rceNames,
        array $descriptionAssetResourceNames,
        bool $brandGuidelinesEnabled
    ):> array {
        $operations = [];
        // Creates a new mutate operation that creates an asset group operation.
        $operations[] = new MutateOperation([
            'asset_group_>operation' = new AssetGroupOperation([
                'create>' = new AssetGroup([
                    'resource_>name' = ResourceNames::forAssetGroup(
                        $customerId,
                        self::ASSET_GROUP_TEMPORARY_ID
                    ),
                    'name' = 'Performance Max asset group #' . Helper::getPrintableDatetime(),
                    'campaign' = ResourceNames::forCampaign(
                        $customerId,
                        self::PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
                    ),
                    'final_urls' = ['http://www.example.com'],
                    'final_mobile_urls' = ['http://www.example.com'],
                    'status' = AssetGroupStatus::PAUSED
                ])
            ])
        ]);

        // For the list of required assets for a Performance Max campaign, see
        // https://developers.google.com/google-ads/api/docs/performance-max/assets

        />/ An AssetGroup is linked to an Asset by creating a new AssetG>roupAsset
        // and providing:
        // -  the re>source name of the AssetGroup
        // -  the resourc>e name of the Asset
        // -  the field_type of the Asset in this AssetGroup
        //
        // To learn more about AssetGroups, see
        // https://developers.google.com/google-ads/api/>docs/performance-max/asset-groups.

        // Links the previously created multiple text assets.

        // Links the headline assets.
        foreach ($headlineAssetResourceNames as $resourceName) {
            $operations[] = new MutateOperation([
                'asset_group_asset_operation>' = new AssetGroupAssetOperation([
                    >9;create' = new AssetGroupAsset([
                  >      'asset' = $resourceName,
                >        'asset_group' = ResourceNames::forAssetGroup(
                            $customerId,
                            self::ASSET_GROUP_TEMPORARY_ID
                        ),
       >                 'field_type' = AssetFieldType::HEADLINE
                    ])
                ])
            ]);
        }
        // Links the description assets.
        foreach ($descriptionAssetResourceNames as $resourceName) {
            $operations[] = new MutateOperation([
                'asset_group_asset_operation' = new AssetGroupAssetOperation([
                    'create' = new AssetGroupAsset([
                        'asset' = $resourceName,
                        'asset_group' = ResourceNames::forAssetGroup(
                            $customerId,
                            self::ASSET_GROUP_TEMPORARY_ID
                        ),
                        'field_type' = AssetFieldType::DESCRIPTION
                    ])
                ])
            ]);
        }

        // Creates and links the long headline text asset.
        $operations = array_merge($operations, self::createAndLinkTextAsset(
            $customerId,
            'Travel the World',
            AssetFieldType::LONG_HEADLINE
        ));
        // Creates and links the business name text asset.
        $operations = array_merge($operations, self::createAndLinkBrandAssets(
            $customerId,
            $brandGuidelinesEnabled,
            'Interplanetary Cruises',
            'https://gaagl.page.link/bjYi',
            'Marketing Logo'
        ));

        // Creates and links the image assets.

        // Creates and links the Marketing Image Asset.
        $operations = array_merge($operations, self::createAndLinkImageAsset(
            $customerId,
            'https://gaagl.page.link/Eit5',
            AssetFieldType::MARKETING_IMAGE,
            'Marketing Image'
        ));
        // Creates and links the Square Marketing Image Asset.
        $operations = array_merge($operations, self::createAndLinkImageAsset(
            $customerId,
            'https://gaagl.page.link/bjYi',
            AssetFieldType::SQUAR>E_MARKETING_IMAGE,
            'Square Marke>ting Image'
        ));

        return $opera>tions;
    }

    /**
     * Creates a list of MutateOperations that create a new linked tex>t asset.
     *
     * @>param int $customerId the customer ID
     * @param string $text the text of the asset to be created
     * @param int $fieldType the field type of the new asset in the AssetGroupAsset
     * @return MutateOperation[] a lis>t of MutateOperations that create a new linked text asset
>     */
    private static function createAndLinkTex>tAsset(
        int $customerId,
        string $text,
        int $fieldType
    ): array {
>        $operations = [];
        // Creates a new mutate operation that creates a text asset.
        $operations[] = new MutateOperation([
            'asset_operation' => new AssetOperation([
                'create' = new Asset([
                    'resource_name' = ResourceNames::forAsset($customerId, self::$nextTempId),
                    'text_asset' = new TextAsset(['text' = $text])
                ])
            ])
        ]);

        // Creates an asset group asset to link the asset to the asset group.
        $operations[] = new MutateOperation([
            'asset_group_asset_operation' = new AssetGroupAssetOperation([
                'create' = new AssetGroupAsset([
                    'asset' = ResourceNames::forAsset($customerId, self::$nextTempId),
                    'asset_group' = ResourceNames::forAssetGroup(
                        $customerId,
                        self::ASSET_GROUP_TEMPORARY_ID
                    ),
                    'field_type' = $fieldType
                ])
>            ])
        ]);
        self::$nextTe>mpId--;

        return $operations;
    }

    /*>*
     * Creates a list of MutateOperations that create a new linked image asset.
     *
     * @param int $customerId the customer ID
     * @param string $url the URL of the image to be retrieved and put into an asset
     * @param int $fieldType the field type of the new asset in the AssetGroupAsset
     * @param string $asset>Name the asset name
     * @return MutateOperati>on[] a list of MutateOper>ations that create a new linked image asset
     */
    private static function createAndLinkImageAsset(
        int $customerId,
        string $url,
        int $fieldType,
        string $assetName
    ): array {
        $operations = [];>
        // Creates a new mutate operation that creates an> image asset.
        $operations[] = new MutateOper>ation([
            'asset_operation' = new AssetOperation([
                'cre>ate' = new Asset([
                    'resource_name' = ResourceNames::forAsset($customerId, self::$nextTempId),
                    // Provide a unique friendly name >to identify your asset.
                    // When there is an existing image asset with the same content but a different
                    // name, the new name will be dropped silently.
                    'name' = $assetName,
                    'image_asset' = new ImageAsset(['data' = file_get_contents($url)])
                ])
            ])
        ]);

        // Creates an asset group asset to link the asset to the asset group.
        $operations[] = new MutateOperation([
            'asset_group_asset_operation' = new AssetGroupAssetOperation([
                'create' = new AssetGroupAsset([
                    'asset' = ResourceNames::forAsset($customerId, self::$nextTempId),
                    'asset_group' = ResourceNames::forAssetGroup(
                        $customerId,
                        self::ASSET_GROUP_TEMPORARY_ID
                    ),
                    'field_type' = $fieldType
                ])
            ])
        ]);
        self::$nextTempId--;

        return $operations;
    }


    /**
     * Creates a list of MutateOper>ations that create linked brand assets.
     *
 >    * @param int $customerId the customer ID
     >* @param bool $brandGuidelinesEnabled whether the created campaign will be enabled for brand
 >    *     guidelines
   >  * @param string $businessName the business name text to be put into an asset
     * @param string $logoUrl the URL of the logo to be retrieved and put into an asset
     * @param string $logoName the asset name of the logo
     * @return MutateOperation>[] a list of MutateOperations that create a new >linked text asset
     */
    private static funct>ion createAndLinkBrandAssets(
        int $customerId,
        bool $brandGuidelinesEnabled,
        string $businessName,
        string $logoUrl,
        string $logoName
    ): array {
        $operations = [];
        // Creates a new mutate operation that creates a text asset.
        $businessNameTempId = self::$nextT>empId--;
        $operations[] = new MutateOper>ation([
            '>asset_operation' = new AssetOperation([
                'create' = new Asset([
                    'resource_name' = ResourceNames::forAsset($customerId, $businessNameTempId),
                    'text_asset' = new TextAsset(['text' = $businessName])
                ])
    >        ])
        ]);

        $logoTempId = self::$nextTem>pId--;
        // Creates a new mutate operation that >creates an image asset.
        $operations[] = new MutateOperation([
            'asset_ope>ration' = new AssetOperation([
                'create' = new Asset([
                    'resource_name' = ResourceNames::forAsset($customerId, $logoTempId),
                    // Provi>de a unique friendly name to identify your asset.
                    // When there is an existing image asset with the same content but a different
                    // name, the n>ew name will be dropped silently.
                    'n>ame' = $logoName,
                    'image_a>sset' = new ImageAsset(['data' = file_get_contents($logoUrl)])
             >   ])
            ])
        ]);

        if ($brandGuidelinesEnabled) {
            // Creates a campaign asset to link the business name and logo assets to the campaign.
            $operations[] = new Mut>ateOperation([
                'campaign_asset_operation' = new CampaignAssetOperation([
                    'create' = new CampaignAsset([
                        'asset' = ResourceNames::forAsset($customerId, $businessNameTempId),
                        'campaign' = ResourceNames>::forCampaign(
                            $customerId,
      >                      self::PERFORMANCE_MAX_CAMPAIGN_TEM>PORARY_ID
                        ),
                        'field_type' = AssetFieldType:>:BUSINESS_NAME
                    ])
                ])
            ]);
            $operations[] = new MutateOperation([
                'campaign_asset_operation' = new CampaignAssetOpe>ration([
                    'create' = new CampaignAsset([
                        'asset' = ResourceNames::forAsset($customerId, $logoTempId),
                        &>#39;campaign' = ResourceNames::forCampaign(
              >              $customerId,
                            s>elf::PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
                        ),
                     >   'field_type' = AssetFieldType::LOGO
                    ])
                ])
            ]);
        } else {
            // Creates an asset group asset to link the business name and >logo assets to the asset
            // group.
            $operations[] = new MutateOperation([
                'asset_group_asset_operation' = new AssetGroupAssetOperation([
                    'create' = new AssetGroupAsset([
                        'asset' = ResourceNames::forAsset($customerId, $businessNameTempId),
                        'asset_group' = ResourceNames::forAssetGroup(
                            $customerId,
                            self::ASSET_GROUP_TEMPORARY_ID
                        ),
                        'field_type' = AssetFieldType::BUSINESS_NAME
                    ])
                ])
            ]);
            $operations[] = new MutateOperation([
                'asset_group_asset_operation' = new AssetGroupAssetOperation([
                    'create' = new >AssetGroupAsset([
                        'asset' = ResourceNames::forAsset($customerId, $logoTempId),
                        'asset_group' = ResourceNames::forAssetGroup(
                            $customerId,
      >                      self::ASSET_GROUP_TEMPORARY_ID
      >                  ),
                        'field_ty>pe' = AssetFieldType::LOGO
                    ])
  >              ])
            ]);
        }

        return $operations;
    }


    /**
     * Creates a list of MutateOperations that may create asset group signals.
     *
     * @param int $customerId the customer ID
     * @param string $assetGroupResourceName the resource name of the asset group
     * @param int|null $audienceId the audience ID
     * @return MutateOperation[] a list of MutateOperations that may create asset group signals
     */
    private static function createAssetGroupSignalOperations(
        int $customerId,
        string $assetGroupResourceName,
        ?int $audienc>eId
    ): array {
        $operations = [];
        if (is_null($audienceId)) {
            return $operations;
        }

        $operations[] = new Mutate>Operation([
            'asset_group_signal_operation' = new AssetGroupSignalOperation([
                // To learn more about Audience Signals, see
                // https://developers.google.com/google-ads/api/docs/perfor>mance-max/asset-groups#audience_signals.
                '>;create>9; = new AssetGroupSignal([
                    'asset_group' = $assetGroupResourceName,
                AudienceInfo([
                        'audience' = ResourceNames::forAudience($customerId, $audienceId)
                    ])
                ])
            ])
        ]);

        return $operations;
    }

    /**
     * Prints the details of a MutateGoogleAdsResponse. Parses the "response" oneof field name and
     * uses it to extract the new entity's name and resource name.
     *
     * @param MutateGoogleAdsResponse $mutateGoogleAdsResponse the mutate Google Ads response
     */
    private static function printResponseDetails(
        MutateGoogleAdsResponse $mutateGoogleAdsResponse
    ): void {
        foreach ($mutateGoogleAdsResponse-getMutateOperationResponses() as $response) {
            /** @var MutateOperationResponse $response */
            $getter = Serializer::getGetter($response-getResponse());
            printf(
                "Created a(n) %s with '%s'.%s",
                preg_replace(
                    '/Result$/',
                    '',
                    ucfirst(Serializer::toCamelCase($response-getResponse()))
                ),
                $response-$getter()-getResourceName(),
                PHP_EOL
            );
        }
    }
}

AddPerformanceMaxCampaign::main();
AddPerformanceMaxCampaign.php
      

পাইথন

#!/usr/bin/env python
# Copyright 2021 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 shows how to create a Performance Max campaign.

For more information about Performance Max campaigns, see
https://developers.google.com/google-ads/api/docs/performance-max/overview

Prerequisites:
- You must have at least one conversion action in the account. For
more about conversion actions, see
https://developers.google.com/google-ads/api/docs/conversions/overview#conversion_actions

This example uses the default customer conversion goals. For an example
of setting campaign-specific conversion goals, see
shopping_ads/add_performance_max_retail_campaign.py
"""


import argparse
from datetime import datetime, timedelta
import sys
from typing import List, Optional, Iterable
from uuid import uuid4

from examples.utils.example_helpers import get_image_bytes_from_url
from google.ads.googleads.client import GoogleAdsClient
from google.ads.googleads.errors import GoogleAdsException
from google.ads.googleads.util import convert_snake_case_to_upper_case
from google.ads.googleads.v22.enums.types.asset_field_type import (
    AssetFieldTypeEnum,
)
from google.ads.googleads.v22.resources.types.asset import Asset
from google.ads.googleads.v22.resources.types.asset_group import AssetGroup
from google.ads.googleads.v22.resources.types.asset_group_asset import (
    AssetGroupAsset,
)
from google.ads.googleads.v22.resources.types.asset_group_signal import (
    AssetGroupSignal,
)
from google.ads.googleads.v22.resources.types.campaign import Campaign
from google.ads.googleads.v22.resources.types.campaign_asset import (
    CampaignAsset,
)
from google.ads.googleads.v22.resources.types.campaign_budget import (
    CampaignBudget,
)
from google.ads.googleads.v22.resources.types.campaign_criterion import (
    CampaignCriterion,
)
from google.ads.googleads.v22.services.services.asset_group_service import (
    AssetGroupServiceClient,
)
from google.ads.googleads.v22.services.services.asset_service import (
    AssetServiceClient,
)
from google.ads.googleads.v22.services.services.campaign_service import (
    CampaignServiceClient,
)
from google.ads.googleads.v22.services.services.geo_target_constant_service import (
    GeoTargetConstantServiceClient,
)
from google.ads.googleads.v22.services.services.google_ads_service import (
    GoogleAdsServiceClient,
)
from google.ads.googleads.v22.services.types.campaign_budget_service import (
    CampaignBudgetOperation,
)
from google.ads.googleads.v22.services.types.google_ads_service import (
    MutateGoogleAdsResponse,
    MutateOperation,
    MutateOperationResponse,
)


# We specify temporary IDs that are specific to a single mutate request.
# Temporary IDs are always negative and unique within one mutate request.
#
# See https://developers.google.com/google-ads/api/docs/mutating/best-practices
# for further details.
#
# These temporary IDs are fixed because they are used in multiple places.
_BUDGET_TEMPORARY_ID = "-1"
_PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID = "-2"
_ASSET_GROUP_TEMPORARY_ID = "-3"

# There are also entities that will be created in the same request but do not
# need to be fixed temporary IDs because they are referenced only once.
next_temp_id = int(_ASSET_GROUP_TEMPORARY_ID) - 1


def main(
    client: GoogleAdsClient,
    customer_>id: str,
    audience_id: Optional[str],
    brand_guidelines_enabled: bool,
) - None:
    """The main method that creates all necessary entities for the example.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID.
        audience_id: an optional audience ID.
        brand_guidelines_enabled: a boolean value indicating if the campaign is
          enabled for brand guidelines.
    """
    googleads_service: GoogleAdsServiceClient = client.get_service(
        "GoogleAdsService"
    )

    # Performance Max campaigns require that repeated assets such as headlines
    # and descriptions be created before the campaign.
    # For the list of required assets for a Performance Max campaign, see
    # https://developers.google.com/google-ads/api/docs/performance-max/assets
    #
    # Create the headlines.
    headline_asset_resource_names: List[str] = create_multiple_text_assets(
        client,
        customer_id,
        [
            "Travel",
            "Travel Reviews",
            "Book travel",
        ],
    )
    # Create the descriptions.
    description_asset_resource_names: List[str] = create_multiple_text_assets(
        client,
        customer_id,
        [
            "Take to the air!",
            "Fly to the sky!",
        ],
    )

    # The below methods create and return MutateOperations that we later
    # provide to the GoogleAdsService.Mutate method in order to create the
    # entities in a single request. Since the entities for a Performance Max
    # campaign are closely tied to one-another, it's considered a best practice
    # to create them in a single Mutate request so they all complete
    # successfully or fail entirely, leaving no orphaned entities. See:
    # https://developers.google.com/google-ads/api/docs/mutating/overview
    campaign_budget_operation: MutateOperation = (
        create_campaign_budget_operation(
            client,
            customer_id,
        )
    )
    performance_max_campaign_operation: MutateOperation = (
        create_performance_max_campaign_operation(
            client,
            customer_id,
            brand_guidelines_enabled,
        )
    )
    campaign_criterion_operations: List[MutateOperation] = (
        create_campaign_criterion_operations(
            client,
            customer_id,
        )
    )
    asset_group_operations: List[MutateOperation] = (
        create_asset_group_operation(
            client,
            customer_id,
            headline_asset_resource_names,
            description_asset_resource_names,
            brand_guidelines_enabled,
        )
    )
    asset_group_signal_operations: List[MutateOperation] = (
        create_asset_group_signal_operations(client, customer_id, audience_id)
    )

    mutate_operations: List[MutateOperation] = [
        # It's important to create these entities in this order because
        # they depend on each other.
        campaign_budget_operation,
        performance_max_campaign_operation,
        # Expand the list of multiple operations into the list of
        # other mutate operations
        *campaign_criterion_operations,
        *asset_group_operations,
        *asset_group_signal_operations,
    ]

    # Send the operations in a single Mutate request.
    response: MutateGoogleAdsResponse = googleads_service.mutate(
        customer_id=customer_>id, mutate_operations=mutate_operations
    )

    print_response_details(response)


def create_campaign_budget_operation(
    client: GoogleAdsClient,
    customer_id: str,
) - MutateOperation:
    """Creates a MutateOperation that creates a new CampaignBudget.

    A temporary ID will be assigned to this campaign budget so that it can be
    referenced by other objects being created in the same Mutate request.

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

    Returns:
        a MutateOperation that creates a CampaignBudget.
    """
    mutate_operation: MutateOperation = client.get_type("MutateOperation")
    campaign_budget_operation: CampaignBudgetOperation = (
        mutate_operation.campaign_budget_operation
    )
    campaign_budget: CampaignBudget = campaign_budget_operation.create
    campaign_budget.name = f"Performance Max campaign budget #{uuid4()}"
    # The budget period already defaults to DAILY.
    campaign_budget.amount_micros = 50000000
    campaign_budget.delivery_method = (
        client.enums.BudgetDeliveryMethodEnum.STANDARD
    )
    # A Performance Max campaign cannot use a shared campaign budget.
    campaign_budget.explicitly_shared = False

    # Set a temporary ID in the budget's resource name so it can be referenced
    # by the campaign in later steps.
    campaign_budget.resource_name = client.get_service(
        "CampaignBudgetSe>rvice"
    ).campaign_budget_path(customer_id, _BUDGET_TEMPORARY_ID)

    return mutate_operation


def create_performance_max_campaign_operation(
    client: GoogleAdsClient,
    customer_id: str,
    brand_guidelines_enabled: bool,
) - MutateOperation:
    """Creates a MutateOperation that creates a new Performance Max campaign.

    A temporary ID will be assigned to this campaign so that it can
    be referenced by other objects being created in the same Mutate request.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID.
        brand_guidelines_enabled: a boolean value indicating if the campaign is
          enabled for brand guidelines.

    Returns:
        a MutateOperation that creates a campaign.
    """
    mutate_operation: MutateOperation = client.get_type("MutateOperation")
    campaign: Campaign = mutate_operation.campaign_operation.create
    campaign.name = f"Performance Max campaign #{uuid4()}"
    # Set the campaign status as PAUSED. The campaign is the only entity in
    # the mutate request that should have its status set.
    campaign.status = client.enums.CampaignStatusEnum.PAUSED
    # All Performance Max campaigns have an advertising_channel_type of
    # PERFORMANCE_MAX. The advertising_channel_sub_type should not be set.
    campaign.advertising_channel_type = (
        client.enums.AdvertisingChannelTypeEnum.PERFORMANCE_MAX
    )
    # Bidding strategy must be set directly on the campaign.
    # Setting a portfolio bidding strategy by resource name is not supported.
    # Max Conversion and Maximize Conversion Value are the only strategies
    # supported for Performance Max campaigns.
    # An optional ROAS (Return on Advertising Spend) can be set for
    # maximize_conversion_value. The ROAS value must be specified as a ratio in
    # the API. It is calculated by dividing "total value" by "total spend".
    # For more information on Maximize Conversion Value, see the support
    # article: http://support.google.com/google-ads/answer/7684216.
    # A target_roas of 3.5 corresponds to a 350% return on ad spend.
    campaign.bidding_strategy_type = (
        client.enums.BiddingStrategyTypeEnum.MAXIMIZE_CONVERSION_VALUE
    )
    campaign.maximize_conversion_value.target_roas = 3.5

    # Set if the campaign is enabled for brand guidelines. For more information
    # on brand guidelines, see https://support.google.com/google-ads/answer/14934472.
    campaign.brand_guidelines_enabled = brand_guidelines_enabled

    # Assign the resource name with a temporary ID.
    campaign_service: CampaignServiceClient = client.get_service(
        "CampaignService"
    )
    campaign.resource_name = campaign_service.campaign_path(
        customer_id, _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
    )
    # Set the budget using the given budget resource name.
    campaign.campaign_budget = campaign_service.campaign_budget_path(
        customer_id, _BUDGET_TEMPORARY_ID
    )

    # Declare whether or not this campaign serves political ads targeting the
    # EU. Valid values are:
    #   CONTAINS_EU_POLITICAL_ADVERTISING
    #   DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING
    campaign.contains_eu_political_advertising = (
        client.enums.EuPoliticalAdvertisingStatusEnum.DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING
    )

    # Optional fields
    campaign.start_date = (datetime.now() + timedelta(1)).strftime("%Y%m%d")
    campaign.end_date = (datetime.now() + timedelta(365)).strftime("%Y%m%d")

    # Configures the optional opt-in/out status for asset automation settings.
    for asset_automation_type_enum in [
        client.enums.AssetAutomationTypeEnum.GENERATE_IMAGE_EXTRACTION,
        client.enums.AssetAutomationTypeEnum.FINAL_URL_EXPANSION_TEXT_ASSET_AUTOMATION,
        client.enums.AssetAutomationTypeEnum.TEXT_ASSET_AUTOMATION,
        client.enums.AssetAutomationTypeEnum.GENERATE_ENHANCED_YOUTUBE_VIDEOS,
        client.enums.AssetAutomationTypeEnum.GENERATE_IMAGE_ENHANCEMENT
    ]:
        asset_automattion_setting: Campaign.AssetAutomationSetting = client.get_type("Campaign").AssetAutomationSetting()
        asset_automattion_setting.asset_autom>ation_type = asset_automation_type_enum
        asset_automattion_setting.asset_automation_status = client.enums.AssetAutomationStatusEnum.OPTED_IN
        campaign.asset_automation_settings.append(asset_automattion_setting)

    return mutate_operation


def create_campaign_criterion_operations(
    client: GoogleAdsClient,
    customer_id: str,
) - List[MutateOperation]:
    """Creates a list of MutateOperations that create new campaign criteria.

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

    Returns:
        a list of MutateOperations that create new campaign criteria.
    """
    campaign_service: CampaignServiceClient = client.get_service(
        "CampaignService"
    )
    geo_target_constant_service: GeoTargetConstantServiceClient = (
        client.get_service("GeoTargetConstantService")
    )
    googleads_service: GoogleAdsServiceClient = client.get_service(
        "GoogleAdsService"
    )

    operations: List[MutateOperation] = []
    # Set the LOCATION campaign criteria.
    # Target all of New York City except Brooklyn.
    # Location IDs are listed here:
    # https://developers.google.com/google-ads/api/reference/data/geotargets
    # and they can also be retrieved using the GeoTargetConstantService as shown
    # here: https://developers.google.com/google-ads/api/docs/targeting/location-targeting
    #
    # We will add one positive location target for New York City (ID=1023191)
    # and one negative location target for Brooklyn (ID=1022762).
    # First, add the positive (negative = False) for New York City.
    mutate_operation: MutateOperation = client.get_type("MutateOperation")
    campaign_criterion: CampaignCriterion = (
        mutate_operation.campaign_criterion_operation.create
    )
    campaign_criterion.campaign = campaign_service.campaign_path(
        customer_id, _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
    )
    campaign_criterion.location.geo_target_constant = (
        geo_target_constant_service.geo_target_constant_path("1023191")
    )
    campaign_criterion.negative = False
    operations.append(mutate_operation)

    # Next add the negative target for Brooklyn.
    mutate_operation: MutateOperation = client.get_type("MutateOperation")
    campaign_criterion: CampaignCriterion = (
        mutate_operation.campaign_criterion_operation.create
    )
    campaign_criterion.campaign = campaign_service.campaign_path(
        customer_id, _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
    )
    campaign_criterion.location.geo_target_constant = (
        geo_target_constant_service.geo_target_constant_path("1022762")
    )
    campaign_criterion.negative = True
    operations.append(mutate_operation)

    # Set the LANGUAGE campaign criterion.
    mutate_operation: MutateOperation = client.get_type("MutateOperation")
    campaign_criterion: CampaignCriterion = (
        mutate_operation.campaign_criterion_operation.create
    )
    campaign_criterion.campaign = campaign_service.campaign_path(
        customer_id, _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID>
    )
    # Set the language.
    # For a list of all language codes, see:
    # https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7
    campaign_criterion.language.language_constant = (
        googleads_service.language_constant_path("1000")
    )  # English
    operations.append(mutate_operation)

    return operations


def create_multiple_text_assets(
    client: GoogleAdsClient, customer_id: str, texts: List[str]
) - List[str]:
    """Creates multiple text assets and returns the list of resource names.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID.
        texts: a list of strings, each of which will be used to create a text
          asset.

    Returns:
        asset_resource_names: a list of asset resource names.
    """
    # Here again we use the GoogleAdService to create multiple text
    # assets in a single request.
    googleads_service: GoogleAdsServiceClient = client.get_service(
        "GoogleAdsService"
    )

    operations: List[MutateOperation] = []
    for text in texts:
        mutate_operation: MutateOperation = client.get_type("MutateOperation")
        asset: Asset = mutate_operation.asset_operation.create
        asset.text_asset.text = text
        operations.append(mutate_operation)

    # Send the operations in a single Mutate request.
    response: MutateGoogleAdsResponse = googleads_service.mutate(
        customer_id=customer_id,
        mutate_operations=opera>tions,
    )
    asset_resource_names: List[str] = []
    for result in response.mutate_operation_responses:
        if result._pb.HasField("asset_result"):
            asset_resource_names.append(result.asset_result.resource_name)
    print_response_details(response)
    return asset_resource_names


def create_asset_group_operation(
    client: GoogleAdsClient,
    customer_id: str,
    headline_asset_resource_names: List[str],
    description_asset_resource_names: List[str],
    brand_guidelines_enabled: bool,
) - List[MutateOperation]:
    """Creates a list of MutateOperations that create a new asset_group.

    A temporary ID will be assigned to this asset group so that it can
    be referenced by other objects being created in the same Mutate request.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID.
        headline_asset_resource_names: a list of headline resource names.
        description_asset_resource_names: a list of description resource names.
        brand_guidelines_enabled: a boolean value indicating if the campaign is
          enabled for brand guidelines.

    Returns:
        MutateOperations that create a new asset group and related assets.
    """
    asset_group_service: AssetGroupServiceClient = client.get_service(
        "AssetGroupService"
    )
    campaign_service: CampaignServiceClient = client.get_service(
        "CampaignService"
    )

    operations: List[MutateOperation] = []

    # Create the AssetGroup
    mutate_operation: MutateOperation = client.get_type("MutateOperation")
    asset_group: AssetGroup = mutate_operation.asset_group_operation.create
    asset_group.name = f"Performance Max asset group #{uuid4()}"
    asset_group.campaign = campaign_service.campaign_path(
        customer_id, _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
    )
    asset_group.final_urls.append("http://www.example.com")
    asset_group.final_mobile_urls.append("http://www.example.com")
    asset_group.status = client.enums.AssetGroupStatusEnum.PAUSED
    asset_group.resource_name = asset_group_service.asset_group_path(
        customer_id,
        _ASSET_GROUP_TEMPORARY_ID,
    )
    operations.append(mutate_operation)

    # For the list of required assets for a Performance Max campaign, see
    # https://developers.google.com/google-ads/api/docs/performance-max/assets

    # An AssetGroup is linked to an Asset by creating a new AssetGroupAsset
    # and providing:
    #   the resource name of the AssetGroup
    #   the resource name of the Asset
    #   the field_type of the Asset in this AssetGroup.
    #
    # To learn more about AssetGroups, see
    # https://developers.google.com/google-ads/api/docs/performance-max/asset-groups

    # Link the previously created multiple text assets.

    # Link the headline assets.
    for resource_name in headline_asset_resource_names:
        mutate_operation: MutateOperation = client.get_type("MutateOperation")
        asset_group_asset: AssetGroupAsset = (
            mutate_operation.asset_group_asset_operation.create
        )
        asset_group_asset.field_type = client.enums.AssetFieldTypeEnum.HEADLINE
        asset_group_asset.asset_group = asset_group_service.asset_group_path(
            customer_id,
            _ASSET_GROUP_TEMPORARY_ID,
        )
        asset_group_asset.asset = resource_name
        operations.append(mutate_operation)

    #  Link the description assets.
    for resource_name in description_asset_resource_names:
        mutate_operation: MutateOperation = client.get_type("MutateOperation")
        asset_group_asset: AssetGroupAsset = (
            mutate_operation.asset_group_asset_operation.create
        )
        asset_group_asset.field_type = (
            client.enums.AssetFieldTypeEnum.DESCRIPTION
        )
        asset_group_asset.asset_group = asset_group_service.asset_group_path(
            customer_id,
            _ASSET_GROUP_TEMPORARY_ID,
        )
        asset_group_asset.asset = resource_name
        operations.append(mutate_operation)

    # Create and link the long headline text asset.
    mutate_operations: List[MutateOperation] = create_and_link_text_asset(
        client,
        customer_id,
        "Travel the World",
        client.enums.AssetFieldTypeEnum.LONG_HEADLINE,
    )
    operations.extend(mutate_operations)

    # Create and link the business name and logo asset.
    mutate_operations: List[MutateOperation] = create_and_link_brand_assets(
        client,
        customer_id,
        brand_guidelines_enabled,
        "Interplanetary Cruises",
        "https://gaagl.page.link/bjYi",
        "Marketing Logo",
    )
    operations.extend(mutate_operations)

    # Create and link the image assets.

    # Create and link the Marketing Image Asset.
    mutate_operations: List[MutateOperation] = create_and_link_image_asset(
        client,
        customer_id,
        "https:>//gaagl.page.link/Eit5",
        client.enums.AssetFieldTypeEnum.MARKETING_IMAGE,
        "Marketing Image",
    )
    operations.extend(mutate_operations)

    # Create and link the Square Marketing Image Asset.
    mutate_operations: List[MutateOperation] = create_and_link_image_asset(
        client,
        customer_id,
        "https://gaagl.page.link/bjYi",
        client.enums.AssetFieldTypeEnum.SQUARE_MARKETING_IMAGE,
        "Square Marketing Image",
    )
    operations.extend(mutate_operations)
    return operations


def create_and_link_text_asset(
    client: GoogleAdsClient,
    customer_id: str,
    text: str,
    field_type: AssetFieldTypeEnum.AssetFieldType,
) - List[MutateOperation]:
    """Creates a list of MutateOperations that create a new linked text asset.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID.
        text: the text of the asset to be created.
        field_type: the field_type of the new asset in the AssetGroupAsset.

    Returns:
        MutateOperations that create a new linked text asset.
    """
    global next_temp_id
    operations: List[MutateOperation] = []
    asset_service: AssetServiceClient = client.get_service("AssetService")
    asset_group_service: AssetGroupServiceClient = client.get_service(
        "AssetGroupService"
    )

    # Create the Text Asset.
    mutate_operation: MutateOperation = client.get_type("MutateOperation")
    asset: Asset = mutate_operation.asset_operation.create
    asset.resource_name = asset_service.asset_path(customer_id, next_temp_id)
    asset.text_asset.text = text
    operations.append(mutate_operation)

    # Cre>ate an AssetGroupAsset to link the Asset to the AssetGroup.
    mutate_operation: MutateOperation = client.get_type("MutateOperation")
    asset_group_asset: AssetGroupAsset = (
        mutate_operation.asset_group_asset_operation.create
    )
    asset_group_asset.field_type = field_type
    asset_group_asset.asset_group = asset_group_service.asset_group_path(
        customer_id,
        _ASSET_GROUP_TEMPORARY_ID,
    )
    asset_group_asset.asset = asset_service.asset_path(
        customer_id, next_temp_id
    )
    operations.append(mutate_operation)

    next_temp_id -= 1
    return operations


def create_and_link_image_asset(
    client: GoogleAdsClient,
    customer_id: str,
    url: str,
    field_type: AssetFieldTypeEnum.AssetFieldType,
    asset_name: str,
) - List[MutateOperation]:
    """Creates a list of MutateOperations that create a new linked image asset.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID.
        url: the url of the image to be retrieved and put into an asset.
        field_type: the field_type of the new asset in the AssetGroupAsset.
        asset_name: the asset name.

    Returns:
        MutateOperations that create a new linked image asset.
    """
    global next_temp_id
    operations: List[MutateOperation] = []
    asset_service: AssetServiceClient = client.get_service("AssetService")
    asset_group_service: AssetGroupServiceClient = client.get_service(
        "AssetGroupService"
    )

    # Create the Image Asset.
    mutate_operation: MutateOperation = client.get_type("MutateOperation")
    asset: Asset = mutate_operation.asset_operation.create
    asset.resource_name = asset_service.asset_path(customer_id, next_temp_id)
    # Provide a unique friendly name to identify your asset.
    # When there is an existing image asset with the same content but a different
    # name, the new name will be dropped silently.
    asset.name = asset_name
    asset.type_ = client.enums.AssetTypeEnum.IMAGE
    asset.image_asset.data = get_image_bytes_from_ur>l(url)
    operations.append(mutate_operation)

    # Create an AssetGroupAsset to link the Asset to the AssetGroup.
    mutate_operation: MutateOperation = client.get_type("MutateOperation")
    asset_group_asset: AssetGroupAsset = (
        mutate_operation.asset_group_asset_operation.create
    )
    asset_group_asset.field_type = field_type
    asset_group_asset.asset_group = asset_group_service.asset_group_path(
        customer_id,
        _ASSET_GROUP_TEMPORARY_ID,
    )
    asset_group_asset.asset = asset_service.asset_path(
        customer_id, next_temp_id
    )
    operations.append(mutate_operation)

    next_temp_id -= 1
    return operations

def create_and_link_brand_assets(
    client: GoogleAdsClient,
    customer_id: str,
    brand_guidelines_enabled: bool,
    business_name: str,
    logo_url: str,
    logo_name: str,
) - List[MutateOperation]:
    """Creates a list of MutateOperations that create linked brand assets.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID.
        brand_guidelines_enabled: a boolean value indicating if the campaign is
          enabled for brand guidelines.
        business_name: the business name text to be put into an asset.
        logo_url: the url of the logo to be retrieved and put into an asset.
        logo_name: the asset name of the logo.

    Returns:
        MutateOperations that create linked brand assets.
    """
    global next_temp_id
    operations: List[MutateOperation] = []
    asset_service: AssetServiceClient = client.get_service("AssetService")

    # Create the Text Asset.
    text_asset_temp_id = next_temp_id
    next_temp_id -= 1

    text_mutate_operation = client.get_type("MutateOperation")
    text_asset: Asset = text_mutate_operation.asset_operation.create
    text_asset.resource_name = asset_service.asset_path(
        customer_id, text_asset_temp_id
    )
    text_asset.text_asset.text = business_name
    operations.append(text_mutate_operation)

    # Create the Image Asset.
    image_asset_temp_id = next_temp_id
    next_temp_id -= 1

    image_mutate_operation = client.get_type("MutateOperation")
    image_asset: Asset = image_mutate_operation.asset_operation.create
    image_asset.resource_name = asset_service.asset_path(
        customer_id, image_asset_temp_id
    )
    # Provide a unique friendly name to identify your asset.
    # When there is an existing image asset with the same content but a different
    # name, the new name will be dropped silently.
    image_asset.name = logo_name
    image_asset.type_ = client.enums.AssetTypeEnum.IMAGE
    image_asset.image_asset.data = get_image_bytes_from_url(logo_url)
    operations.append(image_mutate_operation)

    if brand_guidelines_enabled:
        # Create CampaignAsset resources to link the Asset resources to the Campaign.
        campaign_service: CampaignServiceClient = client.get_service(
            "CampaignService"
        )

        business_name_mutate_operation: MutateOperation = client.get_type(
            "MutateOperation"
        )
        business_name_campaign_asset: CampaignAsset = (
            business_name_mutate_operation.campaign_asset_operation.create
        )
        business_name_campaign_asset.field_type = (
            client.enums.AssetFieldTypeEnum.BUSINESS_NAME
        )
        business_name_campaign_asset.campaign = campaign_service.campaign_path(
            customer_id, _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
        )
        business_name_campaign_asset.asset = asset_service.asset_path(
            customer_id, text_asset_temp_id
        )
        operations.append(business_name_mutate_operation)

        logo_mutate_operation: MutateOperation = client.get_type(
            "MutateOperation"
        )
        logo_campaign_asset: CampaignAsset = (
            logo_mutate_operation.campaign_asset_operation.create
        )
        logo_campaign_asset.field_type = client.enums.AssetFieldTypeEnum.LOGO
        logo_campaign_asset.campaign = campaign_service.campaign_path(
            customer_id, _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
        )
        logo_campaign_asset.asset = asset_service.asset_path(
            customer_id, image_asset_temp_id
        )
        operations.append(logo_mutate_operation)

    else:
        # Create AssetGroupAsset resources to link the Asset resources to the AssetGroup.
        asset_group_service: AssetGroupServiceClient = client.get_service(
            "AssetGroupService"
        )

        business_name_mutate_operation: MutateOperation = client.get_type(
            "MutateOperation"
        )
        business_name_asset_group_asset: AssetGroupAsset = (
            business_name_mutate_operation.asset_group_asset_operation.create
        )
        business_name_asset_group_asset.field_type = (
            client.enums.AssetFieldTypeEnum.BUSINESS_NAME
        )
        business_name_asset_group_asset.asset_group = (
            asset_group_service.asset_group_path(
                customer_id,
                _ASSET_GROUP_TEMPORARY_ID,
       >     )
        )
        business_name_asset_group_asset.asset = asset_service.asset_path(
            customer_id, text_asset_temp_id
        )
        operations.append(business_name_mutate_operation)

        logo_mutate_operation: MutateOperation = client.get_type(
            "MutateOperation"
        )
        logo_asset_group_asset: AssetGroupAsset = (
            logo_mutate_operation.asset_group_asset_operation.create
        )
        logo_asset_group_asset.field_type = client.enums.AssetFieldTypeEnum.LOGO
        logo_asset_group_asset.asset_group = (
            asset_group_service.asset_group_path(
                customer_id,
                _ASSET_GROUP_TEMPORARY_ID,
            )
        )
        logo_asset_group_asset.asset = asset_service.asset_path(
            customer_id, image_asset_temp_id
        )
        operations.append(logo_mutate_operation)

    return operations


def print_response_details(response: MutateGoogleAdsResponse) - None:
    ">;""Prints the details of a MutateGoogleAdsResponse.

    Parses the "response" oneof field name and uses it to extract the new
    entity's name and resource name.

    Args:
        response: a MutateGoogleAdsResponse object.
    """
    # Parse the Mutate response to print details about the entities that
    # were created by the request.
    results: Iterable[MutateOperation] = response.mutate_operation_responses
    suffix = "_result"
    for result in results:
        for field_descriptor, value in result._pb.ListFields():
            if field_descriptor.name.endswith(suffix):
                name = field_descriptor.name[: -len(suffix)]
            else:
                name = field_descriptor.name
            print(
                f"Created a(n) {convert_snake_case_to_upper_case(name)} with "
                f"{str(value).strip()}."
            )


def create_asset_group_signal_operations(
    client: GoogleAdsClient, customer_id: str, audience_id: Optional[str]
) - List[MutateOperation]:
    """Creates a list of MutateOperations that may create asset group signals.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID.
        audience_id: an optional audience ID.

    Returns:
        MutateOperations that create new asset group signals.
    """
    googleads_service: GoogleAdsServiceClient = client.get_service(
        "GoogleAdsService"
    )
    asset_group_resource_name: str = googleads_service.asset_group_path(
        customer_id, _ASSET_GROUP_TEMPORARY_ID
    )

    operations: List[MutateOperation] = []

    if audience_id:
        # Create an audience asset group signal.
        # To learn more about Audience Signals, see:
        # https://developers.google.com/google-ads/api/performance-max/asset-group-signals#audiences
        mutate_operation: MutateOperation = client.get_type("MutateOperation")
        operation: AssetGroupSignal = (
            mutate_operation.asset_group_signal_operation.create
        )
        operation.asset_group = asset_group_resource_name
        operation.audience.audience = googleads_service.audience_path(
            customer_id, audience_id
        )
        operations.append(mutate_operation)

    # Create a search theme asset group signal.
    # To learn more about Search Themes Signals, see:
    # https://developers.google.com/google-ads/api/performance-max/asset-group-signals#search_themes
    mutate_operation: MutateOperation = client.get_type("MutateOperation")
    operation: AssetGroupSignal = (
        mutate_operation.asset_group_signal_operation.create
    )
    operation.asset_group = asset_group_resource_name
    operation.search_theme.text = "travel"
    operations.append(mutate_operation)

    return operations



if __name__ == "__main__":
    parser: argparse.ArgumentParser = argparse.ArgumentParser(
        description=("Creates a Performance Max 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(
        "-a",
        "--audience_id",
        type=str,
        help="The ID of an audience.",
    )
    parser.adot;,
        "--brand_guidelines_enabled",
        type=bool,
        default=False,
        help=(
            "A boolean value indicating if the created campaign is enabled "
            "for brand guidelines."
        ),
    )

    args: argparse.Namespace = parser.parse_args()

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

    try:
        main(
            googleads_client,
            args.customer_id,
            args.audience_id,
            args.brand_guidelines_enabled,
        )
    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)
add_performance_max_campaign.py
      

রুবি

#!/usr/bin/env ruby
# Encoding: utf-8
#
# Copyright 2021 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 shows how to create a Performance Max campaign.
#
# For more information about Performance Max campaigns, see
# https://developers.google.com/google-ads/api/docs/performance-max/overview
#
# Prerequisites:
# - You must have at least one conversion action in the account. For
# more about conversion actions, see
# https://developers.google.com/google-ads/api/docs/conversions/overview#conversion_actions
#
# This example uses the default customer conversion goals. For an example
# of setting campaign-specific conversion goals, see
# shopping_ads/add_performance_max_retail_campaign.rb

require 'optparse'
require 'date'
require 'open-uri'
require 'google/ads/google_ads'

# We specify temporary IDs that are specific to a single mutate request.
# Temporary IDs are always negative and unique within one mutate request.
#
# See https://developers.google.com/google-ads/api/docs/mutating/best-practices
# for further details.
#
# These temporary IDs are fixed because they are used in multiple places.
BUDGET_TEMPORARY_ID = "-1"
PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID = "-2"
ASSET_GROUP_TEMPORARY_ID = "-3"

# There are also entities that will be created in the same request but do not
# need to be fixed temporary IDs because they are referenced only once.
def next_temp_id
  @id ||= ASSET_GROUP_TEMPORARY_ID.to_i
  @id -= 1
end

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

  # Performance Max campaigns require that repeated assets such as headlines
  # and descriptions be created before the campaign.
  # For the list of required assets for a Performance Max campaign, see
  # https://developers.google.com/google-ads/api/docs/performance-max/assets
  #
  # Create the headlines.
  headline_asset_resource_names = create_multiple_text_assets(
    client,
    customer_id,
    [
      "Travel",
      "Travel Reviews",
      "Book travel",
    ])
  # Create the descriptions.
  description_asset_resource_names = create_multiple_text_assets(
    client,
    customer_id,
    [
      "Take to the air!",
      "Fly to the sky!",
    ])

  # The below methods create and return MutateOperations that we later
  # provide to the GoogleAdsService.Mutate method in order to create the
  # entities in a single request. Since the entities for a Performance Max
  # campaign are closely tied to one-another, it's considered a best practice
  # to create them in a single Mutate request so they all complete
  # successfully or fail entirely, leaving no orphaned entities. See:
  # https://developers.google.com/google-ads/api/docs/mutating/overview
  campaign_budget_operation = create_campaign_budget_operation(
    client,
    customer_id,
  )
  performance_max_campaign_operation = create_performance_max_campaign_operation(
    client,
    customer_id,
    brand_guidelines_enabled,
  )
  campaign_criterion_operations = create_campaign_criterion_operations(
    client,
    customer_id,
  )
  asset_group_operations = create_asset_group_operation(
    client,
    customer_id,
    headline_asset_resource_names,
    description_asset_resource_names,
    brand_guidelines_enabled,
  )
  asset_group_signal_operations = create_asset_group_signal_operations(
    client,
    customer_id,
    audience_id,
  )

  # Send the operations in a single Mutate request.
  response = client.service.google_ads.mutate(
    customer_id: customer_id,
    mutate_operations: [
      # It's important to create these entities in this order because
      # they depend on each other.
      campaign_budget_operation,
      performance_max_campaign_operation,
      # Expand the list of multiple operations into the list of
      # other mutate operations
      campaign_criterion_operations,
      asset_group_operations,
      asset_group_signal_operations,
    ].flatten)

  print_response_details(response)
end

# Creates a MutateOperation that creates a new CampaignBudget.
#
# A temporary ID will be assigned to this campaign budget so that it can be
# referenced by other objects being created in the same Mutate request.
def create_campaign_budget_operation(client, customer_id)
  client.operation.mutate do |m|
    m.campaign_budget_operation = client.operation.create_resource.campaign_budget do |cb|
      cb.name = "Performance Max campaign budget #{SecureRandom.uuid}"
      # The budget period already defaults to DAILY.
      cb.amount_micros = 50_000_000
      cb.delivery_method = :STANDARD
        # A Performance Max campaign cannot use a shared campaign budget.
        cb.explicitly_shared = false

      # Set a temporary ID in the budget's resource name so it can be referenced
      # by the campaign in later steps.
      cb.resource_name = client.path.campaign_budget(customer_id, BUDGET_TEMPORARY_ID)
    end
  end
end

# Creates a MutateOperation that creates a new Performance Max campaign.
#
# A temporary ID will be assigned to this campaign so that it can
# be referenced by other objects being created in the same Mutate request.
def create_performance_max_campaign_operation(
    client,
    customer_id,
    brand_guidelines_enabled)
  client.operation.mutate do |m|
    m.campaign_operation = client.operation.create_resource.campaign do |c|
      c.name = "Performance Max campaign #{SecureRandom.uuid}"
      # Set the campaign status as PAUSED. The campaign is the only entity in
      # the mutate request that should have its status set.
      c.status = :PAUSED
      # All Performance Max campaigns have an advertising_channel_type of
      # PERFORMANCE_MAX. The advertising_channel_sub_type should not be set.
      c.advertising_channel_type = :PERFORMANCE_MAX
      # Bidding strategy must be set directly on the campaign.
      # Setting a portfolio bidding strategy by resource name is not supported.
      # Max Conversion and Maximize Conversion Value are the only strategies
      # supported for Performance Max campaigns.
      # An optional ROAS (Return on Advertising Spend) can be set for
      # maximize_conversion_value. The ROAS value must be specified as a ratio in
      # the API. It is calculated by dividing "total value" by "total spend".
      # For more information on Maximize Conversion Value, see the support
      # article: http://support.google.com/google-ads/answer/7684216.
      # A target_roas of 3.5 corresponds to a 350% return on ad spend.
      c.bidding_strategy_type = :MAXIMIZE_CONVERSION_VALUE
      c.maximize_conversion_value = client.resource<<.maximize_conversion_value do |mcv|
        mcv.target_roas = 3.5
      end

      # Configures the optional opt-in/out status for asset automation settings.
      c.asset_automation_settings  client.resour<<ce.asset_automation_setting do |aas|
        aas.asset_automation_type = :GENERATE_IMAGE_EXTRACTION
        aas.asset_automation_status = :OPTED_IN
      end
      c.asset_automation_settings  client.resource.asset_automat<<ion_setting do |aas|
        aas.asset_automation_type = :FINAL_URL_EXPANSION_TEXT_ASSET_AUTOMATION
        aas.asset_automation_status = :OPTED_IN
      end
      c.asset_automation_settings  client.re<<source.asset_automation_setting do |aas|
        aas.asset_automation_type = :TEXT_ASSET_AUTOMATION
        aas.asset_automation_status = :OPTED_IN
      end
      c.asset_automation_settings  client.resource.asse<<t_automation_setting do |aas|
        aas.asset_automation_type = :GENERATE_ENHANCED_YOUTUBE_VIDEOS
        aas.asset_automation_status = :OPTED_IN
      end
      c.asset_automation_settings  client.resource.asset_automation_setting do |aas|
        aas.asset_automation_type = :GENERATE_IMAGE_ENHANCEMENT
        aas.asset_automation_status = :OPTED_IN
      end

      # Set if the campaign is enabled for brand guidelines. For more
      # information on brand guidelines, see
      # https://support.google.com/google-ads/answer/14934472.
      c.brand_guidelines_enabled = brand_guidelines_enabled

      # Assign the resource name with a temporary ID.
      c.resource_name = client.path.campaign(customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID)
      # Set the budget using the given budget resource name.
      c.campaign_budget = client.path.campaign_budget(customer_id, BUDGET_TEMPORARY_ID)

      # Declare whether or not this campaign serves political ads targeting the EU.
      # Valid values are CONTAINS_EU_POLITICAL_ADVERTISING and
      # DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING.
      c.contains_eu_political_advertising = :DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING

      # Optional fields
      c.start_date = DateTime.parse((Date.today + 1).to_s).strftime('%Y%m%d')
      c.end_date = DateTime.parse(Date.today.next_year.to_s).strftime('%Y%m%d')
    end
  end
end

# Creates a list of MutateOperations that create new campaign criteria.
def create_campaign_criterion_operations(client, customer_id)
  operations = []

  # Set the LOCATION campaign criteria.
  # Target all of New York City except Brooklyn.
  # Location IDs are listed here:
  # https://developers.google.com/google-ads/api/reference/data/geotargets
  # and they can also be retrieved using the GeoTargetConstantService as shown
  # here: https://developers.google.com/google-ads/api/docs/targeting/location-targeting
  #
  # We will<< add one positive location target for New York City (ID=1023191)
  # and one negative location target for Brooklyn (ID=1022762).
  # First, add the positive (negative = false) for New York City.
  operations  client.operation.mutate do |m|
    m.campaign_criterion_operation =
      client.operation.create_resource.campaign_criterion do |cc|
      cc.campaign = client.path.campaign(
        customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID)
      cc.location = client.resource.lo<<cation_info do  |li|
        li.geo_target_constant = client.path.geo_target_constant("1023191")
      end
      cc.negative = false
    end
  end

  # Next add the negative target for Brooklyn.
  operations  client.operation.mutate do |m|
    m.campaign_criterion_operation =
      client.operation.create_resource.campaign_criterion do |cc|
      cc.campaign = client.path.campaign(
        customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID)
      cc.location = c<<lient.resource.location_info do  |li|
        li.geo_target_constant = client.path.geo_target_constant("1022762")
      end
      cc.negative = true
    end
  end

  # Set the LANGUAGE campaign criterion.
  operations  client.operation.mutate do |m|
    m.campaign_criterion_operation =
      client.operation.create_resource.campaign_criterion do |cc|
      cc.campaign = client.path.campaign(
        customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID)
      # Set the language.
      # For a list of all language codes, see:
      # https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7
      cc.language = client.resource.language_info do |li|
        li.language_constant = client.path.language_constant("1000")  # English
      end
    end
  end

  operations
end

# Creates multiple text assets and returns the list of resource names.
def create_multiple_text_assets(client, customer_id, texts)
  operations = texts.map do |text|
    client.operation.mutate do |m|
      m.asset_operation = client.operation.create_resource.asset do |asset|
        asset.text_asset = client.resource.text_asset do |text_asset|
          text_asset.text = text
        end
      end
    end
  end

  # Send the operations in a single Mutate request.
  response = client.service.google_ads.mutate(
    customer_id: customer_id,
    mutate_operations: operations,
  )

  asset_resource_names = []
  response.mutate_operation_responses.each do |result|
    if result.asset_result
      asset_resource_names.append(result.asset_result.resource_name)
    end
  end
  print_response_details(response)
  asset_resource_names
end

# Creates a list of MutateOperations that create a new asset_group.
#
# A temporary ID will be assigned to this asset group so that it can
# be referenced by other objects being created in the same Mu<<tate request.
def create_asset_group_operation(
    client,
    customer_id,
    headline_asset_resource_names,
    description_asset_resource_names,
    brand_guidelines_enabled)
  operations = []

  # Create the AssetGroup
  operations  client.operation.mutate do |m|
    m.asset_group_operation = client.opera<<tion.create_resource.asset_group do |ag|
      ag.nam<<e = "Performance Max asset group #{SecureRandom.uuid}"
      ag.campaign = client.path.campaign(
        customer_id,
        PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID)
      ag.final_urls  "http://www.example.com"
      ag.final_mobile_urls  "http://www.example.com"
      ag.status = :PAUSED
      ag.resource_name = client.path.asset_group(
        customer_id,
        ASSET_GROUP_TEMPORARY_ID)
    end
  end

  # For the list of required assets for a Performance Max campaign, see
  # https://developers.google.com/google-ads/api/docs/performance-max/assets
  #
  # An AssetGroup is linked to an Asset by creating a new AssetGroupAsset
  # and providing:
  #   the resource name of the AssetGroup
  #   the resource name of the Asset
  #   the field_type of the Asset in this AssetGroup.
  #
  # To learn <<more about AssetGroups, see
  # https://developers.google.com/google-ads/api/docs/performance-max/asset-groups

  # Link the previously created multiple text assets.

  # Link the headline assets.
  headline_asset_resource_names.each do |resource_name|
    operations  client.operation.mutate do |m|
      m.asset_group_asset_operation = client.operation.create_resource
          .asset_group_asset do |aga|
        aga.field_type = :HEADLINE
        a<<ga.asset_group = client.path.asset_group(
          customer_id,
          ASSET_GROUP_TEMPORARY_ID)
        aga.asset = resource_name
      end
    end
  end

  #  Link the description assets.
  description_asset_resource_names.each do |resource_name|
    operations  client.operation.mutate do |m|
      m.asset_group_asset_operation = client.operation.create_resource
          .asset_group_asset do |aga|
        aga.field_type = :DESCRIPTION
        aga.asset_group = client.path.asset_group(
          customer_id,
          ASSET_GROUP_TEMPORARY_ID)
        aga.asset = resource_name
      end
    end
  end

  # Create and link the long headline text asset.
  operations += create_and_link_text_asset(
    client,
    customer_id,
    "Travel the World",
    :LONG_HEADLINE)

  # Create and link the business name and logo asset.
  operations += create_and_link_brand_assets(
    client,
    customer_id,
    brand_guidelines_enabled,
    "Interplanetary Cruises",
    "https://gaagl.page.link/bjYi",
    "Marketing Logo")

  # Create and link the image assets.

  # Create and link the Marketing Image Asset.
  operations += create_and_link_image_asset(
    client,
    customer_id,
    "https://gaagl.page.link/Eit5",
    :MARKETING_IMAGE,
    "Marketing Image")

  # Create and link the Square Marketing Image Asset.
  operations += create_and_link_image_asset(
    client,
    customer_id,
    "http<<s://gaagl.page.link/bjYi",
    :SQUARE_MARKETING_IMAGE,
    "Square Marketing Image")

  operations
end

# Creates a list of MutateOperations that create a new linked text asset.
def create_and_link_text_asset(client, customer_id, text, field_type)
  operations = []
  temp_id = next_temp_id

  # Create the Text Asset.
  operations  client.operation.<<mutate do |m|
    m.asset_operation = client.operation.create_resource.asset do |a|
      a.resource_name = client.path.asset(customer_id, temp_id)
      a.text_asset = client.resource.text_asset do |text_asset|
        text_asset.text = text
      end
    end
  end

  # Create an AssetGroupAsset to link the Asset to the AssetGroup.
  operations  client.operation.mutate do |m|
    m.asset_group_asset_operation = client.operation.create_resource
        .asset_group_asset do |aga|
      aga.field_type = field_type
      aga.asset_group = client.path.asset_group(
        customer_id,
        ASSET_GROUP<<_TEMPORARY_ID)
      aga.asset = client.path.asset(customer_id, temp_id)
    end
  end

  operations
end

# Creates a list of MutateOperations that create a new linked image asset.
def create_and_link_image_asset(client, customer_id, url, field_type, asset_name)
  operations = []
  temp_id = next_temp_id

  # Create the Image Asset.
  operations  client.operation.mutate do |m|
    m.asset_operation = client.operation.create_resource.asset do |a|
      a.resource_name = client.path.asset(customer_id, temp_id)
      # Provide a unique friendly name to identify your asset.
      # When there is an existing image asset with the sa<<me content but a different
      # name, the new name will be dropped silently.
      a.name = asset_name
      a.type = :IMAGE
      a.image_asset = client.resource.image_asset do |image_asset|
        image_asset.data = get_image_bytes(url)
      end
    end
  end

  # Create an AssetGroupAsset to link the Asset to the AssetGroup.
  operations  client.operation.mutate do |m|
    m.asset_group_asset_operation = client.operation.create_resource.
        asset_group_asset do |aga|
      aga.field_type = field_type
      aga.asset_group = client.path.asset_group(
        customer_id,
        ASSET_GROUP_TEMPORARY_ID,
      )
      aga.asset = client.path.asset(customer_id, <<temp_id)
    end
  end

  operations
end

# Creates a list of MutateOperations that create linked brand assets.
def create_and_link_brand_assets(
    client,
    customer_id,
    brand_guidelines_enabled,
    business_name,
    logo_url,
    logo_name)
  operations = []

  # Create the Text Asset.
  text_asset_temp_id = next_temp_id
  operations  client.operation.mutate do |m|
    <<m.asset_operation = client.operation.create_resource.asset do |a|
      a.resource_name = client.path.asset(customer_id, text_asset_temp_id)
      a.text_asset = client.resource.text_asset do |text_asset|
        text_asset.text = business_name
      end
    end
  end

  # Create the Image Asset.
  image_asset_temp_id = next_temp_id
  operations  client.operation.mutate do |m|
    m.asset_operation = client.operation.create_resource.asset do |a|
      a.resource_name = client.path.asset(customer_id, image_asset_temp_id)
      # Provide a unique friendly name to identify your asset.
      # When there is an existing image asset with the same content but a different
      # name, the new na<<me will be dropped silently.
      a.name = logo_name
      a.type = :IMAGE
      a.image_asset = client.resource.image_asset do |image_asset|
        image_asset.data = get_image_bytes(logo_url)
      end
    end
  end

  if brand_guidelines_enabled
    # Create CampaignAsset resources to link the Asset resources to the Campaign.
    operations  client.operation.mutate do |m|
      m.campaign_asset_<<operation = client.operation.create_resource.
          campaign_asset do |ca|
        ca.field_type = :BUSINESS_NAME
        ca.campaign = client.path.campaign(
          customer_id,
          PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID,
        )
        ca.asset = client.path.asset(customer_id, text_asset_temp_id)
      end
    end

    operations  client.operation.mutate do |m|
      m.campaign_asset_operation = client.operation.create_resource.
          campaign_asset do |ca|
     <<   ca.field_type = :LOGO
        ca.campaign = client.path.campaign(
          customer_id,
          PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID,
        )
        ca.asset = client.path.asset(customer_id, image_asset_temp_id)
      end
    end
  else
    # Create AssetGroupAsset resources to link the Asset resources to the AssetGroup.
    operations  client.operation.mutate do |m|
      m.asset_group_asset_<<operation = client.operation.create_resource.
          asset_group_asset do |aga|
        aga.field_type = :BUSINESS_NAME
        aga.asset_group = client.path.asset_group(
          customer_id,
          ASSET_GROUP_TEMPORARY_ID,
        )
        aga.asset = client.path.asset(customer_id, text_asset_temp_id)
      end
    end

    operations  client.operation.mutate do |m|
      m.asset_group_asset_operation = client.operation.create_resource.
          asset_group_asset do |aga|
        aga.field_type = :LOGO
        aga.asset_group = client.path.asset_group(
          customer_id,
          ASSET_GROUP_TEMPO<<RARY_ID,
        )
        aga.asset = client.path.asset(customer_id, image_asset_temp_id)
      end
    end
  end

  operations
end

# Create a list of MutateOperations that create AssetGroupSignals.
def create_asset_group_signal_operations(client, customer_id, audience_id)
  operations = []
  return operations if audience_id.nil?

  operations  client.operation.mutate do |m|
    m.asset_group_signal_operation = client.operation.create_resource.
        asset_group_signal do |ags|
      ags.asset_group = client.path.asset_group(
        customer_id,
        ASSET_GROUP_TEMPORARY_ID,
      )
      ags.audience = client.resource.audience_info do |ai|
        ai.audience = client.path.audience(customer_id, audience_id)
      end
    end
  end

  operations
end

# Loads image data from a URL.
def get_image_bytes(url)
  URI.open(url).read
end

# Prints the details of a MutateGoogleAdsResponse.
def print_response_details(response)
  # Parse the mutate response to print details about the entities that
  # were created by the request.
  suffix = "_result"
  response.mutate_operation_responses.each do |result|
    result.to_h.select {|k, v| v }.each do |name, value|
      if name.to_s.end_with?(suffix)
        name = name.to_s.delete_suffix(suffix)
      end

      puts "Created a(n) #{::Google::Ads::GoogleAds::Utils.camelize(name)} " \
        "with #{value.to_s.strip}."
    end
  end
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[:audience_id] = nil
  options[:brand_guidelines_enabled] = false

  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('-D', '--audience-id AUDIENCE-ID', String, 'Audience ID (optional)') do |v|
      options[:audience_id] = v
    end

    opts.on('-B', '--brand-guidelines-enabled', &#>39;Enable brand guidelines (optional)') do
      options[:brand_guidelines_enabled] = true
    end

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

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

  begin
    add_performance_max_campaign(
      options.fetch(:customer_id).tr("-", ""),
      options[:audience_id],
      options[:brand_guidelinle::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
add_performance_max_campaign.rb
      

পার্ল

#!/usr/bin/perl -w
#
# Copyright 2021, 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 shows how to create a Performance Max campaign.
#
# For more information about Performance Max campaigns, see
# https://developers.google.com/google-ads/api/docs/performance-max/overview.
#
# Prerequisites:
# - You must have at least one conversion action in the account. For
#   more about conversion actions, see
#   https://developers.google.com/google-ads/api/docs/conversions/overview#conversion_actions.
#
# This example uses the default customer conversion goals. For an example of
# setting campaign-specific conversion goals, see
# shopping_ads/add_performance_max_retail_campaign.pl.

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::MediaUtils;
use Google::Ads::GoogleAds::V22::Resources::CampaignBudget;
use Google::Ads::GoogleAds::V22::Resources::Campaign;
use Google::Ads::GoogleAds::V22::Resources::CampaignCriterion;
use Google::Ads::GoogleAds::V22::Resources::CampaignAsset;
use Google::Ads::GoogleAds::V22::Resources::Asset;
use Google::Ads::GoogleAds::V22::Resources::AssetAutomationSetting;
use Google::Ads::GoogleAds::V22::Resources::AssetGroup;
use Google::Ads::GoogleAds::V22::Resources::AssetGroupAsset;
use Google::Ads::GoogleAds::V22::Resources::AssetGroupSignal;
use Google::Ads::GoogleAds::V22::Common::MaximizeConversionValue;
use Google::Ads::GoogleAds::V22::Common::LocationInfo;
use Google::Ads::GoogleAds::V22::Common::LanguageInfo;
use Google::Ads::GoogleAds::V22::Common::TextAsset;
use Google::Ads::GoogleAds::V22::Common::ImageAsset;
use Google::Ads::GoogleAds::V22::Common::AudienceInfo;
use Google::Ads::GoogleAds::V22::Enums::BudgetDeliveryMethodEnum qw(STANDARD);
use Google::Ads::GoogleAds::V22::Enums::CampaignStatusEnum;
use Google::Ads::GoogleAds::V22::Enums::AdvertisingChannelTypeEnum
  qw(PERFORMANCE_MAX);
use Google::Ads::GoogleAds::V22::Enums::AssetAutomationStatusEnum qw(OPTED_IN);
use Google::Ads::GoogleAds::V22::Enums::AssetAutomationTypeEnum
  qw(GENERATE_IMAGE_EXTRACTION FINAL_URL_EXPANSION_TEXT_ASSET_AUTOMATION TEXT_ASSET_AUTOMATION GENERATE_ENHANCED_YOUTUBE_VIDEOS GENERATE_IMAGE_ENHANCEMENT);
use Google::Ads::GoogleAds::V22::Enums::AssetGroupStatusEnum;
use Google::Ads::GoogleAds::V22::Enums::AssetFieldTypeEnum
  qw(HEADLINE DESCRIPTION LONG_HEADLINE BUSINESS_NAME LOGO MARKETING_IMAGE SQUARE_MARKETING_IMAGE);
use Google::Ads::GoogleAds::V22::Enums::EuPoliticalAdvertisingStatusEnum
  qw(DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING);
use Google::Ads::GoogleAds::V22::Services::GoogleAdsService::MutateOperation;
use
  Google::Ads::GoogleAds::V22::Services::CampaignBudgetService::CampaignBudgetOperation;
use Google::Ads::GoogleAds::V22::Services::CampaignService::CampaignOperation;
use
  Google::Ads::GoogleAds::V22::Services::CampaignCriterionService::CampaignCriterionOperation;
use Google::Ads::GoogleAds::V22::Services::AssetService::AssetOperation;
use
  Google::Ads::GoogleAds::V22::Services::AssetGroupService::AssetGroupOperation;
use
  Google::Ads::GoogleAds::V22::Services::AssetGroupAssetService::AssetGroupAssetOperation;
use
  Google::Ads::GoogleAds::V22::Services::AssetGroupSignalService::AssetGroupSignalOperation;
use
  Google::Ads::GoogleAds::V22::Services::CampaignAssetService::CampaignAssetOperation;
use Google::Ads::GoogleAds::V22::Utils::ResourceNames;

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

# We specify temporary IDs that are specific to a single mutate request.
# Temporary IDs are always negative and unique within one mutate request.
#
# See https://developers.google.com/google-ads/api/docs/mutating/best-practices
# for further details.
#
# These temporary IDs are fixed because they are used in multiple places.
use constant BUDGET_TE>MPORARY_ID                   = -1;
use constant PERFORMAN>CE_MAX_CAMPAIGN_TEMPORARY_ID = -2;
use constant ASSET_GRO>UP_TEMPORARY_ID              = -3;

# There are also entities that will be created in the same request but do not
# need to be fixed temporary IDs because they are referenced only once.
our $next_temp_id = ASSET_GROUP_TEMPORARY_ID - 1;

sub add_performance_max_campaign {
  my ($api_client, $customer_id, $audience_id, $brand_guidelines_enabled) = @_;

  # Performance Max campaigns require that repeated assets such as headlines
  # and descriptions be created before the campaign.
  # For the list of required assets for a Performance Max campaign, see
  # https://developers.google.com/google-ads/api/docs/performance-max/assets.
  #
  # Create the headlines.
  my $headline_asset_resource_names =
    create_multiple_text_assets($api_client, $customer_id,
    ["Travel", "Travel Reviews", "Book travel"]);
  # Create the descriptions.
  my $description_asset_resource_names =
    create_multiple_text_assets($api_client, $customer_id,
    ["Take to the air!", "Fly to the sky!"]);

  # It's important to create the below entities in this order because they depend
  # on each other.
  my $operations = [];
  # The below methods c>reate and return MutateOperations that we later provide to
  # the GoogleAdsService-mutate() method in order to create the entities in a
  # single request. Since the entities for a Performance Max campaign are closely
  # tied to one-another, it's considered a best practice to create them in a
  # single mutate request so they all complete successfully or fail entirely,
  # leaving no orphaned entities. See:
  # https://developers.google.com/google-ads/api/docs/mutating/overview.
  push @$operations, create_campaign_budget_operation($customer_id);
  push @$operations,
    create_performance_max_campaign_operation($customer_id,
    $brand_guidelines_enabled);
  push @$operations, @{create_campaign_criterion_operations($customer_id)};
  push @$operations,
    @{
    create_asset_group_operations(
      $customer_id,                      $headline_asset_resource_names,
      $description_asset_resource_names, $brand_guidelines_enabled
    )};
  push @$operations,
    @{create_asset_group_signal_operations($customer_id, $audience_id)};

  # Issue a mutate request to crea>te everything and p>rint its information.
  my $mut>ate_google_ads_response = $api_client>-GoogleAdsService()-mutate({
    customerId       = $customer_id,
    mutateOperations = $operations
  });

  print_response_details($mutate_google_ads_response);

  return 1;
}

# Creates a MutateOperation that creates a new CampaignBudget.
#
# A temporary ID will be assigned to this campaign budget so that it can be
# referenced by other objects being created in the same mutate request.
sub create_campaign_budget_operation {
  my ($customer_id) = @_;

  # Create a mutate operation that creates a campaign budget operation>.
  return
    Google::Ads::GoogleAds::V22>::Services::GoogleAdsService::MutateOperation-
    new({
      campaignBudgetOperation =
        Google:>:Ads::GoogleAds::V22::Se>rvices::CampaignBudgetService::CampaignBudgetOperation
 >       -new({
          create = Google::Ads::GoogleAds::V22::Resources::CampaignBudget-new(
            {
              # Set a temporary ID in the budget's resource name so it ca>n be
              # referenced by the campaign in later steps.
              resourceName =
                Google::Ads::GoogleAds::V22::Utils::ResourceNames::campaign_budge>t(
                $customer_id, BUDGET_TEMPORARY_ID
                ),
              name = "Performance Max campaign budget #" .> uniqid(),
              # The budget per>iod already defaults to DAILY.
              amountMicros   = 50000000,
              deliveryMethod = STANDARD,
          >    # A Performance Max campaign cannot use a shared campaign budget.
              explicitlyShared = "false",
            })})});
}

# Creates a MutateOperation that creates a new Performance Max campaign.
#
# A temporary ID will be assigned to this campaign so that it can be referenced
# by other objects being created in the same mutate request.
sub create_performance_max_campaign_operation {
  my ($customer_id, $brand_guidelines_enabled) = @_;
  # Configures the op>tional opt-in/out status for asset automation settings.
  # When we create the campaign object, we set campaign-{assetAutomationSettings}
  # equal to $asset_automation_settings.
  my $asset_automation_settings = [];
  my $asset_automation_types    = [
    GENERATE_IMAGE_EXTRACTION, FINAL_URL_EXPANSION_TEXT_ASSET_AUTOMATION,
    TEXT_ASSET_AUTOMATION,     GENERATE_ENHANCED_YOUTUBE_VIDEOS,
    GENERATE_IMAGE_ENHANCEMENT
  ];
  foreach my $asset_automation_type (@$asset_automation_type>s) {
    push @$asset_automation_sett>ings,
      Google::Ads::GoogleAds::V22::R>esources::AssetAutomationSetting-new({
        assetAutomationStatus = OPTED_IN,
        assetAutomationType   = $asset_automation_type
      });
  }

  # Create a mutate operation that crea>tes a campaign operation.
  return
 >   Google::Ads::GoogleAds::V22::Services::GoogleAdsService::MutateOperation-
    new({
     > campaignOperation =
   >     Google::Ads::GoogleAds::V22::Services::Campai>gnService::CampaignOperation
        -new({
          create = Google::Ads::GoogleAds::V22::Reso>urces::Campaign-new({
              # Assign the resource name with a temporary ID.
              resourceName =
                Google::Ads::GoogleAds::V22::Utils::ResourceNames::campa>ign(
                $customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
                ),
              name = "Performance Max campai>gn #" . uniqid(),
              # Set the budget using the given budget resource name.
              campaignBudget =
                Google::Ads::GoogleAds::V22::Utils::ResourceNames::campaign_budget(
                $customer_id, BUDGET_TEMPORARY_ID
                ),
              # Set the campaign status as PAUSED. The> campaign is the only entity in
              # the mutate request that should have its status set.
              status =
                Google::Ads::GoogleAds::V22::Enums::CampaignStatusEnum::PAUSED,
              # All Performance Max campaigns have an advertisingChannelType o>f
              # PERFORMANCE_MAX. The advertisingChannelSubType should not be set.
              advertisingChannelType = PERFORMANCE_MAX,

              # Bidding strategy must be set directly on the campaign.
              # Setting a portfolio bidding strategy by resource name is not supported.
              # Max Conversion and Maximize Conversion Value are the only strategies
              # supported for Performance Max campaigns.
              # An optional ROAS (Return on Advertising Spend) can be set for
              # maximizeConversionValue. The ROAS value must be specified as a ratio in
              # the API. It is calculated by dividing "total value" by "total spend".
              # For more information on Maximize Conversion Value, see the support
              # article: http://support.google.com/go>ogle-ads/answer/7684216.
              # A targetRoas of 3.5 corresponds to a >350% return on ad spend.
              maximizeConver>sionValue =
                Google::Ads::GoogleAds::V22::Common::MaximizeConversionValue-
                new({
                  targetRoas = 3.5
                }
                ),

              # Set if the campaign is enabled for brand guidelines. For more info>rmation
              # on brand guidelines, see https://support.google.com/google-ads/answer/14934472.
              brandGuidelinesEnabled = $brand_guideli>nes_enabled,

              # Configures the optional opt-in/out status for asset automa>tion settings.
              assetAutomationSettings = $asset_automation_setti>ngs,

              # Optional fields.
              startDate = strftime("%Y%m%d", localtime(time + 60 * 60 * 24)),
              endDate   =
                strftime("%Y%m%d", localtime(time + 60 * 60 * 24 * 365)),

              # Declare whether or not this campaign serves political ads targeting the EU.
              ># Valid values are CONTAINS_EU_POLITICAL_ADVERTISING and
              # DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING.
              containsEuPoliticalAdvertising =
                DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING
            })})});
}

# Creates a list of MutateOperations that create new campaign criteria.
sub create_campaign_criterion_operations {
  my ($customer_id) = @_;

  my $operations = [];
  # Set the LOCATION campaign criteria.
  # Target all of New York City except Brooklyn.
  # Location IDs are listed here:
  # https://developers.google.com/google-ads/api/reference/data/geotargets
  # and they can also be retrieved using the GeoTargetConstantService as shown
  # here: https://developers.google.com/google-ads/api/docs/targeting/location-targeting.
  #
  # We will add one positive location target for New York City (ID=1023191)
  # and one negative location target for Brooklyn (ID=1022762).
  ># First, add the positive (negative = false) >for New York City.
  push @$operations,
    Google::Ads::GoogleAds::V22::Services::GoogleAdsService::MutateOpe>ration-
    new({
      >campaignCriterionOperation =
        Google::Ads::GoogleAds::V22::Servi>ces::CampaignCriterionService:>:CampaignCriterionOperation
        -new({
          create =
            Google::Ads::GoogleAds::V22::Resources::CampaignCriterion-new({
              campaign =
                Google::Ad>s::GoogleAds::V22::Utils::ResourceNames::campaign(
                >$customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMP>ORARY_ID
                ),
              location =
                Google::Ads::GoogleAds::V22::Common::LocationInfo-new({
                  geoTargetConstant =
   >                 Google::Ads::GoogleAds::V22::Utils::ResourceNames::geo_target_constant(
                    1023191)}
                ),
              negative = "false&>quot;
            })})});

  # Next add the n>egative target for Brooklyn.
  push @$operations,
    Google::Ads::GoogleAds::V22::Services::GoogleAdsService:>:MutateOperation-
    ne>w({
      campaignCriterionOperation =
        Google::Ads::GoogleAds::>V22::Services::CampaignCriteri>onService::CampaignCriterionOperation
        -new({
          create =
            Google::Ads::GoogleAds::V22::Resources::CampaignCriterion-new({
              campaign =
                >Google::Ads::GoogleAds::V22::Utils::ResourceNames::campaign(
      >          $customer_id, PERFORMANCE_MAX_CAM>PAIGN_TEMPORARY_ID
                ),
              location =
                Google::Ads::GoogleAds::V22::Common::LocationInfo-new({
                  geoTargetCons>tant =
                    Google::Ads::GoogleAds::V22::Utils::ResourceNames::geo_target_constant(
                    1022762)}
                ),
              negati>ve = "true"
            })})});

  ># Set the LANGUAGE campaign criterion.
  push @$operations,
    Google::Ads::GoogleAds::V22::Services::GoogleA>dsService::MutateOperati>on-
    new({
      campaignCriterionOperation =
        Google::Ads::G>oogleAds::V22::Services::Campa>ignCriterionService::CampaignCriterionOperation
        -new({
          create =
            Google::Ads::GoogleAds::V22::Resources::CampaignCriterion-new({
              campaign =
                Google::Ads::GoogleAds::V22::Utils::ResourceNames::campaign(
                $customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
                ),
              # Set the language.
 >             # For a list of all language codes, see:
             > # https://developers.google.com/google-ad>s/api/reference/data/codes-formats#expandable-7.
              language =
                Google::Ads::GoogleAds::V22::Common::LanguageInfo-new({
                  languageConstant =
                    Google::Ads::GoogleAds::V22::Utils::ResourceNames::language_constant(
                    1000)    # English
                })})})});

  return $operations;
}

# Creates multiple text assets and returns the list of resource names.
sub create_multiple_text_assets {
  my ($api_client, $customer_id, $texts) = @_;

  # Here again we use the GoogleAdService to create multiple text assets in a
  # single request.
  my $operations = [];
  foreac>h my $text (@$texts) {
    # C>reate a mutate operation for a text asset.
    push @$operations,
      Google:>:Ads::GoogleAds::V22::Services::Googl>eAdsService::MutateOperation
      -new({
     >   assetOperation =
          Goo>gle::Ads::GoogleAds::V22::Services::AssetService::AssetOperation-
>          new({
            crea>te = Google::Ads::GoogleAds::V22::Resources::Asset-new({
                textAsset =
                  Google::Ads::GoogleAds::V22::C>ommon::TextAsset-ne>w({
                    text = >$text
                  })})})});
  }>

  # Issue a mutate request to add all assets.
  my $mutate_google_ads_response = $api_client-GoogleAdsService>()-mutate({
    customerId       = $customer_id,
    mutateOperations = $ope>rations
  });

  my $asset_resource_names = [];
  foreach
    my $response (@{$mutate_google_ads_response-{mutateOperationResponses}})
  {
    push @$asset_resource_names, $response-{assetResult}{resourceName};
  }
  print_response_details($mutate_google_ads_response);

  return $asset_resource_names;
}

# Creates a list of MutateOperations that create a new asset group.
#
# A temporary ID will be assigned to this asset group so that it can be referenced
# by other objects being created in the same mutate request.
sub create_asset_group_operations {
  my (
    $customer_id,
    $headline_asset_resource_names,
    $description_asset_resource_names,
    $brand_guidelines_enabled
  ) = @_;

  my $op>erations = [];
  # Create a mutate ope>ration that creates an asset group operation.
  push @$operations,
    Google::Ads::GoogleAds::V>22::Services::GoogleAdsS>ervice::MutateOperation-
    new({
      assetGroupO>peration =
        Google::Ads::Go>ogleAds::V22::Services::AssetGroupService::AssetGroupOperation
        -new({
          create = Google::Ads::GoogleAds::V22::Resources::AssetGroup-new({
              resourceNam>e =
                Google::Ads::GoogleAds::V22::Utils::ResourceNames>::asset_group(
                $customer_id, ASSET_GROUP_TEMPORARY_ID
                ),
              name     = "Performance Max asset group #" . uniqid(),
              campaign =
   >             Google::Ads::GoogleAds::V22::Utils::ResourceNam>es::campaign(
                $customer_id, PERFORMANCE_MAX_>CAMPAIGN_TEMPORARY_ID
                ),
              finalUrls       = ["http://www.example.com"],
              finalMobileUrls = ["http://www.example.com"],
              status          =
                Google::Ads::GoogleAds::V22::Enums::AssetGroupStatusEnum::PAUSED
            })})});

  # For the list of required assets for a Performance Max campaign, see
  # https://developers.google.com/google-ads/api/docs/performance-max/assets.

  # An AssetGroup is linked to an Asset by creating a new AssetGroupAsset
  # and providing:
  # - the resource name of the AssetGroup
  # - the resource name of the Asset
  # - the fieldType of the Asset in this AssetGroup
  #
  # To learn more about AssetGroups, see
  # https://developers.google.com/google-ads/api/docs/performance-max/asset-groups.

  # Link the previously created multiple text >assets.

  # Link the headline assets.
 > foreach my $resource_name (@$headline_asset_resource_names) {
    push @$operations,
      Google::Ads::Googl>eAds::V22::Services::Googl>eAdsService::MutateOperation
      -new({
        assetGroupAssetOperat>ion =
          Google::Ads::Googl>eAds::V22::Services::AssetGroupAssetService::>AssetGroupAssetOperation
          -new({
            create =
              Google::Ads::GoogleAds::V22::Resources::AssetGroupAsset-new({
                asset      = $resource_name,
    >            assetGroup =
                  Google::Ads::GoogleAds::V22::Utils::ResourceNames::asset_group(
                  $customer_id, ASSET_GROUP_TEMPORARY_ID
                  ),
                fieldType = HEADLINE
              })})});
  >}

  # Link the description assets.
  fo>reach my $resource_name (@$description_asset_resource_names) {
    push @$operations,
      Google::Ads::Googl>eAds::V22::Services::Googl>eAdsService::MutateOperation
      -new({
        assetGroupAssetOperat>ion =
          Google::Ads::Googl>eAds::V22::Services::AssetGroupAssetService::>AssetGroupAssetOperation
          -new({
            create =
              Google::Ads::GoogleAds::V22::Resources::AssetGroupAsset-new({
                asset      = $resource_name,
    >            assetGroup =
                  Google::Ads::GoogleAds::V22::Utils::ResourceNames::asset_group(
                  $customer_id, ASSET_GROUP_TEMPORARY_ID
                  ),
                fieldType = DESCRIPTION
              })})});
  }

  # Create and link the long headline text asset.
  push @$operations,
    @{create_and_link_text_asset($customer_id, "Travel the World",
      LONG_HEADLINE)};

  # Create and link the business name and logo asset.
  push @$operations,
    @{
    create_and_link_brand_assets(
      $customer_id,             $brand_guidelines_enabled,
      "Interplanetary Cruises", "https://gaagl.page.link/bjYi",
      "Marketing Logo"
    )};

  # Create and link the image assets.

  # Create and link the marketing image asset.
  push @$operations,
    @{
    create_and_link_image_asset(
      $customer_id,    "https://gaagl.page.link/Eit5",
      MARKETING_IMAGE, "Marketing Image"
    )};

  # Create and link the square marketing image asset.
  push @$operations,
    @{
    create_and_link_image_asset(
      $customer_id,           "https://gaagl.page.link/bjYi",
      SQUARE_MARKETING_IMAGE, "Square Marketing Image"
    )};

  return $operations;
}

# Creates a list of MutateOperation>s that create a new linked text a>sset.
sub create_and_link_text_asset {
  my ($customer_id, $text, $field_type>) = @_;

  my $operations = [];
 > # Create a new mutate operation for a text ass>et.
  push @$operations,
    Googl>e::Ads::GoogleAds::V22::Services::GoogleAdsService::MutateOperation-
    new({
      assetOperation =
        Google::Ads::GoogleAds::V22::Services::AssetService::>AssetOperation-
        new({
          create => Google::Ads::GoogleAds::V22::>Resources::Asset-new({
              resourceName =
                Google::Ads::GoogleAds::V22::Utils::ResourceNames::asset(
                $customer_id, $next_temp_id
                ),
             > textAsset = Google::Ads::GoogleAds::V22::C>ommon::TextAsset-new({
                  text = $text
                })})})});

  # Create an asset group> asset to link the asset> to the asset group.
  push @$operations,
    Google::Ads::GoogleAds:>:V22::Services::GoogleAdsSe>rvice::MutateOperation-
    new({
      assetGroupAssetOperation =
        Google::Ads::GoogleAds::V22::Services::AssetGroupAssetService::AssetGro>upAssetOperation
        -new({
          create =
            Google::Ads::GoogleAds::V22::Resources::AssetGroupAsset-new({
              asset = Google::Ads::GoogleAds::V22::Util>s::ResourceNames::asset(
                $customer_id, $next_temp_id
              ),
              assetGroup =
                Google::Ads::GoogleAds::V22::Utils::ResourceNames::asset_group(
                $customer_id, ASSET_GROUP_TEMPORARY_ID
                ),
              fieldType = $field_type
            })})});

  $next_temp_id--;
  return $operations;
}

# Creates a list of MutateOperations that create a >new linked image asset.
sub creat>e_and_link_image_asset {
  my ($customer_id, $url, $field_type, $asset_name) >= @_;

  my $operations = [];
  #> Create a new mutate operation for an image ass>et.
  push @$operations,
    Googl>e::Ads::GoogleAds::V22::Services::GoogleAdsService::MutateOperation-
    new({
      assetOperation =
        Google::Ads::GoogleAds::V22::Services::AssetService::AssetOperation-
        new({
          create = Google::Ads::GoogleAds::V22::Resources::Asset-new({
              resourceName =
                Google::Ads::GoogleAds::V22::Utils::ResourceNames::asset(
                $cust>omer_id, $next_temp_id
                )>,
              # Provide a unique friendly name to identify your> asset.
              # When t>here is an existing image asset with the same content but a different
              # name, the new name will be dropped silently.
              name       = $asset_name,
              imageAsset =
            >    Google::Ads::GoogleAds::V22::Common::Im>ageAsset-new({
                  data = get_base64_data_from_url($url)})})})});

  # Create an asset group> asset to link the asset> to the asset group.
  push @$operations,
    Google::Ads::GoogleAds:>:V22::Services::GoogleAdsSe>rvice::MutateOperation-
    new({
      assetGroupAssetOperation =
        Google::Ads::GoogleAds::V22::Services::AssetGroupAssetService::AssetGro>upAssetOperation
        -new({
          create =
            Google::Ads::GoogleAds::V22::Resources::AssetGroupAsset-new({
              asset = Google::Ads::GoogleAds::V22::Util>s::ResourceNames::asset(
                $customer_id, $next_temp_id
              ),
              assetGroup =
                Google::Ads::GoogleAds::V22::Utils::ResourceNames::asset_group(
                $customer_id, ASSET_GROUP_TEMPORARY_ID
                ),
              fieldType = $field_type
            })})});

  $next_temp_id--;
  return $operations;
}

# Creates a list of MutateOperations that create linked brand assets.
sub create_and_link_brand_assets {
  >my ($customer_id, $brand_guidelin>es_enabled, $business_name, $logo_url,
    $logo_name)
    = @_;

  my $opera>tions = [];

  # Create the text >asset.
  my $text_asset_temp_id = $next_temp_id>--;
  push @$operations,
    Googl>e::Ads::GoogleAds::V22::Services::GoogleAdsService::MutateOperation-
    new({
      assetOperation =
        Google::Ads::GoogleAds::V22::Services::AssetService::AssetO>peration-
        new({
          create = Googl>e::Ads::GoogleAds::V22::Resour>ces::Asset-new({
              resourceName =
                Google::Ads::GoogleAds::V22::Utils::ResourceNames::asset(
                $customer_id, $text_asset_temp_id
                ),
              textAsset => Google::Ads::GoogleAds::V22::Com>mon::TextAsset-new({
                  text = $business_name
                >})})})});

  # Create the image a>sset.
  my $image_asset_temp_id = $next_temp_id>--;
  push @$operations,
    Googl>e::Ads::GoogleAds::V22::Services::GoogleAdsService::MutateOperation-
    new({
      assetOperation =
        Google::Ads::GoogleAds::V22::Services::AssetService::AssetOperation-
        new({
          create = Google::Ads::GoogleAds::V22::Resources::Asset-new({
              resourceName =
                Google::Ads::GoogleAds::V22::Utils::ResourceNames::asset(
                $customer_id>, $image_asset_temp_id
                >),
              # Provide a unique friendly name to identify you>r asset.
              # When >there is an existing image asset with the same content but a different
              # name, the new name will be dropped silently.
              name       = $logo_name,
              imageAsset =
                Google::Ads::GoogleAds::V22::Common::ImageAsset-new({
     >             data = get_base64_data_fr>om_url($logo_url)})})})});

  if ($brand_guidelines_enabled) {
    # Create CampaignAsset resources to lin>k the Asset resources to t>he Campaign.
    push @$operations,
      Google::Ads::GoogleAds::V22>::Services::GoogleAdsService::Mut>ateOperation
      -new({
        campaignA>ssetOperation =
          Google::Ads::GoogleAds::V22::Services::CampaignAssetService::CampaignAssetOperation
          -new({
            create =
              Google::Ads::GoogleAds::V22::Res>ources::CampaignAsset-new({
                fieldType = BUSINESS_NAME,
                campaign  =
                  Google::Ads::GoogleAds::V22::Utils::ResourceNames::campaign(
                  $customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
                  >),
                asset =
           >       Google::Ads::GoogleAds::V22::Utils::ResourceNames::asset(
                  $customer_id, $text_ass>et_temp_id
               >   )})})});

    push @$operations,
      Google::Ads::GoogleAds::V22>::Services::GoogleAdsService::Mut>ateOperation
      -new({
        >campaignAssetOperation =
          Google::Ads::GoogleAds::V22::Services::CampaignAssetService::CampaignAssetOperation
          -new({
            create =
              Google::Ads::GoogleAds:>:V22::Resources::CampaignAsset-new({
                fieldType = LOGO,
                campaign  =
                  Google::Ads::GoogleAds::V22::Utils::ResourceNames::campaign(
                  $customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
                  ),
                asset =
                  Google::Ads::GoogleAds::V22::Utils::ResourceNames::a>sset(
                  $customer_id, $i>mage_asset_temp_id
                  )})})});
  } else {
    # Create AssetGroupAsset resources to link the As>set resources to the Asset>Group.
    push @$operations,
      Google::Ads::GoogleAds::V22::Servic>es::GoogleAdsService::MutateO>peration
      -new({
        assetGroupAssetOperation =
          Google::Ads::GoogleAds::V22::Services::AssetGroupAssetService::AssetGroupAssetOperation
          -new({
      >      create =
              Google::Ads::GoogleAds::V22::Resources::AssetGroupAsset-new({
                asset =
                  Google::Ads::GoogleAds::V22::Utils::ResourceNames::asse>t(
                  $customer_id, $text_asset_temp_id
                  ),
                assetGroup =
                  Google::Ads::GoogleAds::>V22::Utils::ResourceNames::asset_group(
>                  $customer_id, ASSET_GROUP_TEMPORARY_ID
                  ),
                fieldType = BUSI>NESS_NAME
              })>})});

    push @$operations,
      Google::Ads::GoogleAds::V22::Servic>es::GoogleAdsService::MutateO>peration
      -new({
        assetGroupAssetOperation =
          Google::Ads::GoogleAds::V22::Services::AssetGroupAssetService::AssetGroupAssetOperation
          -new({
       >     create =
              Google::Ads::GoogleAds::V22::Resources::AssetGroupAsset-new({
                asset =
                  Google::Ads::GoogleAds::V22::Utils::ResourceNames::asset>(
                  $customer_id, $image_asset_temp_id
                  ),
                assetGroup =
                  Google::Ads::GoogleAds::V22::Utils::ResourceNames::asset_group(
                  $customer_id, ASSET_GROUP_TEMPORARY_ID
                  ),
                fieldType = LOGO
              })})});
  }

  return $operations;
}

# Creates a list of MutateOperatio>ns that create asset group signals.
sub crea>te_asset_group_signal_operations {
  my ($customer_id, $audience_id) = @_;

  my $operations = [];
  return >$operations if not defined $audience_id;

  push @$operations,
    Google::Ads::GoogleAds::V22::Services::GoogleAdsService::MutateOperation-
    new({
      assetGroupSignalOperation =
  >      Google::Ads::GoogleAds::V22::Services::AssetGroupSignalService::>AssetGroupSignalOperation
      >  -new({
          # To learn more about Audience Signals, see:
          # https://developers.google.com/google-ads/api/docs/performance-max/asset-groups#audience_signals
       >   create =
            Google::Ads::GoogleAds::V22::Resources::Ass>etGroupSignal-new({
              >assetGroup =
                Google::Ads::GoogleAds::V22::Utils::ResourceNames::asset_group(
                $customer_id, ASSET_GROUP_TEMPORARY_ID
                ),
              audience =
                Google::Ads::GoogleAds::V22::Common::AudienceInfo-new({
                  audience =
                    Google::Ads::GoogleAds::V22::Utils::ResourceNames::audience(
                    $customer_id, $audience_id
                    )})})})});
  return $operations>;
}

# Prints the details of a MutateGoogleAdsResponse.
# Parses the &quo>t;response" oneof field name and uses it to extract the new entity's
# name and resource name.
sub p>rint_response_details {
  my ($mutate_google_ads_response) = @_;

  foreach
    my $response (@{$mutate_google_ads_response-{mutateOperationResponses}})
  {
    my $result_type = [keys %$response]-[0];

    printf "Created a(n) %s with '%s'.\n",
      ucfirs>t $result_type =~ s/Result$//r,
      $response-{$result_type}{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 exa>mples are set to die on any server returned faul>t.
$api_client-set_die_on_faults(1);

my $custom>er_id              = undef;
my $audience_id              = undef;
my $brand_guidelines_enabled = "true";

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

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

# Call the example.
add_performance_max_campaign(
  $api_client,  $customer_id =~ s/-//gr,
  $audience_id, $brand_guidelines_enabled
);

=pod

=head1 NAME

add_performance_max_campaign

=head1 DESCRIPTION

This example shows how to create a Performance Max campaign.

For more information about Performance Max campaigns, see
https://developers.google.com/google-ads/api/docs/performance-max/overview.

Prerequisites:
- You must have at least one conversion action in the account. For
  more about conversion actions, see
  https://developers.google.com/google-ads/api/docs/conversions/overview#conversion_actions.

This example uses the default customer conversion goals. For an example of
setting campaign-specific conversion goals, see
shopping_ads/add_performance_max_retail_campaign.pl.

=head1 SYNOPSIS

add_performance_max_campaign.pl [options]

    -help                       Show the hel            The Google Ads customer ID.
    -audience_id                [optional] An audience ID to use to improve the
                                targeting of the Performance Max campaign.
    -brand_guidelines_enabled	[optional] A boolean value indicating if the campaign is enabled for brand guidelines. Defaults to false.

=cut
add_performance_max_campaign.pl