클릭 전환수 업로드

Google Ads API를 사용하여 오프라인 클릭 전환을 Google Ads에 업로드하면 전화 또는 영업사원을 통해 오프라인에서 판매로 이어진 광고를 추적할 수 있습니다.

설정

오프라인 전환 설정을 사용하려면 몇 가지 기본 요건이 충족되어야 합니다. 구현을 진행하기 전에 모든 기본 요건이 충족되는지 확인하세요.

  1. Google Ads 전환 고객에서 전환 추적을 사용 설정합니다.

  2. 태그 지정을 구성하고 클릭 ID를 저장합니다.

1. Google Ads 전환 고객에서 전환 추적 사용 설정하기

전환 시작 가이드를 완료하고 전환 추적을 사용 설정한 경우 2단계: 태그 구성으로 건너뛰어도 됩니다.

전환 추적 설정에 대한 정보 검색

ConversionTrackingSettingCustomer 리소스를 쿼리하여 계정의 전환 추적 설정을 확인하고 전환 추적이 사용 설정되어 있는지 확인할 수 있습니다. GoogleAdsService.SearchStream를 사용하여 다음 쿼리를 실행합니다.

SELECT
  customer.conversion_tracking_setting.google_ads_conversion_customer,
  customer.conversion_tracking_setting.conversion_tracking_status,
  customer.conversion_tracking_setting.conversion_tracking_id,
  customer.conversion_tracking_setting.cross_account_conversion_tracking_id
FROM customer

google_ads_conversion_customer 필드는 이 고객의 전환을 생성하고 관리하는 Google Ads 계정을 나타냅니다. 교차 계정 전환 추적을 사용하는 고객의 경우 관리자 계정의 ID입니다. 전환을 생성하고 관리하려면 Google Ads API 요청에서 Google Ads 전환 고객 ID를 customer_id로 지정해야 합니다. 전환 추적이 사용 설정되지 않은 경우에도 이 필드는 채워집니다.

conversion_tracking_status 필드는 전환 추적이 사용 설정되어 있는지, 계정에서 교차 계정 전환 추적을 사용하고 있는지 나타냅니다.

Google Ads 전환 고객 아래에서 전환 액션 만들기

conversion_tracking_status 값이 NOT_CONVERSION_TRACKED이면 계정에 전환 추적이 사용 설정되어 있지 않은 것입니다. 다음 예와 같이 Google Ads 전환 계정에서 ConversionAction를 하나 이상 만들어 전환 추적을 사용 설정합니다. 또는 사용 설정하려는 전환 유형에 관한 고객센터의 안내에 따라 UI에서 전환 액션을 만들 수 있습니다.

향상된 전환은 Google Ads API를 통해 전송될 때 자동으로 사용 설정되지만 Google Ads UI를 통해 사용 중지할 수 있습니다.

코드 예

자바

private void runExample(GoogleAdsClient googleAdsClient, long customerId) {

  // Creates a ConversionAction.
  ConversionAction conversionAction =
      ConversionAction.newBuilder()
          // Note that conversion action names must be unique. If a conversion action already
          // exists with the specified conversion_action_name the create operation will fail with
          // a ConversionActionError.DUPLICATE_NAME error.
          .setName("Earth to Mars Cruises Conversion #" + getPrintableDateTime())
          .setCategory(ConversionActionCategory.DEFAULT)
          .setType(ConversionActionType.WEBPAGE)
          .setStatus(ConversionActionStatus.ENABLED)
          .setViewThroughLookbackWindowDays(15L)
          .setValueSettings(
              ValueSettings.newBuilder()
                  .setDefaultValue(23.41)
                  .setAlwaysUseDefaultValue(true)
                  .build())
          .build();

  // Creates the operation.
  ConversionActionOperation operation =
      ConversionActionOperation.newBuilder().setCreate(conversionAction).build();

  try (ConversionActionServiceClient conversionActionServiceClient =
      googleAdsClient.getLatestVersion().createConversionActionServiceClient()) {
    MutateConversionActionsResponse response =
        conversionActionServiceClient.mutateConversionActions(
            Long.toString(customerId), Collections.singletonList(operation));
    System.out.printf("Added %d conversion actions:%n", response.getResultsCount());
    for (MutateConversionActionResult result : response.getResultsList()) {
      System.out.printf(
          "New conversion action added with resource name: '%s'%n", result.getResourceName());
    }
  }
}
      

C#

public void Run(GoogleAdsClient client, long customerId)
{
    // Get the ConversionActionService.
    ConversionActionServiceClient conversionActionService =
        client.GetService(Services.V18.ConversionActionService);

    // Note that conversion action names must be unique.
    // If a conversion action already exists with the specified name the create operation
    // will fail with a ConversionAction.DUPLICATE_NAME error.
    string ConversionActionName = "Earth to Mars Cruises Conversion #"
        + ExampleUtilities.GetRandomString();

    // Add a conversion action.
    ConversionAction conversionAction = new ConversionAction()
    {
        Name = ConversionActionName,
        Category = ConversionActionCategory.Default,
        Type = ConversionActionType.Webpage,
        Status = ConversionActionStatus.Enabled,
        ViewThroughLookbackWindowDays = 15,
        ValueSettings = new ConversionAction.Types.ValueSettings()
        {
            DefaultValue = 23.41,
            AlwaysUseDefaultValue = true
        }
    };

    // Create the operation.
    ConversionActionOperation operation = new ConversionActionOperation()
    {
        Create = conversionAction
    };

    try
    {
        // Create the conversion action.
        MutateConversionActionsResponse response =
            conversionActionService.MutateConversionActions(customerId.ToString(),
                    new ConversionActionOperation[] { operation });

        // Display the results.
        foreach (MutateConversionActionResult newConversionAction in response.Results)
        {
            Console.WriteLine($"New conversion action with resource name = " +
                $"'{newConversionAction.ResourceName}' was added.");
        }
    }
    catch (GoogleAdsException e)
    {
        Console.WriteLine("Failure:");
        Console.WriteLine($"Message: {e.Message}");
        Console.WriteLine($"Failure: {e.Failure}");
        Console.WriteLine($"Request ID: {e.RequestId}");
        throw;
    }
}
      

PHP

public static function runExample(GoogleAdsClient $googleAdsClient, int $customerId)
{
    // Creates a conversion action.
    $conversionAction = new ConversionAction([
        // Note that conversion action names must be unique.
        // If a conversion action already exists with the specified conversion_action_name
        // the create operation will fail with a ConversionActionError.DUPLICATE_NAME error.
        'name' => 'Earth to Mars Cruises Conversion #' . Helper::getPrintableDatetime(),
        'category' => ConversionActionCategory::PBDEFAULT,
        'type' => ConversionActionType::WEBPAGE,
        'status' => ConversionActionStatus::ENABLED,
        'view_through_lookback_window_days' => 15,
        'value_settings' => new ValueSettings([
            'default_value' => 23.41,
            'always_use_default_value' => true
        ])
    ]);

    // Creates a conversion action operation.
    $conversionActionOperation = new ConversionActionOperation();
    $conversionActionOperation->setCreate($conversionAction);

    // Issues a mutate request to add the conversion action.
    $conversionActionServiceClient = $googleAdsClient->getConversionActionServiceClient();
    $response = $conversionActionServiceClient->mutateConversionActions(
        MutateConversionActionsRequest::build($customerId, [$conversionActionOperation])
    );

    printf("Added %d conversion actions:%s", $response->getResults()->count(), PHP_EOL);

    foreach ($response->getResults() as $addedConversionAction) {
        /** @var ConversionAction $addedConversionAction */
        printf(
            "New conversion action added with resource name: '%s'%s",
            $addedConversionAction->getResourceName(),
            PHP_EOL
        );
    }
}
      

Python

def main(client, customer_id):
    conversion_action_service = client.get_service("ConversionActionService")

    # Create the operation.
    conversion_action_operation = client.get_type("ConversionActionOperation")

    # Create conversion action.
    conversion_action = conversion_action_operation.create

    # Note that conversion action names must be unique. If a conversion action
    # already exists with the specified conversion_action_name, the create
    # operation will fail with a ConversionActionError.DUPLICATE_NAME error.
    conversion_action.name = f"Earth to Mars Cruises Conversion {uuid.uuid4()}"
    conversion_action.type_ = (
        client.enums.ConversionActionTypeEnum.UPLOAD_CLICKS
    )
    conversion_action.category = (
        client.enums.ConversionActionCategoryEnum.DEFAULT
    )
    conversion_action.status = client.enums.ConversionActionStatusEnum.ENABLED
    conversion_action.view_through_lookback_window_days = 15

    # Create a value settings object.
    value_settings = conversion_action.value_settings
    value_settings.default_value = 15.0
    value_settings.always_use_default_value = True

    # Add the conversion action.
    conversion_action_response = (
        conversion_action_service.mutate_conversion_actions(
            customer_id=customer_id,
            operations=[conversion_action_operation],
        )
    )

    print(
        "Created conversion action "
        f'"{conversion_action_response.results[0].resource_name}".'
    )
      

Ruby

def add_conversion_action(customer_id)
  # GoogleAdsClient will read a config file from
  # ENV['HOME']/google_ads_config.rb when called without parameters
  client = Google::Ads::GoogleAds::GoogleAdsClient.new


  # Add a conversion action.
  conversion_action = client.resource.conversion_action do |ca|
    ca.name = "Earth to Mars Cruises Conversion #{(Time.new.to_f * 100).to_i}"
    ca.type = :UPLOAD_CLICKS
    ca.category = :DEFAULT
    ca.status = :ENABLED
    ca.view_through_lookback_window_days = 15

    # Create a value settings object.
    ca.value_settings = client.resource.value_settings do |vs|
      vs.default_value = 15
      vs.always_use_default_value = true
    end
  end

  # Create the operation.
  conversion_action_operation = client.operation.create_resource.conversion_action(conversion_action)

  # Add the ad group ad.
  response = client.service.conversion_action.mutate_conversion_actions(
    customer_id: customer_id,
    operations: [conversion_action_operation],
  )

  puts "New conversion action with resource name = #{response.results.first.resource_name}."
end
      

Perl

sub add_conversion_action {
  my ($api_client, $customer_id) = @_;

  # Note that conversion action names must be unique.
  # If a conversion action already exists with the specified conversion_action_name,
  # the create operation fails with error ConversionActionError.DUPLICATE_NAME.
  my $conversion_action_name = "Earth to Mars Cruises Conversion #" . uniqid();

  # Create a conversion action.
  my $conversion_action =
    Google::Ads::GoogleAds::V18::Resources::ConversionAction->new({
      name                          => $conversion_action_name,
      category                      => DEFAULT,
      type                          => WEBPAGE,
      status                        => ENABLED,
      viewThroughLookbackWindowDays => 15,
      valueSettings                 =>
        Google::Ads::GoogleAds::V18::Resources::ValueSettings->new({
          defaultValue          => 23.41,
          alwaysUseDefaultValue => "true"
        })});

  # Create a conversion action operation.
  my $conversion_action_operation =
    Google::Ads::GoogleAds::V18::Services::ConversionActionService::ConversionActionOperation
    ->new({create => $conversion_action});

  # Add the conversion action.
  my $conversion_actions_response =
    $api_client->ConversionActionService()->mutate({
      customerId => $customer_id,
      operations => [$conversion_action_operation]});

  printf "New conversion action added with resource name: '%s'.\n",
    $conversion_actions_response->{results}[0]{resourceName};

  return 1;
}
      

conversion_action_type가 올바른 ConversionActionType 값으로 설정되어 있는지 확인합니다. Google Ads API에서 전환 액션을 만드는 방법에 관한 자세한 내용은 전환 액션 만들기를 참고하세요.

기존 전환 액션 가져오기

다음 쿼리를 실행하여 기존 전환 액션의 세부정보를 검색할 수 있습니다. 요청의 고객 ID가 위에 식별한 Google Ads 전환 고객으로 설정되어 있고 전환 액션 유형이 올바른 ConversionActionType 값으로 설정되어 있는지 확인합니다.

SELECT
  conversion_action.resource_name,
  conversion_action.name,
  conversion_action.status
FROM conversion_action
WHERE conversion_action.type = 'INSERT_CONVERSION_ACTION_TYPE'

2. 태그 지정 구성 및 클릭 ID 저장

안내에 따라 자동 태그 추가가 사용 설정되어 있는지 확인합니다. Google Ads 계정, 웹사이트, 리드 추적 시스템을 설정하여 광고의 각 노출 및 클릭의 GCLID, GBRAID 또는 WBRAID를 캡처하고 저장합니다. 새 계정의 경우 자동 태그 추가 기능이 기본적으로 사용 설정됩니다.

요청 구성

아래 안내에 따라 UploadClickConversionsRequest를 구성하고 필드를 적절한 값으로 설정하세요.

customer_id

업로드의 Google Ads 계정을 식별합니다. 클릭 소스인 계정의 Google Ads 전환 고객으로 설정합니다.

job_id

업로드 요청을 오프라인 데이터 진단의 작업별 정보와 연결하는 메커니즘을 제공합니다.

이 필드를 설정하지 않으면 Google Ads API는 각 요청에 [2^31, 2^63) 범위의 고유한 값을 할당합니다. 여러 요청을 단일 논리 작업으로 그룹화하려면 작업의 모든 요청에서 이 필드를 [0, 2^31) 범위의 동일한 값으로 설정하세요.

응답job_id에는 값을 지정했는지 또는 Google Ads API가 값을 할당했는지와 관계없이 요청의 작업 ID가 포함됩니다.

partial_failure_enabled

Google Ads API가 작업의 오류를 처리하는 방식을 결정합니다.

이 필드는 true로 설정되어야 합니다. 응답을 처리할 때는 부분 실패 가이드라인을 따르세요.

debug_enabled

리드 확보용 향상된 전환 업로드의 오류 보고 동작을 결정합니다. Google Ads API는 gclid, gbraid 또는 wbraid를 사용하여 클릭 전환 업로드를 처리할 때 이 필드를 무시합니다.

클릭 전환 작업 만들기

UploadClickConversionRequestClickConversion 객체 모음은 업로드할 전환 세트를 정의합니다. 아래 안내에 따라 각 ClickConversion를 구성하고 필드를 적절한 값으로 설정합니다.

각 전환 작업의 필수 입력란 설정

아래 안내에 따라 ClickConversion의 필수 입력란을 적절한 값으로 설정합니다.

gclid, gbraid, wbraid
전환의 클릭 또는 노출을 클릭할 때 캡처한 식별자입니다. 이 필드 중 하나만 설정합니다.
conversion_date_time

전환 날짜 및 시간입니다.

값에는 시간대가 지정되어야 하며 형식은 yyyy-mm-dd HH:mm:ss+|-HH:mm여야 합니다(예: 2022-01-01 19:32:45-05:00(일광 절약 시간 무시)).

시간대는 유효한 값이면 됩니다. 계정의 시간대와 일치할 필요는 없습니다. 하지만 업로드한 전환 데이터를 Google Ads UI의 전환 데이터와 비교하려는 경우 전환수가 일치하도록 Google Ads 계정과 동일한 시간대를 사용하는 것이 좋습니다. 고객센터에서 자세한 내용과 예시를 확인하고 유효한 시간대 ID 목록은 코드 및 형식을 참고하세요.

user_identifiers

클릭 ID만 사용하여 전환을 업로드할 때는 이 필드를 설정하지 마세요. 이 필드가 설정되면 Google Ads에서 업로드 작업을 리드 확보용 향상된 전환의 업로드로 간주합니다.

conversion_action

클릭 전환의 ConversionAction 리소스 이름입니다.

전환 액션의 typeUPLOAD_CLICKS여야 하며 클릭과 연결된 Google Ads 계정의 Google Ads 전환 고객에 있어야 합니다.

conversion_value

전환의 가치입니다.

currency_code

conversion_value통화 코드입니다.

각 전환 작업의 선택적 입력란 설정

아래의 선택사항 필드 목록을 검토하고 필요에 따라 ClickConversion에서 설정하세요.

order_id
전환의 거래 ID입니다. 이 입력란은 선택사항이지만 입력하는 것이 좋습니다. 업로드 중에 설정하는 경우 전환에 대한 조정 시 이를 사용해야 합니다. 거래 ID를 사용하여 중복 전환을 최소화하는 방법에 대해 자세히 알아보려면 이 고객센터 도움말을 참고하세요.
external_attribution_data

서드 파티 도구 또는 자체 개발 솔루션을 사용하여 전환을 추적하는 경우 Google Ads에 전환 기여도를 일부만 부여하거나 여러 클릭에 전환 기여도를 분산할 수 있습니다. 외부 기여 분석 전환 가져오기를 사용하면 각 클릭에 할당된 부분 기여도로 전환을 업로드할 수 있습니다.

비율로 된 크레딧을 업로드하려면 이 필드를 external_attribution_modelexternal_attribution_credit 값이 있는 ExternalAttributionData 객체로 설정합니다.

custom_variables

맞춤 전환 변수의 값입니다.

Google Ads에서는 wbraid 또는 gbraid와 함께 맞춤 전환 변수를 지원하지 않습니다.

cart_data

cart_data 필드에 ClickConversion장바구니 데이터를 포함할 수 있으며, 이 데이터는 다음 속성으로 구성됩니다.

  • merchant_id: 연결된 판매자 센터 계정의 ID입니다.
  • feed_country_code: 판매자 센터 피드의 ISO 3166 2자리 지역 코드입니다.
  • feed_language_code: 판매자 센터 피드의 ISO 639-1 언어 코드입니다.
  • local_transaction_cost: ClickConversioncurrency_code에 있는 모든 거래 수준 할인 금액의 합계입니다.
  • items: 장바구니에 있는 상품입니다.

items의 각 항목은 다음 속성으로 구성됩니다.

  • product_id: 제품의 ID로, 제품 ID 또는 상품 ID라고도 합니다.
  • quantity: 상품 수량입니다.
  • unit_price: 상품의 단가입니다.

conversion_environment

이 전환이 기록된 환경을 나타냅니다. 예를 들어 앱 또는 웹

코드 예

자바

private void runExample(
    GoogleAdsClient googleAdsClient,
    long customerId,
    long conversionActionId,
    String gclid,
    String gbraid,
    String wbraid,
    String conversionDateTime,
    Double conversionValue,
    Long conversionCustomVariableId,
    String conversionCustomVariableValue,
    String orderId,
    ConsentStatus adUserDataConsent)
    throws InvalidProtocolBufferException {
  // Verifies that exactly one of gclid, gbraid, and wbraid is specified, as required.
  // See https://developers.google.com/google-ads/api/docs/conversions/upload-clicks for details.
  long numberOfIdsSpecified =
      Arrays.asList(gclid, gbraid, wbraid).stream().filter(idField -> idField != null).count();
  if (numberOfIdsSpecified != 1) {
    throw new IllegalArgumentException(
        "Exactly 1 of gclid, gbraid, or wbraid is required, but "
            + numberOfIdsSpecified
            + " ID values were provided");
  }

  // Constructs the conversion action resource name from the customer and conversion action IDs.
  String conversionActionResourceName =
      ResourceNames.conversionAction(customerId, conversionActionId);

  // Creates the click conversion.
  ClickConversion.Builder clickConversionBuilder =
      ClickConversion.newBuilder()
          .setConversionAction(conversionActionResourceName)
          .setConversionDateTime(conversionDateTime)
          .setConversionValue(conversionValue)
          .setCurrencyCode("USD");

  // Sets the single specified ID field.
  if (gclid != null) {
    clickConversionBuilder.setGclid(gclid);
  } else if (gbraid != null) {
    clickConversionBuilder.setGbraid(gbraid);
  } else {
    clickConversionBuilder.setWbraid(wbraid);
  }

  if (conversionCustomVariableId != null && conversionCustomVariableValue != null) {
    // Sets the custom variable and value, if provided.
    clickConversionBuilder.addCustomVariables(
        CustomVariable.newBuilder()
            .setConversionCustomVariable(
                ResourceNames.conversionCustomVariable(customerId, conversionCustomVariableId))
            .setValue(conversionCustomVariableValue));
  }

  if (orderId != null) {
    // Sets the order ID (unique transaction ID), if provided.
    clickConversionBuilder.setOrderId(orderId);
  }

  // Sets the consent information, if provided.
  if (adUserDataConsent != null) {
    // Specifies whether user consent was obtained for the data you are uploading. See
    // https://www.google.com/about/company/user-consent-policy for details.
    clickConversionBuilder.setConsent(Consent.newBuilder().setAdUserData(adUserDataConsent));
  }
  ClickConversion clickConversion = clickConversionBuilder.build();

  // Creates the conversion upload service client.
  try (ConversionUploadServiceClient conversionUploadServiceClient =
      googleAdsClient.getLatestVersion().createConversionUploadServiceClient()) {
    // Uploads the click conversion. Partial failure should always be set to true.

    // NOTE: This request contains a single conversion as a demonstration.  However, if you have
    // multiple conversions to upload, it's best to upload multiple conversions per request
    // instead of sending a separate request per conversion. See the following for per-request
    // limits:
    // https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service
    UploadClickConversionsResponse response =
        conversionUploadServiceClient.uploadClickConversions(
            UploadClickConversionsRequest.newBuilder()
                .setCustomerId(Long.toString(customerId))
                .addConversions(clickConversion)
                // Enables partial failure (must be true).
                .setPartialFailure(true)
                .build());

    // Prints any partial errors returned.
    if (response.hasPartialFailureError()) {
      GoogleAdsFailure googleAdsFailure =
          ErrorUtils.getInstance().getGoogleAdsFailure(response.getPartialFailureError());
      // Constructs a protocol buffer printer that will print error details in a concise format.
      Printer errorPrinter = JsonFormat.printer().omittingInsignificantWhitespace();
      for (int operationIndex = 0;
          operationIndex < response.getResultsCount();
          operationIndex++) {
        ClickConversionResult conversionResult = response.getResults(operationIndex);
        if (ErrorUtils.getInstance().isPartialFailureResult(conversionResult)) {
          // Prints the errors for the failed operation.
          System.out.printf("Operation %d failed with the following errors:%n", operationIndex);
          for (GoogleAdsError resultError :
              ErrorUtils.getInstance().getGoogleAdsErrors(operationIndex, googleAdsFailure)) {
            // Prints the error with newlines and extra spaces removed.
            System.out.printf("  %s%n", errorPrinter.print(resultError));
          }
        } else {
          // Prints the information about the successful operation.
          StringBuilder clickInfoBuilder =
              new StringBuilder("conversion that occurred at ")
                  .append(String.format("'%s' ", conversionResult.getConversionDateTime()))
                  .append("with ");
          if (conversionResult.hasGclid()) {
            clickInfoBuilder.append(String.format("gclid '%s'", conversionResult.getGclid()));
          } else if (!conversionResult.getGbraid().isEmpty()) {
            clickInfoBuilder.append(String.format("gbraid '%s'", conversionResult.getGbraid()));
          } else if (!conversionResult.getWbraid().isEmpty()) {
            clickInfoBuilder.append(String.format("wbraid '%s'", conversionResult.getWbraid()));
          } else {
            clickInfoBuilder.append("no click ID");
          }
          System.out.printf("Operation %d for %s succeeded.%n", operationIndex, clickInfoBuilder);
        }
      }
    }
  }
}
      

C#

public void Run(GoogleAdsClient client, long customerId, long conversionActionId,
    string gclid, string gbraid, string wbraid, string conversionTime,
    double conversionValue, ConsentStatus? adUserDataConsent)
{
    // Get the ConversionActionService.
    ConversionUploadServiceClient conversionUploadService =
        client.GetService(Services.V18.ConversionUploadService);

    // Creates a click conversion by specifying currency as USD.
    ClickConversion clickConversion = new ClickConversion()
    {
        ConversionAction = ResourceNames.ConversionAction(customerId, conversionActionId),
        ConversionValue = conversionValue,
        ConversionDateTime = conversionTime,
        CurrencyCode = "USD",
    };

    // Sets the consent information, if provided.
    if (adUserDataConsent != null)
    {
        // Specifies whether user consent was obtained for the data you are uploading. See
        // https://www.google.com/about/company/user-consent-policy
        // for details.
        clickConversion.Consent = new Consent()
        {
            AdUserData = (ConsentStatus)adUserDataConsent
        };
    }

    // Verifies that exactly one of gclid, gbraid, and wbraid is specified, as required.
    // See https://developers.google.com/google-ads/api/docs/conversions/upload-clicks
    // for details.
    string[] ids = { gclid, gbraid, wbraid };
    int idCount = ids.Where(id => !string.IsNullOrEmpty(id)).Count();

    if (idCount != 1)
    {
        throw new ArgumentException($"Exactly 1 of gclid, gbraid, or wbraid is " +
            $"required, but {idCount} ID values were provided");
    }

    // Sets the single specified ID field.
    if (!string.IsNullOrEmpty(gclid))
    {
        clickConversion.Gclid = gclid;
    }
    else if (!string.IsNullOrEmpty(wbraid))
    {
        clickConversion.Wbraid = wbraid;
    }
    else if (!string.IsNullOrEmpty(gbraid))
    {
        clickConversion.Gbraid = gbraid;
    }

    try
    {
        // Issues a request to upload the click conversion.
        UploadClickConversionsResponse response =
            conversionUploadService.UploadClickConversions(
                new UploadClickConversionsRequest()
                {
                    CustomerId = customerId.ToString(),
                    Conversions = { clickConversion },
                    PartialFailure = true,
                    ValidateOnly = false
                });

        // Prints the result.
        ClickConversionResult uploadedClickConversion = response.Results[0];
        Console.WriteLine($"Uploaded conversion that occurred at " +
            $"'{uploadedClickConversion.ConversionDateTime}' from Google " +
            $"Click ID '{uploadedClickConversion.Gclid}' to " +
            $"'{uploadedClickConversion.ConversionAction}'.");
    }
    catch (GoogleAdsException e)
    {
        Console.WriteLine("Failure:");
        Console.WriteLine($"Message: {e.Message}");
        Console.WriteLine($"Failure: {e.Failure}");
        Console.WriteLine($"Request ID: {e.RequestId}");
        throw;
    }
}
      

PHP

public static function runExample(
    GoogleAdsClient $googleAdsClient,
    int $customerId,
    int $conversionActionId,
    ?string $gclid,
    ?string $gbraid,
    ?string $wbraid,
    ?string $orderId,
    string $conversionDateTime,
    float $conversionValue,
    ?string $conversionCustomVariableId,
    ?string $conversionCustomVariableValue,
    ?int $adUserDataConsent
) {
    // Verifies that exactly one of gclid, gbraid, and wbraid is specified, as required.
    // See https://developers.google.com/google-ads/api/docs/conversions/upload-clicks for details.
    $nonNullFields = array_filter(
        [$gclid, $gbraid, $wbraid],
        function ($field) {
            return !is_null($field);
        }
    );
    if (count($nonNullFields) !== 1) {
        throw new \UnexpectedValueException(
            sprintf(
                "Exactly 1 of gclid, gbraid or wbraid is required, but %d ID values were "
                . "provided",
                count($nonNullFields)
            )
        );
    }

    // Creates a click conversion by specifying currency as USD.
    $clickConversion = new ClickConversion([
        'conversion_action' =>
            ResourceNames::forConversionAction($customerId, $conversionActionId),
        'conversion_value' => $conversionValue,
        'conversion_date_time' => $conversionDateTime,
        'currency_code' => 'USD'
    ]);
    // Sets the single specified ID field.
    if (!is_null($gclid)) {
        $clickConversion->setGclid($gclid);
    } elseif (!is_null($gbraid)) {
        $clickConversion->setGbraid($gbraid);
    } else {
        $clickConversion->setWbraid($wbraid);
    }

    if (!is_null($conversionCustomVariableId) && !is_null($conversionCustomVariableValue)) {
        $clickConversion->setCustomVariables([new CustomVariable([
            'conversion_custom_variable' => ResourceNames::forConversionCustomVariable(
                $customerId,
                $conversionCustomVariableId
            ),
            'value' => $conversionCustomVariableValue
        ])]);
    }
    // Sets the consent information, if provided.
    if (!empty($adUserDataConsent)) {
        // Specifies whether user consent was obtained for the data you are uploading. See
        // https://www.google.com/about/company/user-consent-policy for details.
        $clickConversion->setConsent(new Consent(['ad_user_data' => $adUserDataConsent]));
    }

    if (!empty($orderId)) {
        // Sets the order ID (unique transaction ID), if provided.
        $clickConversion->setOrderId($orderId);
    }

    // Issues a request to upload the click conversion.
    $conversionUploadServiceClient = $googleAdsClient->getConversionUploadServiceClient();
    /** @var UploadClickConversionsResponse $response */
    // NOTE: This request contains a single conversion as a demonstration.  However, if you have
    // multiple conversions to upload, it's best to upload multiple conversions per request
    // instead of sending a separate request per conversion. See the following for per-request
    // limits:
    // https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service
    $response = $conversionUploadServiceClient->uploadClickConversions(
        // Uploads the click conversion. Partial failure should always be set to true.
        UploadClickConversionsRequest::build($customerId, [$clickConversion], true)
    );

    // Prints the status message if any partial failure error is returned.
    // Note: The details of each partial failure error are not printed here, you can refer to
    // the example HandlePartialFailure.php to learn more.
    if ($response->hasPartialFailureError()) {
        printf(
            "Partial failures occurred: '%s'.%s",
            $response->getPartialFailureError()->getMessage(),
            PHP_EOL
        );
    } else {
        // Prints the result if exists.
        /** @var ClickConversionResult $uploadedClickConversion */
        $uploadedClickConversion = $response->getResults()[0];
        printf(
            "Uploaded click conversion that occurred at '%s' from Google Click ID '%s' " .
            "to '%s'.%s",
            $uploadedClickConversion->getConversionDateTime(),
            $uploadedClickConversion->getGclid(),
            $uploadedClickConversion->getConversionAction(),
            PHP_EOL
        );
    }
}
      

Python

def main(
    client,
    customer_id,
    conversion_action_id,
    gclid,
    conversion_date_time,
    conversion_value,
    conversion_custom_variable_id,
    conversion_custom_variable_value,
    gbraid,
    wbraid,
    order_id,
    ad_user_data_consent,
):
    """Creates a click conversion with a default currency of USD.

    Args:
        client: An initialized GoogleAdsClient instance.
        customer_id: The client customer ID string.
        conversion_action_id: The ID of the conversion action to upload to.
        gclid: The Google Click Identifier ID. If set, the wbraid and gbraid
            parameters must be None.
        conversion_date_time: The the date and time of the conversion (should be
            after the click time). The format is 'yyyy-mm-dd hh:mm:ss+|-hh:mm',
            e.g. '2021-01-01 12:32:45-08:00'.
        conversion_value: The conversion value in the desired currency.
        conversion_custom_variable_id: The ID of the conversion custom
            variable to associate with the upload.
        conversion_custom_variable_value: The str value of the conversion custom
            variable to associate with the upload.
        gbraid: The GBRAID for the iOS app conversion. If set, the gclid and
            wbraid parameters must be None.
        wbraid: The WBRAID for the iOS app conversion. If set, the gclid and
            gbraid parameters must be None.
        order_id: The order ID for the click conversion.
        ad_user_data_consent: The ad user data consent for the click.
    """
    click_conversion = client.get_type("ClickConversion")
    conversion_upload_service = client.get_service("ConversionUploadService")
    conversion_action_service = client.get_service("ConversionActionService")
    click_conversion.conversion_action = (
        conversion_action_service.conversion_action_path(
            customer_id, conversion_action_id
        )
    )

    # Sets the single specified ID field.
    if gclid:
        click_conversion.gclid = gclid
    elif gbraid:
        click_conversion.gbraid = gbraid
    else:
        click_conversion.wbraid = wbraid

    click_conversion.conversion_value = float(conversion_value)
    click_conversion.conversion_date_time = conversion_date_time
    click_conversion.currency_code = "USD"

    if conversion_custom_variable_id and conversion_custom_variable_value:
        conversion_custom_variable = client.get_type("CustomVariable")
        conversion_custom_variable.conversion_custom_variable = (
            conversion_upload_service.conversion_custom_variable_path(
                customer_id, conversion_custom_variable_id
            )
        )
        conversion_custom_variable.value = conversion_custom_variable_value
        click_conversion.custom_variables.append(conversion_custom_variable)

    if order_id:
        click_conversion.order_id = order_id

    # Sets the consent information, if provided.
    if ad_user_data_consent:
        # Specifies whether user consent was obtained for the data you are
        # uploading. For more details, see:
        # https://www.google.com/about/company/user-consent-policy
        click_conversion.consent.ad_user_data = client.enums.ConsentStatusEnum[
            ad_user_data_consent
        ]

    # Uploads the click conversion. Partial failure must be set to True here.
    #
    # NOTE: This request only uploads a single conversion, but if you have
    # multiple conversions to upload, it's most efficient to upload them in a
    # single request. See the following for per-request limits for reference:
    # https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service
    request = client.get_type("UploadClickConversionsRequest")
    request.customer_id = customer_id
    request.conversions.append(click_conversion)
    request.partial_failure = True
    conversion_upload_response = (
        conversion_upload_service.upload_click_conversions(
            request=request,
        )
    )
    uploaded_click_conversion = conversion_upload_response.results[0]
    print(
        f"Uploaded conversion that occurred at "
        f'"{uploaded_click_conversion.conversion_date_time}" from '
        f'Google Click ID "{uploaded_click_conversion.gclid}" '
        f'to "{uploaded_click_conversion.conversion_action}"'
    )
      

Ruby

def upload_offline_conversion(
  customer_id,
  conversion_action_id,
  gclid,
  gbraid,
  wbraid,
  conversion_date_time,
  conversion_value,
  conversion_custom_variable_id,
  conversion_custom_variable_value,
  ad_user_data_consent)
  # GoogleAdsClient will read a config file from
  # ENV['HOME']/google_ads_config.rb when called without parameters
  client = Google::Ads::GoogleAds::GoogleAdsClient.new

  # Verifies that exactly one of gclid, gbraid, and wbraid is specified, as required.
  # See https://developers.google.com/google-ads/api/docs/conversions/upload-clicks for details.
  identifiers_specified = [gclid, gbraid, wbraid].reject {|v| v.nil?}.count
  if identifiers_specified != 1
    raise "Must specify exactly one of GCLID, GBRAID, and WBRAID. " \
      "#{identifiers_specified} values were provided."
  end

  click_conversion = client.resource.click_conversion do |cc|
    cc.conversion_action = client.path.conversion_action(customer_id, conversion_action_id)
    # Sets the single specified ID field.
    if !gclid.nil?
      cc.gclid = gclid
    elsif !gbraid.nil?
      cc.gbraid = gbraid
    else
      cc.wbraid = wbraid
    end
    cc.conversion_value = conversion_value.to_f
    cc.conversion_date_time = conversion_date_time
    cc.currency_code = 'USD'
    if conversion_custom_variable_id && conversion_custom_variable_value
      cc.custom_variables << client.resource.custom_variable do |cv|
        cv.conversion_custom_variable = client.path.conversion_custom_variable(
          customer_id, conversion_custom_variable_id)
        cv.value = conversion_custom_variable_value
      end
    end
    # Sets the consent information, if provided.
    unless ad_user_data_consent.nil?
      cc.consent = client.resource.consent do |c|
        # Specifies whether user consent was obtained for the data you are
        # uploading. For more details, see:
        # https://www.google.com/about/company/user-consent-policy
        c.ad_user_data = ad_user_data_consent
      end
    end
  end

  response = client.service.conversion_upload.upload_click_conversions(
    customer_id: customer_id,
    # NOTE: This request contains a single conversion as a demonstration.
    # However, if you have multiple conversions to upload, it's best to upload
    # multiple conversions per request instead of sending a separate request per
    # conversion. See the following for per-request limits:
    # https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service
    conversions: [click_conversion],
    partial_failure: true,
  )
  if response.partial_failure_error.nil?
    result = response.results.first
    puts "Uploaded conversion that occurred at #{result.conversion_date_time} " \
      "from Google Click ID #{result.gclid} to #{result.conversion_action}."
  else
    failures = client.decode_partial_failure_error(response.partial_failure_error)
    puts "Request failed. Failure details:"
    failures.each do |failure|
      failure.errors.each do |error|
        puts "\t#{error.error_code.error_code}: #{error.message}"
      end
    end
  end
end
      

Perl

sub upload_offline_conversion {
  my (
    $api_client,                    $customer_id,
    $conversion_action_id,          $gclid,
    $gbraid,                        $wbraid,
    $conversion_date_time,          $conversion_value,
    $conversion_custom_variable_id, $conversion_custom_variable_value,
    $order_id,                      $ad_user_data_consent
  ) = @_;

  # Verify that exactly one of gclid, gbraid, and wbraid is specified, as required.
  # See https://developers.google.com/google-ads/api/docs/conversions/upload-clicks for details.
  my $number_of_ids_specified = grep { defined $_ } ($gclid, $gbraid, $wbraid);
  if ($number_of_ids_specified != 1) {
    die sprintf "Exactly 1 of gclid, gbraid, or wbraid is required, " .
      "but %d ID values were provided.\n",
      $number_of_ids_specified;
  }

  # Create a click conversion by specifying currency as USD.
  my $click_conversion =
    Google::Ads::GoogleAds::V18::Services::ConversionUploadService::ClickConversion
    ->new({
      conversionAction =>
        Google::Ads::GoogleAds::V18::Utils::ResourceNames::conversion_action(
        $customer_id, $conversion_action_id
        ),
      conversionDateTime => $conversion_date_time,
      conversionValue    => $conversion_value,
      currencyCode       => "USD"
    });

  # Set the single specified ID field.
  if (defined $gclid) {
    $click_conversion->{gclid} = $gclid;
  } elsif (defined $gbraid) {
    $click_conversion->{gbraid} = $gbraid;
  } else {
    $click_conversion->{wbraid} = $wbraid;
  }

  if ($conversion_custom_variable_id && $conversion_custom_variable_value) {
    $click_conversion->{customVariables} = [
      Google::Ads::GoogleAds::V18::Services::ConversionUploadService::CustomVariable
        ->new({
          conversionCustomVariable =>
            Google::Ads::GoogleAds::V18::Utils::ResourceNames::conversion_custom_variable(
            $customer_id, $conversion_custom_variable_id
            ),
          value => $conversion_custom_variable_value
        })];
  }

  if (defined $order_id) {
    # Set the order ID (unique transaction ID), if provided.
    $click_conversion->{orderId} = $order_id;
  }

  # Set the consent information, if provided.
  if ($ad_user_data_consent) {
    # Specify whether user consent was obtained for the data you are uploading.
    # See https://www.google.com/about/company/user-consent-policy for details.
    $click_conversion->{consent} =
      Google::Ads::GoogleAds::V18::Common::Consent->new({
        adUserData => $ad_user_data_consent
      });
  }

  # Issue a request to upload the click conversion. Partial failure should
  # always be set to true.
  #
  # NOTE: This request contains a single conversion as a demonstration.
  # However, if you have multiple conversions to upload, it's best to
  # upload multiple conversions per request instead of sending a separate
  # request per conversion. See the following for per-request limits:
  # https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service
  my $upload_click_conversions_response =
    $api_client->ConversionUploadService()->upload_click_conversions({
      customerId     => $customer_id,
      conversions    => [$click_conversion],
      partialFailure => "true"
    });

  # Print any partial errors returned.
  if ($upload_click_conversions_response->{partialFailureError}) {
    printf "Partial error encountered: '%s'.\n",
      $upload_click_conversions_response->{partialFailureError}{message};
  }

  # Print the result if valid.
  my $uploaded_click_conversion =
    $upload_click_conversions_response->{results}[0];
  if (%$uploaded_click_conversion) {
    printf
      "Uploaded conversion that occurred at '%s' from Google Click ID '%s' " .
      "to the conversion action with resource name '%s'.\n",
      $uploaded_click_conversion->{conversionDateTime},
      $uploaded_click_conversion->{gclid},
      $uploaded_click_conversion->{conversionAction};
  }

  return 1;
}
      

문제 해결

오프라인 데이터 진단은 업로드의 전반적인 상태를 지속적으로 검토할 수 있는 단일 리소스를 제공합니다. 그러나 구현 중에 이 섹션의 정보를 사용하여 응답의 partial_failure_error 필드에 보고된 오류를 조사할 수 있습니다.

전환 액션을 업로드할 때 가장 일반적인 오류는 USER_PERMISSION_DENIED와 같은 승인 오류입니다. 요청의 고객 ID가 전환 액션을 소유한 Google Ads 전환 고객으로 설정되어 있는지 다시 확인합니다. 자세한 내용은 승인 가이드를 참고하고 다양한 오류를 디버그하는 방법에 관한 도움말은 일반 오류 가이드를 참고하세요.

일반적인 오류 디버그

오류
ConversionUploadError.INVALID_CONVERSION_ACTION_TYPE 지정된 전환 액션의 유형이 클릭 전환 업로드에 유효하지 않습니다. 업로드 요청에 지정된 ConversionAction의 유형이 UPLOAD_CLICKS인지 확인합니다.
ConversionUploadError.NO_CONVERSION_ACTION_FOUND 지정된 전환 액션이 사용 설정되어 있지 않거나 업로드 중인 customer_id 내에서 찾을 수 없습니다. 전환 설정에 관한 정보를 가져와 업로드의 전환 액션이 사용 설정되어 있고 업로드 요청의 customer_id가 소유하고 있는지 확인합니다.
ConversionUploadError.TOO_RECENT_CONVERSION_ACTION 전환 액션이 새로 생성됩니다. 액션이 생성된 후 6시간 이상 기다린 후 실패한 전환을 다시 시도합니다.
ConversionUploadError.INVALID_CUSTOMER_FOR_CLICK 요청의 customer_id가 클릭 시 Google Ads API 전환 계정이었던 고객 ID와 다릅니다. 요청의 customer_id를 올바른 고객으로 업데이트합니다.
ConversionUploadError.EVENT_NOT_FOUND Google Ads에서 클릭 ID와 customer_id의 조합을 찾을 수 없습니다. customer_id 요구사항을 검토하고 올바른 Google Ads 계정을 사용하여 업로드하고 있는지 확인합니다.
ConversionUploadError.DUPLICATE_CLICK_CONVERSION_IN_REQUEST 요청에 포함된 여러 전환의 클릭 ID, conversion_date_time, conversion_action 조합이 동일합니다. 요청에서 중복 전환을 삭제합니다.
ConversionUploadError.CLICK_CONVERSION_ALREADY_EXISTS 클릭 ID, conversion_date_time, conversion_action의 조합이 동일한 전환을 이전에 업로드했습니다. 업로드를 다시 시도 중이고 이전에 이 변환이 성공한 경우 이 오류를 무시합니다. 이전에 업로드한 전환 외에도 다른 전환을 추가하려면 이전에 업로드한 전환이 중복되지 않도록 ClickConversionconversion_date_time를 조정합니다.
ConversionUploadError.EVENT_NOT_FOUND Google Ads에서 클릭 ID와 customer_id의 조합을 찾을 수 없습니다. customer_id 요구사항을 검토하고 올바른 Google Ads 계정을 사용하여 업로드하고 있는지 확인합니다.
ConversionUploadError.EXPIRED_EVENT 가져온 클릭이 click_through_lookback_window_days 필드에 지정된 기간 전에 발생했습니다. click_through_lookback_window_days를 변경하면 변경 후에 기록된 클릭에만 영향을 미치므로 전환 확인 기간을 변경해도 특정 클릭의 이 오류는 해결되지 않습니다. 적절한 경우 conversion_action를 전환 확인 기간이 더 긴 다른 작업으로 변경합니다.
ConversionUploadError.CONVERSION_PRECEDES_EVENT conversion_date_time는 클릭 날짜와 시간보다 이전입니다. conversion_date_time를 이후 값으로 업데이트합니다.
ConversionUploadError.GBRAID_WBRAID_BOTH_SET ClickConversion에는 gbraidwbraid 모두에 설정된 값이 있습니다. 클릭 ID를 하나만 사용하도록 전환을 업데이트하고 여러 클릭을 하나의 전환으로 결합하지 않도록 합니다. 각 클릭에는 클릭 ID가 하나만 있습니다.
FieldError.VALUE_MUST_BE_UNSET GoogleAdsErrorlocation를 확인하여 다음 문제 중 어떤 문제가 오류를 일으켰는지 확인합니다.
  • ClickConversion에는 gclid에 설정된 값과 gbraid 또는 wbraid 중 하나 이상이 있습니다. 클릭 ID를 하나만 사용하도록 전환을 업데이트하고 여러 클릭을 하나의 전환으로 결합하지 않도록 합니다. 각 클릭에는 클릭 ID가 하나만 있습니다.
  • ClickConversion에는 gbraid 또는 wbraid에 설정된 값이 있고 custom_variables 값이 있습니다. Google Ads에서는 gbraid 또는 wbraid 클릭 ID가 있는 전환에 맞춤 변수를 지원하지 않습니다. 전환의 custom_variables 필드를 설정 해제합니다.

보고서의 전환

업로드된 전환은 업로드 요청 날짜 또는 ClickConversionconversion_date_time 날짜가 아니라 원래 클릭의 노출 날짜의 보고서에 반영됩니다.

가져온 전환 통계가 마지막 클릭 기여 분석을 위해 Google Ads 계정에 표시되기까지 최대 3시간이 걸립니다. 다른 검색 기여 분석 모델의 경우 3시간 넘게 걸릴 수 있습니다. 자세한 내용은 데이터 업데이트 가이드를 참고하세요.