Performance Max optimization and troubleshooting

Similar to Performance Max reporting, use GoogleAdsService.SearchStream to retrieve campaign and asset group metadata to optimize your campaigns and troubleshoot common issues.

Campaign optimization

For the different business objectives that can be achieved through Performance Max campaigns, check out our optimization tips for Performance Max. These tips are equally applicable to Performance Max campaigns created by the Google Ads API.

Campaign troubleshooting

If your Performance Max campaign isn't performing as expected, it could be due to specific problems with your ads, bidding, targeting, conversion tracking, or campaign settings. See the following guides for troubleshooting steps:

Campaigns with brand guidelines enabled

Use brand guidelines to control how your brand is represented in Performance Max campaigns. You can use Campaign.brand_guidelines_enabled to verify that brand guidelines have been enabled for a campaign.

Performance Max campaigns with Campaign.brand_guidelines_enabled set to true use campaign-level brand assets (BUSINESS_NAME, LOGO, and LANDSCAPE_LOGO), and must have

  • Exactly one BUSINESS_NAME asset
  • At least one LOGO asset

If you fail to correctly link these CampaignAsset resources, you will get an error of either CampaignError.REQUIRED_BUSINESS_NAME_ASSET_NOT_LINKED or CampaignError.REQUIRED_LOGO_ASSET_NOT_LINKED, depending on the missing asset type. These errors can be triggered for brand guidelines-enabled campaigns by any of the following actions:

Attempting to link brand assets at the wrong level will also generate errors, which you can fix as follows:

Asset group optimization

To optimize your asset groups, review their Ad Strength and Asset Coverage report. You can access this report using the asset_coverage field on the AssetGroup resource which contains recommended ad_strength_action_items to improve the ad_strength.

SELECT
  asset_group.ad_strength,
  asset_group.asset_coverage
FROM asset_group
WHERE asset_group.resource_name = "customers/CUSTOMER_ID/assetGroups/ASSET_GROUP_ID"

Asset group troubleshooting

Use the asset_group.primary_status and asset_group.primary_status_reasons fields to provide insights into an asset group's performance.

SELECT
  asset_group.resource_name,
  asset_group.primary_status,
  asset_group.primary_status_reasons
FROM asset_group
WHERE asset_group.resource_name = "customers/CUSTOMER_ID/assetGroups/ASSET_GROUP_ID"

Similarly, use the asset_group_asset.primary_status, asset_group_asset.primary_status_details, and asset_group_asset.primary_status_reasons fields to show whether an asset group asset is serving, or the reasons why it's not.

SELECT
  asset_group_asset.resource_name,
  asset_group_asset.primary_status,
  asset_group_asset.primary_status_reasons,
  asset_group_asset.primary_status_details
FROM asset_group_asset
WHERE asset_group_asset.resource_name = "customers/CUSTOMER/assetGroupAssets/ASSET_GROUP_ID~ASSET_ID~FIELD_TYPE"

Common asset group errors

If your request to create an AssetGroup fails with an AssetGroupError and an enum value that begins with NOT_ENOUGH, such as AssetGroupError.NOT_ENOUGH_MARKETING_IMAGE_ASSET, this means your AssetGroup did not meet minimum asset requirements and was not created.

For example, an AssetGroupError.NOT_ENOUGH_MARKETING_IMAGE_ASSET error would suggest the request to create an AssetGroup was submitted without the minimum number of MARKETING_IMAGES, one in this case. To fix this error, resubmit your request to create an AssetGroup as a bulk mutate request using the GoogleAdsService.mutate method containing an asset_group_operation and any missing asset_group_asset_operations as demonstrated in Link asset groups to assets.

In this example, the list of mutate operations in the bulk mutate request must include at least one AssetGroupAsset with a field_type of MARKETING_IMAGE. The asset referenced by the AssetGroupAsset must also meet the specifications for a MARKETING_IMAGE.

Similarly, if your request to create an AssetGroup fails with an AssetGroupError.SHORT_DESCRIPTION_REQUIRED, this means your AssetGroup was missing a TEXT asset with 60 characters or less and a field_type of DESCRIPTION. The steps to fix this issue are the same as shown in the NOT_ENOUGH_MARKETING_IMAGE_ASSET example. However, the request must include at least one AssetGroupAsset with a field_type of DESCRIPTION, and the asset referenced by the AssetGroupAsset must be 60 characters or less.

Find asset source for troubleshooting

Performance Max is unique in that it serves ads containing assets that are uploaded by advertisers and automatically generated by Google. As an advertiser, it can be beneficial to know the source of the asset to troubleshoot or evaluate performance, in which case you can use the asset_group_asset.source field as follows:

SELECT
  asset.id,
  asset.name,
  asset_group.id,
  asset_group_asset.source
FROM asset_group_asset
WHERE campaign.id = CAMPAIGN_ID

Conversion values from new customer acquisition goal

Reported conversion values could be higher than those you manually upload if you've set up new customer acquisition in your Performance Max or Search campaigns. If you've selected New Customer Value mode (Bid higher), your all-new-customer lifetime value is added to your conversion action's conversion value. The all-new-customer lifetime value is only available through the Google Ads web interface.

If you need to calculate conversion values omitting the all-new-customer lifetime value, refer to the following pseudo code. The all-new-customer lifetime value can be downloaded from the Google Ads web interface.

nonNewCustomerAcquisitionConversionValueTotal = 0;
// For each campaign that has that conversion...
for (campaign in campaigns) {
  // If the new customer acquisition value is 'Bid higher', then subtract.
  if (bidHigher == true) {
    nonNewCustomerAcquisitionConversionValueTotal +=
        campaign.allConversionsValue - campaign.allNewCustomerLifetimeValue;
  }
  // If the new customer acquisition value is 'Only bid' or not set, then don't subtract.
  else {
    nonNewCustomerAcquisitionConversionValueTotal += campaign.allConversionsValue;
  }
}