This guide provides a checklist of concepts and tasks for each of the four
Performance Max business goals to help you build your campaign. To get started,
select a business goal:

<button value="standard" default="">Online sales or lead generation</button> <button value="retail">Online sales with a product feed</button> <button value="travel-goals">Travel Goals</button> <button value="pay-per-lead">Pay-per-lead goals</button>

> [!TIP]
> **Tip:** Do you have an existing advertising campaign you want to upgrade? Check out the [upgrade guide](https://developers.google.com/google-ads/api/performance-max/upgrade-overview.md.txt).

## Architecture and bulk mutate summary

The following tables summarize the required resources, campaign settings, and
atomic [`GoogleAdsService.Mutate`](https://developers.google.com/google-ads/api/reference/rpc/v26/GoogleAdsService/Mutate.md.txt) operation order across all
four Performance Max business goals:

### Settings by Performance Max business goal

All Performance Max campaigns require `advertising_channel_type` set to
`PERFORMANCE_MAX`, a [`MaximizeConversions`](https://developers.google.com/google-ads/api/reference/rpc/v26/MaximizeConversions.md.txt) or
[`MaximizeConversionValue`](https://developers.google.com/google-ads/api/reference/rpc/v26/MaximizeConversionValue.md.txt) bidding strategy (`MaximizeConversions` only for
Local Services), and `contains_eu_political_advertising`. The following table
summarizes the goal-specific settings and resource requirements:

| Business goal | Goal-specific `Campaign` settings | Required resources and linkages |
|---|---|---|
| **Standard (online sales or lead generation)** | Leave `advertising_channel_sub_type` unset. Configure `brand_guidelines_enabled` (defaults to `true`). | Create at least one [`AssetGroup`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetGroup.md.txt) atomically with [`AssetGroupAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetGroupAsset.md.txt) operations meeting all [minimum asset requirements](https://developers.google.com/google-ads/api/performance-max/asset-requirements.md.txt), plus campaign-level `BUSINESS_NAME` and `LOGO` [`CampaignAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/CampaignAsset.md.txt) links when `brand_guidelines_enabled` is `true`. |
| **Retail (online sales with a product feed)** | Leave `advertising_channel_sub_type` unset. Set [`shopping_setting.merchant_id`](https://developers.google.com/google-ads/api/reference/rpc/v26/Campaign.ShoppingSetting.md.txt) to your linked Merchant Center ID and configure `brand_guidelines_enabled` (defaults to `true`). | Attach a valid [`AssetGroupListingGroupFilter`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetGroupListingGroupFilter.md.txt) product partition tree to each `AssetGroup`. `AssetGroupAsset` and campaign-level `CampaignAsset` brand links are optional if omitted (auto-generated from Merchant Center) or limited to HTML5 `MEDIA_BUNDLE` assets, and otherwise must meet minimum asset and brand requirements. |
| **Travel Goals (hotel properties)** | Set `advertising_channel_sub_type` to `TRAVEL_GOALS` and [`hotel_property_asset_set`](https://developers.google.com/google-ads/api/reference/rpc/v26/Campaign.md.txt#hotel_property_asset_set) to the hotel property `AssetSet` resource name. Leave `brand_guidelines_enabled` unset or `false`. | Create an [`AssetSet`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetSet.md.txt#type) with `type` set to `HOTEL_PROPERTY` first, optionally call [`SuggestTravelAssets`](https://developers.google.com/google-ads/api/reference/rpc/v26/TravelAssetSuggestionService/SuggestTravelAssets.md.txt) on [`TravelAssetSuggestionService`](https://developers.google.com/google-ads/api/reference/rpc/v26/TravelAssetSuggestionService.md.txt), and attach required assets to each `AssetGroup`. |
| **Pay-per-lead goals (Local Services)** | Leave `advertising_channel_sub_type` unset. Set `brand_guidelines_enabled` to `false`, `pmax_campaign_settings.local_services_enabled` to `true`, and [`pmax_campaign_settings.local_services_pmax_campaign_settings`](https://developers.google.com/google-ads/api/reference/rpc/v26/Campaign.LocalServicesPmaxCampaignSettings.md.txt) (`country_code`, `listing_id`). | Link a synced `LOCATION` asset through a `STATIC_LOCATION_GROUP` `AssetSet` and `CampaignAssetSet`, add positive service-area `LOCATION` criteria and an English `LANGUAGE` criterion (`languageConstants/1000`), create an `ENABLED` `AssetGroup` with `google_local_services_info` (with immutable `category_id` and optional `callouts`; `final_urls` optional; `AssetGroupAsset` links aren't supported), and attach at least one `local_services_id` `AssetGroupSignal`. See the [pay-per-lead guide](https://developers.google.com/google-ads/api/performance-max/pay-per-lead.md.txt). |

### Atomic `GoogleAdsService.Mutate` operation order

When creating a Performance Max campaign in a single
[`GoogleAdsService.Mutate`](https://developers.google.com/google-ads/api/reference/rpc/v26/GoogleAdsService/Mutate.md.txt) request (with
`partial_failure = false` when `brand_guidelines_enabled = true`), order your
[`MutateOperation`](https://developers.google.com/google-ads/api/reference/rpc/v26/MutateOperation.md.txt) entries so that every referenced resource
is created before any operation that references its negative temporary ID, keep
`campaign_asset_operation` entries immediately after `campaign_operation`, and
group all `AssetGroupAssetOperation` entries consecutively:

| Order | `MutateOperation` field | Temporary resource name and required fields |
|---|---|---|
| 1 | `campaign_budget_operation` | **Temp ID:** `customers/{customer_id}/campaignBudgets/-1`. Set `name`, `amount_micros`, `delivery_method` (`STANDARD`), `period` (`DAILY`), and `explicitly_shared` (`false`; shared budgets aren't supported). |
| 2 | `asset_operation` | **Temp IDs:** `customers/{customer_id}/assets/-10`, `-11`, ... (repeated). Create `text_asset`, `image_asset`, or `youtube_video_asset` resources (or reuse existing account-level asset resource names). Must precede `campaign_asset_operation` and `asset_group_asset_operation`; omit for assetless Retail or Local Services campaigns. |
| 3 | `campaign_operation` | **Temp ID:** `customers/{customer_id}/campaigns/-2`. Set `name`, `status`, `advertising_channel_type` (`PERFORMANCE_MAX`), `campaign_budget` (`"customers/{customer_id}/campaignBudgets/-1"`), bidding strategy (`maximize_conversions` or `maximize_conversion_value`; `maximize_conversions` only for Local Services), `brand_guidelines_enabled` (`true` by default for Standard and Retail; unset or `false` for Travel Goals; `false` for Local Services), `contains_eu_political_advertising`, and goal-specific settings (`shopping_setting`, `advertising_channel_sub_type` = `TRAVEL_GOALS` and `hotel_property_asset_set`, or `pmax_campaign_settings`). |
| 4 | `campaign_asset_operation` | **Consecutive block (when `brand_guidelines_enabled` is `true`):** Link 1 `BUSINESS_NAME` and 1 to 5 `LOGO` assets (plus optional `LANDSCAPE_LOGO`) to `campaign` (`"customers/{customer_id}/campaigns/-2"`) immediately after `campaign_operation` in the same request with `partial_failure` set to `false` (exempt for Retail campaigns with no custom non-HTML5 `MEDIA_BUNDLE` `AssetGroupAsset` links). |
| 5 | `asset_group_operation` | **Temp ID:** `customers/{customer_id}/assetGroups/-3`. Set `name`, `campaign` (`"customers/{customer_id}/campaigns/-2"`), `final_urls[]` (at least 1 URL when required; optional for Local Services and for Retail asset groups with no custom non-HTML5 `MEDIA_BUNDLE` `AssetGroupAsset` links), and `status` (`ENABLED` required for Local Services). |
| 6 | `asset_group_asset_operation` | **Consecutive block:** Link required assets to `asset_group` (`"customers/{customer_id}/assetGroups/-3"`) by [`field_type`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetFieldTypeEnum.AssetFieldType.md.txt): at least 3 `HEADLINE`, 1 `LONG_HEADLINE`, 2 `DESCRIPTION`, 1 `MARKETING_IMAGE` (1.91:1), and 1 `SQUARE_MARKETING_IMAGE` (1:1) (plus 1 `BUSINESS_NAME` and 1 `LOGO` on the asset group only when `brand_guidelines_enabled` is `false`, such as Travel Goals). Optional for Retail campaigns if omitted or limited to HTML5 `MEDIA_BUNDLE` assets; not supported for Local Services campaigns. |
| 7 | `asset_group_listing_group_filter_operation` | **Temp IDs (Retail only):** `customers/{customer_id}/assetGroupListingGroupFilters/-4`, ... Attach a complete [`AssetGroupListingGroupFilter`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetGroupListingGroupFilter.md.txt) product partition tree to `asset_group` (`"customers/{customer_id}/assetGroups/-3"`), such as a root `UNIT_INCLUDED` node to target all products. |

> [!NOTE]
> **Note:** For Standard, Retail, and Travel Goals campaigns, optional `campaign_criterion_operation` and `campaign_conversion_goal_operation` entries can be added after `campaign_operation` (referencing `customers/{customer_id}/campaigns/-2`), and optional `asset_group_signal_operation` entries can be added after `asset_group_asset_operation` (referencing `customers/{customer_id}/assetGroups/-3`). Local Services campaigns additionally require `campaign_criterion_operation`, `asset_set_operation`, `asset_set_asset_operation`, `campaign_asset_set_operation`, and `asset_group_signal_operation` (`campaign_criterion_operation` and `asset_group_operation` must precede `asset_group_signal_operation`); see [atomic creation in the pay-per-lead guide](https://developers.google.com/google-ads/api/performance-max/pay-per-lead.md.txt#atomic-creation).


## Performance Max for online sales or lead generation (standard)

[Performance Max](https://support.google.com/google-ads/answer/10724817) allows advertisers to access all Google Ads channels and
inventory from a single, unified campaign. The steps to create a
standard Performance Max campaign are as follows. Click the links in each section for more
information.

> [!IMPORTANT]
> **Important:** In order to use Performance Max campaigns, you must have conversion tracking set up on your Google Ads account.

<br />

### Performance Max concepts

<br />

<br />

[Learn about Performance Max for online sales or lead generation
(standard)](https://developers.google.com/google-ads/api/performance-max/standard)

<br />

One of the most common goals among advertisers is to encourage customers to
pursue a specific action to achieve a goals such as generating sales or leads.
In the Google Ads API, Performance Max campaigns for online sales or lead generation
are often referred to as *standard* Performance Max campaigns.

When creating a Performance Max campaign, you can use a [bulk mutate request](https://developers.google.com/google-ads/api/docs/mutating/bulk-mutate.md.txt)
to create the resources required to form a valid, serving campaign in a single
request. Not all resources must be created in a single bulk mutate request. The
following resources are required to create a valid, serving Performance Max
campaign. Learn more in the [Structure requests guide](https://developers.google.com/google-ads/api/performance-max/structure-requests.md.txt).

- `CampaignBudget`
- `Campaign`
- `CampaignAssets` (for campaigns with brand guidelines enabled only)
- `AssetGroups`
- `AssetGroupAssets`

<br />

*** ** * ** ***

<br />

### Campaign and campaign budget

<br />

[Add a campaign budget](https://developers.google.com/google-ads/api/performance-max/create-budget.md.txt)

<br />

- The budget must have a [`DAILY`](https://developers.google.com/google-ads/api/reference/rpc/v26/BudgetPeriodEnum.BudgetPeriod.md.txt#daily) budget period ([learn more](https://support.google.com/google-ads/answer/6385083)).
- The budget cannot be [shared](https://support.google.com/google-ads/answer/10487241).

<br />

#### Code example

### Java

```java
/** 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();
}

      
```

### C#

```c#
/// <summary>
/// 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.
/// </summary>
/// <param name="budgetResourceName">The temporary resource name of the budget to
/// create.</param>
/// <returns>A 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 = budgetResourceName
            }
        }
    };

    return operation;
}

      
```

### PHP

```php
private static function createCampaignBudgetOperation(int $customerId): MutateOperation
{
    // Creates a mutate operation that creates a campaign budget operation.
    return new MutateOperation(
        [
        'campaign_budget_operation' => new CampaignBudgetOperation(
            [
            'create' => new CampaignBudget(
                [
                // Sets a temporary ID in the budget's resource name so it can be referenced
                // by the campaign in later steps.
                'resource_name' => ResourceNames::forCampaignBudget(
                    $customerId,
                    self::BUDGET_TEMPORARY_ID
                ),
                'name' => 'Performance Max campaign budget #' . Helper::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
                ]
            )
            ]
        )
        ]
    );
}
      
```

### Python

```python
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(
        "CampaignBudgetService"
    ).campaign_budget_path(customer_id, _BUDGET_TEMPORARY_ID)

    return mutate_operation
      
```

### Ruby

```ruby
# 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
      
```

### Perl

```perl
sub create_campaign_budget_operation {
  my ($customer_id) = @_;

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

### curl

> [!NOTE]
> **Note:** While a direct REST code sample for this step isn't provided here, you can achieve this using a manual REST request.   
>
> Refer to the Google Ads API REST interface documentation and the method-specific reference pages. You will need to construct the JSON payload based on the proto definitions.   
>
> Key Resources:
>
> - [Using REST](https://developers.google.com/google-ads/api/rest/overview.md.txt)
> - [REST Interface Structure](https://developers.google.com/google-ads/api/rest/design/overview.md.txt)
> - [JSON Field Mappings](https://developers.google.com/google-ads/api/rest/design/json-mappings.md.txt)
> - Consult the [REST API Reference](https://developers.google.com/google-ads/api/reference/rpc/latest/overview) for the specific service and method.

<br />

*** ** * ** ***

<br />

<br />

<br />

[Add a campaign and bidding strategy](https://developers.google.com/google-ads/api/performance-max/create-campaign.md.txt)

<br />

Performance Max campaigns have an [`AdvertisingChannelType`](https://developers.google.com/google-ads/api/reference/rpc/v26/AdvertisingChannelTypeEnum.AdvertisingChannelType.md.txt) of
`PERFORMANCE_MAX`.

Leave `AdvertisingChannelSubType` unset.


These are the only supported [bidding strategies](https://developers.google.com/google-ads/api/docs/campaigns/bidding/strategy-types.md.txt):

- If you aren't tracking values and care about all of your conversions
  equally, use the [`MaximizeConversions`](https://developers.google.com/google-ads/api/reference/rpc/v26/MaximizeConversions.md.txt) bidding strategy. An optional
  [target CPA (cost-per-action)](https://developers.google.com/google-ads/api/reference/rpc/v26/MaximizeConversions.md.txt#target_cpa_micros) can be set. [Learn more](https://support.google.com/google-ads/answer/7381968).

- If you're tracking values with your conversions, set the
  [`MaximizeConversionValue`](https://developers.google.com/google-ads/api/reference/rpc/v26/MaximizeConversionValue.md.txt) bidding strategy. An optional [target ROAS
  (return on ad spend)](https://developers.google.com/google-ads/api/reference/rpc/v26/MaximizeConversionValue#target_roas) can be set. [Learn more](https://support.google.com/google-ads/answer/7684216).

<br />

#### Code example

### Java

```java
/** Creates a MutateOperation that creates a new Performance Max campaign. */
private MutateOperation createPerformanceMaxCampaignOperation(
    long customerId, boolean brandGuidelinesEnabled) {
  TextGuidelines textGuidelines =
      TextGuidelines.newBuilder()
          // Specifies a list of terms that should not be used in any auto-generated
          // text assets.
          .addAllTermExclusions(ImmutableList.of("cheap", "free"))
          // Specifies freeform messaging restriction prompts that will apply to all
          // auto-generated text assets.
          .addMessagingRestrictions(
              MessagingRestriction.newBuilder()
                  .setRestrictionText("Don't mention competitor names")
                  .setRestrictionType(
                      MessagingRestrictionType.RESTRICTION_BASED_EXCLUSION)
                  .build())
          .build();
  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)
          // Sets the text guidelines.
          .setTextGuidelines(textGuidelines)
          // 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.
          .setStartDateTime(new DateTime().plusDays(1).toString("yyyy-MM-dd 00:00:00"))
          .setEndDateTime(new DateTime().plusDays(365).toString("yyyy-MM-dd 23:59:59"))
          // 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()
      .setCampaignOperation(
          CampaignOperation.newBuilder().setCreate(performanceMaxCampaign).build())
      .build();
}

      
```

### C#

```c#
/// Creates a MutateOperation that creates a new Performance Max campaign.
/// <param name="campaignResourceName">The campaign resource name.</param>
/// <param name="campaignBudgetResourceName">The campaign budget resource name.</param>
/// <param name="brandGuidelinesEnabled">Whether or not to enable brand guidelines.</param>
/// <returns>A MutateOperations that will create this new campaign.</returns>
private MutateOperation CreatePerformanceMaxCampaignOperation(
    string campaignResourceName,
    string campaignBudgetResourceName,
    bool brandGuidelinesEnabled)
{
    Campaign.Types.TextGuidelines textGuidelines =
        new Campaign.Types.TextGuidelines();
    textGuidelines.TermExclusions.AddRange(["cheap", "free"]);
    textGuidelines.MessagingRestrictions.Add(
        new Campaign.Types.MessagingRestriction()
        {
            RestrictionText = "Don't mention competitor names",
            RestrictionType = MessagingRestrictionType.RestrictionBasedExclusion
        }
    );

    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,

        TextGuidelines = textGuidelines,

        // Optional fields
        StartDateTime = DateTime.Now.AddDays(1).ToString("yyyyMMdd 00:00:00"),
        EndDateTime = DateTime.Now.AddDays(365).ToString("yyyyMMdd 23:59:59")
    };

    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 = AssetAutomationStatus.OptedIn
        },
    });

    MutateOperation operation = new MutateOperation()
    {
        CampaignOperation = new CampaignOperation()
        {
            Create = campaign
        }
    };

    return operation;
}

      
```

### PHP

```php
private static function createPerformanceMaxCampaignOperation(
    int $customerId,
    bool $brandGuidelinesEnabled
): MutateOperation {
    // Creates a mutate operation that creates a campaign operation.
    return new MutateOperation(
        [
        'campaign_operation' => new CampaignOperation(
            [
            'create' => new Campaign(
                [
                'name' => 'Performance Max campaign #' . Helper::getPrintableDatetime(),
                // Assigns the resource name with a temporary ID.
                'resource_name' => ResourceNames::forCampaign(
                    $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.
                'status' => 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 support
                // article: http://support.google.com/google-ads/answer/7684216.
                // A target_roas of 3.5 corresponds to a 350% return on ad spend.
                'maximize_conversion_value' => new MaximizeConversionValue(
                    [
                    'target_roas' => 3.5
                    ]
                ),

                'asset_automation_settings' => [
                    new AssetAutomationSetting(
                        [
                        'asset_automation_type' => AssetAutomationType::TEXT_ASSET_AUTOMATION,
                        'asset_automation_status' => AssetAutomationStatus::OPTED_IN
                        ]
                    ),
                    new AssetAutomationSetting(
                        [
                        'asset_automation_type' => AssetAutomationType::URL_EXPANSION,
                        'asset_automation_status' => AssetAutomationStatus::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 or not this campaign serves political ads targeting the EU.
                'contains_eu_political_advertising' =>
                    EuPoliticalAdvertisingStatus::DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING,

                // Optional fields.
                'start_date_time' => date('Y-m-d 00:00:00', strtotime('+1 day')),
                'end_date_time' => date('Y-m-d 23:59:59', strtotime('+365 days'))
                ]
            )
            ]
        )
        ]
    );
}
      
```

### Python

```python
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_time = (datetime.now() + timedelta(1)).strftime(
        "%Y%m%d 00:00:00"
    )
    campaign.end_date_time = (datetime.now() + timedelta(365)).strftime(
        "%Y%m%d 23:59:59"
    )

    campaign.text_guidelines.term_exclusions = ["cheap", "free"]
    messaging_restriction = campaign.MessagingRestriction()
    messaging_restriction.restriction_text = "Don't mention competitor names"
    messaging_restriction.restriction_type = (
        client.enums.MessagingRestrictionTypeEnum.RESTRICTION_BASED_EXCLUSION
    )
    campaign.text_guidelines.messaging_restrictions.append(
        messaging_restriction
    )

    # 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_automation_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
      
```

### Ruby

```ruby
# 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.resource.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_automation_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.resource.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.asset_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_time = DateTime.parse((Date.today + 1).to_s).strftime('%Y%m%d %H:%M:%S')
      c.end_date_time = DateTime.parse(Date.today.next_year.to_s).strftime('%Y%m%d %H:%M:%S')
    end
  end
end
      
```

### Perl

```perl
sub create_performance_max_campaign_operation {
  my ($customer_id, $brand_guidelines_enabled) = @_;
  # Configures the optional 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_types) {
    push @$asset_automation_settings,
      Google::Ads::GoogleAds::V26::Resources::AssetAutomationSetting->new({
        assetAutomationStatus => OPTED_IN,
        assetAutomationType   => $asset_automation_type
      });
  }

  my $text_guidelines =
    Google::Ads::GoogleAds::V26::Resources::TextGuidelines->new({
      termExclusions        => ["cheap", "free"],
      messagingRestrictions => [
        Google::Ads::GoogleAds::V26::Resources::MessagingRestriction->new({
            restrictionText => "Don't mention competitor names",
            restrictionType => RESTRICTION_BASED_EXCLUSION
          })]});

  # Create a mutate operation that creates a campaign operation.
  return
    Google::Ads::GoogleAds::V26::Services::GoogleAdsService::MutateOperation->
    new({
      campaignOperation =>
        Google::Ads::GoogleAds::V26::Services::CampaignService::CampaignOperation
        ->new({
          create => Google::Ads::GoogleAds::V26::Resources::Campaign->new({
              # Assign the resource name with a temporary ID.
              resourceName =>
                Google::Ads::GoogleAds::V26::Utils::ResourceNames::campaign(
                $customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
                ),
              name => "Performance Max campaign #" . uniqid(),
              # Set the budget using the given budget resource name.
              campaignBudget =>
                Google::Ads::GoogleAds::V26::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::V26::Enums::CampaignStatusEnum::PAUSED,
              # All Performance Max campaigns have an advertisingChannelType of
              # 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/google-ads/answer/7684216.
              # A targetRoas of 3.5 corresponds to a 350% return on ad spend.
              maximizeConversionValue =>
                Google::Ads::GoogleAds::V26::Common::MaximizeConversionValue->
                new({
                  targetRoas => 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.
              brandGuidelinesEnabled => $brand_guidelines_enabled,

              # Configures the optional opt-in/out status for asset automation settings.
              assetAutomationSettings => $asset_automation_settings,

              # Set the text guidelines.
              textGuidelines => $text_guidelines,

              # Optional fields.
              startDateTime =>
                strftime("%Y%m%d 00:00:00", localtime(time + 60 * 60 * 24)),
              endDateTime => strftime(
                "%Y%m%d 23:59:59",
                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
            })})});
}
      
```

### curl

> [!NOTE]
> **Note:** While a direct REST code sample for this step isn't provided here, you can achieve this using a manual REST request.   
>
> Refer to the Google Ads API REST interface documentation and the method-specific reference pages. You will need to construct the JSON payload based on the proto definitions.   
>
> Key Resources:
>
> - [Using REST](https://developers.google.com/google-ads/api/rest/overview.md.txt)
> - [REST Interface Structure](https://developers.google.com/google-ads/api/rest/design/overview.md.txt)
> - [JSON Field Mappings](https://developers.google.com/google-ads/api/rest/design/json-mappings.md.txt)
> - Consult the [REST API Reference](https://developers.google.com/google-ads/api/reference/rpc/latest/overview) for the specific service and method.

<br />

<br />

*** ** * ** ***

<br />


Link assets to the campaign

> [!IMPORTANT]
> **Important:** `Campaign` and `CampaignAssets` linking the required brand assets to the campaign for campaigns with brand guidelines enabled must be created together in a single bulk mutate request.

In some cases, such as when brand guidelines are enabled for a campaign, assets
must be linked to a campaign directly. This can be done with a
[`CampaignAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/CampaignAsset.md.txt) by providing the following:

- Resource name of the `Campaign`
- Resource name of the `Asset`
- [`AssetFieldType`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetFieldTypeEnum.AssetFieldType.md.txt) of the `Asset` in the `Campaign`

Refer to the [Assets](https://developers.google.com/google-ads/api/docs/assets/overview.md.txt#asset_types_linked_to_customers_campaigns_and_ad_groups) guide for assets linked to the campaign. See the
[Create a campaign](https://developers.google.com/google-ads/api/performance-max/create-campaign.md.txt#brand-guidelines) guide for more information on Performance Max campaigns
with brand guidelines enabled.

*** ** * ** ***

<br />

<br />

<br />

[Add custom conversion goals (optional)](https://developers.google.com/google-ads/api/performance-max/conversion-goals.md.txt)

<br />

If [conversion goals](https://developers.google.com/google-ads/api/docs/conversions/goals/overview.md.txt) are not explicitly set for the campaign, it defaults
to using customer-level conversion goals. However, you can override customer
conversion goals to [set campaign-specific conversion goals](https://developers.google.com/google-ads/api/performance-max/retail.md.txt#conversion-goals) ( [learn
more](https://support.google.com/google-ads/answer/10995103)).

<br />

#### Code example

### Java

```java
/** Retrieves the list of customer conversion goals. */
private static List<CustomerConversionGoal> getCustomerConversionGoals(
    GoogleAdsClient googleAdsClient, long customerId) {
  String query =
      "SELECT customer_conversion_goal.category, customer_conversion_goal.origin "
          + "FROM customer_conversion_goal";

  List<CustomerConversionGoal> customerConversionGoals = new ArrayList<>();
  try (GoogleAdsServiceClient googleAdsServiceClient =
      googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
    // The number of conversion goals is typically less than 50, so we use
    // GoogleAdsService.search instead of search_stream.
    SearchPagedResponse response =
        googleAdsServiceClient.search(Long.toString(customerId), query);
    for (GoogleAdsRow googleAdsRow : response.iterateAll()) {
      customerConversionGoals.add(googleAdsRow.getCustomerConversionGoal());
    }
  }

  return customerConversionGoals;
}

/** Creates a list of MutateOperations that override customer conversion goals. */
private static List<MutateOperation> createConversionGoalOperations(
    long customerId, List<CustomerConversionGoal> customerConversionGoals) {
  List<MutateOperation> mutateOperations = new ArrayList<>();
  // To override the customer conversion goals, we will change the
  // biddability of each of the customer conversion goals so that only
  // the desired conversion goal is biddable in this campaign.
  for (CustomerConversionGoal customerConversionGoal : customerConversionGoals) {
    ConversionActionCategory category = customerConversionGoal.getCategory();
    ConversionOrigin origin = customerConversionGoal.getOrigin();
    String campaignConversionGoalResourceName =
        ResourceNames.campaignConversionGoal(
            customerId, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID, category, origin);
    CampaignConversionGoal.Builder campaignConversionGoalBuilder =
        CampaignConversionGoal.newBuilder().setResourceName(campaignConversionGoalResourceName);
    // Change the biddability for the campaign conversion goal.
    // Set biddability to True for the desired (category, origin).
    // Set biddability to False for all other conversion goals.
    // Note:
    //  1- It is assumed that this Conversion Action
    //     (category=PURCHASE, origin=WEBSITE) exists in this account.
    //  2- More than one goal can be biddable if desired. This example
    //     shows only one.
    if (category == ConversionActionCategory.PURCHASE && origin == ConversionOrigin.WEBSITE) {
      campaignConversionGoalBuilder.setBiddable(true);
    } else {
      campaignConversionGoalBuilder.setBiddable(false);
    }
    CampaignConversionGoal campaignConversionGoal = campaignConversionGoalBuilder.build();
    CampaignConversionGoalOperation campaignConversionGoalOperation =
        CampaignConversionGoalOperation.newBuilder()
            .setUpdate(campaignConversionGoal)
            .setUpdateMask(FieldMasks.allSetFieldsOf(campaignConversionGoal))
            .build();
    mutateOperations.add(
        MutateOperation.newBuilder()
            .setCampaignConversionGoalOperation(campaignConversionGoalOperation)
            .build());
  }
  return mutateOperations;
}

      
```

### C#

```c#
/// <summary>
/// Creates a MutateOperation that links an asset to an asset group.
/// </summary>
/// <param name="fieldType">The field type of the asset to be linked.</param>
/// <param name="linkedEntityResourceName">The resource name of the entity (asset group or
/// campaign) to link the asset to.</param>
/// <param name="assetResourceName">The resource name of the text asset to be
/// linked.</param>
/// <param name="brandGuidelinesEnabled">Whether or not to enable brand guidelines.</param>
/// <returns>A MutateOperation that links an asset to an asset group.</returns>
private MutateOperation CreateLinkAssetOperation(
    AssetFieldType fieldType,
    string linkedEntityResourceName,
    string assetResourceName,
    bool brandGuidelinesEnabled = false)
{ if (brandGuidelinesEnabled)
    {
        return new MutateOperation()
        {
            CampaignAssetOperation = new CampaignAssetOperation()
            {
                Create = new CampaignAsset()
                {
                    FieldType = fieldType,
                    Campaign = linkedEntityResourceName,
                    Asset = assetResourceName
                }
            }
        };
    } else
    {   return new MutateOperation()
        {
            AssetGroupAssetOperation = new AssetGroupAssetOperation()
            {
                Create = new AssetGroupAsset()
                {
                    FieldType = fieldType,
                    AssetGroup = linkedEntityResourceName,
                    Asset = assetResourceName
                }
            }
        };
    }
}

      
```

### PHP

```php
    private static function getCustomerConversionGoals(
        GoogleAdsClient $googleAdsClient,
        int $customerId
    ): array {
        $customerConversionGoals = [];
        $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
        // Creates a query that retrieves all customer conversion goals.
        $query = 'SELECT customer_conversion_goal.category, customer_conversion_goal.origin ' .
            'FROM customer_conversion_goal';
        // The number of conversion goals is typically less than 50 so we use a search request
        // instead of search stream.
        $response =
            $googleAdsServiceClient->search(SearchGoogleAdsRequest::build($customerId, $query));

        // Iterates over all rows in all pages and builds the list of conversion goals.
        foreach ($response->iterateAllElements() as $googleAdsRow) {
            /**
 * @var GoogleAdsRow $googleAdsRow
*/
            $customerConversionGoals[] = [
                'category' => $googleAdsRow->getCustomerConversionGoal()->getCategory(),
                'origin' => $googleAdsRow->getCustomerConversionGoal()->getOrigin()
            ];
        }

        return $customerConversionGoals;
    }

    /**
     * Creates a list of MutateOperations that override customer conversion goals.
     *
     * @param  int   $customerId              the customer ID
     * @param  array $customerConversionGoals the list of customer conversion goals that will be
     *                                        overridden
     * @return MutateOperation[] a list of MutateOperations that update campaign conversion goals
     */
    private static function createConversionGoalOperations(
        int $customerId,
        array $customerConversionGoals
    ): array {
        $operations = [];

        // To override the customer conversion goals, we will change the biddability of each of the
        // customer conversion goals so that only the desired conversion goal is biddable in this
        // campaign.
        foreach ($customerConversionGoals as $customerConversionGoal) {
            $campaignConversionGoal = new CampaignConversionGoal(
                [
                'resource_name' => ResourceNames::forCampaignConversionGoal(
                    $customerId,
                    self::PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID,
                    ConversionActionCategory::name($customerConversionGoal['category']),
                    ConversionOrigin::name($customerConversionGoal['origin'])
                )
                ]
            );
            // Changes the biddability for the campaign conversion goal.
            // Sets biddability to true for the desired (category, origin).
            // Sets biddability to false for all other conversion goals.
            // Note:
            //  1- It is assumed that this Conversion Action
            //     (category=PURCHASE, origin=WEBSITE) exists in this account.
            //  2- More than one goal can be biddable if desired. This example
            //     shows only one.
            if (
                $customerConversionGoal["category"] === ConversionActionCategory::PURCHASE
                && $customerConversionGoal["origin"] === ConversionOrigin::WEBSITE
            ) {
                $campaignConversionGoal->setBiddable(true);
            } else {
                $campaignConversionGoal->setBiddable(false);
            }

            $operations[] = new MutateOperation(
                [
                'campaign_conversion_goal_operation' => new CampaignConversionGoalOperation(
                    [
                    'update' => $campaignConversionGoal,
                    // Sets the update mask on the operation. Here the update mask will be a list
                    // of all the fields that were set on the update object.
                    'update_mask' => FieldMasks::allSetFieldsOf($campaignConversionGoal)
                    ]
                )
                ]
            );
        }

        return $operations;
    }
      
```

### Python

```python
def get_customer_conversion_goals(
    client: GoogleAdsClient, customer_id: str
) -> List[
    Dict[
        str,
        Union[
            ConversionActionCategoryEnum.ConversionActionCategory,
            ConversionOriginEnum.ConversionOrigin,
        ],
    ]
]:
    """Retrieves the list of customer conversion goals.

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

    Returns:
        a list of dicts containing the category and origin of customer
        conversion goals.
    """
    ga_service: GoogleAdsServiceClient = client.get_service("GoogleAdsService")
    customer_conversion_goals: List[
        Dict[
            str,
            Union[
                ConversionActionCategoryEnum.ConversionActionCategory,
                ConversionOriginEnum.ConversionOrigin,
            ],
        ]
    ] = []
    query: str = """
            SELECT
              customer_conversion_goal.category,
              customer_conversion_goal.origin
            FROM customer_conversion_goal
            """
    # The number of conversion goals is typically less than 50 so we use
    # GoogleAdsService.search instead of search_stream.
    search_request: SearchGoogleAdsRequest = client.get_type(
        "SearchGoogleAdsRequest"
    )
    search_request.customer_id = customer_id
    search_request.query = query
    results: SearchGoogleAdsResponse = ga_service.search(request=search_request)

    # Iterate over the results and build the list of conversion goals.
    for row in results:
        customer_conversion_goals.append(
            {
                "category": row.customer_conversion_goal.category,
                "origin": row.customer_conversion_goal.origin,
            }
        )
    return customer_conversion_goals


def create_conversion_goal_operations(
    client: GoogleAdsClient,
    customer_id: str,
    customer_conversion_goals: List[
        Dict[
            str,
            Union[
                ConversionActionCategoryEnum.ConversionActionCategory,
                ConversionOriginEnum.ConversionOrigin,
            ],
        ]
    ],
) -> List[MutateOperation]:
    """Creates a list of MutateOperations that override customer conversion goals.

    Args:
        client: an initialized GoogleAdsClient instance.
        customer_id: a client customer ID.
        customer_conversion_goals: the list of customer conversion goals that
          will be overridden.

    Returns:
        MutateOperations that update campaign conversion goals.
    """
    campaign_conversion_goal_service: CampaignConversionGoalServiceClient = (
        client.get_service("CampaignConversionGoalService")
    )
    operations: List[MutateOperation] = []

    # To override the customer conversion goals, we will change the
    # biddability of each of the customer conversion goals so that only
    # the desired conversion goal is biddable in this campaign.
    for customer_goal_dict in customer_conversion_goals:
        mutate_operation: MutateOperation = client.get_type("MutateOperation")
        campaign_conversion_goal: CampaignConversionGoal = (
            mutate_operation.campaign_conversion_goal_operation.update
        )

        category_enum_value: (
            ConversionActionCategoryEnum.ConversionActionCategory
        ) = customer_goal_dict["category"]
        origin_enum_value: ConversionOriginEnum.ConversionOrigin = (
            customer_goal_dict["origin"]
        )

        campaign_conversion_goal.resource_name = (
            campaign_conversion_goal_service.campaign_conversion_goal_path(
                customer_id,
                _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID,
                category_enum_value.name,
                origin_enum_value.name,
            )
        )
        # Change the biddability for the campaign conversion goal.
        # Set biddability to True for the desired (category, origin).
        # Set biddability to False for all other conversion goals.
        # Note:
        #  1- It is assumed that this Conversion Action
        #     (category=PURCHASE, origin=WEBSITE) exists in this account.
        #  2- More than one goal can be biddable if desired. This example
        #     shows only one.
        if (
            category_enum_value
            == client.enums.ConversionActionCategoryEnum.PURCHASE
            and origin_enum_value == client.enums.ConversionOriginEnum.WEBSITE
        ):
            biddable = True
        else:
            biddable = False
        campaign_conversion_goal.biddable = biddable
        field_mask = protobuf_helpers.field_mask(
            None, campaign_conversion_goal._pb
        )
        client.copy_from(
            mutate_operation.campaign_conversion_goal_operation.update_mask,
            field_mask,
        )
        operations.append(mutate_operation)

    return operations
      
```

### Ruby

```ruby
def _get_customer_conversion_goals(client, customer_id)
  query = <<~EOD
    SELECT
        customer_conversion_goal.category,
        customer_conversion_goal.origin
    FROM customer_conversion_goal
  EOD

  customer_conversion_goals = []

  ga_service = client.service.google_ads
  # The number of conversion goals is typically less than 50 so we use
  # GoogleAdsService.search instead of search_stream.
  response = ga_service.search(
      customer_id: customer_id,
      query: query,
  )

  # Iterate over the results and build the list of conversion goals.
  response.each do |row|
    customer_conversion_goals << {
        "category" => row.customer_conversion_goal.category,
        "origin" => row.customer_conversion_goal.origin
    }
  end

  customer_conversion_goals
end

def create_conversion_goal_operations(client, customer_id, customer_conversion_goals)
  campaign_conversion_goal_service = client.service.campaign_conversion_goal

  operations = []

  # To override the customer conversion goals, we will change the
  # biddability of each of the customer conversion goals so that only
  # the desired conversion goal is biddable in this campaign.
  customer_conversion_goals.each do |customer_conversion_goal|
    operations << client.operation.mutate do |m|
        m.campaign_conversion_goal_operation = client.operation.campaign_conversion_goal do |op|
          op.update = client.resource.campaign_conversion_goal do |ccg|
              ccg.resource_name = client.path.campaign_conversion_goal(
                  customer_id,
                  PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID,
                  customer_conversion_goal["category"].to_s,
                  customer_conversion_goal["origin"].to_s)
              # Change the biddability for the campaign conversion goal.
              # Set biddability to True for the desired (category, origin).
              # Set biddability to False for all other conversion goals.
              # Note:
              #  1- It is assumed that this Conversion Action
              #     (category=PURCHASE, origin=WEBSITE) exists in this account.
              #  2- More than one goal can be biddable if desired. This example
              #     shows only one.
              ccg.biddable = (customer_conversion_goal["category"] == :PURCHASE &&
                  customer_conversion_goal["origin"] == :WEBSITE)
          end
          op.update_mask = Google::Ads::GoogleAds::FieldMaskUtil.all_set_fields_of(op.update)
        end
    end
  end

  operations
end
      
```

### Perl

```perl
sub get_customer_conversion_goals {
  my ($api_client, $customer_id) = @_;

  my $customer_conversion_goals = [];
  # Create a query that retrieves all customer conversion goals.
  my $query =
    "SELECT customer_conversion_goal.category, customer_conversion_goal.origin "
    . "FROM customer_conversion_goal";
  # The number of conversion goals is typically less than 50 so we use
  # GoogleAdsService->search() method instead of search_stream().
  my $search_response = $api_client->GoogleAdsService()->search({
    customerId => $customer_id,
    query      => $query
  });

  # Iterate over the results and build the list of conversion goals.
  foreach my $google_ads_row (@{$search_response->{results}}) {
    push @$customer_conversion_goals,
      {
      category => $google_ads_row->{customerConversionGoal}{category},
      origin   => $google_ads_row->{customerConversionGoal}{origin}};
  }

  return $customer_conversion_goals;
}

# Creates a list of MutateOperations that override customer conversion goals.
sub create_conversion_goal_operations {
  my ($customer_id, $customer_conversion_goals) = @_;

  my $operations = [];
  # To override the customer conversion goals, we will change the biddability of
  # each of the customer conversion goals so that only the desired conversion goal
  # is biddable in this campaign.
  foreach my $customer_conversion_goal (@$customer_conversion_goals) {
    my $campaign_conversion_goal =
      Google::Ads::GoogleAds::V26::Resources::CampaignConversionGoal->new({
        resourceName =>
          Google::Ads::GoogleAds::V26::Utils::ResourceNames::campaign_conversion_goal(
          $customer_id,
          PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID,
          $customer_conversion_goal->{category},
          $customer_conversion_goal->{origin})});
    # Change the biddability for the campaign conversion goal.
    # Set biddability to true for the desired (category, origin).
    # Set biddability to false for all other conversion goals.
    # Note:
    #  1- It is assumed that this Conversion Action
    #     (category=PURCHASE, origin=WEBSITE) exists in this account.
    #  2- More than one goal can be biddable if desired. This example
    #     shows only one.
    if ( $customer_conversion_goal->{category} eq PURCHASE
      && $customer_conversion_goal->{origin} eq WEBSITE)
    {
      $campaign_conversion_goal->{biddable} = "true";
    } else {
      $campaign_conversion_goal->{biddable} = "false";
    }

    push @$operations,
      Google::Ads::GoogleAds::V26::Services::GoogleAdsService::MutateOperation
      ->new({
        campaignConversionGoalOperation =>
          Google::Ads::GoogleAds::V26::Services::CampaignConversionGoalService::CampaignConversionGoalOperation
          ->new({
            update => $campaign_conversion_goal,
            # Set the update mask on the operation. Here the update mask will be
            # a list of all the fields that were set on the update object.
            updateMask => all_set_fields_of($campaign_conversion_goal)})});
  }

  return $operations;
}
      
```

### curl

> [!NOTE]
> **Note:** While a direct REST code sample for this step isn't provided here, you can achieve this using a manual REST request.   
>
> Refer to the Google Ads API REST interface documentation and the method-specific reference pages. You will need to construct the JSON payload based on the proto definitions.   
>
> Key Resources:
>
> - [Using REST](https://developers.google.com/google-ads/api/rest/overview.md.txt)
> - [REST Interface Structure](https://developers.google.com/google-ads/api/rest/design/overview.md.txt)
> - [JSON Field Mappings](https://developers.google.com/google-ads/api/rest/design/json-mappings.md.txt)
> - Consult the [REST API Reference](https://developers.google.com/google-ads/api/reference/rpc/latest/overview) for the specific service and method.

<br />

*** ** * ** ***

<br />

<br />

<br />

[Add campaign targeting (optional)](https://developers.google.com/google-ads/api/performance-max/create-campaign-criteria.md.txt)

<br />

Performance Max campaigns support the following types of criteria:

- [`AD_SCHEDULE`](https://developers.google.com/google-ads/api/reference/rpc/v26/CriterionTypeEnum.CriterionType.md.txt#ad_schedule) ([learn more](https://support.google.com/google-ads/answer/2404244))
- [`BRAND`](https://developers.google.com/google-ads/api/reference/rpc/v26/CriterionTypeEnum.CriterionType.md.txt#brand)
- [`LANGUAGE`](https://developers.google.com/google-ads/api/reference/rpc/v26/CriterionTypeEnum.CriterionType.md.txt#language) ([learn more](https://support.google.com/google-ads/answer/1722078))
- [`LOCATION`](https://developers.google.com/google-ads/api/reference/rpc/v26/CriterionTypeEnum.CriterionType.md.txt#location) ([learn more](https://support.google.com/google-ads/answer/2453995))
- [`LOCATION_GROUP`](https://developers.google.com/google-ads/api/reference/rpc/v26/CriterionTypeEnum.CriterionType.md.txt#location_group) ([learn more](https://support.google.com/google-ads/answer/2453995))
- [`WEBPAGE`](https://developers.google.com/google-ads/api/reference/rpc/v26/CriterionTypeEnum.CriterionType.md.txt#webpage)

Both positive and negative criteria can be used, except for the `BRAND` and
`KEYWORD` criterion type, which can only be used as negative to exclude brands
and keywords from targeting.

For [location targeting](https://developers.google.com/google-ads/api/docs/targeting/location-targeting.md.txt), a campaign with no specified location or location
groups defaults to including all regions.

Performance Max campaigns can have up to 10,000 negative keywords.

Negative `WEBPAGE` criteria can be used to exclude specific URLs from [final URL
expansion](https://developers.google.com/google-ads/api/performance-max/optimizations#final-url). Learn more about [Final URL expansion](https://support.google.com/google-ads/answer/14337539) and
[URL Exclusion](https://support.google.com/google-ads/answer/14337773).


### Java

```java
/** Creates a list of MutateOperations that create new campaign criteria. */
private List<MutateOperation> createCampaignCriterionOperations(long customerId) {
  String campaignResourceName =
      ResourceNames.campaign(customerId, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID);
  List<CampaignCriterion> 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(
                      CampaignCriterionOperation.newBuilder().setCreate(criterion).build())
                  .build())
      .collect(Collectors.toList());
}

      
```

### C#

```c#
/// <summary>
/// Creates a list of MutateOperations that create new campaign criteria.
/// </summary>
/// <param name="campaignResourceName">The campaign resource name.</param>
/// <returns>A list of MutateOperations that create new campaign criteria.</returns>
private List<MutateOperation> CreateCampaignCriterionOperations(
    string campaignResourceName)
{
    List<MutateOperation> operations = new 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.
    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#expandable-7
                Language = new LanguageInfo()
                {
                    LanguageConstant = ResourceNames.LanguageConstant(1000) // English
                },
            }
        }
    };

    operations.Add(operation3);

    return operations;
}

      
```

### PHP

```php
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
    // 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.
    $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 CampaignCriterionOperation(
            [
            'create' => new CampaignCriterion(
                [
                'campaign' => ResourceNames::forCampaign(
                    $customerId,
                    self::PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
                ),
                'location' => new LocationInfo(
                    [
                    'geo_target_constant' => ResourceNames::forGeoTargetConstant(1022762)
                    ]
                ),
                'negative' => true
                ]
            )
            ]
        )
        ]
    );

    // Sets the LANGUAGE campaign criterion.
    $operations[] = new MutateOperation(
        [
        'campaign_criterion_operation' => new 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;
}
      
```

### Python

```python
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
      
```

### Ruby

```ruby
# 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.location_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 = client.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
      
```

### Perl

```perl
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::V26::Services::GoogleAdsService::MutateOperation->
    new({
      campaignCriterionOperation =>
        Google::Ads::GoogleAds::V26::Services::CampaignCriterionService::CampaignCriterionOperation
        ->new({
          create =>
            Google::Ads::GoogleAds::V26::Resources::CampaignCriterion->new({
              campaign =>
                Google::Ads::GoogleAds::V26::Utils::ResourceNames::campaign(
                $customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
                ),
              location =>
                Google::Ads::GoogleAds::V26::Common::LocationInfo->new({
                  geoTargetConstant =>
                    Google::Ads::GoogleAds::V26::Utils::ResourceNames::geo_target_constant(
                    1023191)}
                ),
              negative => "false"
            })})});

  # Next add the negative target for Brooklyn.
  push @$operations,
    Google::Ads::GoogleAds::V26::Services::GoogleAdsService::MutateOperation->
    new({
      campaignCriterionOperation =>
        Google::Ads::GoogleAds::V26::Services::CampaignCriterionService::CampaignCriterionOperation
        ->new({
          create =>
            Google::Ads::GoogleAds::V26::Resources::CampaignCriterion->new({
              campaign =>
                Google::Ads::GoogleAds::V26::Utils::ResourceNames::campaign(
                $customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
                ),
              location =>
                Google::Ads::GoogleAds::V26::Common::LocationInfo->new({
                  geoTargetConstant =>
                    Google::Ads::GoogleAds::V26::Utils::ResourceNames::geo_target_constant(
                    1022762)}
                ),
              negative => "true"
            })})});

  # Set the LANGUAGE campaign criterion.
  push @$operations,
    Google::Ads::GoogleAds::V26::Services::GoogleAdsService::MutateOperation->
    new({
      campaignCriterionOperation =>
        Google::Ads::GoogleAds::V26::Services::CampaignCriterionService::CampaignCriterionOperation
        ->new({
          create =>
            Google::Ads::GoogleAds::V26::Resources::CampaignCriterion->new({
              campaign =>
                Google::Ads::GoogleAds::V26::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-ads/api/reference/data/codes-formats#expandable-7.
              language =>
                Google::Ads::GoogleAds::V26::Common::LanguageInfo->new({
                  languageConstant =>
                    Google::Ads::GoogleAds::V26::Utils::ResourceNames::language_constant(
                    1000)    # English
                })})})});

  return $operations;
}
      
```

### curl

> [!NOTE]
> **Note:** While a direct REST code sample for this step isn't provided here, you can achieve this using a manual REST request.   
>
> Refer to the Google Ads API REST interface documentation and the method-specific reference pages. You will need to construct the JSON payload based on the proto definitions.   
>
> Key Resources:
>
> - [Using REST](https://developers.google.com/google-ads/api/rest/overview.md.txt)
> - [REST Interface Structure](https://developers.google.com/google-ads/api/rest/design/overview.md.txt)
> - [JSON Field Mappings](https://developers.google.com/google-ads/api/rest/design/json-mappings.md.txt)
> - Consult the [REST API Reference](https://developers.google.com/google-ads/api/reference/rpc/latest/overview) for the specific service and method.

<br />

*** ** * ** ***

<br />

### Assets and asset groups

<br />

[Add account level assets](https://developers.google.com/google-ads/api/performance-max/assets.md.txt)

<br />

Performance Max campaigns have some unique characteristics regarding
[assets](https://developers.google.com/google-ads/api/docs/assets/overview.md.txt).

1. There are a [minimum required number](https://developers.google.com/google-ads/api/performance-max/asset-requirements.md.txt) of advertiser-provided assets of different types.
2. Assets are grouped together in a collection called an [`AssetGroup`](https://developers.google.com/google-ads/api/performance-max/asset-groups.md.txt), which is unique to Performance Max campaigns.
3. Some [assets](https://support.google.com/google-ads/answer/7331111) are generated automatically by Google using machine learning.

> [!NOTE]
> **Note:** Because assets are created at the customer level, you could choose to add assets prior to creating your campaign. However, you could also include asset creation in the bulk mutate request that creates your Performance Max campaign.

<br />

#### Code example

### Java

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

  List<String> 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.getAssetResult().getResourceName());
      }
    }
    printResponseDetails(response);
  }
  return assetResourceNames;
}

      
```

### C#

```c#
/// <summary>
/// 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>
/// <returns>A list of asset resource names.</returns>
private List<string> CreateMultipleTextAssets(
    GoogleAdsClient client,
    long customerId,
    string[] texts)
{
    // Get the GoogleAdsService.
    GoogleAdsServiceClient googleAdsServiceClient =
        client.GetService(Services.V26.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);

    List<string> assetResourceNames = new List<string>();

    foreach (MutateOperationResponse operationResponse in response.MutateOperationResponses)
    {
        MutateAssetResult assetResult = operationResponse.AssetResult;
        assetResourceNames.Add(assetResult.ResourceName);
    }

    PrintResponseDetails(response);

    return assetResourceNames;
}

      
```

### PHP

```php
    private static function createMultipleTextAssets(
        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) {
            // Creates a mutate operation for a text asset.
            $operations[] = new MutateOperation(
                [
                'asset_operation' => new AssetOperation(
                    [
                    '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;
    }
      
```

### Python

```python
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=operations,
    )
    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
      
```

### Ruby

```ruby
# 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
      
```

### Perl

```perl
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 = [];
  foreach my $text (@$texts) {
    # Create a mutate operation for a text asset.
    push @$operations,
      Google::Ads::GoogleAds::V26::Services::GoogleAdsService::MutateOperation
      ->new({
        assetOperation =>
          Google::Ads::GoogleAds::V26::Services::AssetService::AssetOperation->
          new({
            create => Google::Ads::GoogleAds::V26::Resources::Asset->new({
                textAsset =>
                  Google::Ads::GoogleAds::V26::Common::TextAsset->new({
                    text => $text
                  })})})});
  }

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

  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;
}
      
```

### curl

> [!NOTE]
> **Note:** While a direct REST code sample for this step isn't provided here, you can achieve this using a manual REST request.   
>
> Refer to the Google Ads API REST interface documentation and the method-specific reference pages. You will need to construct the JSON payload based on the proto definitions.   
>
> Key Resources:
>
> - [Using REST](https://developers.google.com/google-ads/api/rest/overview.md.txt)
> - [REST Interface Structure](https://developers.google.com/google-ads/api/rest/design/overview.md.txt)
> - [JSON Field Mappings](https://developers.google.com/google-ads/api/rest/design/json-mappings.md.txt)
> - Consult the [REST API Reference](https://developers.google.com/google-ads/api/reference/rpc/latest/overview) for the specific service and method.

<br />

*** ** * ** ***

<br />

<br />

[Add asset groups](https://developers.google.com/google-ads/api/performance-max/asset-groups.md.txt)

<br />

An [asset group](https://support.google.com/google-ads/answer/10729160) is a collection of assets centered on a theme or related to
a target audience. The asset group is used to assemble all of your ads and build
an inventory for all applicable ad formats for your advertising objective.
[Learn more about asset groups](https://support.google.com/google-ads/answer/10724748).
Asset groups contain one or more final URLs. At least one final URL is required. Use the URL that is most relevant to the conversion path for the given asset group and campaign objectives.

<br />

<br />

> [!IMPORTANT]
> **Important:** `Campaign` and `CampaignAssets` linking the required brand assets to the campaign for campaigns with brand guidelines enabled must be created together in a single bulk mutate request. `AssetGroups` and `AssetGroupAssets` linking the [minimum required assets](https://developers.google.com/google-ads/api/performance-max/asset-requirements.md.txt) to each `AssetGroup` must be created together in a single bulk mutate request.

<br />

<br />

#### Code example

### Java

```java
/** Creates a list of MutateOperations that create a new AssetGroup. */
private List<MutateOperation> createAssetGroupOperations(
    long customerId,
    String assetGroupResourceName,
    List<String> headlineAssetResourceNames,
    List<String> descriptionAssetResourceNames,
    boolean brandGuidelinesEnabled)
    throws IOException {
  List<MutateOperation> 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 : descriptionAssetResourceNames) {
    mutateOperations.add(
        createAssetGroupAssetMutateOperation(
            AssetFieldType.DESCRIPTION, resourceName, assetGroupResourceName));
  }

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

  // Creates and links the business name and logo assets.
  List<MutateOperation> 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://gaagl.page.link/bjYi",
          AssetFieldType.SQUARE_MARKETING_IMAGE,
          "Square Marketing Image");
  mutateOperations.addAll(createAndLinkTextAssetOperations);

  return mutateOperations;
}

      
```

### C#

```c#
/// <summary>
/// Creates a list of MutateOperations that create a new asset_group.
/// </summary>
/// <param name="campaignResourceName">The campaign resource name.</param>
/// <param name="assetGroupResourceName">The asset group resource name.</param>
/// <param name="headlineAssetResourceNames">The headline asset resource names.</param>
/// <param name="descriptionAssetResourceNames">The description asset resource
/// names.</param>
/// <param name="resourceNameGenerator">A generator 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>
/// <returns>A list of MutateOperations that create the new asset group.</returns>
private List<MutateOperation> CreateAssetGroupOperations(
    string campaignResourceName,
    string assetGroupResourceName,
    List<string> headlineAssetResourceNames,
    List<string> descriptionAssetResourceNames,
    AssetTemporaryResourceNameGenerator resourceNameGenerator,
    GoogleAdsConfig config,
    bool brandGuidelinesEnabled)
{
    List<MutateOperation> operations = new List<MutateOperation>();

    // 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 Asset.
    operations.AddRange(
        CreateAndLinkImageAsset(
            assetGroupResourceName,
            resourceNameGenerator.Next(),
            "https://gaagl.page.link/bjYi",
            AssetFieldType.SquareMarketingImage,
            "Square Marketing Image",
            config
        )
    );

    return operations;
}

      
```

### PHP

```php
private static function createAssetGroupOperations(
    int $customerId,
    array $headlineAssetResourceNames,
    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 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.
    foreach ($headlineAssetResourceNames 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::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::SQUARE_MARKETING_IMAGE,
            'Square Marketing Image'
        )
    );

    return $operations;
}
      
```

### Python

```python
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
      
```

### Ruby

```ruby
# 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.
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.operation.create_resource.asset_group do |ag|
      ag.name = "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
        aga.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,
    "https://gaagl.page.link/bjYi",
    :SQUARE_MARKETING_IMAGE,
    "Square Marketing Image")

  operations
end
      
```

### Perl

```perl
sub create_asset_group_operations {
  my (
    $customer_id,
    $headline_asset_resource_names,
    $description_asset_resource_names,
    $brand_guidelines_enabled
  ) = @_;

  my $operations = [];
  # Create a mutate operation that creates an asset group operation.
  push @$operations,
    Google::Ads::GoogleAds::V26::Services::GoogleAdsService::MutateOperation->
    new({
      assetGroupOperation =>
        Google::Ads::GoogleAds::V26::Services::AssetGroupService::AssetGroupOperation
        ->new({
          create => Google::Ads::GoogleAds::V26::Resources::AssetGroup->new({
              resourceName =>
                Google::Ads::GoogleAds::V26::Utils::ResourceNames::asset_group(
                $customer_id, ASSET_GROUP_TEMPORARY_ID
                ),
              name     => "Performance Max asset group #" . uniqid(),
              campaign =>
                Google::Ads::GoogleAds::V26::Utils::ResourceNames::campaign(
                $customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
                ),
              finalUrls       => ["http://www.example.com"],
              finalMobileUrls => ["http://www.example.com"],
              status          =>
                Google::Ads::GoogleAds::V26::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::GoogleAds::V26::Services::GoogleAdsService::MutateOperation
      ->new({
        assetGroupAssetOperation =>
          Google::Ads::GoogleAds::V26::Services::AssetGroupAssetService::AssetGroupAssetOperation
          ->new({
            create =>
              Google::Ads::GoogleAds::V26::Resources::AssetGroupAsset->new({
                asset      => $resource_name,
                assetGroup =>
                  Google::Ads::GoogleAds::V26::Utils::ResourceNames::asset_group(
                  $customer_id, ASSET_GROUP_TEMPORARY_ID
                  ),
                fieldType => HEADLINE
              })})});
  }

  # Link the description assets.
  foreach my $resource_name (@$description_asset_resource_names) {
    push @$operations,
      Google::Ads::GoogleAds::V26::Services::GoogleAdsService::MutateOperation
      ->new({
        assetGroupAssetOperation =>
          Google::Ads::GoogleAds::V26::Services::AssetGroupAssetService::AssetGroupAssetOperation
          ->new({
            create =>
              Google::Ads::GoogleAds::V26::Resources::AssetGroupAsset->new({
                asset      => $resource_name,
                assetGroup =>
                  Google::Ads::GoogleAds::V26::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;
}
      
```

### curl

> [!NOTE]
> **Note:** While a direct REST code sample for this step isn't provided here, you can achieve this using a manual REST request.   
>
> Refer to the Google Ads API REST interface documentation and the method-specific reference pages. You will need to construct the JSON payload based on the proto definitions.   
>
> Key Resources:
>
> - [Using REST](https://developers.google.com/google-ads/api/rest/overview.md.txt)
> - [REST Interface Structure](https://developers.google.com/google-ads/api/rest/design/overview.md.txt)
> - [JSON Field Mappings](https://developers.google.com/google-ads/api/rest/design/json-mappings.md.txt)
> - Consult the [REST API Reference](https://developers.google.com/google-ads/api/reference/rpc/latest/overview) for the specific service and method.

<br />

<br />

*** ** * ** ***

<br />

<br />

<br />

[Link assets to asset groups](https://developers.google.com/google-ads/api/performance-max/asset-groups.md.txt#link-asset-groups-to-assets)

<br />

An [`AssetGroup`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetGroup.md.txt) is linked to an [`Asset`](https://developers.google.com/google-ads/api/reference/rpc/v26/Asset.md.txt) by creating a new
[`AssetGroupAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetGroupAsset.md.txt) and providing the following:

- Resource name of the `AssetGroup`
- Resource name of the `Asset`
- [`AssetFieldType`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetFieldTypeEnum.AssetFieldType.md.txt) of the `Asset` in the `AssetGroup`

<br />

#### Code example

### Java

```java
/** Creates a list of MutateOperations that create a new AssetGroup. */
private List<MutateOperation> createAssetGroupOperations(
    long customerId,
    String assetGroupResourceName,
    List<String> headlineAssetResourceNames,
    List<String> descriptionAssetResourceNames,
    boolean brandGuidelinesEnabled)
    throws IOException {
  List<MutateOperation> 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 : descriptionAssetResourceNames) {
    mutateOperations.add(
        createAssetGroupAssetMutateOperation(
            AssetFieldType.DESCRIPTION, resourceName, assetGroupResourceName));
  }

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

  // Creates and links the business name and logo assets.
  List<MutateOperation> 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://gaagl.page.link/bjYi",
          AssetFieldType.SQUARE_MARKETING_IMAGE,
          "Square Marketing Image");
  mutateOperations.addAll(createAndLinkTextAssetOperations);

  return mutateOperations;
}

      
```

### C#

```c#
/// <summary>
/// Creates a list of MutateOperations that create a new asset_group.
/// </summary>
/// <param name="campaignResourceName">The campaign resource name.</param>
/// <param name="assetGroupResourceName">The asset group resource name.</param>
/// <param name="headlineAssetResourceNames">The headline asset resource names.</param>
/// <param name="descriptionAssetResourceNames">The description asset resource
/// names.</param>
/// <param name="resourceNameGenerator">A generator 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>
/// <returns>A list of MutateOperations that create the new asset group.</returns>
private List<MutateOperation> CreateAssetGroupOperations(
    string campaignResourceName,
    string assetGroupResourceName,
    List<string> headlineAssetResourceNames,
    List<string> descriptionAssetResourceNames,
    AssetTemporaryResourceNameGenerator resourceNameGenerator,
    GoogleAdsConfig config,
    bool brandGuidelinesEnabled)
{
    List<MutateOperation> operations = new List<MutateOperation>();

    // 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 Asset.
    operations.AddRange(
        CreateAndLinkImageAsset(
            assetGroupResourceName,
            resourceNameGenerator.Next(),
            "https://gaagl.page.link/bjYi",
            AssetFieldType.SquareMarketingImage,
            "Square Marketing Image",
            config
        )
    );

    return operations;
}

      
```

### PHP

```php
private static function createAssetGroupOperations(
    int $customerId,
    array $headlineAssetResourceNames,
    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 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.
    foreach ($headlineAssetResourceNames 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::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::SQUARE_MARKETING_IMAGE,
            'Square Marketing Image'
        )
    );

    return $operations;
}
      
```

### Python

```python
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
      
```

### Ruby

```ruby
# 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.
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.operation.create_resource.asset_group do |ag|
      ag.name = "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
        aga.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,
    "https://gaagl.page.link/bjYi",
    :SQUARE_MARKETING_IMAGE,
    "Square Marketing Image")

  operations
end
      
```

### Perl

```perl
sub create_asset_group_operations {
  my (
    $customer_id,
    $headline_asset_resource_names,
    $description_asset_resource_names,
    $brand_guidelines_enabled
  ) = @_;

  my $operations = [];
  # Create a mutate operation that creates an asset group operation.
  push @$operations,
    Google::Ads::GoogleAds::V26::Services::GoogleAdsService::MutateOperation->
    new({
      assetGroupOperation =>
        Google::Ads::GoogleAds::V26::Services::AssetGroupService::AssetGroupOperation
        ->new({
          create => Google::Ads::GoogleAds::V26::Resources::AssetGroup->new({
              resourceName =>
                Google::Ads::GoogleAds::V26::Utils::ResourceNames::asset_group(
                $customer_id, ASSET_GROUP_TEMPORARY_ID
                ),
              name     => "Performance Max asset group #" . uniqid(),
              campaign =>
                Google::Ads::GoogleAds::V26::Utils::ResourceNames::campaign(
                $customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID
                ),
              finalUrls       => ["http://www.example.com"],
              finalMobileUrls => ["http://www.example.com"],
              status          =>
                Google::Ads::GoogleAds::V26::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::GoogleAds::V26::Services::GoogleAdsService::MutateOperation
      ->new({
        assetGroupAssetOperation =>
          Google::Ads::GoogleAds::V26::Services::AssetGroupAssetService::AssetGroupAssetOperation
          ->new({
            create =>
              Google::Ads::GoogleAds::V26::Resources::AssetGroupAsset->new({
                asset      => $resource_name,
                assetGroup =>
                  Google::Ads::GoogleAds::V26::Utils::ResourceNames::asset_group(
                  $customer_id, ASSET_GROUP_TEMPORARY_ID
                  ),
                fieldType => HEADLINE
              })})});
  }

  # Link the description assets.
  foreach my $resource_name (@$description_asset_resource_names) {
    push @$operations,
      Google::Ads::GoogleAds::V26::Services::GoogleAdsService::MutateOperation
      ->new({
        assetGroupAssetOperation =>
          Google::Ads::GoogleAds::V26::Services::AssetGroupAssetService::AssetGroupAssetOperation
          ->new({
            create =>
              Google::Ads::GoogleAds::V26::Resources::AssetGroupAsset->new({
                asset      => $resource_name,
                assetGroup =>
                  Google::Ads::GoogleAds::V26::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;
}
      
```

### curl

> [!NOTE]
> **Note:** While a direct REST code sample for this step isn't provided here, you can achieve this using a manual REST request.   
>
> Refer to the Google Ads API REST interface documentation and the method-specific reference pages. You will need to construct the JSON payload based on the proto definitions.   
>
> Key Resources:
>
> - [Using REST](https://developers.google.com/google-ads/api/rest/overview.md.txt)
> - [REST Interface Structure](https://developers.google.com/google-ads/api/rest/design/overview.md.txt)
> - [JSON Field Mappings](https://developers.google.com/google-ads/api/rest/design/json-mappings.md.txt)
> - Consult the [REST API Reference](https://developers.google.com/google-ads/api/reference/rpc/latest/overview) for the specific service and method.

<br />

<br />

*** ** * ** ***

<br />

<br />

<br />

[Add asset group signals (optional)](https://developers.google.com/google-ads/api/performance-max/asset-group-signals.md.txt)

<br />

An [`AssetGroupSignal`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetGroupSignal.md.txt) is a signal that you can provide to Google to
optimize ad serving at the asset group level. There are three types of hints
that you can provide to Google:

- [`audience`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetGroupSignal.md.txt#audience): A reusable collection of focused segments, demographic targeting, and exclusions
- [`search_theme`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetGroupSignal.md.txt#search_theme): Information about what your customers are searching for and which topics lead to conversions for your business that you can [provide to Google AI](https://support.google.com/google-ads/answer/13351809)
- [`local_services_id`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetGroupSignal.md.txt#local_services_id): A Local Services Ads service ID (representing a service type that a campaign can target), restricted to Local Services Performance Max campaigns

<br />

#### Audience signal code example

### Java

```java
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());
      
```

### C#

```c#
operations.Add(
    new MutateOperation()
    {
        AssetGroupSignalOperation = new AssetGroupSignalOperation()
        {
            Create = new AssetGroupSignal()
            {
                AssetGroup = assetGroupResourceName,
                Audience = new AudienceInfo()
                {
                    Audience = ResourceNames.Audience(customerId, audienceId.Value)
                }
            }
        }
    }
);
      
```

### PHP

```php
private static function createAssetGroupSignalOperations(
    int $customerId,
    string $assetGroupResourceName,
    ?int $audienceId
): array {
    $operations = [];
    if (is_null($audienceId)) {
        return $operations;
    }

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

    return $operations;
}
      
```

### Python

```python
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)
      
```

### Ruby

```ruby
# 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
      
```

### Perl

```perl
sub create_asset_group_signal_operations {
  my ($customer_id, $audience_id) = @_;

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

  push @$operations,
    Google::Ads::GoogleAds::V26::Services::GoogleAdsService::MutateOperation->
    new({
      assetGroupSignalOperation =>
        Google::Ads::GoogleAds::V26::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::V26::Resources::AssetGroupSignal->new({
              assetGroup =>
                Google::Ads::GoogleAds::V26::Utils::ResourceNames::asset_group(
                $customer_id, ASSET_GROUP_TEMPORARY_ID
                ),
              audience =>
                Google::Ads::GoogleAds::V26::Common::AudienceInfo->new({
                  audience =>
                    Google::Ads::GoogleAds::V26::Utils::ResourceNames::audience(
                    $customer_id, $audience_id
                    )})})})});
  return $operations;
}
      
```

### curl

> [!NOTE]
> **Note:** While a direct REST code sample for this step isn't provided here, you can achieve this using a manual REST request.   
>
> Refer to the Google Ads API REST interface documentation and the method-specific reference pages. You will need to construct the JSON payload based on the proto definitions.   
>
> Key Resources:
>
> - [Using REST](https://developers.google.com/google-ads/api/rest/overview.md.txt)
> - [REST Interface Structure](https://developers.google.com/google-ads/api/rest/design/overview.md.txt)
> - [JSON Field Mappings](https://developers.google.com/google-ads/api/rest/design/json-mappings.md.txt)
> - Consult the [REST API Reference](https://developers.google.com/google-ads/api/reference/rpc/latest/overview) for the specific service and method.

#### Search theme signal code example

### Java

```java
AssetGroupSignal searchThemeSignal =
    AssetGroupSignal.newBuilder()
        .setAssetGroup(assetGroupResourceName)
        .setSearchTheme(SearchThemeInfo.newBuilder().setText("travel").build())
        .build();

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

### C#

```
This example is not yet available in C#; you can take a look at the other languages.
    
```

### PHP

```
This example is not yet available in PHP; you can take a look at the other languages.
    
```

### Python

```python
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)
      
```

### Ruby

```
This example is not yet available in Ruby; you can take a look at the other languages.
    
```

### Perl

```
This example is not yet available in Perl; you can take a look at the other languages.
    
```

### curl

> [!NOTE]
> **Note:** While a direct REST code sample for this step isn't provided here, you can achieve this using a manual REST request.   
>
> Refer to the Google Ads API REST interface documentation and the method-specific reference pages. You will need to construct the JSON payload based on the proto definitions.   
>
> Key Resources:
>
> - [Using REST](https://developers.google.com/google-ads/api/rest/overview.md.txt)
> - [REST Interface Structure](https://developers.google.com/google-ads/api/rest/design/overview.md.txt)
> - [JSON Field Mappings](https://developers.google.com/google-ads/api/rest/design/json-mappings.md.txt)
> - Consult the [REST API Reference](https://developers.google.com/google-ads/api/reference/rpc/latest/overview) for the specific service and method.

<br />

*** ** * ** ***

<br />

<br />

<br />

[Specify ValueTrack parameters (optional)](https://developers.google.com/google-ads/api/performance-max/valuetrack.md.txt)

<br />

Only some [ValueTrack](https://support.google.com/google-ads/answer/6305348) parameters are supported for Performance Max
campaigns ([learn more](https://support.google.com/google-ads/answer/2375447)).

*** ** * ** ***

<br />

### Optimization with recommendations

<br />

<br />

Optimize campaign performance with recommendations

<br />

Performance Max [recommendations](https://support.google.com/google-ads/answer/3448398) categories:

- [Bidding](https://developers.google.com/google-ads/api/performance-max/create-campaign.md.txt#bidding-recommendations)

- [Asset group strength](https://developers.google.com/google-ads/api/performance-max/asset-group-reporting.md.txt#asset-group-strength-recommendations)

- [Asset group signals](https://developers.google.com/google-ads/api/performance-max/asset-group-signals.md.txt#recommendations)

*** ** * ** ***

<br />

## Verify your campaign and asset groups

After creating your Performance Max campaign, use
[`GoogleAdsService.SearchStream`](https://developers.google.com/google-ads/api/reference/rpc/v26/GoogleAdsService/SearchStream.md.txt) to inspect campaign
settings, asset group serving status (`primary_status` and
`primary_status_reasons`), and `ad_strength`:

```sql
SELECT
  campaign.id,
  campaign.name,
  campaign.status,
  campaign.advertising_channel_type,
  campaign.bidding_strategy_type,
  campaign.brand_guidelines_enabled,
  asset_group.id,
  asset_group.name,
  asset_group.status,
  asset_group.primary_status,
  asset_group.primary_status_reasons,
  asset_group.ad_strength,
  asset_group.final_urls
FROM asset_group
WHERE campaign.advertising_channel_type = 'PERFORMANCE_MAX'
  AND campaign.status != 'REMOVED'
```