Eksperimen yang dikelola sistem digunakan untuk melakukan pengujian A/B terhadap perubahan dengan membuat satu atau beberapa kampanye perlakuan yang dapat diubah dan berjalan bersama kampanye kontrol asli.
Alur kerja ini didukung untuk nilai
ExperimentType berikut:
SEARCH_CUSTOM: Eksperimen kustom yang terdiri dari kampanye penelusuran.DISPLAY_CUSTOM: Eksperimen kustom yang terdiri dari kampanye Display.HOTEL_CUSTOM: Eksperimen kustom yang terdiri dari kampanye Hotel.YOUTUBE_CUSTOM: Eksperimen kustom yang terdiri dari kampanye Video.PMAX_REPLACEMENT_SHOPPING: Eksperimen untuk menguji performa kampanye Shopping dibandingkan dengan Performa Maksimal.
Penyiapan
Penyiapan untuk eksperimen yang dikelola sistem mengikuti langkah-langkah berikut:
- Buat
Experiment. - Buat resource
ExperimentArmuntuk kontrol dan perlakuan. - Ubah
in_design_campaignsdi grup perlakuan.
1. Membuat eksperimen
Langkah pertama dalam menjalankan eksperimen menggunakan Google Ads API adalah membuat
Experiment. Resource ini menentukan beberapa informasi penting tentang eksperimen yang ingin Anda jalankan. Anda tidak menentukan kampanye yang terlibat dalam eksperimen pada langkah ini.
Berikut ringkasan beberapa kolom utama untuk Experiment:
name: Setiap eksperimen harus memiliki nama yang unik.description: Kolom opsional yang dapat Anda gunakan sebagai referensi nanti. Tidak memengaruhi cara eksperimen berjalan.suffix: Akhiran akan ditambahkan ke akhir nama kampanye perlakuan sehingga Anda dapat membedakannya dari kampanye kontrol. Konsep ini akan dijelaskan lebih lanjut di langkah 2.type: Jenis eksperimen yang akan dijalankan. Untuk eksperimen yang dikelola sistem, gunakanSEARCH_CUSTOM,DISPLAY_CUSTOM,HOTEL_CUSTOM,YOUTUBE_CUSTOM, atauPMAX_REPLACEMENT_SHOPPING.status: Saat membuat eksperimen, tetapkan kolom ini keSETUP. Nanti, setelah Anda memulai eksperimen, kolom ini akan memungkinkan Anda memeriksa status saat ini.start_datedanend_date: Tentukan kapan eksperimen harus dimulai dan berakhir.sync_enabled: Dinonaktifkan secara default. Jika ditetapkan ketrue, perubahan yang dilakukan pada kampanye asli saat eksperimen Anda berjalan akan otomatis disalin ke kampanye eksperimen. Pelajari lebih lanjut.
Java
private String createExperimentResource(GoogleAdsClient googleAdsClient, long customerId) { ExperimentOperation operation = ExperimentOperation.newBuilder() .setCreate( Experiment.newBuilder() // Name must be unique. .setName("Example Experiment #" + getPrintableDateTime()) .setType(ExperimentType.SEARCH_CUSTOM) .setSuffix("[experiment]") .setStatus(ExperimentStatus.SETUP) .build()) .build(); try (ExperimentServiceClient experimentServiceClient = googleAdsClient.getLatestVersion().createExperimentServiceClient()) { MutateExperimentsResponse response = experimentServiceClient.mutateExperiments( Long.toString(customerId), ImmutableList.of(operation)); String experiment = response.getResults(0).getResourceName(); System.out.printf("Created experiment with resource name '%s'%n", experiment); return experiment; } }
C#
/// <summary> /// Creates the experiment. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The customer ID for which the call is made.</param> /// <returns>The resource name of the newly created experiment.</returns> private static string CreateAnExperiment(GoogleAdsClient client, long customerId) { // Get the ExperimentService. ExperimentServiceClient experimentService = client.GetService( Services.V24.ExperimentService); // Creates the experiment. Experiment experiment = new Experiment() { // Name must be unique. Name = $"Example Experiment #{ExampleUtilities.GetRandomString()}", Type = ExperimentType.SearchCustom, Suffix = "[experiment]", Status = ExperimentStatus.Setup }; // Creates the operation. ExperimentOperation operation = new ExperimentOperation() { Create = experiment }; // Makes the API call. MutateExperimentsResponse response = experimentService.MutateExperiments( customerId.ToString(), new[] { operation }); // Displays the result. string experimentResourceName = response.Results.First().ResourceName; Console.WriteLine($"Created experiment with resource name " + $"'{experimentResourceName}'."); return experimentResourceName; }
PHP
private static function createExperimentResource( ExperimentServiceClient $experimentServiceClient, int $customerId ): string { // Creates an experiment and its operation. $experiment = new Experiment([ // Name must be unique. 'name' => 'Example Experiment #' . Helper::getPrintableDatetime(), 'type' => ExperimentType::SEARCH_CUSTOM, 'suffix' => '[experiment]', 'status' => ExperimentStatus::SETUP ]); $experimentOperation = new ExperimentOperation(['create' => $experiment]); // Issues a request to create the experiment. $response = $experimentServiceClient->mutateExperiments( MutateExperimentsRequest::build($customerId, [$experimentOperation]) ); $experimentResourceName = $response->getResults()[0]->getResourceName(); print "Created experiment with resource name '$experimentResourceName'" . PHP_EOL; return $experimentResourceName; }
Python
def create_experiment_resource( client: GoogleAdsClient, customer_id: str ) -> str: """Creates a new experiment resource. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. Returns: the resource name for the new experiment. """ experiment_operation: ExperimentOperation = client.get_type( "ExperimentOperation" ) experiment: Experiment = experiment_operation.create experiment.name = f"Example Experiment #{uuid.uuid4()}" # We specify SEARCH_CUSTOM to create a standard search campaign experiment. # This type uses a standard draft-based workflow where the system automatically # creates a draft/in-design campaign for the treatment arm. experiment.type_ = client.enums.ExperimentTypeEnum.SEARCH_CUSTOM experiment.suffix = "[experiment]" experiment.status = client.enums.ExperimentStatusEnum.SETUP experiment_service: ExperimentServiceClient = client.get_service( "ExperimentService" ) response: MutateExperimentsResponse = experiment_service.mutate_experiments( customer_id=customer_id, operations=[experiment_operation] ) experiment_resource_name: str = response.results[0].resource_name print(f"Created experiment with resource name {experiment_resource_name}") return experiment_resource_name
Ruby
def create_experiment_resource(client, customer_id) operation = client.operation.create_resource.experiment do |e| # Name must be unique. e.name = "Example Experiment #{(Time.new.to_f * 1000).to_i}" e.type = :SEARCH_CUSTOM e.suffix = '[experiment]' e.status = :SETUP end response = client.service.experiment.mutate_experiments( customer_id: customer_id, operations: [operation], ) experiment = response.results.first.resource_name puts "Created experiment with resource name #{experiment}." experiment end
Perl
sub create_experiment_resource { my ($api_client, $customer_id) = @_; my $experiment = Google::Ads::GoogleAds::V24::Resources::Experiment->new({ # Name must be unique. name => "Example Experiment #" . uniqid(), type => SEARCH_CUSTOM, suffix => "[experiment]", status => SETUP }); my $operation = Google::Ads::GoogleAds::V24::Services::ExperimentService::ExperimentOperation ->new({ create => $experiment }); my $response = $api_client->ExperimentService()->mutate({ customerId => $customer_id, operations => [$operation]}); my $resource_name = $response->{results}[0]{resourceName}; printf "Created experiment with resource name '%s'.\n", $resource_name; return $resource_name; }
curl
2. Membuat grup eksperimen
Selanjutnya, buat ExperimentArm resource untuk menentukan
grup kontrol dan perlakuan untuk eksperimen. Semua grup harus dibuat dalam satu permintaan.
Setiap eksperimen harus memiliki tepat satu grup kontrol dan satu atau beberapa grup perlakuan. Grup kontrol mengidentifikasi kampanye dasar untuk perbandingan, dan setiap grup perlakuan menghasilkan kampanye baru tempat Anda dapat melakukan perubahan untuk diuji.
Anda juga harus menentukan traffic_split, yaitu persentase traffic yang diarahkan ke setiap grup. Jumlah pemisahan traffic di semua grup harus 100.
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( // The non-"control" arm, also called a "treatment" arm, will automatically // generate draft campaigns 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#
/// <summary> /// Creates the experiment arms. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The customer ID for which the call is made.</param> /// <param name="baseCampaignId">ID of the campaign for which the control arm is /// created.</param> /// <param name="experimentResourceName">Resource name of the experiment.</param> /// <returns>The control and treatment arms.</returns> private static (MutateExperimentArmResult, MutateExperimentArmResult) CreateExperimentArms(GoogleAdsClient client, long customerId, long baseCampaignId, string experimentResourceName) { // Get the ExperimentArmService. ExperimentArmServiceClient experimentService = client.GetService( Services.V24.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. The non-"control" arm, also called a "treatment" arm, // will automatically generate draft campaigns 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::V24::Services::ExperimentArmService::ExperimentArmOperation ->new({ create => Google::Ads::GoogleAds::V24::Resources::ExperimentArm->new({ # The "control" arm references an already-existing campaign. control => "true", campaigns => [ Google::Ads::GoogleAds::V24::Utils::ResourceNames::campaign( $customer_id, $base_campaign_id ) ], experiment => $experiment, name => "control arm", trafficSplit => 40 })}); push @$operations, Google::Ads::GoogleAds::V24::Services::ExperimentArmService::ExperimentArmOperation ->new({ create => Google::Ads::GoogleAds::V24::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]; }
curl
Beberapa poin penting:
- Tepat satu grup harus memiliki
controlyang ditetapkan ketrue. traffic_splitharus berjumlah 100 di semua grup.- Grup kontrol harus menentukan tepat satu kampanye di kolom
campaigns.
3. Mengubah kampanye perlakuan
Saat Anda membuat grup perlakuan (dengan control adalah false), API akan otomatis membuat kampanye draf berdasarkan kampanye kontrol dan mengisi nama resourcenya di kolom in_design_campaigns grup perlakuan. Anda dapat memperlakukan kampanye dalam desain ini sebagai kampanye reguler dan mengubahnya dengan perubahan yang ingin Anda uji. Kampanye kontrol tidak akan terpengaruh.
Perubahan ini akan terwujud menjadi kampanye nyata yang dapat ditayangkan saat Anda menjadwalkan eksperimen.
Setidaknya satu perubahan harus dilakukan pada kampanye dalam desain sebelum Anda dapat menjadwalkan eksperimen.
Untuk mengambil in_design_campaigns untuk grup perlakuan, Anda dapat membuat kueri GoogleAdsService:
SELECT experiment_arm.in_design_campaigns
FROM experiment_arm
WHERE experiment_arm.resource_name = "TREATMENT_ARM_RESOURCE_NAME"
Menjadwalkan eksperimen
Setelah membuat eksperimen dan grup serta mengubah kampanye draf perlakuan, Anda dapat menjadwalkan eksperimen menggunakan
ExperimentService.ScheduleExperiment.
Ini adalah operasi asinkron yang mewujudkan kampanye dalam desain menjadi kampanye sebenarnya, yang siap ditayangkan setelah start_date eksperimen tiba. Lihat
Error asinkron untuk mengetahui detail tentang penanganan operasi yang berjalan lama.
Membuat laporan tentang eksperimen
Setelah eksperimen berjalan, Anda dapat membuat kueri untuk metrik guna membandingkan performa. Lihat panduan Pelaporan untuk mengetahui detailnya.
Menyelesaikan, mempromosikan, atau mengakhiri eksperimen
Setelah membiarkan eksperimen berjalan selama waktu yang cukup, Anda dapat memilih untuk mengakhiri,
mempromosikan, atau menyelesaikannya menggunakan
ExperimentService.
- Akhiri: Jika Anda ingin menghentikan eksperimen tanpa menerapkan perubahan, gunakan
EndExperiment. Kampanye perlakuan berhenti ditayangkan, tetapi tidak dihapus. Ini adalah operasi sinkron. - Promosikan: Jika Anda puas dengan performa grup perlakuan dan
ingin menggabungkan perubahan ke kampanye asli, gunakan
PromoteExperiment. Tindakan ini akan menyalin perubahan dari grup perlakuan ke kampanye kontrol dan menghentikan penayangan grup perlakuan. Ini adalah operasi asinkron; lihat Error asinkron untuk mengetahui detailnya. Catatan: Eksperimen berjenisPMAX_REPLACEMENT_SHOPPINGtidak dapat dipromosikan. - Selesaikan: Jika Anda menyukai perubahan tersebut, tetapi ingin perubahan tersebut ada secara terpisah
dari kampanye asli, gunakan
GraduateExperiment. Tindakan ini akan mengonversi kampanye perlakuan menjadi kampanye standar dan independen yang terus ditayangkan di luar konteks eksperimen. Kampanye kontrol tidak diubah. Ini adalah operasi sinkron.
Persyaratan khusus jenis
PMAX_REPLACEMENT_SHOPPING:
- Memerlukan tepat dua grup (satu kontrol, satu perlakuan).
- Grup kontrol harus menentukan satu kampanye Shopping di kolom
campaigns. - Untuk grup perlakuan, Anda memiliki dua opsi untuk menyiapkan kampanye Performa Maksimal:
- Untuk membuat kampanye PMax baru: Biarkan kolom
campaignsgrup perlakuan kosong. API akan otomatis membuat kampanye dalam desain berdasarkan kampanye Shopping kontrol, seperti yang dijelaskan di Langkah 3. - Untuk menggunakan kampanye PMax yang ada: Tentukan nama resource kampanye PMax di kolom
campaignsgrup perlakuan. Jika Anda memilih opsi ini, tidak ada kampanye dalam desain yang dibuat, dan Anda dapat melewati Langkah 3.
- Untuk membuat kampanye PMax baru: Biarkan kolom
- Sebaiknya abaikan statistik 7 hari pertama dari evaluasi Anda untuk memberi kampanye waktu menyelesaikan fase peningkatan dan pembelajaran.
- Tidak dapat dipromosikan.
YOUTUBE_CUSTOM:
- Mendukung maksimal 10 grup.
- Untuk menguji aset, tetapkan
creative_asset_testing_infodi grup eksperimen.