Asset optimization experiments

Asset optimization experiments test different asset combinations within Performance Max campaigns, which lets you compare how different sets of assets perform against a base set.

This workflow is supported for ExperimentType.OPTIMIZE_ASSETS.

Setup

To set up an asset optimization experiment:

  • Create a new asset and an experiment with control and treatment arms.
  • Link the new asset to the treatment arm's asset group within a single mutate request.

Prerequisites

Before creating an asset optimization experiment, you must have an existing Performance Max campaign and a base AssetGroup resource (customers/{customer_id}/assetGroups/{asset_group_id}) that serves as the baseline for both experiment arms.

Request operation order

Because these entities are interdependent, you must use temporary resource names to refer to resources created in earlier operations within the same request.

The operations in your request must be in the following order:

  1. Create one or more Asset resources with temporary resource names (such as customers/CUSTOMER_ID/assets/-1). These are your test assets.
  2. Create an Experiment with a temporary resource name (for example, customers/CUSTOMER_ID/experiments/-2), type set to OPTIMIZE_ASSETS, status set to ENABLED, and optimize_assets_experiment.optimize_assets_experiment_subtype set to the selected OptimizeAssetsExperimentSubtype (for example, COMPARE_ASSETS).
  3. Create two ExperimentArm resources linked to the temporary experiment resource name from step 2, setting campaigns (to the Performance Max campaign resource name), traffic_split (summing to 100), and asset_groups (ExperimentArm.AssetGroupInfo) on each arm:

    • A control arm (control = true) where asset_groups contains an AssetGroupInfo with asset_group set to the resource name of the base AssetGroup (customers/CUSTOMER_ID/assetGroups/ASSET_GROUP_ID). When testing newly added assets against the baseline asset group (or when using the ADD_ASSETS_TO_ASSETLESS_RETAIL or ADD_VIDEO_ASSETS_TO_VIDEOLESS subtypes), leave asset_group_assets unset on the control arm; when comparing two distinct asset sets under COMPARE_ASSETS, list the control arm's AssetGroupAssetInfo entries (asset and field_type).
    • A treatment arm (control = false) where asset_groups contains an AssetGroupInfo with asset_group set to the same base AssetGroup resource name (customers/CUSTOMER_ID/assetGroups/ASSET_GROUP_ID) and asset_group_assets (repeated AssetGroupAssetInfo) listing the Asset resources and field_types for the treatment arm, including the newly created test Asset (customers/CUSTOMER_ID/assets/-1) from step 1.
  4. Create AssetGroupAsset resources linking the test assets from step 1 (customers/CUSTOMER_ID/assets/-1) to the base AssetGroup used in the experiment arms.

Java

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

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

# 1. Create Assets with temporary resource names.
# We create a text asset and an image asset to showcase different types.
asset_operation_1 = create_text_asset_operation(
    client,
    customer_id,
    ASSET_1_TEMP_ID,
    "Fly to Mars!",
)
asset_operation_2 = create_image_asset_operation(
    client,
    customer_id,
    ASSET_2_TEMP_ID,
    "https://gaagl.page.link/Eit5",
    "Mars Landscape View",
)

# 2. Create an Experiment with a temporary resource name.
experiment_operation = client.get_type("MutateOperation")
experiment = experiment_operation.experiment_operation.create
experiment.resource_name = googleads_service.experiment_path(
    customer_id, EXPERIMENT_TEMP_ID
)
experiment.name = f"Interstellar Asset Experiment #{uuid4()}"
experiment.type_ = client.enums.ExperimentTypeEnum.OPTIMIZE_ASSETS
# Set the optimize assets experiment subtype to COMPARE_ASSETS.
experiment.optimize_assets_experiment.optimize_assets_experiment_subtype = (
    client.enums.OptimizeAssetsExperimentSubtypeEnum.COMPARE_ASSETS
)

# 3. Create two ExperimentArm resources.
treatment_assets = [
    (ASSET_1_TEMP_ID, client.enums.AssetFieldTypeEnum.HEADLINE),
    (ASSET_2_TEMP_ID, client.enums.AssetFieldTypeEnum.MARKETING_IMAGE),
]
arm_operations = create_arms_operations(
    client,
    customer_id,
    EXPERIMENT_TEMP_ID,
    campaign_resource_name,
    asset_group_id,
    treatment_assets,
)

# 4. Create AssetGroupAssets linking the assets to the asset group.
asset_group_asset_operation_1 = create_asset_group_asset_operation(
    client,
    customer_id,
    asset_group_id,
    ASSET_1_TEMP_ID,
    client.enums.AssetFieldTypeEnum.HEADLINE,
)
asset_group_asset_operation_2 = create_asset_group_asset_operation(
    client,
    customer_id,
    asset_group_id,
    ASSET_2_TEMP_ID,
    client.enums.AssetFieldTypeEnum.MARKETING_IMAGE,
)

# Send all operations in a single Mutate request.
# The operations must be in this specific order.
mutate_operations = [
    asset_operation_1,
    asset_operation_2,
    experiment_operation,
    *arm_operations,
    asset_group_asset_operation_1,
    asset_group_asset_operation_2,
]

response = googleads_service.mutate(
    customer_id=customer_id,
    mutate_operations=mutate_operations,
)
      

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

Report on the experiment

See the Reporting guide to query the experiment resource and compare metrics between the control and treatment asset groups.

Graduate or end

After evaluating the results, you can either end or graduate the experiment using ExperimentService.

  • End: If you are not satisfied with the results from the treatment arm, use EndExperiment. This is a synchronous operation.
  • Graduate: If you prefer the performance of the treatment arm's asset group, use GraduateExperiment. As part of this process, the original base campaign associated with the control arm is paused, and the treatment arm is converted to a new, independent campaign. This is a synchronous operation.