ปฏิบัติตามแนวทางปฏิบัติแนะนำเหล่านี้เพื่อเพิ่มประสิทธิภาพ จัดการการอ้างอิงในการดำเนินการต่างๆ และจัดการการตอบกลับเมื่อเปลี่ยนแปลงทรัพยากรใน Google Ads API
ชื่อทรัพยากรชั่วคราว
ทั้ง GoogleAdsService.Mutate และ
BatchJobService รองรับชื่อทรัพยากรชั่วคราวที่
อ้างอิงได้ในการดำเนินการที่ตามมา ซึ่งช่วยให้คุณสร้างแคมเปญและกลุ่มโฆษณา โฆษณา และคีย์เวิร์ดที่เชื่อมโยงในคำขอเปลี่ยนแปลงข้อมูลในเซิร์ฟเวอร์รายการเดียวหรืองานแบบกลุ่มได้
หากต้องการอ้างอิงทรัพยากรที่สร้างขึ้นใหม่ภายในคำขอเปลี่ยนแปลงข้อมูลในเซิร์ฟเวอร์หรือชุดงานเดียวกัน ให้ระบุรหัสจำนวนเต็มลบ (เช่น -1 หรือ -2 ยกเว้น 0) ในฟิลด์ resource_name ของทรัพยากรใหม่ ตัวอย่างเช่น เมื่อสร้างแคมเปญในคำขอแบบกลุ่ม ให้ตั้งชื่อทรัพยากรเป็น customers/CUSTOMER_ID/campaigns/-1
เมื่อสร้างกลุ่มโฆษณาในการดำเนินการในภายหลังภายในคำขอเดียวกัน
ให้อ้างอิง customers/CUSTOMER_ID/campaigns/-1 เป็นแคมเปญหลัก API
จะแทนที่ -1 ด้วยรหัสแคมเปญจริงที่สร้างขึ้นเมื่อสร้างแคมเปญโดยอัตโนมัติ
ข้อจำกัดการใช้งาน
โปรดคำนึงถึงกฎต่อไปนี้เมื่อใช้ชื่อทรัพยากรชั่วคราว
- ลำดับมีความสำคัญ: คุณจะอ้างอิงชื่อทรัพยากรชั่วคราวได้หลังจากที่กำหนดแล้วเท่านั้น ในรายการการดำเนินการ การดำเนินการที่ขึ้นอยู่กับรายการอื่น (เช่น การสร้างกลุ่มโฆษณา) ต้องปรากฏหลังการดำเนินการที่สร้างทรัพยากรหลัก (เช่น การสร้างแคมเปญ)
- ขอบเขตของคำขอเดียวหรืองานแบบกลุ่ม: ชื่อทรัพยากรชั่วคราวจะไม่ คงอยู่ข้ามงานแยกกันหรือคำขอเปลี่ยนแปลง หากต้องการอ้างอิงทรัพยากร ที่สร้างขึ้นในงานก่อนหน้าหรือคำขอเปลี่ยนแปลงข้อมูลในเซิร์ฟเวอร์ ให้ใช้ชื่อทรัพยากรที่ระบบสร้างขึ้นจริง
- ความไม่ซ้ำกันทั่วโลก: ภายในคำของานหรือคำขอเปลี่ยนแปลงข้อมูลในเซิร์ฟเวอร์เดียว ชื่อทรัพยากรชั่วคราวแต่ละชื่อต้องใช้จำนวนเต็มลบที่ไม่ซ้ำกันในทรัพยากรทุกประเภท
เช่น คุณไม่สามารถกําหนด
-1ให้กับทั้งแคมเปญและกลุ่มโฆษณาในคําขอเดียวกันได้ การใช้รหัสชั่วคราวซ้ำภายในคำขอหรือชุดงานเดียวกัน จะแสดงข้อผิดพลาดNewResourceCreationError.DUPLICATE_TEMP_IDS
ตัวอย่างเพย์โหลด
สมมติว่าคุณต้องการเพิ่มแคมเปญ กลุ่มโฆษณา และโฆษณาในคำขอ API เดียว
หรือในงานแบบกลุ่ม คุณสามารถจัดโครงสร้างอาร์เรย์ mutateOperations ในเพย์โหลดคำขอ GoogleAdsService.Mutate หรือ BatchJobService.AddBatchJobOperations ได้ตามที่แสดงในตัวอย่าง JSON ของ REST ต่อไปนี้ (โดยละฟิลด์ทรัพยากรอื่นๆ ที่จำเป็นไว้เพื่อความกระชับ)
{
"mutateOperations": [
{
"campaignOperation": {
"create": {
"resourceName": "customers/CUSTOMER_ID/campaigns/-1"
}
}
},
{
"adGroupOperation": {
"create": {
"resourceName": "customers/CUSTOMER_ID/adGroups/-2",
"campaign": "customers/CUSTOMER_ID/campaigns/-1"
}
}
},
{
"adGroupAdOperation": {
"create": {
"adGroup": "customers/CUSTOMER_ID/adGroups/-2"
}
}
}
]
}
ตัวอย่างนี้แสดงรายละเอียดที่สำคัญต่อไปนี้
- กลุ่มโฆษณาใช้รหัสชั่วคราวใหม่ (
-2) เนื่องจากมีการกำหนด-1ให้กับแคมเปญแล้ว - กลุ่มโฆษณาอ้างอิง
customers/CUSTOMER_ID/campaigns/-1เพื่อลิงก์ตัวเอง กับแคมเปญที่สร้างขึ้นในการดำเนินการก่อนหน้า adGroupAdOperationอ้างอิงcustomers/CUSTOMER_ID/adGroups/-2และ ละเว้นresourceNameเนื่องจากไม่มีการดำเนินการที่ตามมาในคำขอ ที่อ้างอิงโฆษณาใหม่
จัดกลุ่มการดำเนินการประเภทเดียวกัน
เมื่อใช้ GoogleAdsService.Mutate ให้จัดกลุ่มการดำเนินการตามประเภททรัพยากรในอาร์เรย์ mutate_operations ที่ทำซ้ำขณะที่ยังคงคำนึงถึงการขึ้นต่อกันขององค์ประกอบหลักและองค์ประกอบย่อย วิธีนี้จะอ่านการดำเนินการตามลำดับจนกว่าจะ
พบทรัพยากรประเภทอื่น จากนั้นจะจัดกลุ่มการดำเนินการที่ต่อเนื่องทั้งหมด
ของประเภทเดียวกันเป็นคำขอบริการแบ็กเอนด์เดียว
ตัวอย่างเช่น หากคุณรวมการดำเนินการแคมเปญ 5 รายการตามด้วยการดำเนินการกลุ่มโฆษณา 10 รายการ
ในฟิลด์ mutate_operations ที่ทำซ้ำ ระบบจะทำการเรียกใช้แบ็กเอนด์ 2 ครั้ง
ครั้งแรกไปยัง CampaignService สำหรับการดำเนินการแคมเปญ 5 รายการ
และครั้งที่ 2 ไปยัง AdGroupService สำหรับการดำเนินการกลุ่มโฆษณา 10 รายการ
ในทางตรงกันข้าม การสลับการดำเนินการโดยจัดเรียงเป็น [campaign, ad group,
campaign, ad group] จะทำให้เกิดการเรียกข้อมูลจากแบ็กเอนด์ 4 ครั้งแยกกัน การเรียกแบบสลับ
จะลดประสิทธิภาพของ API และอาจทำให้คำขอหมดเวลาในกลุ่มขนาดใหญ่
จัดการข้อผิดพลาดบางส่วนและขีดจำกัดของกลุ่ม
โดยค่าเริ่มต้น GoogleAdsService.Mutate จะย้อนกลับทั้งคำขอ
หากการดำเนินการใดรายการหนึ่งล้มเหลว หากต้องการดำเนินการที่ถูกต้องแม้ว่าการดำเนินการอื่นๆ ในคำขอเดียวกันจะล้มเหลว ให้ตั้งค่า partial_failure เป็น true ในคำขอและตรวจสอบ partial_failure_error ในการตอบกลับ เมื่อ
partial_failureเป็น true หากการดำเนินการระดับบนที่กำหนดรหัสชั่วคราว
(เช่น customers/CUSTOMER_ID/campaigns/-1) ไม่ผ่านการตรวจสอบ การดำเนินการย่อยที่ขึ้นอยู่กับ
การดำเนินการดังกล่าวซึ่งอ้างอิงรหัสชั่วคราวนั้นในคำขอเดียวกันก็จะล้มเหลว
ด้วย NewResourceCreationError.TEMP_ID_RESOURCE_HAD_ERRORS ดูรายละเอียดเพิ่มเติมได้ที่คู่มือการล้มเหลวบางส่วน
นอกจากนี้ โปรดคำนึงถึงขนาดคำขอ การแบ่งกลุ่มย่อย และขีดจำกัดอัตราการส่งคำขอด้วย
- ขีดจำกัดของคำขอและขนาดก้อนข้อมูล: คำขอ
GoogleAdsService.Mutateรายการเดียวจะบังคับใช้ขีดจำกัดของการดำเนินการเปลี่ยนแปลง 10,000 รายการ (หรือสูงสุด 20,000 รายการเมื่อการดำเนินการทั้งหมดในคำขอเป็นAdGroupCriterionOperationโดยจะแสดงRequestError.TOO_MANY_MUTATE_OPERATIONSหากเกิน) และการดำเนินการ action สูงสุด 100 รายการ (RequestError.TOO_MANY_ACTION_OPERATIONS)BatchJobService.AddBatchJobOperationsจะบังคับใช้การดำเนินการสูงสุด 10,000 รายการต่อการเรียกใช้ 1 ครั้ง, 10,484,504 ไบต์ต่อMutateOperation1 รายการ และ 41,937,920 ไบต์ต่อAddBatchJobOperationsRequest1 รายการ (โดยจะแสดงBatchJobError.REQUEST_TOO_LARGEหากเกินขีดจำกัดใดๆ โดยมี การดำเนินการทั้งหมดสูงสุด 1,000,000 รายการต่องานแบบกลุ่ม) การเปลี่ยนแปลงพร้อมกัน ที่กำหนดเป้าหมายไปยังแคมเปญหรือบัญชีเดียวกันอาจทําให้เกิดข้อผิดพลาดDatabaseError.CONCURRENT_MODIFICATION BatchJobServiceการจัดกลุ่มย่อยแบบอะตอมมิก: แม้ว่างานแบบกลุ่มจะดำเนินการภายใต้ ความหมายของการล้มเหลวบางส่วน (ค่าเริ่มต้นคือ 1,000 การดำเนินการต่อกลุ่มย่อยภายใน)BatchJobServiceจะจัดกลุ่มการดำเนินการที่ต่อเนื่องกันบางอย่างโดยอัตโนมัติ ซึ่งขึ้นอยู่กับรหัสหลักเดียวกันเป็นกลุ่มย่อยแบบอะตอมมิกAssetGroupOperation(create) ตามด้วยการดำเนินการที่ต่อเนื่องกันAssetGroupAssetOperation(create) สำหรับรหัสเดียวกันAssetGroup(รวมการดำเนินการสูงสุด 1,000 รายการ ซึ่งจะล้มเหลวแบบอะตอมมิกด้วยBatchJobError.ASSET_GROUP_AND_ASSET_GROUP_ASSET_TRANSACTION_FAILUREแต่ละAssetGroupOperationupdateหรือremoveจะดำเนินการใน การดำเนินการย่อยแบบเดี่ยวแบบสแตนด์อโลน)- Performance Max
CampaignOperation(createเมื่อเปิดใช้หลักเกณฑ์การใช้แบรนด์ ซึ่งเป็นค่าเริ่มต้น เว้นแต่จะตั้งค่าbrand_guidelines_enabledเป็นfalseหรือตั้งค่าhotel_property_asset_set) ตามด้วย การดำเนินการCampaignAssetOperation(create) ที่ต่อเนื่องสำหรับCampaignรหัสเดียวกัน (สูงสุด 1,000 รายการทั้งหมด โดยจะล้มเหลวแบบอะตอมมิกกับBatchJobError.CAMPAIGN_AND_CAMPAIGN_ASSET_TRANSACTION_FAILURE) - การดำเนินการต่อเนื่อง
AssetGroupListingGroupFilterOperation(max 10,000, ล้มเหลวแบบอะตอมมิกกับBatchJobError.ASSET_GROUP_LISTING_GROUP_FILTER_TRANSACTION_FAILURE) หรือAdGroupCriterionOperation(listing_group,max 20,000, ล้มเหลว แบบอะตอมมิกกับCriterionError.LISTING_GROUP_ERROR_IN_ANOTHER_OPERATION) สำหรับรายการหลักเดียวกัน (AssetGroupหรือAdGroup)
ดึงข้อมูลแอตทริบิวต์ที่เปลี่ยนแปลงได้จากคำตอบ
หากตั้งค่า response_content_type ของคำขอเปลี่ยนแปลงข้อมูลในเซิร์ฟเวอร์เป็น
MUTABLE_RESOURCE การตอบกลับจะมี
resource_name และออบเจ็กต์ทรัพยากรที่ป้อนข้อมูลพร้อมฟิลด์ที่แก้ไขได้ (รวมถึงฟิลด์สำคัญที่ระบบสร้างขึ้นในทรัพยากรที่แสดงผล เช่น ExperimentArm.in_design_campaigns) สำหรับออบเจ็กต์ที่รองรับทุกรายการที่สร้างหรืออัปเดต (ไม่ใช่ลบ) โดยคำขอ สำหรับการดำเนินการ remove หรือสำหรับประเภททรัพยากรที่ไม่รองรับการส่งคืน MUTABLE_RESOURCE คำตอบจะส่งคืนเฉพาะ resource_name เสมอ ใช้ฟีเจอร์นี้เพื่อหลีกเลี่ยงการส่งคำขอ Search หรือ SearchStream เพิ่มเติมหลังจากเรียกใช้การเปลี่ยนแปลงแต่ละครั้ง
หากคุณไม่ได้ตั้งค่า response_content_type Google Ads API จะใช้ค่าเริ่มต้นเป็น
RESOURCE_NAME_ONLY และแสดงเฉพาะ resource_name ของแต่ละทรัพยากรที่เปลี่ยนแปลง
ตัวอย่างต่อไปนี้แสดงวิธีดึงข้อมูลทรัพยากรที่เปลี่ยนแปลงได้จากการเรียกใช้ mutate
Java
private String createExperimentArms( GoogleAdsClient googleAdsClient, long customerId, long campaignId, String experiment) { List<ExperimentArmOperation> operations = new ArrayList<>(); operations.add( ExperimentArmOperation.newBuilder() .setCreate( // The "control" arm references an already-existing campaign. ExperimentArm.newBuilder() .setControl(true) .addCampaigns(ResourceNames.campaign(customerId, campaignId)) .setExperiment(experiment) .setName("control arm") .setTrafficSplit(40) .build()) .build()); operations.add( ExperimentArmOperation.newBuilder() .setCreate( // In standard campaign experiments, creating the treatment arm automatically // generates a draft campaign that you can modify before starting the experiment. ExperimentArm.newBuilder() .setControl(false) .setExperiment(experiment) .setName("experiment arm") .setTrafficSplit(60) .build()) .build()); try (ExperimentArmServiceClient experimentArmServiceClient = googleAdsClient.getLatestVersion().createExperimentArmServiceClient()) { // Constructs the mutate request. MutateExperimentArmsRequest mutateRequest = MutateExperimentArmsRequest.newBuilder() .setCustomerId(Long.toString(customerId)) .addAllOperations(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. .setResponseContentType(ResponseContentType.MUTABLE_RESOURCE) .build(); // Sends the mutate request. MutateExperimentArmsResponse response = experimentArmServiceClient.mutateExperimentArms(mutateRequest); // 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. If you don't remember which arm is the // treatment arm, you can always filter the query in the next section with // `experiment_arm.control = false`. MutateExperimentArmResult controlArmResult = response.getResults(0); MutateExperimentArmResult treatmentArmResult = response.getResults(response.getResultsCount() - 1); System.out.printf( "Created control arm with resource name '%s'%n", controlArmResult.getResourceName()); System.out.printf( "Created treatment arm with resource name '%s'%n", treatmentArmResult.getResourceName()); return treatmentArmResult.getExperimentArm().getInDesignCampaigns(0); } }
C#
private static (MutateExperimentArmResult, MutateExperimentArmResult) CreateExperimentArms(GoogleAdsClient client, long customerId, long baseCampaignId, string experimentResourceName) { // Get the ExperimentArmService. ExperimentArmServiceClient experimentService = client.GetService( Services.V25.ExperimentArmService); // Create the control arm. The control arm references an already-existing campaign. ExperimentArmOperation controlArmOperation = new ExperimentArmOperation() { Create = new ExperimentArm() { Control = true, Campaigns = { ResourceNames.Campaign(customerId, baseCampaignId) }, Experiment = experimentResourceName, Name = "Control Arm", TrafficSplit = 40 } }; // Create the non-control arm. // In standard campaign experiments, creating the treatment arm automatically // generates a draft campaign that you can modify before starting the experiment. ExperimentArmOperation treatmentArmOperation = new ExperimentArmOperation() { Create = new ExperimentArm() { Control = false, Experiment = experimentResourceName, Name = "Experiment Arm", TrafficSplit = 60 } }; // 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. MutateExperimentArmsRequest request = new MutateExperimentArmsRequest { CustomerId = customerId.ToString(), Operations = { controlArmOperation, treatmentArmOperation }, ResponseContentType = ResponseContentType.MutableResource }; MutateExperimentArmsResponse response = experimentService.MutateExperimentArms( request ); // 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. MutateExperimentArmResult controlArm = response.Results.First(); MutateExperimentArmResult treatmentArm = response.Results.Last(); Console.WriteLine($"Created control arm with resource name " + $"'{controlArm.ResourceName}'."); Console.WriteLine($"Created treatment arm with resource name" + $" '{treatmentArm.ResourceName}'."); return (controlArm, treatmentArm); }
PHP
private static function createExperimentArms( GoogleAdsClient $googleAdsClient, int $customerId, int $campaignId, string $experimentResourceName ): string { $operations = []; $experimentArm1 = new ExperimentArm( [ // The "control" arm references an already-existing campaign. 'control' => true, 'campaigns' => [ResourceNames::forCampaign($customerId, $campaignId)], 'experiment' => $experimentResourceName, 'name' => 'control arm', 'traffic_split' => 40 ] ); $operations[] = new ExperimentArmOperation(['create' => $experimentArm1]); $experimentArm2 = new ExperimentArm( [ // 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' => $experimentResourceName, 'name' => 'experiment arm', 'traffic_split' => 60 ] ); $operations[] = new ExperimentArmOperation(['create' => $experimentArm2]); // Issues a request to create the experiment arms. $experimentArmServiceClient = $googleAdsClient->getExperimentArmServiceClient(); $response = $experimentArmServiceClient->mutateExperimentArms( MutateExperimentArmsRequest::build($customerId, $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. ->setResponseContentType(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. $controlArmResourceName = $response->getResults()[0]->getResourceName(); $treatmentArm = $response->getResults()[count($operations) - 1]; print "Created control arm with resource name '$controlArmResourceName'" . PHP_EOL; print "Created treatment arm with resource name '{$treatmentArm->getResourceName()}'" . PHP_EOL; return $treatmentArm->getExperimentArm()->getInDesignCampaigns()[0]; }
Python
def create_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 of the 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.create exa_1.control = True exa_1.campaigns.append( campaign_service.campaign_path(customer_id, base_campaign_id) ) exa_1.experiment = experiment exa_1.name = "control arm" exa_1.traffic_split = 40 operations.append(operation_1) # In standard campaign experiments, creating the treatment arm automatically # generates a draft campaign that you can modify before starting the experiment. operation_2: ExperimentArmOperation = client.get_type( "ExperimentArmOperation" ) exa_2: ExperimentArm = operation_2.create exa_2.control = False exa_2.experiment = experiment exa_2.name = "experiment arm" exa_2.traffic_split = 60 operations.append(operation_2) experiment_arm_service: ExperimentArmServiceClient = client.get_service( "ExperimentArmService" ) request: MutateExperimentArmsRequest = client.get_type( "MutateExperimentArmsRequest" ) request.customer_id = customer_id request.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}" ) return treatment_arm_result.experiment_arm.in_design_campaigns[0]
Ruby
def create_experiment_arms(client, customer_id, base_campaign_id, experiment) operations = [] operations << client.operation.create_resource.experiment_arm do |ea| # The "control" arm references an already-existing campaign. ea.control = true ea.campaigns << client.path.campaign(customer_id, base_campaign_id) ea.experiment = experiment ea.name = 'control arm' ea.traffic_split = 40 end operations << client.operation.create_resource.experiment_arm do |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 = false ea.experiment = experiment ea.name = 'experiment arm' ea.traffic_split = 60 end response = 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.first treatment_arm_result = response.results.last puts "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.first end
Perl
sub create_experiment_arms { my ($api_client, $customer_id, $base_campaign_id, $experiment) = @_; my $operations = []; push @$operations, Google::Ads::GoogleAds::V25::Services::ExperimentArmService::ExperimentArmOperation ->new({ create => Google::Ads::GoogleAds::V25::Resources::ExperimentArm->new({ # The "control" arm references an already-existing campaign. control => "true", campaigns => [ Google::Ads::GoogleAds::V25::Utils::ResourceNames::campaign( $customer_id, $base_campaign_id ) ], experiment => $experiment, name => "control arm", trafficSplit => 40 })}); push @$operations, Google::Ads::GoogleAds::V25::Services::ExperimentArmService::ExperimentArmOperation ->new({ create => Google::Ads::GoogleAds::V25::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]; }