Performance Max campaigns using AdsApp

Google Ads scripts provide for some management of your Performance Max campaigns. You can use scripts to retrieve Performance Max campaigns, manage asset groups, and run reports; however, you can't use scripts to create Performance Max campaigns. To do more advanced operations, see the remainder of this guide, which demonstrates a more generic approach using mutate.

Retrieval of Performance Max campaigns

Performance max campaigns are available through the performanceMaxCampaigns collection of an AdsApp object. You can retrieve them as usual:

const campaignName = "My Performance Max campaign";

const campaignIterator = AdsApp.performanceMaxCampaigns()
    .withCondition(` = "${campaignName}"`)

for (const campaign of campaignIterator) {

Unlike some other campaign types, Performance Max campaigns do not have ad groups or ad objects that you can see; everything related to these concepts for other campaigns is handled automatically for you based on the asset groups you set.

Assets and asset groups

Ads from Performance Max campaigns run off of assets such as videos, images, headlines, and descriptions—either provided by you or automatically generated. For a full overview of what kinds of assets are required, see the Google Ads API Performance Max asset guide.

Assets for Performance Max campaigns are bundled together into an asset group, and each Performance Max campaign must have at least one asset group. You cannot create these asset groups directly in scripts, but you can add and remove assets from an existing asset group.

Add asset to asset group

First, create the asset:

const imageUrl = "";
const imageBlob = UrlFetchApp.fetch(imageUrl).getBlob();
const assetOperation = AdsApp.adAssets().newImageAssetBuilder()
   .withName("new asset name")
const imageAsset = assetOperation.getResult();

Then, using the asset you just created, add it to an existing asset group:

// First, fetch the Performance Max campaign we want to operate on.
const campaignIterator = AdsApp.performanceMaxCampaigns()
   .withCondition(` = '${campaignName}'`)
let campaign;
if (campaignIterator.hasNext()) {
   campaign =;
} else {
   throw `No campaign found with name ${campaignName}.`

// Then, get that campaign's asset groups.
const assetGroupIterator = campaign.assetGroups().get();

// The campaign must have at least one asset group, so we can just assume so here.
const assetGroup =;

// Add the asset from the previous step.
assetGroup.addAsset(imageAsset, 'MARKETING_IMAGE');

Note how you must specify the type of asset in the last step. You can find a complete list of asset types in the Google Ads API documentation

To use an existing asset, first create an asset selector:

const assetSelector = AdsApp.adAssets().assets();

Then use a withCondition filter to narrow down to the assets you want to operate on. See the AssetSelector reference documentation for a full list of filter options.

Finally, fetch the iterator and iterate as with other entities:

const assetIterator = assetSelector.get();

for (const asset of assetIterator) {

Text assets

Text assets work a little differently, in that you don't need to make the asset in advance. You just specify the text instead of an asset, and the system will create the asset for you automatically. If the text is an exact duplicate of an existing text asset, the existing asset will be re-used instead.

For example, here's how to create a headline asset:

assetGroup.addAsset('asset text here', 'HEADLINE');

Remove asset from asset group

You can also remove an asset from an asset group; however, keep in mind that you must have a minimum number of certain kinds of assets in order for the campaign to be valid.

Here is how to remove the asset that was added in the previous example:

assetGroup.removeAsset(imageAsset, 'MARKETING_IMAGE');

You can also get a list of assets in a given asset group with the search function:

// The resource name is a unique identifier for this asset group.
const assetGroupName = assetGroup.getResourceName();
results =
   `SELECT asset.resource_name, asset_group_asset.field_type
    FROM asset_group_asset
    WHERE asset_group.resource_name = '${assetGroupName}'`

This selects the asset's resource name as its unique identifier. You could select other fields as well, such as asset.type or asset.text_asset.text to further refine the results. Use the query builder for this report type to craft your own query.

Once you have the target asset, call remove on the asset group to remove the asset from the asset group:

// Let's assume at least one asset is returned. We'll just remove the first
// asset, whatever it is. In your code, customize this to choose the right asset.
const row_info =;
assetGroup.remove(row_info.asset.resource_name, row_info.asset_group_asset.field_type);