上传点击转化数据

您可以使用 Google Ads API 将 线下点击转化数据上传到 Google Ads,以便跟踪促成线下销售(例如 通过电话或销售代表)的广告。

设置

要成功设置线下转化,需要满足一些前提条件。请确保满足所有前提条件,然后再继续进行实现:

  1. 在 Google Ads 转化客户中启用转化跟踪。

  2. 配置标记并存储点击 ID。

1. 在 Google Ads 转化客户中启用转化跟踪

如果您已完成转化入门指南并 启用了转化跟踪,则可以跳到 第二步:配置标记。

检索有关转化跟踪设置的信息

您可以查询 Customer 资源的 ConversionTrackingSetting,检查账号的转化跟踪设置并确认转化 跟踪已启用。 使用 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 提供,以创建和管理转化。请注意,即使未启用转化跟踪,系统也会填充此字段。

The conversion_tracking_status 字段表示是否启用了转化跟踪,以及账号 是否在使用跨账号转化跟踪。

在 Google Ads 转化客户下创建转化操作

如果 conversion_tracking_status 值为 NOT_CONVERSION_TRACKED,则表示该账号未启用转化跟踪。若要启用转化跟踪 ,请在 Google Ads 转化账号中创建至少一个 ConversionAction,如以下示例所示。或者,您 也可以按照 Google Ads 帮助中心文章中有关要启用的转化类型的转化跟踪 设置的说明,在界面中创建转化操作。

请注意,通过 Google Ads API 发送增强型转化时,系统会自动启用增强型转化,但您可以通过 Google Ads 界面停用增强型转化。

代码示例

Java

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.V25.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: GoogleAdsClient, customer_id: str) -> None:
    conversion_action_service: ConversionActionServiceClient = (
        client.get_service("ConversionActionService")
    )

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

    # Create conversion action.
    conversion_action: ConversionAction = 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: ConversionAction.ValueSettings = (
        conversion_action.value_settings
    )
    value_settings.default_value = 15.0
    value_settings.always_use_default_value = True

    # Add the conversion action.
    conversion_action_response: MutateConversionActionsResponse = (
        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::V25::Resources::ConversionAction->new({
      name                          => $conversion_action_name,
      category                      => DEFAULT,
      type                          => WEBPAGE,
      status                        => ENABLED,
      viewThroughLookbackWindowDays => 15,
      valueSettings                 =>
        Google::Ads::GoogleAds::V25::Resources::ValueSettings->new({
          defaultValue          => 23.41,
          alwaysUseDefaultValue => "true"
        })});

  # Create a conversion action operation.
  my $conversion_action_operation =
    Google::Ads::GoogleAds::V25::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;
}
      

curl

确保 type 设置为正确的 ConversionActionType 值。如需详细了解如何在 Google Ads API 中创建转化操作,请参阅 创建 转化操作。

检索现有转化操作

您可以通过发出以下查询来检索现有转化操作的详细信息。确保请求中的客户 ID 设置为您之前确定的 Google Ads 转化客户,并且转化操作类型 设置为正确的 ConversionActionType 值。

SELECT
  conversion_action.id,
  conversion_action.resource_name,
  conversion_action.name,
  conversion_action.type,
  conversion_action.category,
  conversion_action.status
FROM conversion_action

WHERE conversion_action.type = 'UPLOAD_CLICKS'

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 包含请求的任务 ID,无论您是否指定了值或让 Google Ads API 分配了值。

partial_failure

确定 Google Ads API 如何处理操作中的错误。

此字段必须设置为 true。处理响应时,请遵循 部分失败指南。

创建点击转化操作

UploadClickConversionsRequest 中的 ClickConversion 对象集合定义了您要 上传的转化集。按照此指南构建每个 ClickConversion,并将其字段设置为适当的值。

设置每个转化操作的必填字段

按照以下说明将 ClickConversion 的必填字段设置为适当的值。

gclid、gbraid、wbraid

用户点击广告后进入您的网站或应用时捕获的 GCLID 或网址参数。您必须提供以下其中一项:

  • gclid
  • gbraid
  • wbraid
conversion_date_time

转化的日期和时间。

该值必须指定时区,并且格式必须为 yyyy-mm-dd HH:mm:ss+|-HH:mm,例如:2022-01-01 19:32:45-05:00(忽略夏令时) 。

时区可以是任何有效值,不必与账号的时区一致。 不过,如果您打算将上传的转化数据与 Google Ads 界面中的转化数据进行比较,我们建议您使用与 Google Ads 账号相同的时区,以便转化次数保持一致。 如需了解更多详细信息和示例,请参阅 准备要导入的数据,并查看 代码和格式,获取有效时区 ID 的列表。

user_identifiers

如果仅使用点击 ID 上传转化,请勿设置此字段。如果设置了此 字段,Google Ads 会将上传操作视为 增强型潜在客户转化的上传。

conversion_action

点击 转化的 ConversionAction 的资源名称。

转化操作的 type 必须为 UPLOAD_CLICKS,并且必须存在于与点击关联的 Google Ads 账号的 Google Ads 转化客户中。

conversion_value

转化的价值。

currency_code

货币代码的conversion_value。

设置每个转化操作的可选字段

查看以下可选字段列表,并根据需要在 ClickConversion 中设置这些字段。

order_id
转化的交易 ID。此字段是可选字段,但强烈建议您设置。如果您在上传期间设置了此字段,则必须将其用于对转化所做的任何 调整。如需详细了解 如何使用交易 ID 尽可能避免重复统计转化次数,请参阅 使用交易 ID 尽可能避免重复统计转化次数。
external_attribution_data

如果您使用第三方工具或自行开发的解决方案来跟踪转化,则可能希望仅将部分转化功劳归因于 Google Ads,或者希望将转化的功劳分配给多次点击。 通过对转化进行外部归因,您可以 上传转化,并为每次点击分配部分功劳。

若要上传按比例分配的功劳,请将此字段设置为 ExternalAttributionData对象,并为 external_attribution_model和external_attribution_credit设置值。

custom_variables

自定义转化变量的值。

Google Ads 不支持将自定义转化变量与 wbraid 或 gbraid 结合使用。

cart_data

您可以在 购物车数据 字段中为 ClickConversion 添加 cart_data,该字段包含以下属性:

  • merchant_id:关联的 Merchant Center 账号的 ID。
  • feed_country_code:Merchant Center Feed 的 ISO 3166 双字符 区域代码 。
  • feed_language_code:Merchant Center Feed 的 ISO 639-1 语言代码。
  • local_transaction_cost:所有交易级折扣的总和,以 ClickConversion 的 currency_code 表示。
  • items:购物车中的商品。

items 中的每个商品都包含以下属性:

  • product_id:商品 ID,有时也称为 优惠 ID 或商品 ID。
  • quantity:商品的数量。
  • unit_price:商品的单价。
conversion_environment

表示记录此转化的环境。例如,应用或网站。

代码示例

Java

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.V25.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: GoogleAdsClient,
    customer_id: str,
    conversion_action_id: str,
    gclid: Optional[str],
    conversion_date_time: str,
    conversion_value: str,
    conversion_custom_variable_id: Optional[str],
    conversion_custom_variable_value: Optional[str],
    gbraid: Optional[str],
    wbraid: Optional[str],
    order_id: Optional[str],
    ad_user_data_consent: Optional[str],
) -> None:
    """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: ClickConversion = client.get_type("ClickConversion")
    conversion_upload_service: ConversionUploadServiceClient = (
        client.get_service("ConversionUploadService")
    )
    conversion_action_service: ConversionActionServiceClient = (
        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: CustomVariable = 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: UploadClickConversionsRequest = client.get_type(
        "UploadClickConversionsRequest"
    )
    request.customer_id = customer_id
    request.conversions.append(click_conversion)
    request.partial_failure = True
    conversion_upload_response: UploadClickConversionsResponse = (
        conversion_upload_service.upload_click_conversions(
            request=request,
        )
    )
    uploaded_click_conversion: ClickConversionResult = (
        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::V25::Services::ConversionUploadService::ClickConversion
    ->new({
      conversionAction =>
        Google::Ads::GoogleAds::V25::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::V25::Services::ConversionUploadService::CustomVariable
        ->new({
          conversionCustomVariable =>
            Google::Ads::GoogleAds::V25::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::V25::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;
}
      

curl

# This code example uploads a click conversion.
#
# Variables:
#   API_VERSION,
#   CUSTOMER_ID,
#   MANAGER_CUSTOMER_ID,
#   OAUTH2_ACCESS_TOKEN:
#     See https://developers.google.com/google-ads/api/rest/auth#request_headers
#     for details.
#
#   CONVERSION_ACTION_RESOURCE_NAME: Resource name of the conversion action
#     associated with this conversion.
#   GCLID: The Google click ID (gclid) associated with this conversion.
#   CONVERSION_VALUE: The value of the conversion for the advertiser.
#   CONVERSION_DATE_TIME: The date time at which the conversion occurred. The
#     format is "yyyy-mm-dd hh:mm:ss+|-hh:mm", for example,
#     "2019-01-01 12:32:45-08:00".
#   CURRENCY_CODE: The currency code of the conversion value. This is the
#     ISO 4217 3-character currency code. For example: USD, EUR.
#   CONVERSION_CUSTOM_VARIABLE: The name of the conversion custom variable.
#   CONVERSION_CUSTOM_VARIABLE_VALUE: The value of the conversion custom
#     variable.
#   ORDER_ID: The order ID of the conversion.
curl -f --request POST \
"https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}:uploadClickConversions" \
--header "Content-Type: application/json" \
--header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--data @- <<EOF
{
  "conversions": [
    {
      "conversionAction": "${CONVERSION_ACTION_RESOURCE_NAME}",
      "gclid": "${GCLID}",
      "conversionValue": ${CONVERSION_VALUE},
      "conversionDateTime": "${CONVERSION_DATE_TIME}",
      "currencyCode": "${CURRENCY_CODE}",
      "customVariables": [
        {
          "conversionCustomVariable": "${CONVERSION_CUSTOM_VARIABLE}",
          "value": "${CONVERSION_CUSTOM_VARIABLE_VALUE}"
        }
      ],
      "orderId": "${ORDER_ID}",
      "consent": {
        "adUserData": "GRANTED"
      }
    }
  ],
  "partialFailure": true
}
EOF
      

问题排查

线下数据诊断提供了一个资源,供您 持续查看上传的整体健康状况。不过, 在实现过程中,您可以使用本部分中的信息来调查 响应的 partial_failure_error 字段中报告的任何错误。

上传转化操作时,一些最常见的错误是授权错误,例如 USER_PERMISSION_DENIED。请仔细检查请求中的客户 ID 是否设置为拥有转化操作的 Google Ads 广告转化客户。如需了解更多详细信息,请访问我们的 授权指南;如需了解如何调试这些不同 错误的提示,请参阅我们的 常见错误指南。

调试常见错误

错误
INVALID_CONVERSION_ACTION_TYPE 指定的转化操作的 类型 对于上传点击转化无效。确保上传请求中指定的 ConversionAction 的类型为 UPLOAD_CLICKS.
NO_CONVERSION_ACTION_FOUND 指定的转化操作未启用,或者找不到 上传的customer_id。检索有关转化设置的信息 确保上传中的转化操作已启用,并且归上传请求的 customer_id 所有。
TOO_RECENT_CONVERSION_ACTION 转化操作是新创建的。请在创建操作后至少等待 6 小时,然后再重试失败的转化。
INVALID_CUSTOMER_FOR_CLICK 请求的 customer_id 与点击时 Google Ads API 转化账号的客户 ID 不同。将请求的 customer_id 更新为正确的客户。
EVENT_NOT_FOUND Google Ads 找不到点击 ID 和 customer_id 的组合。查看 的要求customer_id,并确认您使用的是正确的 Google Ads 账号进行上传。
DUPLICATE_CLICK_CONVERSION_IN_REQUEST 请求中的多个转化具有相同的点击 ID、conversion_date_time 和 conversion_action 组合。从您的 请求中移除重复的转化。
CLICK_CONVERSION_ALREADY_EXISTS 之前已上传具有相同点击 ID、 conversion_date_time 和 conversion_action 组合的转化。如果您重试上传,并且此 转化之前已成功,请忽略此错误。如果您想在之前上传的转化之外再添加一个转化,请调整conversion_date_time的ClickConversion,以避免重复之前上传的转化。
EVENT_NOT_FOUND Google Ads 找不到点击 ID 和 customer_id 的组合。查看 的要求customer_id,并确认您使用的是正确的 Google Ads 账号进行上传。
EXPIRED_EVENT 导入的点击发生在 click_through_lookback_window_days 字段中指定的时间范围之前。对 click_through_lookback_window_days 的 更改只会影响更改后记录的 点击,因此更改回溯期不会 解决特定点击的此错误。如果合适,请将 conversion_action 更改为具有较长回溯 期的其他操作。
CONVERSION_PRECEDES_EVENT conversion_date_time 早于点击的日期和时间。将 conversion_date_time 更新为较晚的值。
GBRAID_WBRAID_BOTH_SET ClickConversion 同时为 gbraid 和 wbraid 设置了值。更新转化,使其仅使用 一个点击 ID 或网址参数,并确保您没有将 多个点击合并到同一转化中。每次点击只有一个点击 ID 或网址参数。
VALUE_MUST_BE_UNSET 检查 location 的 GoogleAdsError,以确定导致错误的以下哪个问题。
  • ClickConversion 为 gclid 以及 gbraid 或 wbraid 中的至少一个设置了值。更新转化,使其仅使用一个点击 ID 或网址参数,并确保您没有将多个点击合并到同一转化中。每次点击 只有一个点击 ID 或网址参数。
  • ClickConversion 为 gbraid 或 wbraid 设置了值,并且为 custom_variables 设置了值。Google Ads 不支持为具有 gbraid 或 wbraid 网址参数的转化设置自定义变量。取消设置转化的 custom_variables 字段。

报告中的转化

上传的转化反映在原始点击的 展示 日期的报告中,而不是 上传请求的日期或 conversion_date_time 的 ClickConversion的日期。

对于最终点击归因,导入的转化统计信息最多需要 3 小时才能显示在您的 Google Ads 账号中。对于其他搜索归因模型,可能需要超过 3 小时。如需了解详情,请参阅 数据新鲜度指南。