Most asset types must be created using the
[`AssetService`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetService) before they can be used in an ad.
The [`TextAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/TextAsset) type is the exception as it is
created inline during ad creation. All other types must first be uploaded to a
Google Ads account before they can be used.

## Asset association levels

Assets are made available for serving by linking them to different entities in
your Google Ads account hierarchy. The level of association depends on the asset
type and the campaign type. Common resources for managing these links include:

- [`CustomerAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/CustomerAsset): For assets linked at the account level.
- [`CampaignAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/CampaignAsset): For assets linked to a specific campaign.
- [`AdGroupAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/AdGroupAsset): For assets linked to a specific ad group.
- [`AssetGroupAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetGroupAsset): For assets linked to an asset group within [Performance Max campaigns](https://developers.google.com/google-ads/api/performance-max).

The specific service and resource to use will depend on what you are trying to
achieve.

### Performance Max brand assets

While many assets in [Performance Max campaigns](https://developers.google.com/google-ads/api/performance-max) are linked to asset
groups using `AssetGroupAsset`, **Business Name** and **Business Logo** assets
are an exception if brand guidelines are enabled for the campaign. In this case,
they are linked directly at the campaign level using
[`CampaignAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/CampaignAsset) with the field
types `BUSINESS_NAME` and `LOGO`, respectively. If brand guidelines are
disabled for the campaign, then these assets must be attached using
`AssetGroupAsset`. See
[Assets in Performance Max](https://developers.google.com/google-ads/api/performance-max/assets) for more details.

## Create an asset

Unique names are required when creating image and media bundle assets. If you
supply an existing name, a new name will be created by appending a unique
string to the existing name. We strongly recommend that you use unique names
that are descriptive to make it easier to manage and identify individual assets
as your collection grows.

Key point: The [`AssetService`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetService) supports `create`
and `update` operations for many asset types (such as sitelinks, callouts, or
promotions), while immutable assets like
[`TextAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/TextAsset) and
[`ImageAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/ImageAsset) cannot be modified in place once
uploaded to a Google Ads account. You must use ad-level or entity-level operations
to manage associations between individual assets and ads or campaigns.

The following example shows how to create a new image asset from a URL of raw
image data.


### Java

```java
private void runExample(GoogleAdsClient googleAdsClient, long customerId) throws IOException {
  byte[] imageData = ByteStreams.toByteArray(new URL(IMAGE_URL).openStream());

  // Create the image asset.
  ImageAsset imageAsset = ImageAsset.newBuilder().setData(ByteString.copyFrom(imageData)).build();

  // Creates an asset.
  Asset asset =
      Asset.newBuilder()
          // Provide a unique friendly name to identify your asset.
          // When there is an existing image asset with the same content but a different name, the
          // new name will be dropped silently.
          .setName("Marketing Image")
          .setType(AssetType.IMAGE)
          .setImageAsset(imageAsset)
          .build();

  // Creates the operation.
  AssetOperation operation = AssetOperation.newBuilder().setCreate(asset).build();

  // Creates the service client.
  try (AssetServiceClient assetServiceClient =
      googleAdsClient.getLatestVersion().createAssetServiceClient()) {
    // Issues a mutate request to add the asset.
    MutateAssetsResponse response =
        assetServiceClient.mutateAssets(Long.toString(customerId), ImmutableList.of(operation));
    // Prints the result.
    System.out.printf(
        "The image asset with resource name '%s' was created.%n",
        response.getResults(0).getResourceName());
  }
}
      
```

### C#

```c#
public void Run(GoogleAdsClient client, long customerId)
{
    // Get the AssetServiceClient.
    AssetServiceClient assetService =
        client.GetService(Services.V26.AssetService);

    // Creates an image content.
    byte[] imageContent = MediaUtilities.GetAssetDataFromUrl(IMAGE_URL, client.Config);

    // Creates an image asset.
    ImageAsset imageAsset = new ImageAsset()
    {
        Data = ByteString.CopyFrom(imageContent),
        FileSize = imageContent.Length,
        MimeType = MimeType.ImageJpeg,
        FullSize = new ImageDimension()
        {
            HeightPixels = 315,
            WidthPixels = 600,
            Url = IMAGE_URL
        }
    };

    // Creates an asset.
    Asset asset = new Asset()
    {
        // Optional: Provide a unique friendly name to identify your asset.
        // If you specify the name field, then both the asset name and the image being
        // uploaded should be unique, and should not match another ACTIVE asset in this
        // customer account.
        // Name = 'Jupiter Trip #' + ExampleUtilities.GetRandomString(),
        Type = AssetType.Image,
        ImageAsset = imageAsset,
        // Provide a unique friendly name to identify your asset.
        // When there is an existing image asset with the same content but a different
        // name, the new name will be dropped silently.
        Name = "Marketing Image"
    };

    // Creates an asset operation.
    AssetOperation operation = new AssetOperation()
    {
        Create = asset
    };

    try
    {
        // Issues a mutate request to add the asset.
        MutateAssetsResponse response =
            assetService.MutateAssets(customerId.ToString(), new[] { operation });

        // Displays the result.
        Console.WriteLine($"Image asset with resource name: " +
            $"'{response.Results.First().ResourceName}' is created.");
    }
    catch (GoogleAdsException e)
    {
        Console.WriteLine("Failure:");
        Console.WriteLine($"Message: {e.Message}");
        Console.WriteLine($"Failure: {e.Failure}");
        Console.WriteLine($"Request ID: {e.RequestId}");
        throw;
    }
}
      
```

### PHP

```php
    public static function runExample(GoogleAdsClient $googleAdsClient, int $customerId)
    {
        // Creates an image content.
        $imageContent = file_get_contents(self::IMAGE_URL);

        // Creates an asset.
        $asset = new Asset(
            [
            // Provide a unique friendly name to identify your asset.
            // When there is an existing image asset with the same content but a different
            // name, the new name will be dropped silently.
            'name' => 'Marketing Image',
            'type' => AssetType::IMAGE,
            'image_asset' => new ImageAsset(['data' => $imageContent])
            ]
        );

        // Creates an asset operation.
        $assetOperation = new AssetOperation();
        $assetOperation->setCreate($asset);

        // Issues a mutate request to add the asset.
        $assetServiceClient = $googleAdsClient->getAssetServiceClient();
        $response = $assetServiceClient->mutateAssets(
            MutateAssetsRequest::build(
                $customerId,
                [$assetOperation]
            )
        );

        if (!empty($response->getResults())) {
            // Prints the resource name of the added image asset.
            /**
 * @var MutateAssetResult $addedImageAsset
*/
            $addedImageAsset = $response->getResults()[0];
            printf(
                "The image asset with resource name '%s' was created.%s",
                $addedImageAsset->getResourceName(),
                PHP_EOL
            );
        } else {
            print 'No image asset was created.' . PHP_EOL;
        }
    }
      
```

### Python

```python
def main(client: GoogleAdsClient, customer_id: str) -> None:
    """Main method, to run this code example as a standalone application."""

    # Download image from URL
    url: str = "https://gaagl.page.link/Eit5"
    image_content: bytes = get_image_bytes_from_url(url)

    asset_service: AssetServiceClient = client.get_service("AssetService")
    asset_operation: AssetOperation = client.get_type("AssetOperation")
    asset: Asset = asset_operation.create
    asset.type_ = client.enums.AssetTypeEnum.IMAGE
    asset.image_asset.data = image_content
    asset.image_asset.file_size = len(image_content)
    asset.image_asset.mime_type = client.enums.MimeTypeEnum.IMAGE_JPEG
    # Use your favorite image library to determine dimensions
    asset.image_asset.full_size.height_pixels = 315
    asset.image_asset.full_size.width_pixels = 600
    asset.image_asset.full_size.url = url
    # Provide a unique friendly name to identify your asset.
    # When there is an existing image asset with the same content but a different
    # name, the new name will be dropped silently.
    asset.name = "Marketing Image"
    mutate_asset_response: MutateAssetsResponse = asset_service.mutate_assets(
        customer_id=customer_id, operations=[asset_operation]
    )
    print("Uploaded file(s):")
    row: MutateAssetResult
    for row in mutate_asset_response.results:
        print(f"\tResource name: {row.resource_name}")

      
```

### Ruby

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

  url = 'https://gaagl.page.link/Eit5'
  image_data = open(url) { |f| f.read }

  # Create the operation for uploading the image asset.
  asset_operation = client.operation.create_resource.asset do |asset|
    asset.type = :IMAGE
    asset.image_asset = client.resource.image_asset do |image_asset|
      image_asset.data = image_data
      image_asset.file_size = image_data.length()
      image_asset.mime_type = :IMAGE_JPEG
      image_asset.full_size = client.resource.image_dimension do |dimension|
        dimension.height_pixels = 315
        dimension.width_pixels = 600
        dimension.url = url
      end
    end
    # Provide a unique friendly name to identify your asset.
    # When there is an existing image asset with the same content but a different
    # name, the new name will be dropped silently.
    asset.name = "Marketing Image"
  end

  # Upload the image asset.
  response = client.service.asset.mutate_assets(
    customer_id: customer_id,
    operations: [asset_operation],
  )

  puts "Uploaded image asset #{response.results.first.resource_name}."
end
      
```

### Perl

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

  # Create an image content.
  my $image_content = get_base64_data_from_url(IMAGE_URL);

  # Create an asset.
  my $asset = Google::Ads::GoogleAds::V26::Resources::Asset->new({
      # Provide a unique friendly name to identify your asset.
      # When there is an existing image asset with the same content but a different
      # name, the new name will be dropped silently.
      name       => "Marketing Image",
      type       => IMAGE,
      imageAsset => Google::Ads::GoogleAds::V26::Common::ImageAsset->new({
          data => $image_content
        })});

  # Create an asset operation.
  my $asset_operation =
    Google::Ads::GoogleAds::V26::Services::AssetService::AssetOperation->new({
      create => $asset
    });

  # Issue a mutate request to add the asset.
  my $assets_response = $api_client->AssetService()->mutate({
      customerId => $customer_id,
      operations => [$asset_operation]});

  printf "The image asset with resource name '%s' was created.\n",
    $assets_response->{results}[0]{resourceName};

  return 1;
}
      
```

### 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)
> - [REST Interface Structure](https://developers.google.com/google-ads/api/rest/design/overview)
> - [JSON Field Mappings](https://developers.google.com/google-ads/api/rest/design/json-mappings)
> - Consult the [REST API Reference](https://developers.google.com/google-ads/api/reference/rpc/latest/overview) for the specific service and method.

<br />

After the asset has been created, the API returns a
[`MutateAssetResult`](https://developers.google.com/google-ads/api/reference/rpc/v26/MutateAssetResult) object that contains the
resource name of the new [`ImageAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/ImageAsset). This resource
name is used to reference the `ImageAsset` when creating an asset-based ad.

You can retrieve a list of existing assets and their resource names by querying
the [`GoogleAdsService`](https://developers.google.com/google-ads/api/reference/rpc/v26/GoogleAdsService). See
[Fetching asset attributes and metrics](https://developers.google.com/google-ads/api/docs/assets/fetching-assets)
for more details.

### Track external promotion redemptions

Starting in **`v26`** , when you create a
[`PromotionAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/PromotionAsset), you can populate the immutable
(`CREATE_ONLY`) [`promotion_asset.external_redeem_info`](https://developers.google.com/google-ads/api/reference/rpc/v26/PromotionAsset#external_redeem_info)
field of type [`ExternalRedeemInfo`](https://developers.google.com/google-ads/api/reference/rpc/v26/ExternalRedeemInfo) to track
offline promotion redemptions in a partner's point-of-sale (POS) system. If the
account has a promotion redemption integration, that integration determines
which `partner_promotion_id` variant the API accepts. Because these fields are
immutable, you can set them only when you create the `PromotionAsset`.
Attempting to modify or clear
`external_redeem_info` or any of its subfields in an `update` operation returns
a [`RequestError.IMMUTABLE_FIELD`](https://developers.google.com/google-ads/api/reference/rpc/v26/RequestErrorEnum.RequestError#immutable_field) error.

The `ExternalRedeemInfo` message contains the following immutable
(`CREATE_ONLY`) fields:

- [`code_type`](https://developers.google.com/google-ads/api/reference/rpc/v26/ExternalRedeemInfo#code_type) (required): An [`OfflinePromotionCodeType`](https://developers.google.com/google-ads/api/reference/rpc/v26/OfflinePromotionCodeTypeEnum.OfflinePromotionCodeType) enum value specifying whether the promotion code can be redeemed once (`SINGLE_USE_PROMOTION_CODE`) or multiple times (`MULTI_USE_PROMOTION_CODE`).
- [`code_source`](https://developers.google.com/google-ads/api/reference/rpc/v26/ExternalRedeemInfo#code_source) (required): An [`OfflinePromotionCodeSource`](https://developers.google.com/google-ads/api/reference/rpc/v26/OfflinePromotionCodeSourceEnum.OfflinePromotionCodeSource) enum value specifying whether the promotion code is uploaded by the advertiser (`CUSTOMER_UPLOADED`) or generated by Google (`GOOGLE_GENERATED`). When you set this field to `GOOGLE_GENERATED`, the `partner_promotion_id` field is required (otherwise, the API returns a [`FieldError.REQUIRED`](https://developers.google.com/google-ads/api/reference/rpc/v26/FieldErrorEnum.FieldError#required) error). When you set this field to `CUSTOMER_UPLOADED`, the `partner_promotion_id` field is optional.
- [`partner_promotion_id`](https://developers.google.com/google-ads/api/reference/rpc/v26/ExternalRedeemInfo#partner_promotion_id): An
  [`ExternalPartnerId`](https://developers.google.com/google-ads/api/reference/rpc/v26/ExternalPartnerId) message that identifies the
  promotion in the partner's POS system. Confirm which identifier format your
  POS integration uses, and then set one of the following `oneof` variants:

  - [`int_value`](https://developers.google.com/google-ads/api/reference/rpc/v26/ExternalPartnerId#int_value) (`int64`): A positive integer identifier (`1` or greater). A value of `0` or less returns a [`RangeError.TOO_LOW`](https://developers.google.com/google-ads/api/reference/rpc/v26/RangeErrorEnum.RangeError#too_low) error.
  - [`string_value`](https://developers.google.com/google-ads/api/reference/rpc/v26/ExternalPartnerId#string_value) (`string`): A string identifier of 1--50 printable characters. The API trims leading and trailing whitespace before validation, so an empty or whitespace-only string returns a [`StringLengthError.TOO_SHORT`](https://developers.google.com/google-ads/api/reference/rpc/v26/StringLengthErrorEnum.StringLengthError#too_short) error, a trimmed value longer than 50 characters returns a [`StringLengthError.TOO_LONG`](https://developers.google.com/google-ads/api/reference/rpc/v26/StringLengthErrorEnum.StringLengthError#too_long) error, and a value with non-printable characters returns a [`StringFormatError.ILLEGAL_CHARS`](https://developers.google.com/google-ads/api/reference/rpc/v26/StringFormatErrorEnum.StringFormatError#illegal_chars) error.

  If your account's promotion integration requires a specific
  `partner_promotion_id` variant and you set the other variant (`int_value`
  instead of `string_value`, or `string_value` instead of `int_value`), the
  API returns an
  [`AssetError.PARTNER_PROMOTION_ID_TYPE_INCOMPATIBLE`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetErrorEnum.AssetError#partner_promotion_id_type_incompatible)
  error.

You can select, filter (`WHERE`), and sort (`ORDER BY`) by all four leaf fields
in [`asset`](https://developers.google.com/google-ads/api/fields/v26/asset) reports. Because the `partner_promotion_id` field
is a `oneof`, at most one of the `int_value` or `string_value` fields is
populated for a given promotion asset, and the unset variant returns `null`:

    SELECT
      asset.resource_name,
      asset.id,
      asset.name,
      asset.promotion_asset.promotion_target,
      asset.promotion_asset.external_redeem_info.code_source,
      asset.promotion_asset.external_redeem_info.code_type,
      asset.promotion_asset.external_redeem_info.partner_promotion_id.int_value,
      asset.promotion_asset.external_redeem_info.partner_promotion_id.string_value
    FROM asset
    WHERE asset.type = 'PROMOTION'

## Use the asset in an ad

Different ad and campaign types support different asset types as shown in the
following table:

| Ad/Campaign types and the asset types they support ||
|---|---|
| `AppAd` | `TextAsset` `ImageAsset` `YoutubeVideoAsset` `MediaBundleAsset` |
| `AppEngagementAd` | `TextAsset` `ImageAsset` `YoutubeVideoAsset` |
| `Demand Gen` | `TextAsset` `ImageAsset` `YoutubeVideoAsset` `DemandGenCarouselCardAsset` |
| `DisplayUploadAd` | `MediaBundleAsset` |
| [Performance Max campaign](https://developers.google.com/google-ads/api/performance-max/assets) | `TextAsset` `ImageAsset` `MediaBundleAsset` `YoutubeVideoAsset` `CallToActionAsset` |
| `ResponsiveDisplayAd` | `TextAsset` `ImageAsset` `YoutubeVideoAsset` |
| `ResponsiveSearchAd` | `TextAsset` (for headlines, descriptions in the ad creative) <br /> The following asset types can be linked at the customer, campaign, or ad group level using `CustomerAsset`, `CampaignAsset`, or `AdGroupAsset`, respectively, to serve with the ad as extensions: - `SitelinkAsset` - `CalloutAsset` - `StructuredSnippetAsset` - `CallAsset` - `LeadFormAsset` - `PriceAsset` - `PromotionAsset` - `MobileAppAsset` - `ImageAsset` (for image extensions) - `HotelCalloutAsset` - `BusinessMessageAsset` <br /> *Note: Location assets and affiliate location assets are managed differently, often through `CustomerAssetSet` or `CampaignAssetSet`. See [Location assets](https://developers.google.com/google-ads/api/docs/assets/location-assets) for details.* |

Each of these ad types has fields for setting the various asset types that
it supports. For [`TextAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/TextAsset), a new string asset is
created inline within the ad. For all other asset types, existing assets are
added to the ad by referencing their resource names.

The following example demonstrates adding a
[`TextAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/TextAsset) and an
[`ImageAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/ImageAsset) to a
[`ResponsiveDisplayAd`](https://developers.google.com/google-ads/api/reference/rpc/v26/ResponsiveDisplayAdInfo). The
[`TextAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/TextAsset) is created inline as the ad's headlines
and description. The [`ImageAsset`](https://developers.google.com/google-ads/api/reference/rpc/v26/ImageAsset) is specified by
a resource name.

> [!NOTE]
> **Note:** Multiple ads can refer to the same underlying asset, enabling sharing and reuse of their content within a Google Ads account. The logo image resource names in the following example can be referenced by multiple ads across different campaigns within the Google Ads account.


### Java

```java
private void createAd(
    GoogleAdsClient googleAdsClient, long customerId, String adGroupResourceName)
    throws IOException {
  String marketingImageUrl = "https://gaagl.page.link/Eit5";
  String marketingImageName = "Marketing Image";
  String marketingImageResourceName =
      uploadAsset(googleAdsClient, customerId, marketingImageUrl, marketingImageName);
  String squareMarketingImageName = "Square Marketing Image";
  String squareMarketingImageUrl = "https://gaagl.page.link/bjYi";
  String squareMarketingImageResourceName =
      uploadAsset(googleAdsClient, customerId, squareMarketingImageUrl, squareMarketingImageName);

  // Creates the responsive display ad info object.
  ResponsiveDisplayAdInfo responsiveDisplayAdInfo =
      ResponsiveDisplayAdInfo.newBuilder()
          .addMarketingImages(
              AdImageAsset.newBuilder().setAsset(marketingImageResourceName).build())
          .addSquareMarketingImages(
              AdImageAsset.newBuilder().setAsset(squareMarketingImageResourceName).build())
          .addHeadlines(AdTextAsset.newBuilder().setText("Travel").build())
          .setLongHeadline(AdTextAsset.newBuilder().setText("Travel the World").build())
          .addDescriptions(AdTextAsset.newBuilder().setText("Take to the air!").build())
          .setBusinessName("Interplanetary Cruises")
          // Optional: Call to action text.
          // Valid texts: https://support.google.com/adwords/answer/7005917
          .setCallToActionText("Apply Now")
          // Optional: Sets the ad colors.
          .setMainColor("#0000ff")
          .setAccentColor("#ffff00")
          // Optional: Sets to false to strictly render the ad using the colors.
          .setAllowFlexibleColor(false)
          // Optional: Sets the format setting that the ad will be served in.
          .setFormatSetting(DisplayAdFormatSetting.NON_NATIVE)
          // Optional: Creates a logo image and sets it to the ad.
          /*
          .addLogoImages(
              AdImageAsset.newBuilder()
                  .setAsset(StringValue.of("INSERT_LOGO_IMAGE_RESOURCE_NAME_HERE"))
                  .build())
          */
          // Optional: Creates a square logo image and sets it to the ad.
          /*
          .addSquareLogoImages(
              AdImageAsset.newBuilder()
                  .setAsset(StringValue.of("INSERT_SQUARE_LOGO_IMAGE_RESOURCE_NAME_HERE"))
                  .build())
          */
          .build();

  // Creates the ad.
  Ad ad =
      Ad.newBuilder()
          .setResponsiveDisplayAd(responsiveDisplayAdInfo)
          .addFinalUrls("http://www.example.com/")
          .build();

  // Creates the ad group ad.
  AdGroupAd adGroupAd = AdGroupAd.newBuilder().setAdGroup(adGroupResourceName).setAd(ad).build();

  // Creates the ad group ad operation.
  AdGroupAdOperation operation = AdGroupAdOperation.newBuilder().setCreate(adGroupAd).build();

  // Creates the ad group ad service client.
  try (AdGroupAdServiceClient adGroupAdServiceClient =
      googleAdsClient.getLatestVersion().createAdGroupAdServiceClient()) {
    // Adds the ad group ad.
    MutateAdGroupAdsResponse response =
        adGroupAdServiceClient.mutateAdGroupAds(
            Long.toString(customerId), ImmutableList.of(operation));
    System.out.printf(
        "Created ad group ad with resource name '%s'.%n",
        response.getResults(0).getResourceName());
  }
}

      
```

### C#

```c#
private void CreateAd(GoogleAdsClient client, long customerId, string adGroupResourceName)
{
    // Creates the ad group ad service client.
    AdGroupAdServiceClient adGroupAdServiceClient =
        client.GetService(Services.V26.AdGroupAdService);

    string marketingImageUrl = "https://gaagl.page.link/Eit5";
    string marketingImageName = "Marketing Image";
    string marketingImageResourceName =
        UploadAsset(client, customerId, marketingImageUrl, marketingImageName);
    string squareMarketingImageName = "Square Marketing Image";
    string squareMarketingImageUrl = "https://gaagl.page.link/bjYi";
    string squareMarketingImageResourceName =
        UploadAsset(client, customerId, squareMarketingImageUrl, squareMarketingImageName);

    // Creates the responsive display ad info object.
    ResponsiveDisplayAdInfo responsiveDisplayAdInfo = new ResponsiveDisplayAdInfo()
    {
        MarketingImages =
        {
            new AdImageAsset()
            {
                Asset = marketingImageResourceName
            }
        },
        SquareMarketingImages =
        {
            new AdImageAsset()
            {
                Asset = squareMarketingImageResourceName
            }
        },
        Headlines =
        {
            new AdTextAsset()
            {
                Text = "Travel"
            }
        },
        LongHeadline = new AdTextAsset()
        {
            Text = "Travel the World"
        },
        Descriptions =
        {
            new AdTextAsset()
            {
                Text = "Take to the air!"
            }
        },
        BusinessName = "Interplanetary Cruises",
        // Optional: Call to action text.
        // Valid texts: https://support.google.com/adwords/answer/7005917
        CallToActionText = "Apply Now",
        // Optional: Sets the ad colors.
        MainColor = "#0000ff",
        AccentColor = "#ffff00",
        // Optional: Sets to false to strictly render the ad using the colors.
        AllowFlexibleColor = false,
        // Optional: Sets the format setting that the ad will be served in.
        FormatSetting = DisplayAdFormatSetting.NonNative,
        // Optional: Creates a logo image and sets it to the ad.
        /*
            LogoImages = { new AdImageAsset()
            {
                Asset = "INSERT_LOGO_IMAGE_RESOURCE_NAME_HERE"
            }}
        */
        // Optional: Creates a square logo image and sets it to the ad.
        /*
            SquareLogoImages = { new AdImageAsset()
            {
                Asset = "INSERT_SQUARE_LOGO_IMAGE_RESOURCE_NAME_HERE"
            }}
        */
    };

    // Creates the ad.
    Ad ad = new Ad()
    {
        ResponsiveDisplayAd = responsiveDisplayAdInfo,
        FinalUrls = { "http://www.example.com/" }
    };

    // Creates the ad group ad.
    AdGroupAd adGroupAd = new AdGroupAd()
    {
        AdGroup = adGroupResourceName,
        Ad = ad
    };

    // Creates the ad group ad operation.
    AdGroupAdOperation operation = new AdGroupAdOperation()
    {
        Create = adGroupAd
    };

    // Adds the ad group ad.
    MutateAdGroupAdsResponse response = adGroupAdServiceClient.MutateAdGroupAds
        (customerId.ToString(), new[] { operation });
    Console.WriteLine("Created ad group ad with resource name " +
                      $"'{response.Results.First().ResourceName}'.");
}
      
```

### PHP

```php
    private static function createAd(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        string $adGroupResourceName
    ) {
        $marketingImageResourceName = self::uploadAsset(
            $googleAdsClient,
            $customerId,
            'https://gaagl.page.link/Eit5',
            'Marketing Image'
        );
        $squareMarketingImageResourceName = self::uploadAsset(
            $googleAdsClient,
            $customerId,
            'https://gaagl.page.link/bjYi',
            'Square Marketing Image'
        );

        // Creates the responsive display ad info object.
        $responsiveDisplayAdInfo = new ResponsiveDisplayAdInfo(
            [
            'marketing_images' => [new AdImageAsset(['asset' => $marketingImageResourceName])],
            'square_marketing_images' => [new AdImageAsset(
                [
                'asset' => $squareMarketingImageResourceName
                ]
            )],
            'headlines' => [new AdTextAsset(['text' => 'Travel'])],
            'long_headline' => new AdTextAsset(['text' => 'Travel the World']),
            'descriptions' => [new AdTextAsset(['text' => 'Take to the air!'])],
            'business_name' => 'Interplanetary Cruises',
            // Optional: Call to action text.
            // Valid texts: https://support.google.com/google-ads/answer/7005917
            'call_to_action_text' => 'Apply Now',
            // Optional: Sets the ad colors.
            'main_color' => '#0000ff',
            'accent_color' => '#ffff00',
            // Optional: Sets to false to strictly render the ad using the colors.
            'allow_flexible_color' => false,
            // Optional: Sets the format setting that the ad will be served in.
            'format_setting' => DisplayAdFormatSetting::NON_NATIVE
            // Optional: Creates a logo image and sets it to the ad.
            // 'logo_images' => [new AdImageAsset([
            //     'asset' => 'INSERT_LOGO_IMAGE_RESOURCE_NAME_HERE'
            // ])],
            // Optional: Creates a square logo image and sets it to the ad.
            // 'square_logo_images' => [new AdImageAsset([
            //     'asset' => 'INSERT_SQUARE_LOGO_IMAGE_RESOURCE_NAME_HERE'
            // ])]
            ]
        );

        // Creates a new ad group ad.
        $adGroupAd = new AdGroupAd(
            [
            'ad' => new Ad(
                [
                'responsive_display_ad' => $responsiveDisplayAdInfo,
                'final_urls' => ['http://www.example.com/']
                ]
            ),
            'ad_group' => $adGroupResourceName
            ]
        );

        // Creates an ad group ad operation.
        $adGroupAdOperation = new AdGroupAdOperation();
        $adGroupAdOperation->setCreate($adGroupAd);

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

        /**
 * @var AdGroupAd $addedAdGroupAd
*/
        $addedAdGroupAd = $response->getResults()[0];
        printf(
            "Created ad group ad with resource name '%s'.%s",
            $addedAdGroupAd->getResourceName(),
            PHP_EOL
        );
    }
      
```

### Python

```python
def create_ad(
    client: GoogleAdsClient, customer_id: str, ad_group_resource_name: str
) -> None:
    """Creates the responsive display ad.

    Args:
        client: An initialized GoogleAds client.
        customer_id: The Google Ads customer ID.
        ad_group_resource_name: The resource name of the target ad group.
    """
    # Get the AdGroupAdService client.
    ad_group_ad_service: AdGroupAdServiceClient = client.get_service(
        "AdGroupAdService"
    )

    # Upload image assets for the ad.
    marketing_image_resource_name: str = upload_image_asset(
        client, customer_id, "https://gaagl.page.link/Eit5", "Marketing Image"
    )
    square_marketing_image_resource_name: str = upload_image_asset(
        client,
        customer_id,
        "https://gaagl.page.link/bjYi",
        "Square Marketing Image",
    )

    # Create the relevant asset objects for the ad.
    marketing_image: AdImageAsset = client.get_type("AdImageAsset")
    marketing_image.asset = marketing_image_resource_name
    square_marketing_image: AdImageAsset = client.get_type("AdImageAsset")
    square_marketing_image.asset = square_marketing_image_resource_name
    headline: AdTextAsset = client.get_type("AdTextAsset")
    headline.text = "Travel"
    description: AdTextAsset = client.get_type("AdTextAsset")
    description.text = "Take to the air!"

    # Create an ad group ad operation and set the ad group ad values.
    ad_group_ad_operation: AdGroupAdOperation = client.get_type(
        "AdGroupAdOperation"
    )
    ad_group_ad: AdGroupAd = ad_group_ad_operation.create
    ad_group_ad.ad_group = ad_group_resource_name
    ad_group_ad.ad.final_urls.append("http://www.example.com/")

    # Configure the responsive display ad info object.
    responsive_display_ad_info: ResponsiveDisplayAdInfo = (
        ad_group_ad.ad.responsive_display_ad
    )
    responsive_display_ad_info.marketing_images.append(marketing_image)
    responsive_display_ad_info.square_marketing_images.append(
        square_marketing_image
    )
    responsive_display_ad_info.headlines.append(headline)
    responsive_display_ad_info.long_headline.text = "Travel the World"
    responsive_display_ad_info.descriptions.append(description)
    responsive_display_ad_info.business_name = "Interplanetary Cruises"
    # Optional: Call to action text.
    # Valid texts: https://support.google.com/google-ads/answer/7005917
    responsive_display_ad_info.call_to_action_text = "Apply Now"
    # Optional: Set the ad colors.
    responsive_display_ad_info.main_color = "#0000ff"
    responsive_display_ad_info.accent_color = "#ffff00"
    # Optional: Set to false to strictly render the ad using the colors.
    responsive_display_ad_info.allow_flexible_color = False
    # Optional: Set the format setting that the ad will be served in.
    responsive_display_ad_info.format_setting = (
        client.enums.DisplayAdFormatSettingEnum.NON_NATIVE
    )
    # Optional: Create a logo image and set it to the ad.
    # logo_image = client.get_type("AdImageAsset")
    # logo_image.asset = "INSERT_LOGO_IMAGE_RESOURCE_NAME_HERE"
    # responsive_display_ad_info.logo_images.append(logo_image)
    # Optional: Create a square logo image and set it to the ad.
    # square_logo_image = client.get_type("AdImageAsset")
    # square_logo_image.asset = "INSERT_SQUARE_LOGO_IMAGE_RESOURCE_NAME_HERE"
    # responsive_display_ad_info.square_logo_images.append(square_logo_image)

    # Issue a mutate request to add the ad group ad.
    ad_group_ad_response: MutateAdGroupAdsResponse = (
        ad_group_ad_service.mutate_ad_group_ads(
            customer_id=customer_id, operations=[ad_group_ad_operation]
        )
    )
    print(
        "Created ad group ad with resource name "
        f"'{ad_group_ad_response.results[0].resource_name}'."
    )
      
```

### Ruby

```ruby
def create_ad(client, customer_id, ad_group_resource_name)
  marketing_image_url = "https://gaagl.page.link/Eit5"
  square_marketing_image_url = "https://gaagl.page.link/bjYi"
  marketing_image_asset_resource_name = upload_asset(
    client, customer_id, marketing_image_url, "Marketing Image"
  )
  square_marketing_image_asset_resource_name = upload_asset(
    client, customer_id, square_marketing_image_url, "Square Marketing Image"
  )

  # Creates an ad group ad operation.
  operation = client.operation.create_resource.ad_group_ad do |aga|
    aga.ad_group = ad_group_resource_name
    aga.status = :PAUSED
    aga.ad = client.resource.ad do |a|
      a.final_urls << "https://www.example.com"

      # Creates the responsive display ad info object.
      a.responsive_display_ad = client.resource.responsive_display_ad_info do |rda|
        rda.headlines << client.resource.ad_text_asset do |ata|
          ata.text = "Travel"
        end
        rda.long_headline = client.resource.ad_text_asset do |ata|
          ata.text = "Travel the World"
        end
        rda.descriptions << client.resource.ad_text_asset do |ata|
          ata.text = "Take to the air!"
        end
        rda.business_name = "Interplanetary Cruises"
        rda.marketing_images << client.resource.ad_image_asset do |aia|
          aia.asset = marketing_image_asset_resource_name
        end
        rda.square_marketing_images << client.resource.ad_image_asset do |aia|
          aia.asset = square_marketing_image_asset_resource_name
        end
        # Optional: Call to action text.
        # Valid texts: https://support.google.com/google-ads/answer/7005917
        rda.call_to_action_text = "Apply Now"
        # Optional: Sets the ad colors.
        rda.main_color = "#0000ff"
        rda.accent_color = "#ffff00"
        # Optional: Sets to false to strictly render the ad using the colors.
        rda.allow_flexible_color = false
        # Optional: Sets the format setting that the ad will be served in.
        rda.format_setting = :NON_NATIVE
        # Optional: Creates a logo image and sets it to the ad.
        # rda.logo_images << client.resource.ad_image_asset do |aia|
        #   aia.asset = "INSERT_LOGO_IMAGE_RESOURCE_NAME_HERE"
        # end
        # Optional: Creates a square logo image and sets it to the ad.
        # rda.square_logo_images << client.resource.ad_image_asset do |aia|
        #   aia.asset = "INSERT_SQUARE_LOGO_IMAGE_RESOURCE_NAME_HERE"
        # end
      end
    end
  end

  # Issues a mutate request to add the ad group ad.
  response = client.service.ad_group_ad.mutate_ad_group_ads(
    customer_id: customer_id,
    operations: [operation]
  )

  # Prints out some information about the newly created ad.
  resource_name = response.results.first.resource_name
  puts "Created ad group ad: #{resource_name}"

  resource_name
end
      
```

### Perl

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

  my $marketing_image_resource_name = upload_asset(
    $api_client, $customer_id,
    "https://gaagl.page.link/Eit5",
    "Marketing Image"
  );

  my $square_marketing_image_resource_name = upload_asset(
    $api_client, $customer_id,
    "https://gaagl.page.link/bjYi",
    "Square Marketing Image"
  );

  # Create the responsive display ad info object.
  my $responsive_display_ad_info =
    Google::Ads::GoogleAds::V26::Common::ResponsiveDisplayAdInfo->new({
      marketingImages => [
        Google::Ads::GoogleAds::V26::Common::AdImageAsset->new({
            asset => $marketing_image_resource_name
          })
      ],
      squareMarketingImages => [
        Google::Ads::GoogleAds::V26::Common::AdImageAsset->new({
            asset => $square_marketing_image_resource_name
          })
      ],
      headlines => [
        Google::Ads::GoogleAds::V26::Common::AdTextAsset->new({
            text => "Travel"
          })
      ],
      longHeadline => Google::Ads::GoogleAds::V26::Common::AdTextAsset->new({
          text => "Travel the World"
        }
      ),
      descriptions => [
        Google::Ads::GoogleAds::V26::Common::AdTextAsset->new({
            text => "Take to the air!"
          })
      ],
      businessName => "Interplanetary Cruises",
      # Optional: Call to action text.
      # Valid texts: https://support.google.com/google-ads/answer/7005917
      callToActionText => "Apply Now",
      # Optional: Set the ad colors.
      mainColor   => "#0000ff",
      accentColor => "#ffff00",
      # Optional: Set to false to strictly render the ad using the colors.
      allowFlexibleColor => "false",
      # Optional: Set the format setting that the ad will be served in.
      formatSetting => NON_NATIVE,
      # Optional: Create a logo image and set it to the ad.
      # logoImages => [
      #   Google::Ads::GoogleAds::V26::Common::AdImageAsset->new({
      #       asset => "INSERT_LOGO_IMAGE_RESOURCE_NAME_HERE"
      #     })
      # ],
      # Optional: Create a square logo image and set it to the ad.
      # squareLogoImages => [
      #   Google::Ads::GoogleAds::V26::Common::AdImageAsset->new({
      #       asset => "INSERT_SQUARE_LOGO_IMAGE_RESOURCE_NAME_HERE"
      #     })
      # ]
    });

  # Create an ad group ad.
  my $ad_group_ad = Google::Ads::GoogleAds::V26::Resources::AdGroupAd->new({
      adGroup => $ad_group_resource_name,
      ad      => Google::Ads::GoogleAds::V26::Resources::Ad->new({
          responsiveDisplayAd => $responsive_display_ad_info,
          finalUrls           => ["http://www.example.com/"]})});

  # Create an ad group ad operation.
  my $ad_group_ad_operation =
    Google::Ads::GoogleAds::V26::Services::AdGroupAdService::AdGroupAdOperation
    ->new({create => $ad_group_ad});

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

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

### 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)
> - [REST Interface Structure](https://developers.google.com/google-ads/api/rest/design/overview)
> - [JSON Field Mappings](https://developers.google.com/google-ads/api/rest/design/json-mappings)
> - Consult the [REST API Reference](https://developers.google.com/google-ads/api/reference/rpc/latest/overview) for the specific service and method.

<br />

## Asset recommendations

[Recommendations](https://support.google.com/google-ads/answer/3448398) can improve
your assets in a couple ways:

1. They can suggest assets for you, which you can add to your campaign by
   calling
   [`RecommendationService.ApplyRecommendation`](https://developers.google.com/google-ads/api/reference/rpc/v26/RecommendationService/ApplyRecommendation).
   For example, you can retrieve `CALLOUT_ASSET`, `SITELINK_ASSET`,
   `CALL_ASSET`, `LEAD_FORM_ASSET` and `RESPONSIVE_SEARCH_AD_ASSET`
   recommendations, and then apply them to attach the recommended assets to the
   relevant campaign, ad group, or ad.

2. They can help you identify areas where you can update your assets to
   improve the overall strength of your responsive search ads or your
   Performance Max campaigns. For example, you can retrieve
   [`IMPROVE_PERFORMANCE_MAX_AD_STRENGTH`](https://developers.google.com/google-ads/api/reference/rpc/v26/Recommendation#improve_performance_max_ad_strength_recommendation)
   recommendations to see which asset groups should be updated to improve their
   strength.

Visit the [Optimization score and recommendations](https://developers.google.com/google-ads/api/docs/recommendations)
guide for more information.