Stay organized with collectionsSave and categorize content based on your preferences.
Once you've created an experiment, you need to create multiple experiment arms
in order to give the experiment more information about what exactly you're
testing.
Experiment arms
TheExperimentArmrepresents one part of the
comparison you're performing for the experiment. All experiments must always
haveexactly one control arm. This arm is an existing campaign that forms
the basis against which you compare the other arm.
The other arms are called treatment arms, and in these arms you make changes to
the campaign before beginning the experiment.
TheExperimentArmalso contains thetraffic_splitsetting. This lets you
specify the percentage of traffic that is directed to each arm of the
experiment. Each arm must specify a traffic split, and the sum of traffic split
values in all arms must add up to 100.
Because of this traffic split restriction, all experiment arms must be created
in the same request.
defcreate_experiment_arms(client:GoogleAdsClient,customer_id:str,base_campaign_id:str,experiment:str,)->str:"""Creates a control and treatment experiment arms.Args:client: an initialized GoogleAdsClient instance.customer_id: a client customer ID.base_campaign_id: the campaign ID to associate with the control arm ofthe experiment.experiment: the resource name for an experiment.Returns:the resource name for the new treatment experiment arm."""operations:List[ExperimentArmOperation]=[]campaign_service:CampaignServiceClient=client.get_service("CampaignService")# The "control" arm references an already-existing campaign.operation_1:ExperimentArmOperation=client.get_type("ExperimentArmOperation")exa_1:ExperimentArm=operation_1.createexa_1.control=Trueexa_1.campaigns.append(campaign_service.campaign_path(customer_id,base_campaign_id))exa_1.experiment=experimentexa_1.name="control arm"exa_1.traffic_split=40operations.append(operation_1)# The non-"control" arm, also called a "treatment" arm, will automatically# generate draft campaigns that you can modify before starting the# experiment.operation_2:ExperimentArmOperation=client.get_type("ExperimentArmOperation")exa_2:ExperimentArm=operation_2.createexa_2.control=Falseexa_2.experiment=experimentexa_2.name="experiment arm"exa_2.traffic_split=60operations.append(operation_2)experiment_arm_service:ExperimentArmServiceClient=client.get_service("ExperimentArmService")request:MutateExperimentArmsRequest=client.get_type("MutateExperimentArmsRequest")request.customer_id=customer_idrequest.operations=operations# We want to fetch the draft campaign IDs from the treatment arm, so the# easiest way to do that is to have the response return the newly created# entities.request.response_content_type=(client.enums.ResponseContentTypeEnum.MUTABLE_RESOURCE)response:MutateExperimentArmsResponse=(experiment_arm_service.mutate_experiment_arms(request=request))# Results always return in the order that you specify them in the request.# Since we created the treatment arm second, it will be the second result.control_arm_result:Any=response.results[0]treatment_arm_result:Any=response.results[1]print(f"Created control arm with resource name{control_arm_result.resource_name}")print(f"Created treatment arm with resource name{treatment_arm_result.resource_name}")returntreatment_arm_result.experiment_arm.in_design_campaigns[0]
defcreate_experiment_arms(client,customer_id,base_campaign_id,experiment)operations=[]operations<<client.operation.create_resource.experiment_armdo|ea|# The "control" arm references an already-existing campaign.ea.control=trueea.campaigns<<client.path.campaign(customer_id,base_campaign_id)ea.experiment=experimentea.name='control arm'ea.traffic_split=40endoperations<<client.operation.create_resource.experiment_armdo|ea|# The non-"control" arm, also called a "treatment" arm, will automatically# generate draft campaigns that you can modify before starting the# experiment.ea.control=falseea.experiment=experimentea.name='experiment arm'ea.traffic_split=60endresponse=client.service.experiment_arm.mutate_experiment_arms(customer_id:customer_id,operations:operations,# We want to fetch the draft campaign IDs from the treatment arm, so the# easiest way to do that is to have the response return the newly created# entities.response_content_type::MUTABLE_RESOURCE,)# Results always return in the order that you specify them in the request.# Since we created the treatment arm last, it will be the last result.control_arm_result=response.results.firsttreatment_arm_result=response.results.lastputs"Created control arm with resource name#{control_arm_result.resource_name}."puts"Created treatment arm with resource name#{treatment_arm_result.resource_name}."treatment_arm_result.experiment_arm.in_design_campaigns.firstend
subcreate_experiment_arms{my($api_client,$customer_id,$base_campaign_id,$experiment)=@_;my$operations=[];push@$operations,Google::Ads::GoogleAds::V21::Services::ExperimentArmService::ExperimentArmOperation->new({create=>Google::Ads::GoogleAds::V21::Resources::ExperimentArm->new({# The "control" arm references an already-existing campaign.control=>"true",campaigns=>[Google::Ads::GoogleAds::V21::Utils::ResourceNames::campaign($customer_id,$base_campaign_id)],experiment=>$experiment,name=>"control arm",trafficSplit=>40})});push@$operations,Google::Ads::GoogleAds::V21::Services::ExperimentArmService::ExperimentArmOperation->new({create=>Google::Ads::GoogleAds::V21::Resources::ExperimentArm->new({# The non-"control" arm, also called a "treatment" arm, will automatically# generate draft campaigns that you can modify before starting the# experiment.control=>"false",experiment=>$experiment,name=>"experiment arm",trafficSplit=>60})});my$response=$api_client->ExperimentArmService()->mutate({customerId=>$customer_id,operations=>$operations,# We want to fetch the draft campaign IDs from the treatment arm, so the# easiest way to do that is to have the response return the newly created# entities.responseContentType=>MUTABLE_RESOURCE});# Results always return in the order that you specify them in the request.# Since we created the treatment arm last, it will be the last result.my$control_arm_result=$response->{results}[0];my$treatment_arm_result=$response->{results}[1];printf"Created control arm with resource name '%s'.\n",$control_arm_result->{resourceName};printf"Created treatment arm with resource name '%s'.\n",$treatment_arm_result->{resourceName};return$treatment_arm_result->{experimentArm}{inDesignCampaigns}[0];}
Thenameof each arm must be unique within theExperiment.
Thetraffic_splitmust add up to 100 across all arms.
Exactly one arm must havecontrolset totrue; all other arms must have
it set tofalse.
Only the control arm specifies acampaignsarray, which holds only one
campaign.
Treatment arms
Once you've created all the experiment arms, the treatment arms—the arms
wherecontrolis set tofalse—automatically populate theirin_design_campaignsfield. You can retrieve the field from the API response
by setting the response content type toMUTABLE_RESOURCElike in the code
example. You can also fetch it through aGoogleAdsServicequery:
You can treat these in-design campaigns as regular campaigns. Make whatever
changes you want to test in your experiment to these campaigns; the control
campaign won't be affected. Once you schedule the experiment, these changes
are materialized into a real campaign that can serve ads.
These in-design campaigns are technically draft campaigns. If you want to
find them inGoogleAdsService, add theinclude_drafts=trueparameterto the query.
At least one change must be made to the in-design campaign before you can
schedule the experiment.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-03 UTC."],[[["\u003cp\u003eTo test changes effectively in Google Ads experiments, you need to create multiple experiment arms, including a control arm and treatment arm(s).\u003c/p\u003e\n"],["\u003cp\u003eThe control arm uses an existing campaign as a baseline, while treatment arms involve creating new draft campaigns where changes are made for testing.\u003c/p\u003e\n"],["\u003cp\u003eTraffic is split between the control and treatment arms, allowing you to compare their performance and determine the impact of your changes.\u003c/p\u003e\n"],["\u003cp\u003eDraft campaigns for treatment arms are automatically generated and can be modified through the Google Ads API before scheduling the experiment.\u003c/p\u003e\n"],["\u003cp\u003eEnsure at least one change is applied to the draft campaign(s) before scheduling the experiment for accurate results.\u003c/p\u003e\n"]]],[],null,[]]