검색 캠페인을 사용하면 Google 검색 결과 페이지와 Google 파트너 사이트에 텍스트 광고를 게재할 수 있습니다. Google Ads API를 사용하면 이러한 캠페인을 프로그래매틱 방식으로 만들고, 관리하고, 최적화할 수 있습니다.
검색 캠페인은 비즈니스와 관련된 특정 키워드를 적극적으로 검색하는 사용자에게 도달하려는 경우에 적합합니다.
이 가이드에서는 첫 번째 검색 캠페인을 만드는 데 필요한 모든 단계를 안내합니다.
기본 요건
검색 캠페인을 만들기 전에 다음 사항을 확인하세요.
- 유효한 프로덕션 Google Ads 계정
- 승인된 결제 설정
- Google Ads API 액세스
필요한 리소스
검색 캠페인을 만들 때 GoogleAdsService.Mutate를 사용하는 일괄 mutate 요청을 사용하면 필요한 여러 리소스를 원자적으로 만들 수 있습니다. 즉, 요청 한 번으로 유효한 게재 캠페인을 설정할 수 있습니다. 단일 일괄 요청으로 모든 리소스를 만들 필요는 없지만 검색 캠페인이 유효하고 활성 상태가 되려면 다음 리소스가 필요합니다.
리소스 계층 구조
객체 계층 구조 차트는 검색 캠페인의 조직 구조를 보여줍니다.
검색 캠페인 만들기
Google Ads API를 사용하여 검색 캠페인을 만들려면 다음 단계를 따르세요.
캠페인 예산을 만듭니다.
- 기존
CampaignBudget를 만들거나 사용합니다. 평균 일일 예산 또는 캠페인 총 예산을 사용할 수 있습니다. 캠페인 총 예산은 시작일과 종료일이 설정된 캠페인 (start_date_time및end_date_time를 사용하여 구성됨)에만 사용할 수 있습니다. 자세한 내용은 캠페인 예산 만들기를 참고하세요. 이 리소스는 캠페인 간에 공유할 수 있습니다.
- 기존
검색 캠페인을 만듭니다.
AdvertisingChannelType을SEARCH으로 설정합니다.- 입찰 전략 (예:
ManualCpc또는TargetCpa)을 설정합니다. - 이전 단계에서 만든
CampaignBudget를 연결합니다. contains_eu_political_advertising(예:DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING)를 설정합니다.
광고 그룹 만들기:
AdGroup를 만듭니다.AdGroup은 광고와 키워드의 컨테이너입니다.
키워드 추가 (광고 그룹 기준):
AdGroupCriterion리소스를 만들어 타겟팅 키워드를 정의합니다.
반응형 검색 광고 만들기:
ResponsiveSearchAdInfo를 만듭니다.ResponsiveSearchAdInfo객체는Ad객체에 포함되며, 이 객체는AdGroupAd리소스에 포함됩니다. 반응형 검색 광고에 대한 자세한 내용은 반응형 검색 광고에 대한 정보를 참고하세요.
원자적 GoogleAdsService.Mutate 작업 순서
단일 GoogleAdsService.Mutate 요청에서 검색 캠페인을 만드는 경우:
POST https://googleads.googleapis.com/v26/customers/{customer_id}/googleAds:mutate
최상위 MutateGoogleAdsRequest 필드를 구성합니다.
customer_id: 하이픈이 없는 10자리 고객 ID입니다(필수).partial_failure: 선택사항bool(원자 생성의 경우 기본값은false).validate_only: 변형을 실행하지 않고 요청을 검증하는 선택적bool입니다.response_content_type: 선택사항ResponseContentType(RESOURCE_NAME_ONLY또는MUTABLE_RESOURCE)입니다.
모든 상위 리소스가 음수 임시 ID를 참조하는 하위 작업 전에 정의되도록 mutate_operations[] (MutateOperation) 항목을 정렬합니다.
| 단계 | MutateOperation 필드 |
임시 ID 또는 상위 참조 | 필수 및 일반 필드 |
|---|---|---|---|
| 1 | campaign_budget_operation.create |
임시 ID: customers/{customer_id}/campaignBudgets/-1 |
name, amount_micros (또는 total_amount_micros), delivery_method (STANDARD), explicitly_shared (true 또는 false, total_amount_micros를 사용할 때는 false여야 하며, 2단계에서 캠페인에 start_date_time 및 end_date_time도 필요함) |
| 2 | campaign_operation.create |
임시 ID: customers/{customer_id}/campaigns/-2상위: campaign_budget ("customers/{customer_id}/campaignBudgets/-1") |
핵심: name, status (PAUSED 또는 ENABLED), advertising_channel_type (SEARCH)규정 준수: contains_eu_political_advertising (DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING 또는 CONTAINS_EU_POLITICAL_ADVERTISING)네트워크 및 입찰: network_settings (target_google_search, target_search_network, target_content_network, target_partner_search_network — Google 파트너 계정에서만 선택 가능, 표준 계정의 경우 false로 설정하거나 생략) 및 입찰 전략 (예: manual_cpc, maximize_conversions, target_cpa) |
| 3 (선택사항) | campaign_criterion_operation.create |
상위: campaign ("customers/{customer_id}/campaigns/-2") |
캠페인 수준 CampaignCriterion 타겟팅 (예: location 또는 language, negative = true 키워드 제외) |
| 4 | ad_group_operation.create |
임시 ID: customers/{customer_id}/adGroups/-3상위: campaign ("customers/{customer_id}/campaigns/-2") |
name, type (SEARCH_STANDARD), status (ENABLED 또는 PAUSED), 선택사항인 cpc_bid_micros (수동 CPC를 사용하는 경우) |
| 5 | ad_group_criterion_operation.create |
상위: ad_group ("customers/{customer_id}/adGroups/-3") |
status (ENABLED 또는 PAUSED) 및 keyword (text 및 match_type가 있는 KeywordInfo: EXACT, PHRASE 또는 BROAD). adGroups/-3가 정의되면 ad_group_ad_operation 앞이나 뒤에 표시될 수 있습니다. |
| 6 | ad_group_ad_operation.create |
상위: ad_group ("customers/{customer_id}/adGroups/-3") |
상태 및 URL: status(PAUSED 또는 ENABLED) 및 ad.final_urls[](URL 1개 이상).RSA: ad.responsive_search_ad(ResponsiveSearchAdInfo, headlines 3~15개, descriptions 2~4개(AdTextAsset 객체), 선택사항인 path1 및 path2). |
검색 캠페인을 만드는 코드 예시
다음 코드 예는 전체 검색 캠페인을 만드는 방법을 보여줍니다. 다음 방법을 다룹니다.
Campaign및CampaignBudget만들기- 입찰 전략을 설정합니다.
AdGroup,AdGroupAd(ResponsiveSearchAdInfo포함),AdGroupCriterion리소스로 캠페인을 채웁니다.- 원하는 경우
CampaignCriterion객체를 사용하여 잠재고객을 지역 타겟팅합니다.
자바
// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.ads.googleads.examples.advancedoperations; import static com.google.ads.googleads.examples.utils.CodeSampleHelper.getPrintableDateTime; import com.beust.jcommander.Parameter; import com.google.ads.googleads.examples.utils.ArgumentNames; import com.google.ads.googleads.examples.utils.CodeSampleParams; import com.google.ads.googleads.lib.GoogleAdsClient; import com.google.ads.googleads.v26.common.LocationInfo; import com.google.ads.googleads.v26.resources.CampaignCriterion; import com.google.ads.googleads.v26.services.CampaignCriterionOperation; import com.google.ads.googleads.v26.services.CampaignCriterionServiceClient; import com.google.ads.googleads.v26.services.GeoTargetConstantServiceClient; import com.google.ads.googleads.v26.services.GeoTargetConstantSuggestion; import com.google.ads.googleads.v26.services.MutateAdGroupCriteriaResponse; import com.google.ads.googleads.v26.common.KeywordInfo; import com.google.ads.googleads.v26.enums.AdGroupCriterionStatusEnum.AdGroupCriterionStatus; import com.google.ads.googleads.v26.enums.KeywordMatchTypeEnum.KeywordMatchType; import com.google.ads.googleads.v26.resources.AdGroupCriterion; import com.google.ads.googleads.v26.services.AdGroupCriterionOperation; import com.google.ads.googleads.v26.services.AdGroupCriterionServiceClient; import com.google.ads.googleads.v26.services.AdGroupOperation; import com.google.ads.googleads.v26.services.AdGroupServiceClient; import com.google.ads.googleads.v26.common.TargetSpend; import com.google.ads.googleads.v26.enums.AdGroupAdStatusEnum.AdGroupAdStatus; import com.google.ads.googleads.v26.enums.AdGroupStatusEnum.AdGroupStatus; import com.google.ads.googleads.v26.enums.AdGroupTypeEnum.AdGroupType; import com.google.ads.googleads.v26.enums.AdvertisingChannelTypeEnum.AdvertisingChannelType; import com.google.ads.googleads.v26.enums.BudgetDeliveryMethodEnum.BudgetDeliveryMethod; import com.google.ads.googleads.v26.enums.CampaignStatusEnum.CampaignStatus; import com.google.ads.googleads.v26.enums.ServedAssetFieldTypeEnum.ServedAssetFieldType; import com.google.ads.googleads.v26.resources.AdGroup; import com.google.ads.googleads.v26.resources.Campaign; import com.google.ads.googleads.v26.resources.Campaign.NetworkSettings; import com.google.ads.googleads.v26.resources.CampaignBudget; import com.google.ads.googleads.v26.services.AdGroupAdOperation; import com.google.ads.googleads.v26.services.AdGroupAdServiceClient; import com.google.ads.googleads.v26.services.CampaignBudgetOperation; import com.google.ads.googleads.v26.services.CampaignBudgetServiceClient; import com.google.ads.googleads.v26.services.CampaignOperation; import com.google.ads.googleads.v26.services.CampaignServiceClient; import com.google.ads.googleads.v26.services.MutateAdGroupAdsResponse; import com.google.ads.googleads.v26.services.MutateAdGroupCriterionResult; import com.google.ads.googleads.v26.services.MutateAdGroupsResponse; import com.google.ads.googleads.v26.services.MutateCampaignBudgetsResponse; import com.google.ads.googleads.v26.services.MutateCampaignCriteriaResponse; import com.google.ads.googleads.v26.services.MutateCampaignCriterionResult; import com.google.ads.googleads.v26.services.MutateCampaignsResponse; import com.google.ads.googleads.v26.services.SuggestGeoTargetConstantsRequest; import com.google.ads.googleads.v26.services.SuggestGeoTargetConstantsRequest.LocationNames; import com.google.ads.googleads.v26.services.SuggestGeoTargetConstantsResponse; import com.google.ads.googleads.v26.common.AdTextAsset; import com.google.ads.googleads.v26.common.CustomizerValue; import com.google.ads.googleads.v26.common.ResponsiveSearchAdInfo; import com.google.ads.googleads.v26.enums.CustomizerAttributeTypeEnum.CustomizerAttributeType; import com.google.ads.googleads.v26.errors.GoogleAdsError; import com.google.ads.googleads.v26.errors.GoogleAdsException; import com.google.ads.googleads.v26.resources.Ad; import com.google.ads.googleads.v26.resources.AdGroupAd; import com.google.ads.googleads.v26.resources.CustomerCustomizer; import com.google.ads.googleads.v26.resources.CustomizerAttribute; import com.google.ads.googleads.v26.services.CustomerCustomizerOperation; import com.google.ads.googleads.v26.services.CustomerCustomizerServiceClient; import com.google.ads.googleads.v26.services.CustomizerAttributeOperation; import com.google.ads.googleads.v26.services.CustomizerAttributeServiceClient; import com.google.ads.googleads.v26.services.MutateCustomerCustomizersResponse; import com.google.ads.googleads.v26.services.MutateCustomizerAttributesResponse; import com.google.common.collect.ImmutableList; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import javax.annotation.Nullable; /** * This example shows how to create a complete Responsive Search Ad. * * <p>Includes creation of: budget, campaign, ad group, ad group ad, keywords, and geo targeting. * * <p>More details on Responsive Search Ads can be found here: * https://support.google.com/google-ads/answer/7684791 */ public class AddResponsiveSearchAdFull { private static class AddResponsiveSearchAdFullParams extends CodeSampleParams { @Parameter(names = ArgumentNames.CUSTOMER_ID, required = true) private Long customerId; // The name of the customizer attribute to be used in the ad customizer, which must be unique. // To run this example multiple times, change this value or specify its corresponding argument. // Note that there is a limit for the number of enabled customizer attributes in one account, // so you shouldn't run this example more than necessary. // Visit // https://developers.google.com/google-ads/api/docs/ads/customize-responsive-search-ads?hl=en#rules_and_limitations // for details. // // Specify the customizer attribute name here or the default specified below will be used. @Parameter(names = ArgumentNames.CUSTOMIZER_ATTRIBUTE_NAME) private String customizerAttributeName = "Price"; } public static void main(String[] args) { AddResponsiveSearchAdFullParams params = new AddResponsiveSearchAdFullParams(); if (!params.parseArguments(args)) { // Either pass the required parameters for this example on the command line, or insert them // into the code here. See the parameter class definition above for descriptions. params.customerId = Long.parseLong("INSERT_CUSTOMER_ID_HERE"); // Optional: To use a different customizer attribute name from the default ("Price"), // uncomment the line below and insert the desired customizer attribute name. // params.customizerAttributeName = "INSERT_CUSTOMIZER_ATTRIBUTE_NAME_HERE"; } GoogleAdsClient googleAdsClient = null; try { googleAdsClient = GoogleAdsClient.newBuilder().fromPropertiesFile().build(); } catch (FileNotFoundException fnfe) { System.err.printf( "Failed to load GoogleAdsClient configuration from file. Exception: %s%n", fnfe); System.exit(1); } catch (IOException ioe) { System.err.printf("Failed to create GoogleAdsClient. Exception: %s%n", ioe); System.exit(1); } try { new AddResponsiveSearchAdFull() .runExample(googleAdsClient, params.customerId, params.customizerAttributeName); } catch (GoogleAdsException gae) { // GoogleAdsException is the base class for most exceptions thrown by an API request. // Instances of this exception have a message and a GoogleAdsFailure that contains a // collection of GoogleAdsErrors that indicate the underlying causes of the // GoogleAdsException. System.err.printf( "Request ID %s failed due to GoogleAdsException. Underlying errors:%n", gae.getRequestId()); int i = 0; for (GoogleAdsError googleAdsError : gae.getGoogleAdsFailure().getErrorsList()) { System.err.printf(" Error %d: %s%n", i++, googleAdsError); } System.exit(1); } } /** * Runs the example. * * @param googleAdsClient the Google Ads API client. * @param customerId the client customer ID. * @param customizerAttributeName the customizer attribute name. */ private void runExample( GoogleAdsClient googleAdsClient, long customerId, String customizerAttributeName) { if (customizerAttributeName != null && !customizerAttributeName.isEmpty()) { String customizerAttributeResourceName = createCustomizerAttribute(googleAdsClient, customerId, customizerAttributeName); linkCustomizerAttributeToCustomer( googleAdsClient, customerId, customizerAttributeResourceName); } String campaignBudget = createCampaignBudget(googleAdsClient, customerId); String campaignResourceName = createCampaign(googleAdsClient, customerId, campaignBudget); String adGroupResourceName = createAdGroup(googleAdsClient, customerId, campaignResourceName); createAdGroupAd(googleAdsClient, customerId, adGroupResourceName, customizerAttributeName); addKeywords(googleAdsClient, customerId, adGroupResourceName); addGeoTargeting(googleAdsClient, customerId, campaignResourceName); } /** Creates a customizer attribute with the specified customizer attribute name. */ private static String createCustomizerAttribute( GoogleAdsClient googleAdsClient, long customerId, String customizerAttributeName) { // Creates a customizer attribute with the specified name. CustomizerAttribute customizerAttribute = CustomizerAttribute.newBuilder() .setName(customizerAttributeName) // Specifies the type to be 'PRICE' so that we can dynamically customize the part of the // ad's description that is a price of a product/service we advertise. .setType(CustomizerAttributeType.PRICE) .build(); // Creates a customizer attribute operation for creating a customizer attribute. CustomizerAttributeOperation operation = CustomizerAttributeOperation.newBuilder().setCreate(customizerAttribute).build(); try (CustomizerAttributeServiceClient customizerAttributeServiceClient = googleAdsClient.getLatestVersion().createCustomizerAttributeServiceClient()) { // Issues a mutate request to add the customizer attribute and prints its information. MutateCustomizerAttributesResponse response = customizerAttributeServiceClient.mutateCustomizerAttributes( Long.toString(customerId), ImmutableList.of(operation)); String resourceName = response.getResults(0).getResourceName(); System.out.printf("Added a customizer with resource name '%s'.%n", resourceName); return resourceName; } } /** * Links the customizer attribute to the customer by providing a value to be used in a responsive * search ad that will be created in a later step. */ private static void linkCustomizerAttributeToCustomer( GoogleAdsClient googleAdsClient, long customerId, String customizerAttributeResourceName) { // Creates a customer customizer with the value to be used in the responsive search ad. CustomerCustomizer customerCustomizer = CustomerCustomizer.newBuilder() .setCustomizerAttribute(customizerAttributeResourceName) // Specify '100USD' as a text value. The ad customizer will dynamically replace the // placeholder with this value when the ad serves. .setValue( CustomizerValue.newBuilder() .setType(CustomizerAttributeType.PRICE) .setStringValue("100USD") .build()) .build(); // Creates a customer customizer operation. CustomerCustomizerOperation operation = CustomerCustomizerOperation.newBuilder().setCreate(customerCustomizer).build(); try (CustomerCustomizerServiceClient customerCustomizerServiceClient = googleAdsClient.getLatestVersion().createCustomerCustomizerServiceClient()) { // Issues a mutate request to add the customer customizer and prints its information. MutateCustomerCustomizersResponse response = customerCustomizerServiceClient.mutateCustomerCustomizers( Long.toString(customerId), ImmutableList.of(operation)); System.out.printf( "Added a customer customizer with resource name '%s'.%n", response.getResults(0).getResourceName()); } } /** * Create an AdTextAsset. * * @param text: Text for headlines and descriptions. * @param pinnedField: To pin a text asset so it always shows in the ad. */ private static AdTextAsset createAdTextAsset( String text, @Nullable ServedAssetFieldType pinnedField) { AdTextAsset.Builder adTextAsset = AdTextAsset.newBuilder().setText(text); if (pinnedField != null) { adTextAsset.setPinnedField(pinnedField); } return adTextAsset.build(); } /** * Creates an AdTextAsset with a customizer. * * @param customizerAttributeResourceName: The resource name of the customizer attribute. */ private static AdTextAsset createAdTextAssetWithCustomizer( String customizerAttributeResourceName) { // Creates this particular description using the ad customizer. Visit // https://developers.google.com/google-ads/api/docs/ads/customize-responsive-search-ads#ad_customizers_in_responsive_search_ads // for details about the placeholder format. The ad customizer replaces the placeholder with // the value we previously created and linked to the customer using CustomerCustomizer. AdTextAsset.Builder adTextAsset = AdTextAsset.newBuilder() .setText(String.format("Just {CUSTOMIZER.%s:10USD}", customizerAttributeResourceName)); return adTextAsset.build(); } /** * Creates the campaign budget resource. * * @param googleAdsClient: An initialized GoogleAdsClient instance. * @param customerId: A client customer ID. */ private static String createCampaignBudget(GoogleAdsClient googleAdsClient, Long customerId) { // Creates the budget. CampaignBudget budget = CampaignBudget.newBuilder() .setName("Interplanetary Cruise Budget #" + getPrintableDateTime()) .setDeliveryMethod(BudgetDeliveryMethod.STANDARD) .setAmountMicros(500000) .build(); // Creates the operation. CampaignBudgetOperation operation = CampaignBudgetOperation.newBuilder().setCreate(budget).build(); // Gets the CampaignBudgetService. try (CampaignBudgetServiceClient campaignBudgetServiceClient = googleAdsClient.getLatestVersion().createCampaignBudgetServiceClient()) { // Adds the campaign budget. MutateCampaignBudgetsResponse response = campaignBudgetServiceClient.mutateCampaignBudgets( Long.toString(customerId), ImmutableList.of(operation)); // Displays the results. String resourceName = response.getResults(0).getResourceName(); System.out.printf("Added budget with resource name %s.", resourceName); return resourceName; } } /** * Creates a campaign resource. * * @param googleAdsClient: An initialized GoogleAdsClient instance. * @param customerId: A client customer ID. * @param campaignBudget: A budget resource name. */ private static String createCampaign( GoogleAdsClient googleAdsClient, Long customerId, String campaignBudget) { // Creates the campaign. Campaign.Builder campaignBuilder = Campaign.newBuilder(); campaignBuilder.setName("Testing RSA via API #" + getPrintableDateTime()); campaignBuilder.setAdvertisingChannelType(AdvertisingChannelType.SEARCH); // Recommendation: Set the campaign to PAUSED when creating it to prevent the ads from // immediately serving. Set to ENABLED once you've added targeting and the ads are ready to // serve. campaignBuilder.setStatus(CampaignStatus.PAUSED); // Sets the bidding strategy and budget. The bidding strategy for Maximize Clicks is TargetSpend. // The targetSpendMicros is deprecated so don't put any value. See other bidding strategies you // can select in the link below. // https://developers.google.com/google-ads/api/reference/rpc/latest/Campaign#campaign_bidding_strategy campaignBuilder.setTargetSpend(TargetSpend.newBuilder().setTargetSpendMicros(0).build()); campaignBuilder.setCampaignBudget(campaignBudget); // Sets the campaign network operations. campaignBuilder.setNetworkSettings( NetworkSettings.newBuilder() .setTargetGoogleSearch(true) .setTargetSearchNetwork(true) .setTargetPartnerSearchNetwork(false) // Enables Display Expansion on Search campaigns. For more details see: // https://support.google.com/google-ads/answer/7193800 .setTargetContentNetwork(true) .build()); // Optional: Sets the start date. // DateTime startTime = DateTime.now().plusDays(1); // campaignBuilder.setStartDate(startTime.toDate().toString()); // Optional: Sets the end date. // DateTime endTime = startTime.plusWeeks(4); // campaignBuilder.setEndDate(endTime.toDate().toString()); // Creates the operation. CampaignOperation operation = CampaignOperation.newBuilder().setCreate(campaignBuilder.build()).build(); // Gets the CampaignService. try (CampaignServiceClient campaignServiceClient = googleAdsClient.getLatestVersion().createCampaignServiceClient()) { // Adds the campaign. MutateCampaignsResponse response = campaignServiceClient.mutateCampaigns( Long.toString(customerId), ImmutableList.of(operation)); String resourceName = response.getResults(0).getResourceName(); // Displays the result. System.out.printf("Added campaign with resource name %s", resourceName); return resourceName; } } /** * Creates an ad group. * * @param googleAdsClient: An initialized GoogleAdsClient instance. * @param customerId: A client customer ID. * @param campaignResourceName: An campaign resource name. */ private static String createAdGroup( GoogleAdsClient googleAdsClient, Long customerId, String campaignResourceName) { // Creates the ad group. AdGroup adGroup = AdGroup.newBuilder() .setName("Testing RSA via API " + getPrintableDateTime()) .setStatus(AdGroupStatus.ENABLED) .setCampaign(campaignResourceName) .setType(AdGroupType.SEARCH_STANDARD) .build(); // If you want to set up a max CPC bid, uncomment the line below; // adGroup = adGroup.toBuilder().setCpcBidMicros(10000000).build(); // Creates the operation. AdGroupOperation operation = AdGroupOperation.newBuilder().setCreate(adGroup).build(); // Gets the AdGroupService. try (AdGroupServiceClient adGroupServiceClient = googleAdsClient.getLatestVersion().createAdGroupServiceClient()) { // Add the ad group. MutateAdGroupsResponse response = adGroupServiceClient.mutateAdGroups( Long.toString(customerId), ImmutableList.of(operation)); // Displays the result. String resourceName = response.getResults(0).getResourceName(); System.out.printf("Added ad group with resource name %s.", resourceName); return resourceName; } } /** * Creates an ad group ad. * * @param googleAdsClient: An initialized GoogleAdsClient instance. * @param customerId: A client customer ID. * @param adGroupResourceName: An ad group resource name. * @param customizerAttributeName: (optional) If present, indicates the resource name of the * custoimizer attribute to use in one of the descriptions. */ private static void createAdGroupAd( GoogleAdsClient googleAdsClient, Long customerId, String adGroupResourceName, String customizerAttributeName) { // Creates an ad group ad to hold the ad. AdGroupAd.Builder adGroupAdBuilder = AdGroupAd.newBuilder().setStatus(AdGroupAdStatus.ENABLED); adGroupAdBuilder.setAdGroup(adGroupResourceName); // Creates the ad and set responsive search ad info. // The list of possible final URLs after all cross-domain redirects for the ad. Ad.Builder adBuilder = Ad.newBuilder().addFinalUrls("https://www.example.com/"); // Sets a pinning to always choose this asset for HEADLINE_1. Pinning is optional; if no pinning // is set, then headlines and descriptions will be rotated and the ones that perform best will // be used more often. // Headline 1 AdTextAsset pinned_headline = createAdTextAsset("Headline 1 testing", ServedAssetFieldType.HEADLINE_1); // Headline 2 and 3 ResponsiveSearchAdInfo.Builder responsiveSearchAdBuilder = ResponsiveSearchAdInfo.newBuilder() .addAllHeadlines( ImmutableList.of( pinned_headline, createAdTextAsset("Headline 2 testing", null), createAdTextAsset("Headline 3 testing", null))); // Description 1. AdTextAsset description1 = createAdTextAsset("Desc 1 testing", null); // Creates this particular description using the ad customizer. AdTextAsset description2 = null; if (customizerAttributeName != null) { description2 = createAdTextAssetWithCustomizer(customizerAttributeName); } else { description2 = createAdTextAsset("Desc 2 testing", null); } responsiveSearchAdBuilder.addAllDescriptions(ImmutableList.of(description1, description2)); // Paths // First and second part of text that can be appended to the URL in the ad. // If you use the examples below, the ad will show https://www.example.com/all-inclusive/deals responsiveSearchAdBuilder.setPath1("all-inclusive"); responsiveSearchAdBuilder.setPath2("deals"); adBuilder.setResponsiveSearchAd(responsiveSearchAdBuilder); adGroupAdBuilder.setAd(adBuilder); // Creates an ad group ad operation. AdGroupAdOperation operation = AdGroupAdOperation.newBuilder().setCreate(adGroupAdBuilder).build(); // Gets the AdGroupAdService. try (AdGroupAdServiceClient adGroupAdServiceClient = googleAdsClient.getLatestVersion().createAdGroupAdServiceClient()) { // Sends a request to the server to add a responsive search ad MutateAdGroupAdsResponse response = adGroupAdServiceClient.mutateAdGroupAds( Long.toString(customerId), ImmutableList.of(operation)); // Displays the result. System.out.printf( "Created responsive search ad with resource name '%s'.%n", response.getResults(0).getResourceName()); } } /** * Creates keywords. * * <p>For smart bidding, BROAD is the recommended match type. * * @param googleAdsClient: An initialized GoogleAdsClient instance. * @param customerId: A client customer ID. * @param adGroupResourceName: An ad group resource name. */ private static void addKeywords( GoogleAdsClient googleAdsClient, Long customerId, String adGroupResourceName) { // Creates keyword. AdGroupCriterion.Builder keyword = AdGroupCriterion.newBuilder() .setAdGroup(adGroupResourceName) .setStatus(AdGroupCriterionStatus.ENABLED) .setKeyword( KeywordInfo.newBuilder() .setText("example of broad match") .setMatchType(KeywordMatchType.BROAD)); // Uncomment the below line if you want to change this keyword to a negative target. // keyword.setNegative(true); // Optional repeated field // keyword.setFinalUrls("https://www.example.com"); AdGroupCriterionOperation operation = AdGroupCriterionOperation.newBuilder().setCreate(keyword).build(); // Gets the AdGroupCriterionService. try (AdGroupCriterionServiceClient adGroupCriterionServiceClient = googleAdsClient.getLatestVersion().createAdGroupCriterionServiceClient()) { // Adds the keyword. MutateAdGroupCriteriaResponse response = adGroupCriterionServiceClient.mutateAdGroupCriteria( Long.toString(customerId), ImmutableList.of(operation)); // Displays the results. for (MutateAdGroupCriterionResult result : response.getResultsList()) { System.out.printf("Created keyword '%s'.%n", result.getResourceName()); } } } /** * Creates geo targets. * * @param googleAdsClient: An initialized GoogleAdsClient instance. * @param customerId: A client customer ID. * @param campaignResourceName: A campaign resource name. */ private static void addGeoTargeting( GoogleAdsClient googleAdsClient, Long customerId, String campaignResourceName) { // Searches by location names from GeoTargetConstantService.suggestGeoTargetConstants() and // directly apply GeoTargetConstant.resourceName. SuggestGeoTargetConstantsRequest.Builder gtcRequestBuilder = SuggestGeoTargetConstantsRequest.newBuilder().setLocale("es").setCountryCode("AR"); // The location names to get suggested geo target constants. gtcRequestBuilder.setLocationNames( LocationNames.newBuilder() .addAllNames(ImmutableList.of("Buenos Aires", "San Isidro", "Mar del Plata")) .build()); try (GeoTargetConstantServiceClient geoTargetConstantServiceClient = googleAdsClient.getLatestVersion().createGeoTargetConstantServiceClient()) { SuggestGeoTargetConstantsResponse results = geoTargetConstantServiceClient.suggestGeoTargetConstants(gtcRequestBuilder.build()); ArrayList<CampaignCriterionOperation> operations = new ArrayList<CampaignCriterionOperation>(); for (GeoTargetConstantSuggestion suggestion : results.getGeoTargetConstantSuggestionsList()) { System.out.printf( "geoTargetConstant: %s is found in LOCALE %s with reach %s from search term %s.", suggestion.getGeoTargetConstant().getResourceName(), suggestion.getLocale(), suggestion.getReach(), suggestion.getSearchTerm()); // Creates the campaign criterion for loaction targeting. CampaignCriterion campaignCriterion = CampaignCriterion.newBuilder() .setCampaign(campaignResourceName) .setLocation( LocationInfo.newBuilder() .setGeoTargetConstant(suggestion.getGeoTargetConstant().getResourceName()) .build()) .build(); CampaignCriterionOperation operation = CampaignCriterionOperation.newBuilder().setCreate(campaignCriterion).build(); operations.add(operation); } // Gets the CampaignCriterionService. try (CampaignCriterionServiceClient campaignCriterionServiceClient = googleAdsClient.getLatestVersion().createCampaignCriterionServiceClient()) { MutateCampaignCriteriaResponse response = campaignCriterionServiceClient.mutateCampaignCriteria( Long.toString(customerId), operations); // Displays the results. for (MutateCampaignCriterionResult result : response.getResultsList()) { System.out.printf("Added campaign criterion %s", result.getResourceName()); } } } } }
C#
// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using CommandLine; using Google.Ads.Gax.Examples; using Google.Ads.Gax.Util; using Google.Ads.GoogleAds.Lib; using Google.Ads.GoogleAds.V26.Common; using Google.Ads.GoogleAds.V26.Resources; using Google.Ads.GoogleAds.V26.Services; using System.Collections.Generic; using System.Linq; using System; using static Google.Ads.GoogleAds.V26.Enums.AdGroupTypeEnum.Types; using static Google.Ads.GoogleAds.V26.Enums.AdGroupAdStatusEnum.Types; using static Google.Ads.GoogleAds.V26.Enums.AdGroupCriterionStatusEnum.Types; using static Google.Ads.GoogleAds.V26.Enums.AdGroupStatusEnum.Types; using static Google.Ads.GoogleAds.V26.Enums.AdvertisingChannelTypeEnum.Types; using static Google.Ads.GoogleAds.V26.Enums.BudgetDeliveryMethodEnum.Types; using static Google.Ads.GoogleAds.V26.Enums.CampaignStatusEnum.Types; using static Google.Ads.GoogleAds.V26.Enums.CustomizerAttributeTypeEnum.Types; using static Google.Ads.GoogleAds.V26.Enums.KeywordMatchTypeEnum.Types; using static Google.Ads.GoogleAds.V26.Services.SuggestGeoTargetConstantsRequest.Types; using Google.Ads.GoogleAds.Config; using Google.Ads.GoogleAds.Extensions.Config; namespace Google.Ads.GoogleAds.Examples.V26 { /// <summary> /// Adds a customizer attribute, links the customizer attribute to a customer, and then adds /// a responsive search ad with a description using the ad customizer to the specified ad group. /// </summary> public class AddResponsiveSearchAdFull : ExampleBase { /// <summary> /// </summary> public class Options : OptionsBase { /// <summary> /// The Google Ads customer ID. /// </summary> [Option("customerId", Required = true, HelpText = "The Google Ads customer ID.")] public long CustomerId { get; set; } /// <summary> /// The Google Ads customizer attribute name ID. /// </summary> [Option("customizerAttributeName", Required = false, HelpText = "The Google Ads customizer attribute name.", Default = CUSTOMIZER_ATTRIBUTE_NAME)] public string CustomizerAttributeName { get; set; } } /// <summary> /// Main method, to run this code example as a standalone application. /// </summary> /// <param name="args">The command line arguments.</param> public static void Main(string[] args) { Options options = ExampleUtilities.ParseCommandLine<Options>(args); AddResponsiveSearchAdFull codeExample = new AddResponsiveSearchAdFull(); Console.WriteLine(codeExample.Description); codeExample.Run( new GoogleAdsClient(), options.CustomerId, options.CustomizerAttributeName ); } // The name of the customizer attribute to be used in the ad customizer must be unique for a // given client account. To run this example multiple times, change this value or specify // its corresponding argument. Note that there is a limit for the number of enabled // customizer attributes in one account, so you shouldn't run this example more than // necessary. // // Visit the following link for more details: // https://developers.google.com/google-ads/api/docs/ads/customize-responsive-search-ads#rules_and_limitations private const string CUSTOMIZER_ATTRIBUTE_NAME = "Price"; /// <summary> /// Returns a description about the code example. /// </summary> public override string Description => "Adds a customizer attribute, links the customizer attribute to a customer, and then " + "adds a responsive search ad with a description using the ad customizer to the " + "specified ad group."; /// <summary> /// Runs the example. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The Google Ads customer ID.</param> /// <param name="customizerAttributeName">The customizer attribute name.</param> public void Run( GoogleAdsClient client, long customerId, string customizerAttributeName) { string customizerAttributeResourceName = CreateCustomizerAttribute( client, customerId, customizerAttributeName ); LinkCustomizerAttributeToCustomer(client, customerId, customizerAttributeResourceName); string campaignBudgetResourceName = AddCampaignBudget(client, customerId); string campaignResourceName = AddCampaign(client, customerId, campaignBudgetResourceName); string adGroupResourceName = AddAdGroup(client, customerId, campaignResourceName); CreateResponsiveSearchAdWithCustomization( client, customerId, adGroupResourceName, customizerAttributeName ); AddKeywords(client, customerId, adGroupResourceName); AddGeoTargeting(client, customerId, campaignResourceName); } /// <summary> /// Creates a customizer attribute with the specified customizer attribute name. /// </summary> /// <param name="client">The Google Ads API client.</param> /// <param name="customerId">The customer ID.</param> /// <param name="customizerAttributeName">The name of the customizer attribute.</param> /// <returns>The created customizer attribute resource name.</returns> private string CreateCustomizerAttribute( GoogleAdsClient client, long customerId, string customizerAttributeName) { // Creates a customizer attribute operation for creating a customizer attribute. CustomizerAttributeOperation operation = new CustomizerAttributeOperation() { // Creates a customizer attribute with the specified name. Create = new CustomizerAttribute() { Name = customizerAttributeName, // Specifies the type to be 'PRICE' so that we can dynamically customize the part of // the ad's description that is a price of a product/service we advertise. Type = CustomizerAttributeType.Price } }; CustomizerAttributeServiceClient serviceClient = client.GetService(Services.V26.CustomizerAttributeService); // Issues a mutate request to add the customizer attribute and prints its information. MutateCustomizerAttributesResponse response = serviceClient.MutateCustomizerAttributes( customerId.ToString(), new [] { operation }.ToList() ); string resourceName = response.Results[0].ResourceName; Console.WriteLine($"Added a customizer attribute with resource name '{resourceName}'."); return resourceName; } /// <summary> /// Links the customizer attribute to the customer by providing a value to be used in a /// responsive search ad that will be created in a later step. /// </summary> /// <param name="client">The Google Ads API client.</param> /// <param name="customerId">The customer ID.</param> /// <param name="customizerAttributeResourceName">The resource name of the customizer /// attribute.</param> private void LinkCustomizerAttributeToCustomer( GoogleAdsClient client, long customerId, string customizerAttributeResourceName) { // Creates a customer customizer operation. CustomerCustomizerOperation operation = new CustomerCustomizerOperation() { // Creates a customer customizer with the value to be used in the responsive search // ad. Create = new CustomerCustomizer() { CustomizerAttribute = customizerAttributeResourceName, Value = new CustomizerValue() { Type = CustomizerAttributeType.Price, // Specify '100USD' as a text value. The ad customizer will dynamically // replace the placeholder with this value when the ad serves. StringValue = "100USD" } } }; CustomerCustomizerServiceClient serviceClient = client.GetService(Services.V26.CustomerCustomizerService); // Issues a mutate request to add the customer customizer and prints its information. MutateCustomerCustomizersResponse response = serviceClient.MutateCustomerCustomizers( customerId.ToString(), new [] { operation }.ToList() ); string resourceName = response.Results[0].ResourceName; Console.WriteLine($"Added a customer customizer with resource name '{resourceName}'."); } /// <summary> /// Adds a campaign budget. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <returns>The campaign budget resource name.</returns> private static string AddCampaignBudget(GoogleAdsClient client, long customerId) { // Get the CampaignBudgetService. CampaignBudgetServiceClient campaignBudgetService = client.GetService(Services.V26.CampaignBudgetService); // Create the budget. CampaignBudget campaignBudget = new CampaignBudget() { Name = "Interplanetary Cruise Budget #" + ExampleUtilities.GetRandomString(), AmountMicros = 3_000_000, DeliveryMethod = BudgetDeliveryMethod.Standard }; // Create the operation. CampaignBudgetOperation operation = new CampaignBudgetOperation() { Create = campaignBudget }; // Add the campaign budget. MutateCampaignBudgetsResponse response = campaignBudgetService.MutateCampaignBudgets(customerId.ToString(), new CampaignBudgetOperation[] { operation }); // Display the result. string budgetResourceName = response.Results[0].ResourceName; Console.WriteLine($"Added budget with resource name '{budgetResourceName}'."); return budgetResourceName; } /// <summary> /// Adds a campaign. /// </summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <param name="budgetResourceName">The campaign budget resource name.</param> /// <returns>The campaign resource name.</returns> private static string AddCampaign(GoogleAdsClient client, long customerId, string budgetResourceName) { // Get the CampaignService. CampaignServiceClient campaignService = client.GetService(Services.V26.CampaignService); // Create the campaign. Campaign campaign = new Campaign() { Name = "Testing RSA via API #" + ExampleUtilities.GetRandomString(), AdvertisingChannelType = AdvertisingChannelType.Search, Status = CampaignStatus.Paused, ManualCpc = new ManualCpc(), NetworkSettings = new Campaign.Types.NetworkSettings() { TargetGoogleSearch = true, TargetSearchNetwork = true, TargetPartnerSearchNetwork = false, // Enable Display Expansion on Search campaigns. For more details see: // https://support.google.com/google-ads/answer/7193800 TargetContentNetwork = true }, CampaignBudget = budgetResourceName, StartDateTime = DateTime.Now.AddDays(1).ToString("yyyyMMdd 00:00:00"), EndDateTime = DateTime.Now.AddDays(30).ToString("yyyyMMdd 23:59:59") }; // Create the operation. CampaignOperation operation = new CampaignOperation() { Create = campaign }; // Add the campaign. MutateCampaignsResponse response = campaignService.MutateCampaigns(customerId.ToString(), new CampaignOperation[] { operation }); // Displays the result. string campaignResourceName = response.Results[0].ResourceName; Console.WriteLine($"Added campaign with resource name '{campaignResourceName}'."); return campaignResourceName; } /// <summary>Adds an ad group.</summary> /// <param name="client">The Google Ads client.</param> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> /// <param name="campaignResourceName">The campaign resource name.</param> /// <returns>The ad group resource name.</returns> private static string AddAdGroup(GoogleAdsClient client, long customerId, string campaignResourceName) { // Get the AdGroupService. AdGroupServiceClient adGroupService = client.GetService(Services.V26.AdGroupService); // Create the ad group. AdGroup adGroup = new AdGroup() { Name = "Testing RSA via API #" + ExampleUtilities.GetRandomString(), Campaign = campaignResourceName, Type = AdGroupType.SearchStandard, Status = AdGroupStatus.Enabled, // If you want to set up a max CPC bid, uncomment the line below. // CpcBidMicros = 50_000 }; // Create the operation. AdGroupOperation operation = new AdGroupOperation() { Create = adGroup }; // Add the ad group. MutateAdGroupsResponse response = adGroupService.MutateAdGroups(customerId.ToString(), new AdGroupOperation[] { operation }); // Display the results. string adGroupResourceName = response.Results[0].ResourceName; Console.WriteLine($"Added ad group with resource name '{adGroupResourceName}'."); return adGroupResourceName; } /// <summary> /// Creates a responsive search ad that uses the specified customizer attribute. /// </summary> /// <param name="client">The Google Ads API client.</param> /// <param name="customerId">The customer ID.</param> /// <param name="adGroupResourceName">The resource name of the ad group.</param> /// <param name="customizerAttributeName">The name of the customizer attribute.</param> private void CreateResponsiveSearchAdWithCustomization( GoogleAdsClient client, long customerId, string adGroupResourceName, string customizerAttributeName) { // Creates an ad group ad operation. AdGroupAdOperation operation = new AdGroupAdOperation() { // Creates an ad group ad to hold the ad. Create = new AdGroupAd() { AdGroup = adGroupResourceName, Status = AdGroupAdStatus.Enabled, // Creates an ad and sets responsive search ad info. Ad = new Ad() { ResponsiveSearchAd = new ResponsiveSearchAdInfo() { Headlines = { // Sets a pinning to always choose this asset for HEADLINE_1. // Pinning is optional; if no pinning is set, then headlines and // descriptions will be rotated and the ones that perform best will //be used more often. new AdTextAsset() { Text = "Cruise to Mars" }, new AdTextAsset() { Text = "Best Space Cruise Line" }, new AdTextAsset() { Text = "Experience the Stars" } }, Descriptions = { new AdTextAsset() { Text = "Buy your tickets now" }, // Creates this particular description using the ad customizer. For // details about the placeholder format, visit the following: // https://developers.google.com/google-ads/api/docs/ads/customize-responsive-search-ads#ad_customizers_in_responsive_search_ads // // The ad customizer replaces the placeholder with the value we // previously created and linked to the customer using // `CustomerCustomizer`. new AdTextAsset() { Text = $"Just {{CUSTOMIZER.{customizerAttributeName}:10USD}}" } }, Path1 = "all-inclusive", Path2 = "deals" }, FinalUrls = { "http://www.example.com" } } } }; // Issues a mutate request to add the ad group ad and prints its information. AdGroupAdServiceClient serviceClient = client.GetService(Services.V26.AdGroupAdService); MutateAdGroupAdsResponse response = serviceClient.MutateAdGroupAds( customerId.ToString(), new [] { operation }.ToList() ); string resourceName = response.Results[0].ResourceName; Console.WriteLine($"Created responsive search ad with resource name '{resourceName}'."); } /// <summary> /// Creates 3 keyword match types: EXACT, PHRASE, and BROAD. /// EXACT: ads may show on searches that ARE the same meaning as your keyword. /// PHRASE: ads may show on searches that INCLUDE the meaning of your keyword. /// BROAD: ads may show on searches that RELATE to your keyword. /// For smart bidding, BROAD is the recommended one. /// </summary> /// <param name="client">The Google Ads API client.</param> /// <param name="customerId">The customer ID.</param> /// <param name="adGroupResourceName">The resource name of the ad group.</param> private void AddKeywords(GoogleAdsClient client, long customerId, string adGroupResourceName) { // Get the AdGroupCriterionService. AdGroupCriterionServiceClient adGroupCriterionService = client.GetService(Services.V26.AdGroupCriterionService); List<AdGroupCriterionOperation> operations = new List<AdGroupCriterionOperation>(); AdGroupCriterionOperation exactMatchOperation = new AdGroupCriterionOperation() { Create = new AdGroupCriterion() { AdGroup = adGroupResourceName, Status = AdGroupCriterionStatus.Enabled, Keyword = new KeywordInfo() { Text = "example of exact match", MatchType = KeywordMatchType.Exact }, // Uncomment the line below if you want to change this keyword to a negative // target. // Negative = true } }; // Optional repeated field // exactMatchOperation.Create.FinalUrls.Add("https://www.example.com"); operations.Add(exactMatchOperation); AdGroupCriterionOperation phraseMatchOperation = new AdGroupCriterionOperation() { Create = new AdGroupCriterion() { AdGroup = adGroupResourceName, Status = AdGroupCriterionStatus.Enabled, Keyword = new KeywordInfo() { Text = "example of phrase match", MatchType = KeywordMatchType.Phrase }, // Uncomment the line below if you want to change this keyword to a negative // target. // Negative = true } }; // Optional repeated field // phraseMatchOperation.Create.FinalUrls.Add("https://www.example.com"); operations.Add(phraseMatchOperation); AdGroupCriterionOperation broadMatchOperation = new AdGroupCriterionOperation() { Create = new AdGroupCriterion() { AdGroup = adGroupResourceName, Status = AdGroupCriterionStatus.Enabled, Keyword = new KeywordInfo() { Text = "example of broad match", MatchType = KeywordMatchType.Broad }, // Uncomment the line below if you want to change this keyword to a negative // target. // Negative = true } }; // Optional repeated field // broadMatchOperation.Create.FinalUrls.Add("https://www.example.com"); operations.Add(broadMatchOperation); MutateAdGroupCriteriaResponse response = adGroupCriterionService.MutateAdGroupCriteria(customerId.ToString(), operations); // Display the results. foreach (MutateAdGroupCriterionResult newAdGroupCriterion in response.Results) { Console.WriteLine("Keyword with resource name '{0}' was created.", newAdGroupCriterion.ResourceName); } } /// <summary> /// Creates geo targets. /// </summary> /// <param name="client">The Google Ads API client.</param> /// <param name="customerId">The customer ID.</param> /// <param name="campaignResourceName">The resource name of the campaign.</param> private void AddGeoTargeting(GoogleAdsClient client, long customerId, string campaignResourceName) { GeoTargetConstantServiceClient geoTargetConstantService = client.GetService(Services.V26.GeoTargetConstantService); SuggestGeoTargetConstantsRequest suggestGeoTargetConstantsRequest = new SuggestGeoTargetConstantsRequest() { // Locale uses the ISO 639-1 format. Locale = "es", // A list of available country codes can be referenced here: // https://developers.google.com/google-ads/api/reference/data/geotargets CountryCode = "AR", LocationNames = new LocationNames() { Names = {"Buenos aires", "San Isidro", "Mar del Plata"} } }; SuggestGeoTargetConstantsResponse suggestGeoTargetConstantsResponse = geoTargetConstantService.SuggestGeoTargetConstants( suggestGeoTargetConstantsRequest); List<CampaignCriterionOperation> operations = new List<CampaignCriterionOperation>(); foreach (GeoTargetConstantSuggestion suggestion in suggestGeoTargetConstantsResponse.GeoTargetConstantSuggestions) { Console.WriteLine($"Geo target constant: {suggestion.GeoTargetConstant.Name} was " + $"found in locale ({suggestion.Locale}) with reach ({suggestion.Reach}) from " + $"search term ({suggestion.SearchTerm})"); CampaignCriterionOperation operation = new CampaignCriterionOperation() { Create = new CampaignCriterion() { Campaign = campaignResourceName, Location = new LocationInfo() { GeoTargetConstant = suggestion.GeoTargetConstant.ResourceName } } }; operations.Add(operation); } CampaignCriterionServiceClient campaignCriterionService = client.GetService(Services.V26.CampaignCriterionService); MutateCampaignCriteriaResponse mutateCampaignCriteriaResponse = campaignCriterionService.MutateCampaignCriteria(customerId.ToString(), operations); foreach (MutateCampaignCriterionResult result in mutateCampaignCriteriaResponse.Results) { Console.WriteLine($"Added campaign criterion {result.ResourceName}"); } } } }
PHP
This example is not yet available in PHP; you can take a look at the other languages.
Python
#!/usr/bin/env python # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ This example shows how to create a complete Responsive Search ad. Includes creation of: budget, campaign, ad group, ad group ad, keywords, and geo targeting. More details on Responsive Search ads can be found here: https://support.google.com/google-ads/answer/7684791 """ import argparse import sys import uuid from typing import List, Optional from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException from google.ads.googleads.v24.common.types.ad_asset import AdTextAsset from google.ads.googleads.v24.enums.types.served_asset_field_type import ( ServedAssetFieldTypeEnum, ) from google.ads.googleads.v24.resources.types.ad_group import AdGroup from google.ads.googleads.v24.resources.types.ad_group_ad import AdGroupAd from google.ads.googleads.v24.resources.types.ad_group_criterion import ( AdGroupCriterion, ) from google.ads.googleads.v24.resources.types.campaign import Campaign from google.ads.googleads.v24.resources.types.campaign_budget import ( CampaignBudget, ) from google.ads.googleads.v24.resources.types.campaign_criterion import ( CampaignCriterion, ) from google.ads.googleads.v24.resources.types.customer_customizer import ( CustomerCustomizer, ) from google.ads.googleads.v24.resources.types.customizer_attribute import ( CustomizerAttribute, ) from google.ads.googleads.v24.services.services.ad_group_ad_service import ( AdGroupAdServiceClient, ) from google.ads.googleads.v24.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient, ) from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) from google.ads.googleads.v24.services.services.campaign_budget_service import ( CampaignBudgetServiceClient, ) from google.ads.googleads.v24.services.services.campaign_criterion_service import ( CampaignCriterionServiceClient, ) from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) from google.ads.googleads.v24.services.services.customer_customizer_service import ( CustomerCustomizerServiceClient, ) from google.ads.googleads.v24.services.services.customizer_attribute_service import ( CustomizerAttributeServiceClient, ) from google.ads.googleads.v24.services.services.geo_target_constant_service import ( GeoTargetConstantServiceClient, ) from google.ads.googleads.v24.services.types.geo_target_constant_service import ( SuggestGeoTargetConstantsRequest, SuggestGeoTargetConstantsResponse, ) from google.ads.googleads.v24.services.types.ad_group_ad_service import ( AdGroupAdOperation, MutateAdGroupAdsResponse, ) from google.ads.googleads.v24.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation, MutateAdGroupCriteriaResponse, ) from google.ads.googleads.v24.services.types.ad_group_service import ( AdGroupOperation, MutateAdGroupsResponse, ) from google.ads.googleads.v24.services.types.campaign_budget_service import ( CampaignBudgetOperation, MutateCampaignBudgetsResponse, ) from google.ads.googleads.v24.services.types.campaign_criterion_service import ( CampaignCriterionOperation, MutateCampaignCriteriaResponse, ) from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, MutateCampaignsResponse, ) from google.ads.googleads.v24.services.types.customer_customizer_service import ( CustomerCustomizerOperation, MutateCustomerCustomizersResponse, ) from google.ads.googleads.v24.services.types.customizer_attribute_service import ( CustomizerAttributeOperation, MutateCustomizerAttributesResponse, ) # Keywords from user. KEYWORD_TEXT_EXACT = "example of exact match" KEYWORD_TEXT_PHRASE = "example of phrase match" KEYWORD_TEXT_BROAD = "example of broad match" # Geo targeting from user. GEO_LOCATION_1 = "Buenos aires" GEO_LOCATION_2 = "San Isidro" GEO_LOCATION_3 = "Mar del Plata" # LOCALE and COUNTRY_CODE are used for geo targeting. # LOCALE is using ISO 639-1 format. If an invalid LOCALE is given, # 'es' is used by default. LOCALE = "es" # A list of country codes can be referenced here: # https://developers.google.com/google-ads/api/reference/data/geotargets COUNTRY_CODE = "AR" def main( client: GoogleAdsClient, customer_id: str, customizer_attribute_name: Optional[str] = None, ) -> None: """ The main method that creates all necessary entities for the example. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. customizer_attribute_name: The name of the customizer attribute to be created """ if customizer_attribute_name: customizer_attribute_resource_name: str = create_customizer_attribute( client, customer_id, customizer_attribute_name ) link_customizer_attribute_to_customer( client, customer_id, customizer_attribute_resource_name ) # Create a budget, which can be shared by multiple campaigns. campaign_budget: str = create_campaign_budget(client, customer_id) campaign_resource_name: str = create_campaign( client, customer_id, campaign_budget ) ad_group_resource_name: str = create_ad_group( client, customer_id, campaign_resource_name ) create_ad_group_ad( client, customer_id, ad_group_resource_name, customizer_attribute_name ) add_keywords(client, customer_id, ad_group_resource_name) add_geo_targeting(client, customer_id, campaign_resource_name) def create_customizer_attribute( client: GoogleAdsClient, customer_id: str, customizer_attribute_name: str ) -> str: """Creates a customizer attribute with the given customizer attribute name. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. customizer_attribute_name: the name for the customizer attribute. Returns: A resource name for a customizer attribute. """ # Create a customizer attribute operation for creating a customizer # attribute. operation: CustomizerAttributeOperation = client.get_type( "CustomizerAttributeOperation" ) # Create a customizer attribute with the specified name. customizer_attribute: CustomizerAttribute = operation.create customizer_attribute.name = customizer_attribute_name # Specify the type to be 'PRICE' so that we can dynamically customize the # part of the ad's description that is a price of a product/service we # advertise. customizer_attribute.type_ = client.enums.CustomizerAttributeTypeEnum.PRICE # Issue a mutate request to add the customizer attribute and prints its # information. customizer_attribute_service: CustomizerAttributeServiceClient = ( client.get_service("CustomizerAttributeService") ) response: MutateCustomizerAttributesResponse = ( customizer_attribute_service.mutate_customizer_attributes( customer_id=customer_id, operations=[operation] ) ) resource_name: str = response.results[0].resource_name print(f"Added a customizer attribute with resource name: '{resource_name}'") return resource_name def link_customizer_attribute_to_customer( client: GoogleAdsClient, customer_id: str, customizer_attribute_resource_name: str, ) -> None: """Links the customizer attribute to the customer. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. customizer_attribute_resource_name: a resource name for customizer attribute. """ # Create a customer customizer operation. operation: CustomerCustomizerOperation = client.get_type( "CustomerCustomizerOperation" ) # Create a customer customizer with the value to be used in the responsive # search ad. customer_customizer: CustomerCustomizer = operation.create customer_customizer.customizer_attribute = ( customizer_attribute_resource_name ) customer_customizer.value.type_ = ( client.enums.CustomizerAttributeTypeEnum.PRICE ) # The ad customizer will dynamically replace the placeholder with this value # when the ad serves. customer_customizer.value.string_value = "100USD" customer_customizer_service: CustomerCustomizerServiceClient = ( client.get_service("CustomerCustomizerService") ) # Issue a mutate request to create the customer customizer and prints its # information. response: MutateCustomerCustomizersResponse = ( customer_customizer_service.mutate_customer_customizers( customer_id=customer_id, operations=[operation] ) ) resource_name: str = response.results[0].resource_name print( f"Added a customer customizer to the customer with resource name: '{resource_name}'" ) def create_ad_text_asset( client: GoogleAdsClient, text: str, pinned_field: Optional[ ServedAssetFieldTypeEnum.ServedAssetFieldType ] = None, ) -> AdTextAsset: """Create an AdTextAsset. Args: client: an initialized GoogleAdsClient instance. text: text for headlines and descriptions. pinned_field: to pin a text asset so it always shows in the ad. Returns: An AdTextAsset. """ ad_text_asset: AdTextAsset = client.get_type("AdTextAsset") ad_text_asset.text = text if pinned_field: ad_text_asset.pinned_field = pinned_field return ad_text_asset def create_ad_text_asset_with_customizer( client: GoogleAdsClient, customizer_attribute_resource_name: str ) -> AdTextAsset: """Create an AdTextAsset. Args: client: an initialized GoogleAdsClient instance. customizer_attribute_resource_name: The resource name of the customizer attribute. Returns: An AdTextAsset. """ ad_text_asset: AdTextAsset = client.get_type("AdTextAsset") # Create this particular description using the ad customizer. Visit # https://developers.google.com/google-ads/api/docs/ads/customize-responsive-search-ads#ad_customizers_in_responsive_search_ads # for details about the placeholder format. The ad customizer replaces the # placeholder with the value we previously created and linked to the # customer using CustomerCustomizer. ad_text_asset.text = ( f"Just {{CUSTOMIZER.{customizer_attribute_resource_name}:10USD}}" ) return ad_text_asset def create_campaign_budget(client: GoogleAdsClient, customer_id: str) -> str: """Creates campaign budget resource. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. Returns: Campaign budget resource name. """ # Create a budget, which can be shared by multiple campaigns. campaign_budget_service: CampaignBudgetServiceClient = client.get_service( "CampaignBudgetService" ) campaign_budget_operation: CampaignBudgetOperation = client.get_type( "CampaignBudgetOperation" ) campaign_budget: CampaignBudget = campaign_budget_operation.create campaign_budget.name = f"Campaign budget {uuid.uuid4()}" campaign_budget.delivery_method = ( client.enums.BudgetDeliveryMethodEnum.STANDARD ) campaign_budget.amount_micros = 500000 # Add budget. campaign_budget_response: MutateCampaignBudgetsResponse = ( campaign_budget_service.mutate_campaign_budgets( customer_id=customer_id, operations=[campaign_budget_operation] ) ) return campaign_budget_response.results[0].resource_name def create_campaign( client: GoogleAdsClient, customer_id: str, campaign_budget: str ) -> str: """Creates campaign resource. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. campaign_budget: a budget resource name. Returns: Campaign resource name. """ campaign_service: CampaignServiceClient = client.get_service( "CampaignService" ) campaign_operation: CampaignOperation = client.get_type("CampaignOperation") campaign: Campaign = campaign_operation.create campaign.name = f"Testing RSA via API {uuid.uuid4()}" campaign.advertising_channel_type = ( client.enums.AdvertisingChannelTypeEnum.SEARCH ) # Recommendation: Set the campaign to PAUSED when creating it to prevent # the ads from immediately serving. Set to ENABLED once you've added # targeting and the ads are ready to serve. campaign.status = client.enums.CampaignStatusEnum.PAUSED # Set the bidding strategy and budget. # The bidding strategy for Maximize Clicks is TargetSpend. # The target_spend_micros is deprecated so don't put any value. # See other bidding strategies you can select in the link below. # https://developers.google.com/google-ads/api/reference/rpc/latest/Campaign#campaign_bidding_strategy campaign.target_spend.target_spend_micros = 0 campaign.campaign_budget = campaign_budget # Set the campaign network options. campaign.network_settings.target_google_search = True campaign.network_settings.target_search_network = True campaign.network_settings.target_partner_search_network = False # Enable Display Expansion on Search campaigns. For more details see: # https://support.google.com/google-ads/answer/7193800 campaign.network_settings.target_content_network = True # # Optional: Set the start date. # start_time = datetime.date.today() + datetime.timedelta(days=1) # campaign.start_date_time = datetime.date.strftime(start_time, "%Y%m%d 00:00:00") # # Optional: Set the end date. # end_time = start_time + datetime.timedelta(weeks=4) # campaign.end_date_time = datetime.date.strftime(end_time, "%Y%m%d 23:59:59") # Add the campaign. campaign_response: MutateCampaignsResponse = ( campaign_service.mutate_campaigns( customer_id=customer_id, operations=[campaign_operation] ) ) resource_name: str = campaign_response.results[0].resource_name print(f"Created campaign {resource_name}.") return resource_name def create_ad_group( client: GoogleAdsClient, customer_id: str, campaign_resource_name: str, ) -> str: """Creates ad group. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. campaign_resource_name: a campaign resource name. Returns: Ad group ID. """ ad_group_service: AdGroupServiceClient = client.get_service( "AdGroupService" ) ad_group_operation: AdGroupOperation = client.get_type("AdGroupOperation") ad_group: AdGroup = ad_group_operation.create ad_group.name = f"Testing RSA via API {uuid.uuid4()}" ad_group.status = client.enums.AdGroupStatusEnum.ENABLED ad_group.campaign = campaign_resource_name ad_group.type_ = client.enums.AdGroupTypeEnum.SEARCH_STANDARD # If you want to set up a max CPC bid uncomment line below. # ad_group.cpc_bid_micros = 10000000 # Add the ad group. ad_group_response: MutateAdGroupsResponse = ( ad_group_service.mutate_ad_groups( customer_id=customer_id, operations=[ad_group_operation] ) ) ad_group_resource_name: str = ad_group_response.results[0].resource_name print(f"Created ad group {ad_group_resource_name}.") return ad_group_resource_name def create_ad_group_ad( client: GoogleAdsClient, customer_id: str, ad_group_resource_name: str, customizer_attribute_name: Optional[str], ) -> None: """Creates ad group ad. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. ad_group_resource_name: an ad group resource name. customizer_attribute_name: (optional) If present, indicates the resource name of the customizer attribute to use in one of the descriptions Returns: None. """ ad_group_ad_service: AdGroupAdServiceClient = client.get_service( "AdGroupAdService" ) ad_group_ad_operation: AdGroupAdOperation = client.get_type( "AdGroupAdOperation" ) ad_group_ad: AdGroupAd = ad_group_ad_operation.create ad_group_ad.status = client.enums.AdGroupAdStatusEnum.ENABLED ad_group_ad.ad_group = ad_group_resource_name # Set responsive search ad info. # https://developers.google.com/google-ads/api/reference/rpc/latest/ResponsiveSearchAdInfo # The list of possible final URLs after all cross-domain redirects for the ad. ad_group_ad.ad.final_urls.append("https://www.example.com/") # Set a pinning to always choose this asset for HEADLINE_1. Pinning is # optional; if no pinning is set, then headlines and descriptions will be # rotated and the ones that perform best will be used more often. # Headline 1 served_asset_enum: ServedAssetFieldTypeEnum = ( client.enums.ServedAssetFieldTypeEnum ) pinned_headline: AdTextAsset = create_ad_text_asset( client, "Headline 1 testing", served_asset_enum ) # Headline 2 and 3 ad_group_ad.ad.responsive_search_ad.headlines.extend( [ pinned_headline, create_ad_text_asset(client, "Headline 2 testing"), create_ad_text_asset(client, "Headline 3 testing"), ] ) # Description 1 and 2 description_1: AdTextAsset = create_ad_text_asset(client, "Desc 1 testing") description_2: Optional[AdTextAsset] = None if customizer_attribute_name: description_2 = create_ad_text_asset_with_customizer( client, customizer_attribute_name ) else: description_2 = create_ad_text_asset(client, "Desc 2 testing") ad_group_ad.ad.responsive_search_ad.descriptions.extend( [description_1, description_2] ) # Paths # First and second part of text that can be appended to the URL in the ad. # If you use the examples below, the ad will show # https://www.example.com/all-inclusive/deals ad_group_ad.ad.responsive_search_ad.path1 = "all-inclusive" ad_group_ad.ad.responsive_search_ad.path2 = "deals" # Send a request to the server to add a responsive search ad. ad_group_ad_response: MutateAdGroupAdsResponse = ( ad_group_ad_service.mutate_ad_group_ads( customer_id=customer_id, operations=[ad_group_ad_operation] ) ) for result in ad_group_ad_response.results: print( f"Created responsive search ad with resource name " f'"{result.resource_name}".' ) def add_keywords( client: GoogleAdsClient, customer_id: str, ad_group_resource_name: str ) -> None: """Creates keywords. Creates 3 keyword match types: EXACT, PHRASE, and BROAD. EXACT: ads may show on searches that ARE the same meaning as your keyword. PHRASE: ads may show on searches that INCLUDE the meaning of your keyword. BROAD: ads may show on searches that RELATE to your keyword. For smart bidding, BROAD is the recommended one. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. ad_group_resource_name: an ad group resource name. """ ad_group_criterion_service: AdGroupCriterionServiceClient = ( client.get_service("AdGroupCriterionService") ) operations: List[AdGroupCriterionOperation] = [] # Create keyword 1. ad_group_criterion_operation: AdGroupCriterionOperation = client.get_type( "AdGroupCriterionOperation" ) ad_group_criterion: AdGroupCriterion = ad_group_criterion_operation.create ad_group_criterion.ad_group = ad_group_resource_name ad_group_criterion.status = client.enums.AdGroupCriterionStatusEnum.ENABLED ad_group_criterion.keyword.text = KEYWORD_TEXT_EXACT ad_group_criterion.keyword.match_type = ( client.enums.KeywordMatchTypeEnum.EXACT ) # Uncomment the below line if you want to change this keyword to a negative target. # ad_group_criterion.negative = True # Optional repeated field # ad_group_criterion.final_urls.append('https://www.example.com') # Add operation operations.append(ad_group_criterion_operation) # Create keyword 2. ad_group_criterion_operation: AdGroupCriterionOperation = client.get_type( "AdGroupCriterionOperation" ) ad_group_criterion: AdGroupCriterion = ad_group_criterion_operation.create ad_group_criterion.ad_group = ad_group_resource_name ad_group_criterion.status = client.enums.AdGroupCriterionStatusEnum.ENABLED ad_group_criterion.keyword.text = KEYWORD_TEXT_PHRASE ad_group_criterion.keyword.match_type = ( client.enums.KeywordMatchTypeEnum.PHRASE ) # Uncomment the below line if you want to change this keyword to a negative target. # ad_group_criterion.negative = True # Optional repeated field # ad_group_criterion.final_urls.append('https://www.example.com') # Add operation operations.append(ad_group_criterion_operation) # Create keyword 3. ad_group_criterion_operation: AdGroupCriterionOperation = client.get_type( "AdGroupCriterionOperation" ) ad_group_criterion: AdGroupCriterion = ad_group_criterion_operation.create ad_group_criterion.ad_group = ad_group_resource_name ad_group_criterion.status = client.enums.AdGroupCriterionStatusEnum.ENABLED ad_group_criterion.keyword.text = KEYWORD_TEXT_BROAD ad_group_criterion.keyword.match_type = ( client.enums.KeywordMatchTypeEnum.BROAD ) # Uncomment the below line if you want to change this keyword to a negative target. # ad_group_criterion.negative = True # Optional repeated field # ad_group_criterion.final_urls.append('https://www.example.com') # Add operation operations.append(ad_group_criterion_operation) # Add keywords ad_group_criterion_response: MutateAdGroupCriteriaResponse = ( ad_group_criterion_service.mutate_ad_group_criteria( customer_id=customer_id, operations=operations, ) ) for result in ad_group_criterion_response.results: print("Created keyword " f"{result.resource_name}.") def add_geo_targeting( client: GoogleAdsClient, customer_id: str, campaign_resource_name: str ) -> None: """Creates geo targets. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. campaign_resource_name: an campaign resource name. Returns: None. """ geo_target_constant_service: GeoTargetConstantServiceClient = ( client.get_service("GeoTargetConstantService") ) # Search by location names from # GeoTargetConstantService.suggest_geo_target_constants() and directly # apply GeoTargetConstant.resource_name. gtc_request: SuggestGeoTargetConstantsRequest = client.get_type( "SuggestGeoTargetConstantsRequest" ) gtc_request.locale = LOCALE gtc_request.country_code = COUNTRY_CODE # The location names to get suggested geo target constants. gtc_request.location_names.names.extend( [GEO_LOCATION_1, GEO_LOCATION_2, GEO_LOCATION_3] ) results: SuggestGeoTargetConstantsResponse = ( geo_target_constant_service.suggest_geo_target_constants(gtc_request) ) operations: List[CampaignCriterionOperation] = [] for suggestion in results.geo_target_constant_suggestions: print( "geo_target_constant: " f"{suggestion.geo_target_constant.resource_name} " f"is found in LOCALE ({suggestion.locale}) " f"with reach ({suggestion.reach}) " f"from search term ({suggestion.search_term})." ) # Create the campaign criterion for location targeting. campaign_criterion_operation: CampaignCriterionOperation = ( client.get_type("CampaignCriterionOperation") ) campaign_criterion: CampaignCriterion = ( campaign_criterion_operation.create ) campaign_criterion.campaign = campaign_resource_name campaign_criterion.location.geo_target_constant = ( suggestion.geo_target_constant.resource_name ) operations.append(campaign_criterion_operation) campaign_criterion_service: CampaignCriterionServiceClient = ( client.get_service("CampaignCriterionService") ) campaign_criterion_response: MutateCampaignCriteriaResponse = ( campaign_criterion_service.mutate_campaign_criteria( customer_id=customer_id, operations=[*operations] ) ) for result in campaign_criterion_response.results: print(f'Added campaign criterion "{result.resource_name}".') if __name__ == "__main__": parser: argparse.ArgumentParser = argparse.ArgumentParser( description=("Creates a Responsive Search Ad for specified customer.") ) # The following argument(s) should be provided to run the example. parser.add_argument( "-c", "--customer_id", type=str, required=True, help="The Google Ads customer ID.", ) # The name of the customizer attribute used in the ad customizer, which # must be unique for a given customer account. To run this example multiple # times, specify a unique value as a command line argument. Note that there is # a limit for the number of enabled customizer attributes in one account # For more details visit: # https://developers.google.com/google-ads/api/docs/ads/customize-responsive-search-ads#rules_and_limitations parser.add_argument( "-n", "--customizer_attribute_name", type=str, default=None, help=( "The name of the customizer attribute to be created. The name must " "be unique across a client account, so be sure not to use " "the same value more than once." ), ) args: argparse.Namespace = parser.parse_args() # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( version="v24" ) try: main( googleads_client, args.customer_id, args.customizer_attribute_name, ) except GoogleAdsException as ex: print( f'Request with ID "{ex.request_id}" failed with status ' f'"{ex.error.code().name}" and includes the following errors:' ) for error in ex.failure.errors: print(f'Error with message "{error.message}".') if error.location: for field_path_element in error.location.field_path_elements: print(f"\t\tOn field: {field_path_element.field_name}") sys.exit(1)
Ruby
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # This example shows how to create a complete Responsive Search ad. # # Includes creation of: budget, campaign, ad group, ad group ad, # keywords, and geo targeting. # # More details on Responsive Search ads can be found here: # https://support.google.com/google-ads/answer/7684791 require 'optparse' require 'google/ads/google_ads' require 'date' # The name of the customizer attribute to be used in the ad customizer must be unique for a # given client account. To run this example multiple times, change this value or specify # its corresponding argument. Note that there is a limit for the number of enabled # customizer attributes in one account, so you shouldn't run this example more than # necessary. # # Visit the following link for more details: # https://developers.google.com/google-ads/api/docs/ads/customize-responsive-search-ads#rules_and_limitations DEFAULT_CUSTOMIZER_ATTRIBUTE_NAME = "Price" # Keywords from user. KEYWORD_TEXT_EXACT = "example of exact match" KEYWORD_TEXT_PHRASE = "example of phrase match" KEYWORD_TEXT_BROAD = "example of broad match" # Geo targeting from user. GEO_LOCATION_1 = "Buenos aires" GEO_LOCATION_2 = "San Isidro" GEO_LOCATION_3 = "Mar del Plata" # LOCALE and COUNTRY_CODE are used for geo targeting. # LOCALE is using ISO 639-1 format. If an invalid LOCALE is given, # 'es' is used by default. LOCALE = "es" # A list of country codes can be referenced here: # https://developers.google.com/google-ads/api/reference/data/geotargets COUNTRY_CODE = "AR" # Creates a customizer attribute with the given customizer attribute name. # # Args: # client: An initialized GoogleAdsClient instance. # customer_id: A client customer ID. # customizer_attribute_name: The name for the customizer attribute. # # Returns: # A resource name for a customizer attribute. def create_customizer_attribute(client, customer_id, customizer_attribute_name) # Create a customizer attribute operation for creating a customizer attribute. operation = client.operation.create_resource.customizer_attribute do |ca| ca.name = customizer_attribute_name # Specify the type to be 'PRICE' so that we can dynamically customize the # part of the ad's description that is a price of a product/service we # advertise. ca.type = :PRICE end # Issue a mutate request to add the customizer attribute and print its # information. customizer_attribute_service = client.service.customizer_attribute response = customizer_attribute_service.mutate_customizer_attributes( customer_id: customer_id, operations: [operation], ) resource_name = response.results.first.resource_name puts "Added a customizer attribute with resource name: '#{resource_name}'" resource_name end # Links the customizer attribute to the customer. # # Args: # client: An initialized GoogleAdsClient instance. # customer_id: A client customer ID. # customizer_attribute_resource_name: A resource name for a customizer attribute. def link_customizer_attribute_to_customer(client, customer_id, customizer_attribute_resource_name) # Create a customer customizer operation. operation = client.operation.create_customer_customizer do |cc| cc.customizer_attribute = customizer_attribute_resource_name cc.value = client.resource.customizer_value do |val| val.type = :PRICE # The ad customizer will dynamically replace the placeholder with this value # when the ad serves. val.string_value = "100USD" end end customer_customizer_service = client.service.customer_customizer # Issue a mutate request to create the customer customizer and prints its # information. response = customer_customizer_service.mutate_customer_customizers( customer_id: customer_id, operations: [operation], ) resource_name = response.results.first.resource_name puts "Added a customer customizer to the customer with resource name: '#{resource_name}'" end # Helper function to create an AdTextAsset. # # Args: # client: An initialized GoogleAdsClient instance. # text: Text for headlines and descriptions. # pinned_field: To pin a text asset so it always shows in the ad. # # Returns: # An AdTextAsset. def create_ad_text_asset(client, text, pinned_field = nil) client.resource.ad_text_asset do |ad_text_asset| ad_text_asset.text = text unless pinned_field.nil? ad_text_asset.pinned_field = pinned_field end end end # Helper function to create an AdTextAsset with a customizer. # # Args: # client: An initialized GoogleAdsClient instance. # customizer_attribute_resource_name: The resource name of the customizer attribute. # # Returns: # An AdTextAsset. def create_ad_text_asset_with_customizer(client, customizer_attribute_resource_name) client.resource.ad_text_asset do |ad_text_asset| # Create this particular description using the ad customizer. Visit # https://developers.google.com/google-ads/api/docs/ads/customize-responsive-search-ads#ad_customizers_in_responsive_search_ads # for details about the placeholder format. The ad customizer replaces the # placeholder with the value we previously created and linked to the # customer using CustomerCustomizer. ad_text_asset.text = "Just {CUSTOMIZER.#{customizer_attribute_resource_name}:10USD}" end end # Creates a campaign budget resource. # # Args: # client: An initialized GoogleAdsClient instance. # customer_id: A client customer ID. # # Returns: # Campaign budget resource name. def create_campaign_budget(client, customer_id) # Create a budget, which can be shared by multiple campaigns. campaign_budget_service = client.service.campaign_budget operation = client.operation.create_resource.campaign_budget do |cb| cb.name = "Campaign budget \#{SecureRandom.uuid}" cb.delivery_method = :STANDARD cb.amount_micros = 500_000 # 500,000 end # Add budget. response = campaign_budget_service.mutate_campaign_budgets( customer_id: customer_id, operations: [operation], ) resource_name = response.results.first.resource_name puts "Created campaign budget #{resource_name}" resource_name end # Creates a campaign resource. # # Args: # client: An initialized GoogleAdsClient instance. # customer_id: A client customer ID. # campaign_budget_resource_name: A budget resource name. # # Returns: # Campaign resource name. def create_campaign(client, customer_id, campaign_budget_resource_name) campaign_service = client.service.campaign operation = client.operation.create_campaign do |campaign| campaign.name = "Testing RSA via API \#{SecureRandom.uuid}" campaign.advertising_channel_type = :SEARCH # Recommendation: Set the campaign to PAUSED when creating it to prevent # the ads from immediately serving. Set to ENABLED once you've added # targeting and the ads are ready to serve. campaign.status = :PAUSED # Set the bidding strategy and budget. # The bidding strategy for Maximize Clicks is TargetSpend. # The target_spend_micros is deprecated so don't put any value. # See other bidding strategies you can select in the link below. # https://developers.google.com/google-ads/api/reference/rpc/latest/Campaign#campaign_bidding_strategy campaign.bidding_strategy_type = :TARGET_SPEND campaign.target_spend = client.resource.target_spend do |ts| ts.target_spend_micros = 0 end campaign.campaign_budget = campaign_budget_resource_name # Set the campaign network options. campaign.network_settings = client.resource.network_settings do |ns| ns.target_google_search = true ns.target_search_network = true ns.target_partner_search_network = false # Enable Display Expansion on Search campaigns. For more details see: # https://support.google.com/google-ads/answer/7193800 ns.target_content_network = true end # Optional: Set the start date. #c.start_date_time = DateTime.parse((Date.today + 1).to_s).strftime('%Y%m%d %H:%M:%S') # Optional: Set the end date. #c.end_date_time = DateTime.parse((Date.today.next_year).to_s).strftime('%Y%m%d %H:%M:%S') end # Add the campaign. response = campaign_service.mutate_campaigns( customer_id: customer_id, operations: [operation], ) resource_name = response.results.first.resource_name puts "Created campaign #{resource_name}." resource_name end # Creates an ad group. # # Args: # client: An initialized GoogleAdsClient instance. # customer_id: A client customer ID. # campaign_resource_name: A campaign resource name. # customizer_attribute_resource_name: (optional) If present, indicates the resource # name of the customizer attribute to use in one of the descriptions. # # Returns: # Ad group resource name. def create_ad_group(client, customer_id, campaign_resource_name) ad_group_service = client.service.ad_group operation = client.operation.create_ad_group do |ag| ag.name = "Testing RSA via API \#{SecureRandom.uuid}" ag.status = :ENABLED ag.campaign = campaign_resource_name ag.type = :SEARCH_STANDARD # If you want to set up a max CPC bid uncomment line below. # ag.cpc_bid_micros = 1_000_000 # 1,000,000 end # Add the ad group. response = ad_group_service.mutate_ad_groups( customer_id: customer_id, operations: [operation], ) ad_group_resource_name = response.results.first.resource_name puts "Created ad group #{ad_group_resource_name}." ad_group_resource_name end # Creates an ad group ad (Responsive Search Ad). # # Args: # client: An initialized GoogleAdsClient instance. # customer_id: A client customer ID. # ad_group_resource_name: An ad group resource name. # # Returns: # Ad group ad resource name. def create_ad_group_ad(client, customer_id, ad_group_resource_name, customizer_attribute_resource_name=nil) ad_group_ad_service = client.service.ad_group_ad operation = client.operation.create_ad_group_ad do |aga| aga.status = :ENABLED aga.ad_group = ad_group_resource_name # Set responsive search ad info. # https://developers.google.com/google-ads/api/reference/rpc/latest/ResponsiveSearchAdInfo aga.ad = client.resource.ad do |ad| ad.final_urls << "https://www.example.com/" # Headline 1 (pinned) pinned_headline = create_ad_text_asset( client, "Headline 1 testing", client.enum.served_asset_field_type.HEADLINE_1, ) # Headlines ad.responsive_search_ad = client.resource.responsive_search_ad_info do |rsa| rsa.headlines << pinned_headline rsa.headlines << create_ad_text_asset(client, "Headline 2 testing") rsa.headlines << create_ad_text_asset(client, "Headline 3 testing") # Descriptions description_1 = create_ad_text_asset(client, "Desc 1 testing") description_2 = if customizer_attribute_resource_name create_ad_text_asset_with_customizer(client, customizer_attribute_resource_name) else create_ad_text_asset(client, "Desc 2 testing") end rsa.descriptions << description_1 rsa.descriptions << description_2 # Paths rsa.path1 = "all-inclusive" rsa.path2 = "deals" end end end # Send a request to the server to add a responsive search ad. response = ad_group_ad_service.mutate_ad_group_ads( customer_id: customer_id, operations: [operation], ) response.results.each do |result| puts "Created responsive search ad with resource name "#{result.resource_name}"." end end # Creates keywords. # # Creates 3 keyword match types: EXACT, PHRASE, and BROAD. # # Args: # client: An initialized GoogleAdsClient instance. # customer_id: A client customer ID. # ad_group_resource_name: An ad group resource name. def add_keywords(client, customer_id, ad_group_resource_name) ad_group_criterion_service = client.service.ad_group_criterion keywords_to_add = [ { text: KEYWORD_TEXT_EXACT, match_type: :EXACT }, { text: KEYWORD_TEXT_PHRASE, match_type: :PHRASE }, { text: KEYWORD_TEXT_BROAD, match_type: :BROAD }, ] operations = keywords_to_add.map do |keyword_info| client.operation.create_ad_group_criterion do |agc| agc.ad_group = ad_group_resource_name agc.status = :ENABLED agc.keyword = client.resource.keyword_info do |ki| ki.text = keyword_info[:text] ki.match_type = keyword_info[:match_type] end # Optional: agc.negative = true # Optional: agc.final_urls << 'https://www.example.com' end end # Add keywords response = ad_group_criterion_service.mutate_ad_group_criteria( customer_id: customer_id, operations: operations, ) response.results.each do |result| puts "Created keyword #{result.resource_name}." end end # Creates geo targets. # # Args: # client: An initialized GoogleAdsClient instance. # customer_id: A client customer ID. # campaign_resource_name: A campaign resource name. def add_geo_targeting(client, customer_id, campaign_resource_name) geo_target_constant_service = client.service.geo_target_constant # Search by location names from # GeoTargetConstantService.suggest_geo_target_constants() and directly # apply GeoTargetConstant.resource_name. gtc_request = client.request.suggest_geo_target_constants do |req| req.locale = LOCALE req.country_code = COUNTRY_CODE # The location names to get suggested geo target constants. req.location_names = client.resource.location_names do |ln| ln.names << GEO_LOCATION_1 ln.names << GEO_LOCATION_2 ln.names << GEO_LOCATION_3 end end response = geo_target_constant_service.suggest_geo_target_constants(gtc_request) operations = response.geo_target_constant_suggestions.map do |suggestion| puts "geo_target_constant: #{suggestion.geo_target_constant.resource_name} "\ "is found in LOCALE (#{suggestion.locale}) "\ "with reach (#{suggestion.reach}) "\ "from search term (#{suggestion.search_term})." # Create the campaign criterion for location targeting. client.operation.create_campaign_criterion do |cc| cc.campaign = campaign_resource_name cc.location = client.resource.location_info do |li| li.geo_target_constant = suggestion.geo_target_constant.resource_name end end end unless operations.empty? campaign_criterion_service = client.service.campaign_criterion response = campaign_criterion_service.mutate_campaign_criteria( customer_id: customer_id, operations: operations, ) response.results.each do |result| puts "Added campaign criterion "#{result.resource_name}"." end else puts "No geo target suggestions found for the given locations. Skipping campaign criteria creation." end end # Main function that creates all necessary entities for the example. # # Args: # client: An initialized GoogleAdsClient instance. # customer_id: A client customer ID. # customizer_attribute_name: The name of the customizer attribute to be created. def main_function(client, customer_id, customizer_attribute_name = nil) customizer_attribute_resource_name = nil if customizer_attribute_name customizer_attribute_resource_name = create_customizer_attribute( client, customer_id, customizer_attribute_name, ) link_customizer_attribute_to_customer( client, customer_id, customizer_attribute_resource_name, ) end # Create a budget, which can be shared by multiple campaigns. campaign_budget_resource_name = create_campaign_budget(client, customer_id) campaign_resource_name = create_campaign( client, customer_id, campaign_budget_resource_name, ) ad_group_resource_name = create_ad_group( client, customer_id, campaign_resource_name, ) create_ad_group_ad( client, customer_id, ad_group_resource_name, customizer_attribute_resource_name, # Pass the resource name here ) add_keywords(client, customer_id, ad_group_resource_name) add_geo_targeting(client, customer_id, campaign_resource_name) end # Entry point of the script if __FILE__ == $0 options = {} # The following parameter(s) should be provided to run the example. You can # either specify them here or provide them as command-line arguments. # # e.g. add_responsive_search_ad_full.rb -C YOUR_CUSTOMER_ID OptionParser.new do |opts| opts.banner = "Usage: add_responsive_search_ad_full.rb [options]" opts.on('-C', '--customer-id CUSTOMER-ID', String, 'Customer ID') do |v| options[:customer_id] = v end opts.on('-N', '--customizer-attribute-name CUSTOMIZER-ATTRIBUTE-NAME', String, 'Customizer attribute name') do |v| options[:customizer_attribute_name] = v end end.parse! if options[:customizer_attribute_name].nil? options[:customizer_attribute_name] = DEFAULT_CUSTOMIZER_ATTRIBUTE_NAME end # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. client = Google::Ads::GoogleAds::GoogleAdsClient.new begin main_function( client, options.fetch(:customer_id).tr("-", ""), options.fetch(:customizer_attribute_name), ) rescue Google::Ads::GoogleAds::Errors::GoogleAdsError => e e.failure.errors.each do |error| STDERR.puts " Error with message '#{error.message}'." if error.location error.location.field_path_elements.each do |field_path_element| STDERR.puts " On field: #{field_path_element.field_name}" end end end exit 1 rescue OptionParser::MissingArgument, KeyError puts "Missing required argument: -C or --customer-id" exit 1 end end
Perl
#!/usr/bin/perl -w # # Copyright 2024, Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # This example shows how to create a complete Responsive Search ad. # Includes creation of: budget, campaign, ad group, ad group ad, keywords, # and geo targeting. More details on Responsive Search ads can be found here: # https://support.google.com/google-ads/answer/7684791 use strict; use warnings; use utf8; use FindBin qw($Bin); use lib "$Bin/../../lib"; use Google::Ads::GoogleAds::Client; use Google::Ads::GoogleAds::Utils::GoogleAdsHelper; use Google::Ads::GoogleAds::V26::Resources::Campaign; use Google::Ads::GoogleAds::V26::Resources::CampaignBudget; use Google::Ads::GoogleAds::V26::Resources::CampaignCriterion; use Google::Ads::GoogleAds::V26::Resources::CustomizerAttribute; use Google::Ads::GoogleAds::V26::Resources::CustomerCustomizer; use Google::Ads::GoogleAds::V26::Resources::Ad; use Google::Ads::GoogleAds::V26::Resources::AdGroup; use Google::Ads::GoogleAds::V26::Resources::AdGroupAd; use Google::Ads::GoogleAds::V26::Resources::AdGroupCriterion; use Google::Ads::GoogleAds::V26::Resources::NetworkSettings; use Google::Ads::GoogleAds::V26::Common::AdTextAsset; use Google::Ads::GoogleAds::V26::Common::CustomizerValue; use Google::Ads::GoogleAds::V26::Common::ImageDimension; use Google::Ads::GoogleAds::V26::Common::KeywordInfo; use Google::Ads::GoogleAds::V26::Common::LocationInfo; use Google::Ads::GoogleAds::V26::Common::ResponsiveSearchAdInfo; use Google::Ads::GoogleAds::V26::Common::TargetSpend; use Google::Ads::GoogleAds::V26::Enums::AdvertisingChannelTypeEnum qw(SEARCH); use Google::Ads::GoogleAds::V26::Enums::BudgetDeliveryMethodEnum qw(STANDARD); use Google::Ads::GoogleAds::V26::Enums::CustomizerAttributeTypeEnum qw(PRICE); use Google::Ads::GoogleAds::V26::Enums::AdGroupAdStatusEnum; use Google::Ads::GoogleAds::V26::Enums::AdGroupCriterionStatusEnum; use Google::Ads::GoogleAds::V26::Enums::AdGroupStatusEnum; use Google::Ads::GoogleAds::V26::Enums::AdGroupTypeEnum qw(SEARCH_STANDARD); use Google::Ads::GoogleAds::V26::Enums::AssetTypeEnum qw(IMAGE); use Google::Ads::GoogleAds::V26::Enums::CampaignStatusEnum qw(PAUSED); use Google::Ads::GoogleAds::V26::Enums::KeywordMatchTypeEnum qw(BROAD EXACT PHRASE); use Google::Ads::GoogleAds::V26::Enums::MimeTypeEnum qw(IMAGE_PNG); use Google::Ads::GoogleAds::V26::Enums::ServedAssetFieldTypeEnum qw(HEADLINE_1); use Google::Ads::GoogleAds::V26::Services::AdGroupService::AdGroupOperation; use Google::Ads::GoogleAds::V26::Services::AdGroupAdService::AdGroupAdOperation; use Google::Ads::GoogleAds::V26::Services::AdGroupCriterionService::AdGroupCriterionOperation; use Google::Ads::GoogleAds::V26::Services::AssetService::AssetOperation; use Google::Ads::GoogleAds::V26::Services::CampaignBudgetService::CampaignBudgetOperation; use Google::Ads::GoogleAds::V26::Services::CampaignCriterionService::CampaignCriterionOperation; use Google::Ads::GoogleAds::V26::Services::CampaignService::CampaignOperation; use Google::Ads::GoogleAds::V26::Services::CustomizerAttributeService::CustomizerAttributeOperation; use Google::Ads::GoogleAds::V26::Services::CustomerCustomizerService::CustomerCustomizerOperation; use Google::Ads::GoogleAds::V26::Services::GeoTargetConstantService::LocationNames; use Google::Ads::GoogleAds::V26::Utils::ResourceNames; use Getopt::Long qw(:config auto_help); use Pod::Usage; use Cwd qw(abs_path); use Data::Uniqid qw(uniqid); # Keywords from the user. use constant KEYWORD_TEXT_EXACT => "example of exact match"; use constant KEYWORD_TEXT_PHRASE => "example of phrase match"; use constant KEYWORD_TEXT_BROAD => "example of broad match"; # Geo targeting from the user. use constant GEO_LOCATION_1 => "Buenos Aires"; use constant GEO_LOCATION_2 => "San Isidro"; use constant GEO_LOCATION_3 => "Mar del Plata"; # LOCALE and COUNTRY_CODE are used for geo targeting. # LOCALE is using ISO 639-1 format. If an invalid LOCALE is given, # 'es' is used by default. use constant LOCALE => "es"; # A list of country codes can be referenced here: # https://developers.google.com/google-ads/api/reference/data/geotargets use constant COUNTRY_CODE => "AR"; use constant IMAGE_URL => "https://gaagl.page.link/bjYi"; sub add_responsive_search_ad_full { my ($api_client, $customer_id, $customizer_attribute_name) = @_; # If a customizer attribute name is provided, create the customizer # attribute and link it to the customer. # For more information on customizer attributes, visit: # https://developers.google.com/google-ads/api/docs/ads/customize-responsive-search-ads if (defined $customizer_attribute_name) { my $customizer_attribute_resource_name = create_customizer_attribute($api_client, $customer_id, $customizer_attribute_name); link_customizer_attribute_to_customer($api_client, $customer_id, $customizer_attribute_resource_name); } # Create a budget, which can be shared by multiple campaigns. my $campaign_budget = create_campaign_budget($api_client, $customer_id); # Create a search campaign. my $campaign_resource_name = create_campaign($api_client, $customer_id, $campaign_budget); # Create an empty ad group. my $ad_group_resource_name = create_ad_group($api_client, $customer_id, $campaign_resource_name); # Create a responsive search ad within the ad group we just created. create_ad_group_ad($api_client, $customer_id, $ad_group_resource_name, $customizer_attribute_name); # Create 3 keywords of match type EXACT, PHRASE, and BROAD, and add them # as criteria on our ad group. add_keywords($api_client, $customer_id, $ad_group_resource_name); # Create geo targets and add them as criteria on our campaign. add_geo_targeting($api_client, $customer_id, $campaign_resource_name); return 1; } # Creates a customizer attribute with the given customizer attribute name. sub create_customizer_attribute { my ($api_client, $customer_id, $customizer_attribute_name) = @_; my $customizer_attribute = Google::Ads::GoogleAds::V26::Resources::CustomizerAttribute->new({ name => $customizer_attribute_name, # Specify the type to be 'PRICE' so that we can dynamically customize the part # of the ad's description that is a price of a product/service we advertise. type => PRICE }); # Create a customizer attribute operation for creating a customizer attribute. my $operation = Google::Ads::GoogleAds::V26::Services::CustomizerAttributeService::CustomizerAttributeOperation ->new({ create => $customizer_attribute }); my $response = $api_client->CustomizerAttributeService()->mutate({ customerId => $customer_id, operations => [$operation]}); my $resource_name = $response->{results}[0]{resourceName}; printf "Added a customizer attribute with resource name '%s'.\n", $resource_name; return $resource_name; } # Links the customizer attribute to the customer. sub link_customizer_attribute_to_customer { my ($api_client, $customer_id, $customizer_attribute_resource_name) = @_; # Create a customer customizer with the value to be used in the responsive search ad. my $customer_customizer = Google::Ads::GoogleAds::V26::Resources::CustomerCustomizer->new({ customizerAttribute => $customizer_attribute_resource_name, # Specify '100USD' as a text value. The ad customizer will dynamically replace # the placeholder with this value when the ad serves. value => Google::Ads::GoogleAds::V26::Common::CustomizerValue->new({ type => PRICE, stringValue => "100USD" })}); # Create a customer customizer operation. my $operation = Google::Ads::GoogleAds::V26::Services::CustomerCustomizerService::CustomerCustomizerOperation ->new({ create => $customer_customizer }); # Issue a mutate request to add the customer customizer and print its information. my $response = $api_client->CustomerCustomizerService()->mutate({ customerId => $customer_id, operations => [$operation]}); printf "Added a customer customizer with resource name '%s'.\n", $response->{results}[0]{resourceName}; } # Creates an AdTextAsset. sub create_ad_text_asset { my ($api_client, $text, $pinned_field) = @_; my $ad_text_asset = Google::Ads::GoogleAds::V26::Common::AdTextAsset->new({ text => $text }); if (defined $pinned_field) { $ad_text_asset->{pinnedField} = $pinned_field; } return $ad_text_asset; } # Creates an AdTextAsset with a customizer in the text. sub create_ad_text_asset_with_customizer { my ($api_client, $customizer_attribute_resource_name) = @_; my $ad_text_asset = create_ad_text_asset($api_client, "Just {CUSTOMIZER.$customizer_attribute_resource_name:10USD}"); return $ad_text_asset; } # Creates a campaign budget. sub create_campaign_budget { my ($api_client, $customer_id) = @_; # Create a campaign budget. my $campaign_budget = Google::Ads::GoogleAds::V26::Resources::CampaignBudget->new({ name => "Campaign budget " . uniqid(), amountMicros => 50000000, deliveryMethod => STANDARD }); # Create a campaign budget operation. my $campaign_budget_operation = Google::Ads::GoogleAds::V26::Services::CampaignBudgetService::CampaignBudgetOperation ->new({ create => $campaign_budget }); # Issue a mutate request to add the campaign budget. my $campaign_budgets_response = $api_client->CampaignBudgetService()->mutate({ customerId => $customer_id, operations => [$campaign_budget_operation]}); my $campaign_budget_resource_name = $campaign_budgets_response->{results}[0]{resourceName}; return $campaign_budget_resource_name; } # Creates a campaign. sub create_campaign { my ($api_client, $customer_id, $campaign_budget) = @_; # Create a campaign. my $campaign = Google::Ads::GoogleAds::V26::Resources::Campaign->new({ name => "Testing RSA via API " . uniqid(), campaignBudget => $campaign_budget, # Recommendation: Set the campaign to PAUSED when creating it to prevent # the ads from immediately serving. Set to ENABLED once you've added # targeting and the ads are ready to serve. status => PAUSED, advertisingChannelType => SEARCH, # Set the bidding strategy and budget. # The bidding strategy for Maximize Clicks is TargetSpend. # The target_spend_micros is deprecated so don't put any value. # See other bidding strategies you can select in the link below. # https://developers.google.com/google-ads/api/reference/rpc/latest/Campaign#campaign_bidding_strategy targetSpend => Google::Ads::GoogleAds::V26::Common::TargetSpend->new(), # Set the campaign network options networkSettings => Google::Ads::GoogleAds::V26::Resources::NetworkSettings->new({ targetGoogleSearch => "true", targetSearchNetwork => "true", # Enable Display Expansion on Search campaigns. See # https://support.google.com/google-ads/answer/7193800 to learn more. targetContentNetwork => "true", targetPartnerSearchNetwork => "false" } ), # Optional: Set the start datetime. The campaign starts tomorrow. # startDateTime => strftime("%Y%m%d 00:00:00", localtime(time + 60 * 60 * 24)), # Optional: Set the end datetime. The campaign runs for 30 days. # endDateTime => strftime("%Y%m%d 23:59:59", localtime(time + 60 * 60 * 24 * 30)), }); # Create a campaign operation. my $campaign_operation = Google::Ads::GoogleAds::V26::Services::CampaignService::CampaignOperation-> new({ create => $campaign }); # Issue a mutate request to add the campaign. my $campaigns_response = $api_client->CampaignService()->mutate({ customerId => $customer_id, operations => [$campaign_operation]}); my $resource_name = $campaigns_response->{results}[0]{resourceName}; printf "Created App campaign with resource name: '%s'.\n", $resource_name; return $resource_name; } # Creates an ad group. sub create_ad_group { my ($api_client, $customer_id, $campaign_resource_name) = @_; # Create an ad group, setting an optional CPC value. my $ad_group = Google::Ads::GoogleAds::V26::Resources::AdGroup->new({ name => "Testing RSA via API " . uniqid(), status => Google::Ads::GoogleAds::V26::Enums::AdGroupStatusEnum::ENABLED, campaign => $campaign_resource_name, type => SEARCH_STANDARD, # If you want to set up a max CPC bid, uncomment the line below. # cpcBidMicros => 10000000 }); # Create an ad group operation. my $ad_group_operation = Google::Ads::GoogleAds::V26::Services::AdGroupService::AdGroupOperation-> new({create => $ad_group}); # Add the ad group. my $ad_groups_response = $api_client->AdGroupService()->mutate({ customerId => $customer_id, operations => [$ad_group_operation]}); my $ad_group_resource_name = $ad_groups_response->{results}[0]{resourceName}; printf "Created ad group '%s'.\n", $ad_group_resource_name; return $ad_group_resource_name; } # Creates an ad group ad. sub create_ad_group_ad { my ($api_client, $customer_id, $ad_group_resource_name, $customizer_attribute_name) = @_; # Set a pinning to always choose this asset for HEADLINE_1. Pinning is optional; if no # pinning is set, then headlines and descriptions will be rotated and the ones that perform # best will be used more often. my $pinned_headline = create_ad_text_asset($api_client, "Headline 1 testing", HEADLINE_1); my $ad_group_ad = Google::Ads::GoogleAds::V26::Resources::AdGroupAd->new({ adGroup => $ad_group_resource_name, status => Google::Ads::GoogleAds::V26::Enums::AdGroupAdStatusEnum::ENABLED, ad => Google::Ads::GoogleAds::V26::Resources::Ad->new({ # Set responsive search ad info. # https://developers.google.com/google-ads/api/reference/rpc/latest/ResponsiveSearchAdInfo responsiveSearchAd => Google::Ads::GoogleAds::V26::Common::ResponsiveSearchAdInfo->new({ headlines => [ $pinned_headline, create_ad_text_asset($api_client, "Headline 2 testing"), create_ad_text_asset($api_client, "Headline 3 testing"), ], descriptions => [ create_ad_text_asset($api_client, "Desc 1 testing"), defined $customizer_attribute_name ? create_ad_text_asset_with_customizer($api_client, $customizer_attribute_name) : create_ad_text_asset($api_client, "Desc 2 testing"), ], # First and second part of text that can be appended to the URL in the ad. # If you use the examples below, the ad will show # https://www.example.com/all-inclusive/deals path1 => "all-inclusive", path2 => "deals" } ), finalUrls => ["https://www.example.com"]})}); # Create an ad group ad operation. my $operation = Google::Ads::GoogleAds::V26::Services::AdGroupAdService::AdGroupAdOperation ->new({ create => $ad_group_ad }); # Issue a mutate request to add the ad group ad and print its information. my $response = $api_client->AdGroupAdService()->mutate({ customerId => $customer_id, operations => [$operation]}); printf "Created responsive search ad with resource name '%s'.\n", $response->{results}[0]{resourceName}; } # Creates keywords of 3 keyword match types: EXACT, PHRASE, and BROAD. # EXACT: ads may show on searches that ARE the same meaning as your keyword. # PHRASE: ads may show on searches that INCLUDE the meaning of your keyword. # BROAD: ads may show on searches that RELATE to your keyword. # For smart bidding, BROAD is the recommended one. sub add_keywords { my ($api_client, $customer_id, $ad_group_resource_name) = @_; my $operations = []; # Create a hash of keyword match types to keyword text to simplify ad group # criteria construction. my $keywords = { EXACT() => KEYWORD_TEXT_EXACT, BROAD() => KEYWORD_TEXT_BROAD, PHRASE() => KEYWORD_TEXT_PHRASE, }; foreach my $keyword (keys %$keywords) { my $keyword_info = Google::Ads::GoogleAds::V26::Common::KeywordInfo->new({ text => $keywords->{$keyword}, matchType => $keyword, }); my $ad_group_criterion = Google::Ads::GoogleAds::V26::Resources::AdGroupCriterion->new({ adGroup => $ad_group_resource_name, status => Google::Ads::GoogleAds::V26::Enums::AdGroupCriterionStatusEnum::ENABLED, keyword => $keyword_info, # Uncomment the below line if you want to change this keyword to a negative target. # negative => "true", # Optional repeated field. # finalUrls => ["https://www.example.com"], }); my $ad_group_criterion_operation = Google::Ads::GoogleAds::V26::Services::AdGroupCriterionService::AdGroupCriterionOperation ->new({create => $ad_group_criterion}); push @$operations, $ad_group_criterion_operation; } my $response = $api_client->AdGroupCriterionService()->mutate({ customerId => $customer_id, operations => $operations }); foreach my $result (@{$response->{results}}) { printf "Created keyword with resource name: '%s'.\n", $result->{resourceName}; } } # Creates geo targets. sub add_geo_targeting { my ($api_client, $customer_id, $campaign_resource_name) = @_; my $suggest_response = $api_client->GeoTargetConstantService()->suggest({ locale => LOCALE, countryCode => COUNTRY_CODE, locationNames => Google::Ads::GoogleAds::V26::Services::GeoTargetConstantService::LocationNames ->new({ names => [GEO_LOCATION_1, GEO_LOCATION_2, GEO_LOCATION_3]})}); my $operations = []; foreach my $geo_target_constant_suggestion ( @{$suggest_response->{geoTargetConstantSuggestions}}) { printf "geo target constant: '%s' is found in locale '%s' with reach %d" . " for the search term '%s'.\n", $geo_target_constant_suggestion->{geoTargetConstant}{resourceName}, $geo_target_constant_suggestion->{locale}, $geo_target_constant_suggestion->{reach}, $geo_target_constant_suggestion->{searchTerm}; # Create the campaign criterion for location targeting. my $campaign_criterion = Google::Ads::GoogleAds::V26::Resources::CampaignCriterion->new({ location => Google::Ads::GoogleAds::V26::Common::LocationInfo->new({ geoTargetConstant => $geo_target_constant_suggestion->{geoTargetConstant}{resourceName} } ), campaign => $campaign_resource_name }); push @$operations, Google::Ads::GoogleAds::V26::Services::CampaignCriterionService::CampaignCriterionOperation ->new({ create => $campaign_criterion }); } # Return if operations is empty. if (scalar @$operations == 0) { return; } my $campaign_criterion_response = $api_client->CampaignCriterionService()->mutate({ customerId => $customer_id, operations => $operations }); my $campaign_criterion_results = $campaign_criterion_response->{results}; printf "Added %d campaign criteria:\n", scalar @$campaign_criterion_results; foreach my $campaign_criterion_result (@$campaign_criterion_results) { printf "\t%s\n", $campaign_criterion_result->{resourceName}; } } # Don't run the example if the file is being included. if (abs_path($0) ne abs_path(__FILE__)) { return 1; } # Get Google Ads Client, credentials will be read from ~/googleads.properties. my $api_client = Google::Ads::GoogleAds::Client->new(); # By default examples are set to die on any server returned fault. $api_client->set_die_on_faults(1); my $customer_id; my $customizer_attribute_name; # Parameters passed on the command line will override any parameters set in code. GetOptions( "customer_id=s" => \$customer_id, "customizer_attribute_name=s" => \$customizer_attribute_name, ); # Print the help message if the parameters are not initialized in the code nor # in the command line. pod2usage(2) if not check_params($customer_id); # Call the example. add_responsive_search_ad_full($api_client, $customer_id =~ s/-//gr, $customizer_attribute_name); =pod =head1 NAME add_responsive_search_ad_full =head1 DESCRIPTION This example shows how to create a complete Responsive Search ad. Includes creation of: budget, campaign, ad group, ad group ad, keywords, and geo targeting. More details on Responsive Search ads can be found here: https://support.google.com/google-ads/answer/7684791 =head1 SYNOPSIS add_responsive_search_ad_full.pl [options] -help Show the help message. -customer_id The Google Ads customer ID. -customizer_attribute_name [optional] The name of the customizer attribute. =cut
curl
REST 요청 및 응답 구조
REST를 통해 검색 캠페인을 원자적으로 만들려면 음수 임시 ID (-1, -2, -3)를 사용하여 GoogleAdsService.Mutate에 POST 요청을 전송하여 단일 트랜잭션에서 예산, 캠페인, 광고 그룹, 키워드 기준, 반응형 검색 광고를 연결합니다.
POST https://googleads.googleapis.com/v26/customers/{customer_id}/googleAds:mutate
{
"mutateOperations": [
{
"campaignBudgetOperation": {
"create": {
"resourceName": "customers/{customer_id}/campaignBudgets/-1",
"name": "Search Campaign Budget #1",
"deliveryMethod": "STANDARD",
"amountMicros": "50000000",
"explicitlyShared": false
}
}
},
{
"campaignOperation": {
"create": {
"resourceName": "customers/{customer_id}/campaigns/-2",
"name": "Search Campaign #1",
"advertisingChannelType": "SEARCH",
"status": "PAUSED",
"manualCpc": {},
"campaignBudget": "customers/{customer_id}/campaignBudgets/-1",
"networkSettings": {
"targetGoogleSearch": true,
"targetSearchNetwork": true,
"targetContentNetwork": false,
"targetPartnerSearchNetwork": false
},
"containsEuPoliticalAdvertising": "DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING"
}
}
},
{
"adGroupOperation": {
"create": {
"resourceName": "customers/{customer_id}/adGroups/-3",
"name": "Search Ad Group #1",
"campaign": "customers/{customer_id}/campaigns/-2",
"status": "ENABLED",
"type": "SEARCH_STANDARD",
"cpcBidMicros": "10000000"
}
}
},
{
"adGroupCriterionOperation": {
"create": {
"adGroup": "customers/{customer_id}/adGroups/-3",
"status": "ENABLED",
"keyword": {
"text": "mars cruise",
"matchType": "BROAD"
}
}
}
},
{
"adGroupAdOperation": {
"create": {
"adGroup": "customers/{customer_id}/adGroups/-3",
"status": "PAUSED",
"ad": {
"finalUrls": [
"https://www.example.com"
],
"responsiveSearchAd": {
"headlines": [
{
"text": "Cruise to Mars",
"pinnedField": "HEADLINE_1"
},
{
"text": "Best Space Cruise Line"
},
{
"text": "Experience the Stars"
}
],
"descriptions": [
{
"text": "Buy your tickets now"
},
{
"text": "Visit the Red Planet"
}
],
"path1": "all-inclusive",
"path2": "deals"
}
}
}
}
}
]
}
응답에 성공하면 제출된 순서대로 각 작업에 대한 mutateOperationResponses 항목이 반환되며, 음수 임시 ID는 영구 리소스 이름으로 대체됩니다.
{
"mutateOperationResponses": [
{
"campaignBudgetResult": {
"resourceName": "customers/{customer_id}/campaignBudgets/1111111111"
}
},
{
"campaignResult": {
"resourceName": "customers/{customer_id}/campaigns/2222222222"
}
},
{
"adGroupResult": {
"resourceName": "customers/{customer_id}/adGroups/3333333333"
}
},
{
"adGroupCriterionResult": {
"resourceName": "customers/{customer_id}/adGroupCriteria/3333333333~5555555555"
}
},
{
"adGroupAdResult": {
"resourceName": "customers/{customer_id}/adGroupAds/3333333333~4444444444"
}
}
]
}
검색 캠페인 확인하기
검색 캠페인을 만든 후 GoogleAdsService.SearchStream를 쿼리하여 생성된 캠페인, 예산 할당, 광고 그룹, 반응형 검색 광고 확장 소재를 ad_strength 및 정책 승인 상태와 함께 확인합니다.
SELECT
campaign.id,
campaign.name,
campaign.status,
campaign.primary_status,
campaign.campaign_budget,
campaign.bidding_strategy_type,
campaign.contains_eu_political_advertising,
ad_group.id,
ad_group.name,
ad_group.status,
ad_group.type,
ad_group_ad.ad.id,
ad_group_ad.status,
ad_group_ad.ad_strength,
ad_group_ad.policy_summary.approval_status,
ad_group_ad.ad.final_urls,
ad_group_ad.ad.responsive_search_ad.headlines,
ad_group_ad.ad.responsive_search_ad.descriptions
FROM ad_group_ad
WHERE campaign.advertising_channel_type = 'SEARCH'
AND campaign.status != 'REMOVED'
AND ad_group_ad.status != 'REMOVED'
광고 그룹에 연결된 키워드 기준을 확인하려면 ad_group_criterion를 쿼리합니다.
SELECT
campaign.id,
ad_group.id,
ad_group_criterion.criterion_id,
ad_group_criterion.keyword.text,
ad_group_criterion.keyword.match_type,
ad_group_criterion.status,
ad_group_criterion.approval_status
FROM ad_group_criterion
WHERE ad_group_criterion.type = 'KEYWORD'
AND campaign.advertising_channel_type = 'SEARCH'
AND ad_group_criterion.status != 'REMOVED'
권장사항
- 설정 중에 새 캠페인 또는 광고 일시중지: 이렇게 하면 불완전한 상태에서 광고가 게재되는 것을 방지하여 처음부터 더 나은 사용자 경험과 캠페인 실적을 만들 수 있습니다.
- 공유 제외 키워드 목록 사용: 관련 없는 검색어를 제외하여 트래픽 품질과 광고비 지출 효율성을 개선할 수 있습니다.
- 전환 추적 구현: 이를 통해 비즈니스 목표에 부합하는 액션 (예: 판매 또는 가입)을 측정하고 이에 따라 캠페인을 최적화할 수 있습니다.