مدیریت تبدیل‌های کلیک آنلاین

می‌توانید از Google Ads API برای مدیریت تبدیل‌های کلیک آنلاین در Google Ads استفاده کنید. تبدیل‌های کلیک آنلاین به شما کمک می‌کند آگهی‌هایی را که منجر به فروش در دنیای آنلاین شده‌اند، مثلاً ازطریق وب‌سایت، پیگیری کنید.

تبدیل‌های آنلاین بااستفاده از برچسب Google ردیابی می‌شوند، اما می‌توانید آن‌ها را بااستفاده از Google Ads API اصلاح یا بهبود دهید.

اگر قبلاً برچسب Google را راه‌اندازی کرده‌اید و می‌خواهید تبدیل‌های آنلاینتان را اصلاح کنید، به صفحه اصلاح تبدیل مراجعه کنید. اگر برچسب Google را راه‌اندازی کرده‌اید و می‌خواهید تبدیل‌های آنلاینتان را با داده‌های ارائه‌شده توسط کاربر، که با نام تبدیل‌های بهبودیافته برای وب نیز شناخته می‌شود، بهبود دهید، به خواندن ادامه دهید.

تبدیل‌های بهبودیافته برای وب

بخش زیر نحوه بهبود تبدیل‌های کلیک آنلاین را توضیح می‌دهد که با نام تبدیل‌های بهبودیافته برای وب نیز شناخته می‌شود.

تبدیل‌های بهبودیافته برای وب نیاز به راه‌اندازی برچسبی دارد که وقتی کاربر تبدیل می‌کند، به‌طور خودکار شناسه کلیک، مانند GCLID، و شناسه سفارش را به Google Ads ارسال کند. می‌توانید تبدیل‌های بهبودیافته را ازطریق Google Tag Manager، برچسب Google، یا Google Ads API راه‌اندازی کنید. استفاده از Google Ads API این مزیت را به شما می‌دهد که داده‌های تبدیل شخص اول را ظرف ۲۴ ساعت پس‌از رویداد تبدیل ارسال کنید، به‌جای اینکه هم‌زمان ارسال کنید. این کار امکان یافتن داده‌های طرف اول را از منابع مختلف، مانند پایگاه داده مشتری یا سیستم CRM، فراهم می‌کند.

نحوه عملکرد تبدیل‌های بهبودیافته برای وب

تبدیل‌های بهبودیافته برای وب در Google Ads API مکمل مرحله ۳ در نمودار زیر است. به‌جای ارسال اطلاعات درهم‌سازی‌شده کاربر هنگام تبدیل کاربر، برچسب فقط GCLID و شناسه سفارش را ارسال می‌کند و شما اطلاعات درهم‌سازی‌شده کاربر را بعداً با وارد کردن شناسه سفارش به‌همراه داده‌های درهم‌سازی‌شده ارسال می‌کنید. برای کسب اطلاعات بیشتر درباره تبدیل‌های بهبودیافته برای وب، درباره تبدیل‌های بهبودیافته را ببینید.

تبدیل‌های بهبودیافته برای وب

پیش‌نیازها

قبل‌از اینکه بتوانید از تبدیل‌های بهبودیافته برای وب استفاده کنید، باید شرایط داده‌های مشتری را بپذیرید. با ارسال پُرسمان زیر به مشتری تبدیل Google Ads، می‌توانید بررسی کنید که آیا شرایط داده‌های مشتری پذیرفته شده است یا نه:

SELECT
  customer.id,
  customer.conversion_tracking_setting.accepted_customer_data_terms
FROM customer

اگر accepted_customer_data_terms false است، دستورالعمل‌های راه‌اندازی تبدیل‌های بهبودیافته برای وب را دنبال کنید تا این پیش‌نیاز را تکمیل کنید.

پیکربندی برچسب‌گذاری

با دنبال کردن دستورالعمل‌های راه‌اندازی تبدیل‌های بهبودیافته برای وب بااستفاده از Google Ads API، برچسب‌گذاری را برای وب‌سایتتان پیکربندی کنید. وقتی از Google Ads API برای تبدیل‌های بهبودیافته برای وب استفاده می‌کنید، باید شناسه‌های تراکنش (شناسه‌های سفارش) را نیز به برچسب تبدیل وب‌سایتتان اضافه کنید. ‫Google Ads از شناسه تراکنش برای مطابقت دادن فیلد order_id هر بهبود میانای برنامه‌سازی کاربردی با رویداد تبدیل مربوطه استفاده می‌کند.

پیاده‌سازی میانای برنامه‌سازی کاربردی

در اینجا جریان کلی برای وارد کردن تبدیل‌های بهبودیافته برای وب در Google Ads API آورده شده است.

  1. داده‌های ارائه‌شده توسط کاربر را نرمال‌سازی و درهم‌سازی کنید، مانند نشانی ایمیل، شماره تلفن، و نشانی پستی.

  2. اشیاء ConversionAdjustment را با داده‌های ارائه‌شده توسط کاربر که نرمال‌سازی و درهم‌سازی شده‌اند پر کنید.

  3. ConversionAdjustment شیء را به ConversionAdjustmentUploadService وارد کنید.

  4. موارد واردشده را مرور کنید.

نرمال‌سازی و درهم‌سازی داده‌های ارائه‌شده توسط کاربر

به‌دلیل ملاحظات حریم خصوصی، داده‌های زیر باید پیش‌از وارد شدن بااستفاده از SHA-256 درهم‌سازی شوند:

  • نشانی ایمیل
  • شماره تلفن
  • نام
  • نام خانوادگی
  • نشانی خیابان

داده‌های زیر را درهم‌سازی نکنید:

  • کشور (country_code، قالب‌بندی‌شده به‌عنوان کد دوحرفی ISO 3166-1 alpha-2)
  • استان (state)
  • شهر (city)
  • کد پستی (postal_code)

برای استانداردسازی نتایج درهم‌سازی، قبل‌از درهم‌سازی یکی از این مقادیر، کارهای زیر را انجام دهید:

  • فاصله‌های سفید اضافی در ابتدا و انتهای متن را بردارید.
  • نوشتار را به حروف کوچک تبدیل کن.
  • شماره تلفن‌ها را طبق استاندارد E.164 قالب‌بندی کنید.

قالب‌بندی نشانی ایمیل برای تبدیل‌های بهبودیافته

برای اطمینان از بالاترین نرخ مطابقت برای تبدیل‌های به‌سازی‌شده، باید نشانی‌های ایمیل را بااستفاده از مراحل زیر به‌درستی قالب‌بندی و درهم‌سازی کنید:

  1. اعمال کردن عادی‌سازی استاندارد (همه نشانی‌های ایمیل):

    • هرگونه فاصله سفید ASCII در ابتدا و انتهای متن را حذف کنید.
    • همه نویسه‌های نشانی ایمیل را به حروف کوچک تبدیل کنید.
  2. اعمال کردن نرمال‌سازی مختص دامنه (فقط gmail.com و googlemail.com):

    • پس‌از تبدیل نشانی ایمیل به حروف کوچک، بررسی کنید که دامنه (بعداز نماد @) gmail.com یا googlemail.com باشد.
    • حذف نقطه‌ها (.): از بخش نام کاربری (قبل‌از نماد @ )، همه نویسه‌های نقطه را حذف کنید.
    • برداشتن پسوندهای علامت جمع (+): از بخش نام کاربری، اولین علامت جمع (+) و همه نویسه‌های بعدی تا نماد @ را بردارید.
      • مثال: Jane.Doe+Shopping@googlemail.com ابتدا به jane.doe+shopping@googlemail.com (حروف کوچک) تبدیل می‌شود، و سپس janedoe@googlemail.com (قوانین Gmail و Googlemail).
    • دامنه‌های دیگر: برای هر دامنه‌ای غیراز gmail.com یا googlemail.com، نقطه‌ها یا پسوندهای علامت جمع را از نام کاربری برندارید. فقط از عادی‌سازی استاندارد استفاده کنید (فاصله سفید را حذف کنید و به حروف کوچک تبدیل کنید).
      • مثال: user.name+NYC@Example.com به user.name+nyc@example.com نرمال‌سازی می‌شود.
  3. نشانی ایمیل نرمال‌سازی‌شده را درهم‌سازی کنید:

    • رشته ایمیل نرمال‌شده را به‌صورت بایت‌های UTF-8 کدبندی کنید.
    • بایت‌های UTF-8 را بااستفاده از الگوریتم SHA-256 درهم‌سازی کنید.
    • خلاصه حاصل را به‌عنوان رشته شانزده‌شانزدهی حروف کوچک (۶۴ نویسه) قالب‌بندی کنید.
import hashlib
import re


def normalize_and_hash_email(email: str) -> str:
    """Normalizes and SHA-256 hashes an email address for enhanced conversions."""
    normalized = email.strip().lower()
    parts = normalized.split("@")
    if len(parts) != 2:
        raise ValueError("Invalid email address format.")
    username, domain = parts
    if domain in ("gmail.com", "googlemail.com"):
        username = username.replace(".", "")
        username = re.sub(r"\+.*$", "", username)
    normalized = f"{username}@{domain}"
    return hashlib.sha256(normalized.encode("utf-8")).hexdigest()

نمونه کد

این مثال نشان می‌دهد که چگونه داده‌های ارائه‌شده توسط کاربر را نرمال‌سازی و درهم‌سازی کنید.

جاوا

private String normalizeAndHash(MessageDigest digest, String s, boolean trimIntermediateSpaces)
    throws UnsupportedEncodingException {
  // Normalizes by first converting all characters to lowercase, then trimming spaces.
  String normalized = s.toLowerCase();
  if (trimIntermediateSpaces) {
    // Removes leading, trailing, and intermediate spaces.
    normalized = normalized.replaceAll("\\s+", "");
  } else {
    // Removes only leading and trailing spaces.
    normalized = normalized.trim();
  }
  // Hashes the normalized string using the hashing algorithm.
  byte[] hash = digest.digest(normalized.getBytes("UTF-8"));
  StringBuilder result = new StringBuilder();
  for (byte b : hash) {
    result.append(String.format("%02x", b));
  }

  return result.toString();
}

/**
 * Returns the result of normalizing and hashing an email address. For this use case, Google Ads
 * requires removal of any '.' characters or trailing '+' and characters that follow it from the
 * username portion of the email address if the domain is {@code gmail.com} or {@code
 * googlemail.com}.
 *
 * @param digest the digest to use to hash the normalized string.
 * @param emailAddress the email address to normalize and hash.
 */
private String normalizeAndHashEmailAddress(MessageDigest digest, String emailAddress)
    throws UnsupportedEncodingException {
  // Removes all whitespace (leading, trailing, and intermediate) from the email address.
  String normalizedEmail = emailAddress.toLowerCase().replaceAll("\\s+", "");
  String[] emailParts = normalizedEmail.split("@", 2);
  if (emailParts.length == 2 && emailParts[1].matches("^(gmail|googlemail)\\.com$")) {
    // Removes any '.' characters from the portion of the email address before the domain if the
    // domain is gmail.com or googlemail.com.
    emailParts[0] = emailParts[0].replaceAll("\\.", "");
    // Removes any '+' and all characters that follow it from the portion of the email address
    // before the domain if the domain is gmail.com or googlemail.com.
    emailParts[0] = emailParts[0].replaceAll("\\+.*", "");
    normalizedEmail = String.format("%s@%s", emailParts[0], emailParts[1]);
  }
  return normalizeAndHash(digest, normalizedEmail, true);
}

/**
 * Returns the result of normalizing and hashing a phone number. For this use case, Google Ads
 * requires phone numbers to be in E.164 format.
 *
 * @param digest the digest to use to hash the normalized string.
 * @param phoneNumber the phone number to normalize and hash.
 */
private String normalizeAndHashPhoneNumber(MessageDigest digest, String phoneNumber)
    throws UnsupportedEncodingException {
  // Removes non-digit characters and prepends a leading '+' sign.
  String digitsOnly = phoneNumber.replaceAll("[^0-9]", "");
  String formattedPhone = "+" + digitsOnly;
  if (!formattedPhone.matches("^\\+[1-9]\\d{6,14}$")) {
    throw new IllegalArgumentException("Phone number must be in E.164 format: " + phoneNumber);
  }
  return normalizeAndHash(digest, formattedPhone, true);
}
      

C#‎

/// <summary>
/// Normalizes the email address and hashes it. For this use case, Google Ads requires
/// removal of any '.' characters preceding <code>gmail.com</code> or
/// <code>googlemail.com</code>.
/// </summary>
/// <param name="emailAddress">The email address.</param>
/// <returns>The hash code.</returns>
private string NormalizeAndHashEmailAddress(string emailAddress)
{
    string normalizedEmail = emailAddress.ToLower();
    string[] emailParts = normalizedEmail.Split('@');
    if (emailParts.Length > 1 && (emailParts[1] == "gmail.com" ||
        emailParts[1] == "googlemail.com"))
    {
        // Removes any '.' characters from the portion of the email address before
        // the domain if the domain is gmail.com or googlemail.com.
        emailParts[0] = emailParts[0].Replace(".", "");
        normalizedEmail = $"{emailParts[0]}@{emailParts[1]}";
    }
    return NormalizeAndHash(normalizedEmail);
}

/// <summary>
/// Normalizes and hashes a string value.
/// </summary>
/// <param name="value">The value to normalize and hash.</param>
/// <returns>The normalized and hashed value.</returns>
private static string NormalizeAndHash(string value)
{
    return ToSha256String(digest, ToNormalizedValue(value));
}

/// <summary>
/// Hash a string value using SHA-256 hashing algorithm.
/// </summary>
/// <param name="digest">Provides the algorithm for SHA-256.</param>
/// <param name="value">The string value (e.g. an email address) to hash.</param>
/// <returns>The hashed value.</returns>
private static string ToSha256String(SHA256 digest, string value)
{
    byte[] digestBytes = digest.ComputeHash(Encoding.UTF8.GetBytes(value));
    // Convert the byte array into an unhyphenated hexadecimal string.
    return BitConverter.ToString(digestBytes).Replace("-", string.Empty);
}

/// <summary>
/// Removes leading and trailing whitespace and converts all characters to
/// lower case.
/// </summary>
/// <param name="value">The value to normalize.</param>
/// <returns>The normalized value.</returns>
private static string ToNormalizedValue(string value)
{
    return value.Trim().ToLower();
}
      

PHP

private static function normalizeAndHash(
    string $hashAlgorithm,
    string $value,
    bool $trimIntermediateSpaces
): string {
    // Normalizes by first converting all characters to lowercase, then trimming spaces.
    $normalized = strtolower($value);
    if ($trimIntermediateSpaces === true) {
        // Removes leading, trailing, and intermediate spaces.
        $normalized = str_replace(' ', '', $normalized);
    } else {
        // Removes only leading and trailing spaces.
        $normalized = trim($normalized);
    }
    return hash($hashAlgorithm, strtolower(trim($normalized)));
}

/**
 * Returns the result of normalizing and hashing an email address. For this use case, Google
 * Ads requires removal of any '.' characters preceding "gmail.com" or "googlemail.com".
 *
 * @param  string $hashAlgorithm the hash algorithm to use
 * @param  string $emailAddress  the email address to normalize and hash
 * @return string the normalized and hashed email address
 */
private static function normalizeAndHashEmailAddress(
    string $hashAlgorithm,
    string $emailAddress
): string {
    $normalizedEmail = strtolower($emailAddress);
    $emailParts = explode("@", $normalizedEmail);
    if (
        count($emailParts) > 1
        && preg_match('/^(gmail|googlemail)\.com\s*/', $emailParts[1])
    ) {
        // Removes any '.' characters from the portion of the email address before the domain
        // if the domain is gmail.com or googlemail.com.
        $emailParts[0] = str_replace(".", "", $emailParts[0]);
        $normalizedEmail = sprintf('%s@%s', $emailParts[0], $emailParts[1]);
    }
    return self::normalizeAndHash($hashAlgorithm, $normalizedEmail, true);
}
      

Python

def normalize_and_hash_email_address(email_address):
    """Returns the result of normalizing and hashing an email address.

    For this use case, Google Ads requires removal of any '.' characters
    preceding "gmail.com" or "googlemail.com"

    Args:
        email_address: An email address to normalize.

    Returns:
        A normalized (lowercase, removed whitespace) and SHA-265 hashed string.
    """
    normalized_email = email_address.strip().lower()
    email_parts = normalized_email.split("@")

    # Check that there are at least two segments
    if len(email_parts) > 1:
        # Removes any '.' and '+' characters from the portion of the email address
        # before the domain
        chars_to_remove = ".+"
        translation_table = str.maketrans("", "", chars_to_remove)
        email_parts[0] = email_parts[0].translate(translation_table)
        normalized_email = "@".join(email_parts)

    return normalize_and_hash(normalized_email)


def normalize_and_hash(s):
    """Normalizes and hashes a string with SHA-256.

    Private customer data must be hashed during upload, as described at:
    https://support.google.com/google-ads/answer/9888656

    Args:
        s: The string to perform this operation on.

    Returns:
        A normalized (lowercase, removed whitespace) and SHA-256 hashed string.
    """
    return hashlib.sha256(s.strip().lower().encode()).hexdigest()
      

Ruby

# Returns the result of normalizing and then hashing the string using the
# provided digest.  Private customer data must be hashed during upload, as
# described at https://support.google.com/google-ads/answer/9888656.
def normalize_and_hash(str)
  # Remove leading and trailing whitespace and ensure all letters are lowercase
  # before hasing.
  Digest::SHA256.hexdigest(str.strip.downcase)
end

# Returns the result of normalizing and hashing an email address. For this use
# case, Google Ads requires removal of any '.' characters preceding 'gmail.com'
# or 'googlemail.com'.
def normalize_and_hash_email(email)
  email_parts = email.downcase.split("@")
  # Removes any '.' characters from the portion of the email address before the
  # domain if the domain is gmail.com or googlemail.com.
  if email_parts.last =~ /^(gmail|googlemail)\.com\s*/
    email_parts[0] = email_parts[0].gsub('.', '')
  end
  normalize_and_hash(email_parts.join('@'))
end
      

پرل

sub normalize_and_hash {
  my $value                    = shift;
  my $trim_intermediate_spaces = shift;

  if ($trim_intermediate_spaces) {
    $value =~ s/\s+//g;
  } else {
    $value =~ s/^\s+|\s+$//g;
  }
  return sha256_hex(lc $value);
}

# Returns the result of normalizing and hashing an email address. For this use
# case, Google Ads requires removal of any '.' characters preceding 'gmail.com'
# or 'googlemail.com'.
sub normalize_and_hash_email_address {
  my $email_address = shift;

  my $normalized_email = lc $email_address;
  my @email_parts      = split('@', $normalized_email);
  if (scalar @email_parts > 1
    && $email_parts[1] =~ /^(gmail|googlemail)\.com\s*/)
  {
    # Remove any '.' characters from the portion of the email address before the
    # domain if the domain is 'gmail.com' or 'googlemail.com'.
    $email_parts[0] =~ s/\.//g;
    $normalized_email = sprintf '%s@%s', $email_parts[0], $email_parts[1];
  }
  return normalize_and_hash($normalized_email, 1);
}
      

curl

پر کردن اشیاء ConversionAdjustment

بخش زیر نشان می‌دهد که چگونه یک اصلاح بهبودیافته بسازید که حاوی شناسه سفارش، به‌علاوه شناسه‌های نشانی ایمیل، شماره تلفن، و نشانی فیزیکی باشد، و استانداردسازی و درهم‌سازی به‌صورت لازم اعمال شده باشد. به‌عنوان روال مطلوب، gclid را درصورت دردسترس بودن در اصلاحیه بگنجانید.

این مرحله تقریباً مشابه راهنمای وارد کردن اصلاحات تبدیل است، با چند نکته:

  • فیلد user_identifiers را با داده‌های کاربر نرمال‌سازی‌شده و درهم‌سازی‌شده پر کنید. اگر چند شناسه کاربر دردسترس دارید، برای هرکدام یک شیء UserIdentifier جداگانه ایجاد کنید (حداکثر پنج شناسه). برای گنجاندن نشانی فیزیکی در فیلد address_info، هر چهار فیلد الزامی (hashed_first_name،‏ hashed_last_name، country_code، و postal_code) را ارائه دهید. اگر هرکدام از این چهار فیلد دردسترس نباشد (برای مثال، وقتی فقط نام و نام خانوادگی کاربر را دارید)، شیء UserIdentifier را برای فیلد address_info حذف کنید.

جاوا

// Creates a builder for constructing the enhancement adjustment.
ConversionAdjustment.Builder enhancementBuilder =
    ConversionAdjustment.newBuilder().setAdjustmentType(ConversionAdjustmentType.ENHANCEMENT);

// Extracts user email, phone, and address info from the raw data, normalizes and hashes it,
// then wraps it in UserIdentifier objects.
// Creates a separate UserIdentifier object for each. The data in this example is hardcoded, but
// in your application you might read the raw data from an input file.

// IMPORTANT: Since the identifier attribute of UserIdentifier
// (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier) is a
// oneof
// (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must set only ONE of
// hashedEmail, hashedPhoneNumber, mobileId, thirdPartyUserId, or addressInfo. Setting more
// than one of these attributes on the same UserIdentifier will clear all the other members
// of the oneof. For example, the following code is INCORRECT and will result in a
// UserIdentifier with ONLY a hashedPhoneNumber.
//
// UserIdentifier incorrectlyPopulatedUserIdentifier =
//     UserIdentifier.newBuilder()
//         .setHashedEmail("...")
//         .setHashedPhoneNumber("...")
//         .build();

ImmutableMap.Builder<String, String> rawRecordBuilder =
    ImmutableMap.<String, String>builder()
        // Email address that includes a period (.) and plus (+) suffix before the Gmail domain.
        .put("email", "alex.2+myalias@gmail.com")
        // Address that includes all four required elements: first name, last name, country
        // code, and postal code.
        .put("firstName", "Alex")
        .put("lastName", "Quinn")
        .put("countryCode", "US")
        .put("postalCode", "94045")
        // Phone number to be converted to E.164 format, with a leading '+' as required.
        .put("phone", "+1 800-555-0102")
        // This example lets you put conversion details as arguments, but in reality you might
        // store this data alongside other user data, so we include it in this sample user
        // record.
        .put("orderId", orderId)
        .put("conversionActionId", Long.toString(conversionActionId))
        .put("currencyCode", "USD");

// Adds entries for the optional fields.
if (conversionDateTime != null) {
  rawRecordBuilder.put("conversionDateTime", conversionDateTime);
}
if (userAgent != null) {
  rawRecordBuilder.put("userAgent", userAgent);
}

// Builds the map representing the record.
Map<String, String> rawRecord = rawRecordBuilder.build();

// Creates a SHA256 message digest for hashing user identifiers in a privacy-safe way, as
// described at https://support.google.com/google-ads/answer/9888656.
MessageDigest sha256Digest = MessageDigest.getInstance("SHA-256");

// Creates a list for the user identifiers.
List<UserIdentifier> userIdentifiers = new ArrayList<>();

// Creates a user identifier using the hashed email address, using the normalize and hash method
// specifically for email addresses.
UserIdentifier emailIdentifier =
    UserIdentifier.newBuilder()
        // Optional: specify the user identifier source.
        .setUserIdentifierSource(UserIdentifierSource.FIRST_PARTY)
        // Uses the normalize and hash method specifically for email addresses.
        .setHashedEmail(normalizeAndHashEmailAddress(sha256Digest, rawRecord.get("email")))
        .build();
userIdentifiers.add(emailIdentifier);

// Checks if the record has a phone number, and if so, adds a UserIdentifier for it.
if (rawRecord.containsKey("phone")) {
  UserIdentifier hashedPhoneNumberIdentifier =
      UserIdentifier.newBuilder()
          .setHashedPhoneNumber(
              normalizeAndHashPhoneNumber(sha256Digest, rawRecord.get("phone")))
          .build();
  // Adds the hashed phone number identifier to the UserData object's list.
  userIdentifiers.add(hashedPhoneNumberIdentifier);
}

// Checks if the record has all the required mailing address elements, and if so, adds a
// UserIdentifier for the mailing address.
if (rawRecord.containsKey("firstName")) {
  // Checks if the record contains all the other required elements of a mailing address.
  Set<String> missingAddressKeys = new HashSet<>();
  for (String addressKey : new String[] {"lastName", "countryCode", "postalCode"}) {
    if (!rawRecord.containsKey(addressKey)) {
      missingAddressKeys.add(addressKey);
    }
  }

  if (!missingAddressKeys.isEmpty()) {
    System.out.printf(
        "Skipping addition of mailing address information because the following required keys"
            + " are missing: %s%n",
        missingAddressKeys);
  } else {
    // Creates an OfflineUserAddressInfo object that contains all the required elements of a
    // mailing address.
    OfflineUserAddressInfo addressInfo =
        OfflineUserAddressInfo.newBuilder()
            .setHashedFirstName(
                normalizeAndHash(sha256Digest, rawRecord.get("firstName"), false))
            .setHashedLastName(normalizeAndHash(sha256Digest, rawRecord.get("lastName"), false))
            .setCountryCode(rawRecord.get("countryCode"))
            .setPostalCode(rawRecord.get("postalCode"))
            .build();
    UserIdentifier addressIdentifier =
        UserIdentifier.newBuilder().setAddressInfo(addressInfo).build();
    // Adds the address identifier to the UserData object's list.
    userIdentifiers.add(addressIdentifier);
  }
}

// Adds the user identifiers to the enhancement adjustment.
enhancementBuilder.addAllUserIdentifiers(userIdentifiers);
      

C#‎

// Normalize and hash the raw data, then wrap it in UserIdentifier objects.
// Create a separate UserIdentifier object for each. The data in this example is
// hardcoded, but in your application you might read the raw data from an input file.
//
// IMPORTANT: Since the identifier attribute of UserIdentifier
// (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier)
// is a oneof
// (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must set
// only ONE of hashed_email, hashed_phone_number, mobile_id, third_party_user_id,
// or address-info. Setting more than one of these attributes on the same UserIdentifier
// will clear all the other members of the oneof. For example, the following code is
// INCORRECT and will result in a UserIdentifier with ONLY a hashed_phone_number:
// UserIdentifier incorrectlyPopulatedUserIdentifier = new UserIdentifier()
// {
//         HashedEmail = "..."
//         HashedPhoneNumber = "..."
// }
UserIdentifier addressIdentifier = new UserIdentifier()
{
    AddressInfo = new OfflineUserAddressInfo()
    {
        HashedFirstName = NormalizeAndHash("Dana"),
        HashedLastName = NormalizeAndHash("Quinn"),
        HashedStreetAddress = NormalizeAndHash("1600 Amphitheatre Pkwy"),
        City = "Mountain View",
        State = "CA",
        PostalCode = "94043",
        CountryCode = "US"
    },
    // Optional: Specifies the user identifier source.
    UserIdentifierSource = UserIdentifierSource.FirstParty
};

// Creates a user identifier using the hashed email address.
UserIdentifier emailIdentifier = new UserIdentifier()
{
    UserIdentifierSource = UserIdentifierSource.FirstParty,
    // Uses the normalize and hash method specifically for email addresses.
    HashedEmail = NormalizeAndHashEmailAddress("dana@example.com")
};

// Adds the user identifiers to the enhancement adjustment.
enhancement.UserIdentifiers.AddRange(new[] { addressIdentifier, emailIdentifier });
      

PHP

// Creates the conversion enhancement.
$enhancement =
    new ConversionAdjustment(['adjustment_type' => ConversionAdjustmentType::ENHANCEMENT]);

// Extracts user email, phone, and address info from the raw data, normalizes and hashes it,
// then wraps it in UserIdentifier objects.
// Creates a separate UserIdentifier object for each. The data in this example is hardcoded,
// but in your application you might read the raw data from an input file.

// IMPORTANT: Since the identifier attribute of UserIdentifier
// (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier) is a
// oneof
// (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must set only ONE
// of hashedEmail, hashedPhoneNumber, mobileId, thirdPartyUserId, or addressInfo. Setting
// more than one of these attributes on the same UserIdentifier will clear all the other
// members of the oneof. For example, the following code is INCORRECT and will result in a
// UserIdentifier with ONLY a hashedPhoneNumber.
//
// $incorrectlyPopulatedUserIdentifier = new UserIdentifier([
//    'hashed_email' => '...',
//    'hashed_phone_number' => '...'
// ]);

$rawRecord = [
    // Email address that includes a period (.) before the Gmail domain.
    'email' => 'alex.2@example.com',
    // Address that includes all four required elements: first name, last name, country
    // code, and postal code.
    'firstName' => 'Alex',
    'lastName' => 'Quinn',
    'countryCode' => 'US',
    'postalCode' => '94045',
    // Phone number to be converted to E.164 format, with a leading '+' as required.
    'phone' => '+1 800 5550102',
    // This example lets you input conversion details as arguments, but in reality you might
    // store this data alongside other user data, so we include it in this sample user
    // record.
    'orderId' => $orderId,
    'conversionActionId' => $conversionActionId,
    'conversionDateTime' => $conversionDateTime,
    'currencyCode' => 'USD'
];

// Creates a list for the user identifiers.
$userIdentifiers = [];

// Uses the SHA-256 hash algorithm for hashing user identifiers in a privacy-safe way, as
// described at https://support.google.com/google-ads/answer/9888656.
$hashAlgorithm = "sha256";

// Creates a user identifier using the hashed email address, using the normalize and hash
// method specifically for email addresses.
$emailIdentifier = new UserIdentifier(
    [
    // Uses the normalize and hash method specifically for email addresses.
    'hashed_email' => self::normalizeAndHashEmailAddress(
        $hashAlgorithm,
        $rawRecord['email']
    ),
    // Optional: Specifies the user identifier source.
    'user_identifier_source' => UserIdentifierSource::FIRST_PARTY
    ]
);
$userIdentifiers[] = $emailIdentifier;

// Checks if the record has a phone number, and if so, adds a UserIdentifier for it.
if (array_key_exists('phone', $rawRecord)) {
    $hashedPhoneNumberIdentifier = new UserIdentifier(
        [
        'hashed_phone_number' => self::normalizeAndHash(
            $hashAlgorithm,
            $rawRecord['phone'],
            true
        )
        ]
    );
    // Adds the hashed email identifier to the user identifiers list.
    $userIdentifiers[] = $hashedPhoneNumberIdentifier;
}

// Checks if the record has all the required mailing address elements, and if so, adds a
// UserIdentifier for the mailing address.
if (array_key_exists('firstName', $rawRecord)) {
    // Checks if the record contains all the other required elements of a mailing
    // address.
    $missingAddressKeys = [];
    foreach (['lastName', 'countryCode', 'postalCode'] as $addressKey) {
        if (!array_key_exists($addressKey, $rawRecord)) {
            $missingAddressKeys[] = $addressKey;
        }
    }
    if (!empty($missingAddressKeys)) {
        printf(
            "Skipping addition of mailing address information because the "
            . "following required keys are missing: %s%s",
            json_encode($missingAddressKeys),
            PHP_EOL
        );
    } else {
        // Creates an OfflineUserAddressInfo object that contains all the required
        // elements of a mailing address.
        $addressIdentifier = new UserIdentifier(
            [
            'address_info' => new OfflineUserAddressInfo(
                [
                'hashed_first_name' => self::normalizeAndHash(
                    $hashAlgorithm,
                    $rawRecord['firstName'],
                    false
                ),
                'hashed_last_name' => self::normalizeAndHash(
                    $hashAlgorithm,
                    $rawRecord['lastName'],
                    false
                ),
                'country_code' => $rawRecord['countryCode'],
                'postal_code' => $rawRecord['postalCode']
                ]
            )
            ]
        );
        // Adds the address identifier to the user identifiers list.
        $userIdentifiers[] = $addressIdentifier;
    }
}

// Adds the user identifiers to the conversion.
$enhancement->setUserIdentifiers($userIdentifiers);
      

Python

# Extracts user email, phone, and address info from the raw data, normalizes
# and hashes it, then wraps it in UserIdentifier objects. Creates a separate
# UserIdentifier object for each. The data in this example is hardcoded, but
# in your application you might read the raw data from an input file.

# IMPORTANT: Since the identifier attribute of UserIdentifier
# (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier)
# is a oneof
# (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must
# set only ONE of hashed_email, hashed_phone_number, mobile_id,
# third_party_user_id, or address_info. Setting more than one of these
# attributes on the same UserIdentifier will clear all the other members of
# the oneof. For example, the following code is INCORRECT and will result in
# a UserIdentifier with ONLY a hashed_phone_number:
#
# incorrectly_populated_user_identifier = client.get_type("UserIdentifier")
# incorrectly_populated_user_identifier.hashed_email = "...""
# incorrectly_populated_user_identifier.hashed_phone_number = "...""

raw_record = {
    # Email address that includes a period (.) before the Gmail domain.
    "email": "alex.2@example.com",
    # Address that includes all four required elements: first name, last
    # name, country code, and postal code.
    "first_name": "Alex",
    "last_name": "Quinn",
    "country_code": "US",
    "postal_code": "94045",
    # Phone number to be converted to E.164 format, with a leading '+' as
    # required.
    "phone": "+1 800 5550102",
    # This example lets you input conversion details as arguments, but in
    # reality you might store this data alongside other user data, so we
    # include it in this sample user record.
    "order_id": order_id,
    "conversion_action_id": conversion_action_id,
    "conversion_date_time": conversion_date_time,
    "currency_code": "USD",
    "user_agent": user_agent,
}

# Constructs the enhancement adjustment.
conversion_adjustment = client.get_type("ConversionAdjustment")
conversion_adjustment.adjustment_type = (
    client.enums.ConversionAdjustmentTypeEnum.ENHANCEMENT
)

# Creates a user identifier using the hashed email address, using the
# normalize and hash method specifically for email addresses.
email_identifier = client.get_type("UserIdentifier")
# Optional: Specifies the user identifier source.
email_identifier.user_identifier_source = (
    client.enums.UserIdentifierSourceEnum.FIRST_PARTY
)
# Uses the normalize and hash method specifically for email addresses.
email_identifier.hashed_email = normalize_and_hash_email_address(
    raw_record["email"]
)
# Adds the email identifier to the conversion adjustment.
conversion_adjustment.user_identifiers.append(email_identifier)

# Checks if the record has a phone number, and if so, adds a UserIdentifier
# for it.
if raw_record.get("phone") is not None:
    phone_identifier = client.get_type("UserIdentifier")
    phone_identifier.hashed_phone_number = normalize_and_hash(
        raw_record["phone"]
    )
    # Adds the phone identifier to the conversion adjustment.
    conversion_adjustment.user_identifiers.append(phone_identifier)

# Checks if the record has all the required mailing address elements, and if
# so, adds a UserIdentifier for the mailing address.
if raw_record.get("first_name") is not None:
    # Checks if the record contains all the other required elements of a
    # mailing address.
    required_keys = ["last_name", "country_code", "postal_code"]
    # Builds a new list of the required keys that are missing from
    # raw_record.
    missing_keys = [
        key for key in required_keys if key not in raw_record.keys()
    ]
    if len(missing_keys) > 0:
        print(
            "Skipping addition of mailing address information because the"
            f"following required keys are missing: {missing_keys}"
        )
    else:
        # Creates a user identifier using sample values for the user address,
        # hashing where required.
        address_identifier = client.get_type("UserIdentifier")
        address_info = address_identifier.address_info
        address_info.hashed_first_name = normalize_and_hash(
            raw_record["first_name"]
        )
        address_info.hashed_last_name = normalize_and_hash(
            raw_record["last_name"]
        )
        address_info.country_code = raw_record["country_code"]
        address_info.postal_code = raw_record["postal_code"]
        # Adds the address identifier to the conversion adjustment.
        conversion_adjustment.user_identifiers.append(address_identifier)
      

Ruby

# Extracts user email, phone, and address info from the raw data, normalizes
# and hashes it, then wraps it in UserIdentifier objects. Creates a separate
# UserIdentifier object for each. The data in this example is hardcoded, but
# in your application you might read the raw data from an input file.

# IMPORTANT: Since the identifier attribute of UserIdentifier
# (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier)
# is a oneof
# (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must
# set only ONE of hashed_email, hashed_phone_number, mobile_id,
# third_party_user_id, or address_info. Setting more than one of these
# attributes on the same UserIdentifier will clear all the other members of
# the oneof. For example, the following code is INCORRECT and will result in
# a UserIdentifier with ONLY a hashed_phone_number:
#
# incorrectly_populated_user_identifier.hashed_email = "...""
# incorrectly_populated_user_identifier.hashed_phone_number = "...""

raw_record = {
    # Email address that includes a period (.) before the Gmail domain.
    "email" => "alex.2@example.com",
    # Address that includes all four required elements: first name, last
    # name, country code, and postal code.
    "first_name" => "Alex",
    "last_name" => "Quinn",
    "country_code" => "US",
    "postal_code" => "94045",
    # Phone number to be converted to E.164 format, with a leading '+' as
    # required.
    "phone" => "+1 800 5550102",
    # This example lets you input conversion details as arguments, but in
    # reality you might store this data alongside other user data, so we
    # include it in this sample user record.
    "order_id" => order_id,
    "conversion_action_id" => conversion_action_id,
    "conversion_date_time" => conversion_date_time,
    "currency_code" => "USD",
    "user_agent" => user_agent,
}

enhancement = client.resource.conversion_adjustment do |ca|
  ca.conversion_action = client.path.conversion_action(customer_id, conversion_action_id)
  ca.adjustment_type = :ENHANCEMENT
  ca.order_id = order_id

  # Sets the conversion date and time if provided. Providing this value is
  # optional but recommended.
  unless conversion_date_time.nil?
    ca.gclid_date_time_pair = client.resource.gclid_date_time_pair do |pair|
      pair.conversion_date_time = conversion_date_time
    end
  end

  # Creates a user identifier using the hashed email address, using the
  # normalize and hash method specifically for email addresses.
  ca.user_identifiers << client.resource.user_identifier do |ui|
    # Uses the normalize and hash method specifically for email addresses.
    ui.hashed_email = normalize_and_hash_email(raw_record["email"])
    # Optional: Specifies the user identifier source.
    ui.user_identifier_source = :FIRST_PARTY
  end

  # Checks if the record has a phone number, and if so, adds a UserIdentifier
  # for it.
  unless raw_record["phone"].nil?
    ca.user_identifiers << client.resource.user_identifier do |ui|
      ui.hashed_phone_number = normalize_and_hash_email(raw_record["phone"])
    end
  end

  # Checks if the record has all the required mailing address elements, and if
  # so, adds a UserIdentifier for the mailing address.
  unless raw_record["first_name"].nil?
    # Checks if the record contains all the other required elements of a
    # mailing address.
    required_keys = ["last_name", "country_code", "postal_code"]
    # Builds a new list of the required keys that are missing from
    # raw_record.
    missing_keys = required_keys - raw_record.keys
    if missing_keys
        puts(
            "Skipping addition of mailing address information because the" \
            "following required keys are missing: #{missing_keys}"
        )
    else
      ca.user_identifiers << client.resource.user_identifier do |ui|
        ui.address_info = client.resource.offline_user_address_info do |info|
          # Certain fields must be hashed using SHA256 in order to handle
          # identifiers in a privacy-safe way, as described at
          # https://support.google.com/google-ads/answer/9888656.
          info.hashed_first_name = normalize_and_hash( raw_record["first_name"])
          info.hashed_last_name = normalize_and_hash( raw_record["last_name"])
          info.postal_code = normalize_and_hash(raw_record["country_code"])
          info.country_code = normalize_and_hash(raw_record["postal_code"])
        end
      end
    end
  end
      

پرل

# Construct the enhancement adjustment.
my $enhancement =
  Google::Ads::GoogleAds::V26::Services::ConversionAdjustmentUploadService::ConversionAdjustment
  ->new({
    adjustmentType => ENHANCEMENT
  });

# Extract user email, phone, and address info from the raw data,
# normalize and hash it, then wrap it in UserIdentifier objects.
# Create a separate UserIdentifier object for each.
# The data in this example is hardcoded, but in your application
# you might read the raw data from an input file.
#
# IMPORTANT: Since the identifier attribute of UserIdentifier
# (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier)
# is a oneof
# (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must set
# only ONE of hashed_email, hashed_phone_number, mobile_id, third_party_user_id,
# or address-info. Setting more than one of these attributes on the same UserIdentifier
# will clear all the other members of the oneof. For example, the following code is
# INCORRECT and will result in a UserIdentifier with ONLY a hashed_phone_number:
#
# my $incorrect_user_identifier = Google::Ads::GoogleAds::V26::Common::UserIdentifier->new({
#   hashedEmail => '...',
#   hashedPhoneNumber => '...',
# });
my $raw_record = {
  # Email address that includes a period (.) before the Gmail domain.
  email => 'alex.2@example.com',
  # Address that includes all four required elements: first name, last
  # name, country code, and postal code.
  firstName   => 'Alex',
  lastName    => 'Quinn',
  countryCode => 'US',
  postalCode  => '94045',
  # Phone number to be converted to E.164 format, with a leading '+' as
  # required.
  phone => '+1 800 5550102',
  # This example lets you input conversion details as arguments,
  # but in reality you might store this data alongside other user data,
  # so we include it in this sample user record.
  orderId            => $order_id,
  conversionActionId => $conversion_action_id,
  conversionDateTime => $conversion_date_time,
  currencyCode       => "USD",
  userAgent          => $user_agent,
};
my $user_identifiers = [];

# Create a user identifier using the hashed email address, using the normalize
# and hash method specifically for email addresses.
my $hashed_email = normalize_and_hash_email_address($raw_record->{email});
push(
  @$user_identifiers,
  Google::Ads::GoogleAds::V26::Common::UserIdentifier->new({
      hashedEmail => $hashed_email,
      # Optional: Specify the user identifier source.
      userIdentifierSource => FIRST_PARTY
    }));

# Check if the record has a phone number, and if so, add a UserIdentifier for it.
if (defined $raw_record->{phone}) {
  # Add the hashed phone number identifier to the list of UserIdentifiers.
  push(
    @$user_identifiers,
    Google::Ads::GoogleAds::V26::Common::UserIdentifier->new({
        hashedPhoneNumber => normalize_and_hash($raw_record->{phone}, 1)}));
}

# Confirm the record has all the required mailing address elements, and if so, add
# a UserIdentifier for the mailing address.
if (defined $raw_record->{firstName}) {
  my $required_keys = ["lastName", "countryCode", "postalCode"];
  my $missing_keys  = [];

  foreach my $key (@$required_keys) {
    if (!defined $raw_record->{$key}) {
      push(@$missing_keys, $key);
    }
  }

  if (@$missing_keys) {
    print
      "Skipping addition of mailing address information because the following"
      . "keys are missing: "
      . join(",", @$missing_keys);
  } else {
    push(
      @$user_identifiers,
      Google::Ads::GoogleAds::V26::Common::UserIdentifier->new({
          addressInfo =>
            Google::Ads::GoogleAds::V26::Common::OfflineUserAddressInfo->new({
              # First and last name must be normalized and hashed.
              hashedFirstName => normalize_and_hash($raw_record->{firstName}),
              hashedLastName  => normalize_and_hash($raw_record->{lastName}),
              # Country code and zip code are sent in plain text.
              countryCode => $raw_record->{countryCode},
              postalCode  => $raw_record->{postalCode},
            })}));
  }
}

# Add the user identifiers to the enhancement adjustment.
$enhancement->{userIdentifiers} = $user_identifiers;
      

curl

جاوا

// Sets the conversion action.
enhancementBuilder.setConversionAction(
    ResourceNames.conversionAction(
        customerId, Long.parseLong(rawRecord.get("conversionActionId"))));

// Sets the order ID. Enhancements MUST use order ID instead of GCLID date/time pair.
enhancementBuilder.setOrderId(rawRecord.get("orderId"));

// Sets the conversion date and time if provided. Providing this value is optional but
// recommended.
if (rawRecord.containsKey("conversionDateTime")) {
  enhancementBuilder.setGclidDateTimePair(
      GclidDateTimePair.newBuilder()
          .setConversionDateTime(rawRecord.get("conversionDateTime")));
}

// Sets the user agent if provided. This should match the user agent of the request that sent
// the original conversion so the conversion and its enhancement are either both attributed as
// same-device or both attributed as cross-device.
if (rawRecord.containsKey("userAgent")) {
  enhancementBuilder.setUserAgent(rawRecord.get("userAgent"));
}
      

C#‎

// Set the conversion action.
enhancement.ConversionAction =
    ResourceNames.ConversionAction(customerId, conversionActionId);

// Set the order ID. Enhancements MUST use order ID instead of GCLID date/time pair.
enhancement.OrderId = orderId;

// Sets the conversion date and time if provided. Providing this value is optional but
// recommended.
if (string.IsNullOrEmpty(conversionDateTime))
{
    enhancement.GclidDateTimePair = new GclidDateTimePair()
    {
        ConversionDateTime = conversionDateTime
    };
}

// Sets optional fields where a value was provided.
if (!string.IsNullOrEmpty(userAgent))
{
    // Sets the user agent. This should match the user agent of the request that
    // sent the original conversion so the conversion and its enhancement are either
    // both attributed as same-device or both attributed as cross-device.
    enhancement.UserAgent = userAgent;
}

      

PHP

// Sets the conversion action.
$enhancement->setConversionAction(
    ResourceNames::forConversionAction($customerId, $rawRecord['conversionActionId'])
);

// Sets the order ID. Enhancements MUST use order ID instead of GCLID date/time pair.
if (!empty($rawRecord['orderId'])) {
    $enhancement->setOrderId($rawRecord['orderId']);
}

// Sets the conversion date and time if provided. Providing this value is optional but
// recommended.
if (!empty($rawRecord['conversionDateTime'])) {
    // Sets the conversion date and time if provided. Providing this value is optional but
    // recommended.
    $enhancement->setGclidDateTimePair(
        new GclidDateTimePair(
            [
            'conversion_date_time' => $rawRecord['conversionDateTime']
            ]
        )
    );
}

// Sets the user agent if provided. This should match the user agent of the request that
// sent the original conversion so the conversion and its enhancement are either both
// attributed as same-device or both attributed as cross-device.
if (!empty($rawRecord['userAgent'])) {
    $enhancement->setUserAgent($rawRecord['userAgent']);
}
      

Python

conversion_action_service = client.get_service("ConversionActionService")
# Sets the conversion action.
conversion_adjustment.conversion_action = (
    conversion_action_service.conversion_action_path(
        customer_id, raw_record["conversion_action_id"]
    )
)

# Sets the order ID. Enhancements MUST use order ID instead of GCLID
# date/time pair.
conversion_adjustment.order_id = order_id

# Sets the conversion date and time if provided. Providing this value is
# optional but recommended.
if raw_record.get("conversion_date_time"):
    conversion_adjustment.gclid_date_time_pair.conversion_date_time = (
        raw_record["conversion_date_time"]
    )

# Sets optional fields where a value was provided
if raw_record.get("user_agent"):
    # Sets the user agent. This should match the user agent of the request
    # that sent the original conversion so the conversion and its
    # enhancement are either both attributed as same-device or both
    # attributed as cross-device.
    conversion_adjustment.user_agent = user_agent
      

Ruby

ca.conversion_action = client.path.conversion_action(customer_id, conversion_action_id)
ca.adjustment_type = :ENHANCEMENT
ca.order_id = order_id

# Sets the conversion date and time if provided. Providing this value is
# optional but recommended.
unless conversion_date_time.nil?
  ca.gclid_date_time_pair = client.resource.gclid_date_time_pair do |pair|
    pair.conversion_date_time = conversion_date_time
  end
end

# Creates a user identifier using the hashed email address, using the
# normalize and hash method specifically for email addresses.
ca.user_identifiers << client.resource.user_identifier do |ui|
  # Uses the normalize and hash method specifically for email addresses.
  ui.hashed_email = normalize_and_hash_email(raw_record["email"])
  # Optional: Specifies the user identifier source.
  ui.user_identifier_source = :FIRST_PARTY
end

# Checks if the record has a phone number, and if so, adds a UserIdentifier
# for it.
unless raw_record["phone"].nil?
  ca.user_identifiers << client.resource.user_identifier do |ui|
    ui.hashed_phone_number = normalize_and_hash_email(raw_record["phone"])
  end
end

# Checks if the record has all the required mailing address elements, and if
# so, adds a UserIdentifier for the mailing address.
unless raw_record["first_name"].nil?
  # Checks if the record contains all the other required elements of a
  # mailing address.
  required_keys = ["last_name", "country_code", "postal_code"]
  # Builds a new list of the required keys that are missing from
  # raw_record.
  missing_keys = required_keys - raw_record.keys
  if missing_keys
      puts(
          "Skipping addition of mailing address information because the" \
          "following required keys are missing: #{missing_keys}"
      )
  else
    ca.user_identifiers << client.resource.user_identifier do |ui|
      ui.address_info = client.resource.offline_user_address_info do |info|
        # Certain fields must be hashed using SHA256 in order to handle
        # identifiers in a privacy-safe way, as described at
        # https://support.google.com/google-ads/answer/9888656.
        info.hashed_first_name = normalize_and_hash( raw_record["first_name"])
        info.hashed_last_name = normalize_and_hash( raw_record["last_name"])
        info.postal_code = normalize_and_hash(raw_record["country_code"])
        info.country_code = normalize_and_hash(raw_record["postal_code"])
      end
    end
  end
end

# Sets optional fields where a value was provided.
unless user_agent.nil?
  # Sets the user agent. This should match the user agent of the request
  # that sent the original conversion so the conversion and its enhancement
  # are either both attributed as same-device or both attributed as
  # cross-device.
  ca.user_agent = user_agent
end
      

پرل

# Set the conversion action.
$enhancement->{conversionAction} =
  Google::Ads::GoogleAds::V26::Utils::ResourceNames::conversion_action(
  $customer_id, $raw_record->{conversionActionId});

# Set the order ID. Enhancements MUST use order ID instead of GCLID date/time pair.
$enhancement->{orderId} = $raw_record->{orderId};

# Set the conversion date and time if provided. Providing this value is optional
# but recommended.
if (defined $raw_record->{conversionDateTime}) {
  $enhancement->{gclidDateTimePair} =
    Google::Ads::GoogleAds::V26::Services::ConversionAdjustmentUploadService::GclidDateTimePair
    ->new({
      conversionDateTime => $raw_record->{conversionDateTime}});
}

# Set the user agent if provided. This should match the user agent of the
# request that sent the original conversion so the conversion and its enhancement
# are either both attributed as same-device or both attributed as cross-device.
if (defined $raw_record->{userAgent}) {
  $enhancement->{userAgent} = $raw_record->{userAgent};
}
      

curl

خلاصه طرحواره Request و ConversionAdjustment

جدول‌های زیر فیلدهای سطح بالا را در UploadConversionAdjustmentsRequest و فیلدهای هر مورد را در ConversionAdjustment (conversion_adjustments[]) هنگام بارگذاری تبدیل‌های بهبودیافته برای وب بااستفاده از ConversionAdjustmentUploadService.UploadConversionAdjustments خلاصه می‌کنند:

فیلد درخواست الزام قالب و محدودیت‌ها
customer_id الزامی روی شناسه مشتری تبدیل Google Ads (google_ads_conversion_customer در customer.conversion_tracking_setting)، بدون خط تیره، تنظیم شده است.
conversion_adjustments[] الزامی تا ۲٬۰۰۰ ورودی ConversionAdjustment در هر درخواست (TOO_MANY_ADJUSTMENTS_IN_REQUEST).
partial_failure الزامی باید روی true تنظیم شود تا اصلاحات معتبر پردازش شوند و خطاهای سطح ردیف در partial_failure_error برگردانده شوند.
validate_only اختیاری وقتی true، درخواست را بدون اجرای اصلاحات اعتبارسنجی می‌کند.
job_id اختیاری مثبت int32 (1 تا 2^31 - 1؛ 0 نگهبان تنظیم‌نشده است و اگر مشخص شده باشد INVALID_JOB_ID را برمی‌گرداند) برای گروه‌بندی چند درخواست تحت یک کار منطقی واحد در job_summaries.

هر ConversionAdjustment در conversion_adjustments[] (حداکثر ۲۰۰۰ اصلاح در هر درخواست) از فیلدهای زیر پشتیبانی می‌کند:

ConversionAdjustment فیلد الزام قالب و محدودیت‌ها
adjustment_type الزامی باید روی ENHANCEMENT (ConversionAdjustmentType) تنظیم شود.
conversion_action الزامی نام منبع (customers/{conversion_customer_id}/conversionActions/{action_id}) کنش تبدیل ENABLED با type = WEBPAGE حداقل ۶ ساعت قبل‌از بارگذاری (TOO_RECENT_CONVERSION_ACTION) ایجاد شده است.
order_id الزامی شناسه تراکنش تبدیل برای بهبود؛ باید با شناسه سفارش ارسال‌شده توسط برچسب تبدیل وب‌سایت مطابقت داشته باشد.
user_identifiers[] الزامی یک تا پنج شیء UserIdentifier در هر بهبود. فیلد اختیاری user_identifier_source (مانند FIRST_PARTY) و یک فیلد شناسه را برای هر ورودی تنظیم کنید:
  • hashed_email: رشته بر مبنای شانزده SHA-256.
  • hashed_phone_number: رشته هگزادسیمال SHA-256 E.164.
  • ‫address_info: شیء OfflineUserAddressInfo. به hashed_first_name و hashed_last_name (رشته‌های شانزده‌شانزدهی SHA-256)،‏ country_code (کد دوحرفی ISO 3166-1 alpha-2 درهم‌نشده)، و postal_code (درهم‌نشده) در همان ورودی نیاز دارد. فیلدهای hashed_street_address (رشته بر مبنای شانزده SHA-256)، city (درهم‌سازی‌نشده)، و state (درهم‌سازی‌نشده) اختیاری هستند. اگر هرکدام از چهار فیلد الزامی دردسترس نبود، فیلد address_info را حذف کنید. این میانای برنامه‌سازی کاربردی نشانی‌های جزئی غیرخالی را بدون برگرداندن خطا در فیلد partial_failure_error می‌پذیرد، اما تطابق پایین‌دست آن‌ها را رد می‌کند.
gclid_date_time_pair اختیاری (توصیه‌شده) شیء GclidDateTimePair حاوی فیلدهای gclid و conversion_date_time تبدیل اصلی، با قالب yyyy-mm-dd HH:mm:ss+|-HH:mm (برای مثال، 2026-06-01 14:30:00-04:00). بهبودها را ظرف ۲۴ ساعت از رویداد تبدیل بارگذاری کنید. پیام GclidDateTimePair فقط فیلد gclid را می‌پذیرد. وقتی کلیک به‌جای پارامتر gclid، پارامتر gbraid یا wbraid را پر می‌کند، Google Ads از تبدیل‌های بهبودیافته برای وب پشتیبانی نمی‌کند.
adjustment_date_time اختیاری مُهر زمان وقوع اصلاح، با قالب yyyy-mm-dd HH:mm:ss+|-HH:mm. اگر تنظیم شود، این مُهر زمان باید بعداز مقدار conversion_date_time باشد و در آینده نباشد.
user_agent اختیاری رشته سرایند HTTP User-Agent از درخواست تبدیل اصلی تا تبدیل و بهبود، اسناد دستگاه یکسانی را هم‌رسانی کنند (same-device یا cross-device).
restatement_value تنظیم نشدن در ENHANCEMENT وقتی adjustment_type روی ENHANCEMENT باشد، نادیده گرفته می‌شود. برای تغییر مقدار تبدیل، عملیات جداگانه‌ای با adjustment_type = RESTATEMENT ارسال کنید.

وارد کردن بهبودهای تبدیل

جاوا

// Creates the conversion adjustment upload service client.
try (ConversionAdjustmentUploadServiceClient conversionUploadServiceClient =
    googleAdsClient.getLatestVersion().createConversionAdjustmentUploadServiceClient()) {
  // Uploads the enhancement adjustment. Partial failure should always be set to true.

  // NOTE: This request contains a single adjustment as a demonstration. However, if you have
  // multiple adjustments to upload, it's best to upload multiple adjustments per request
  // instead of sending a separate request per adjustment. See the following for per-request
  // limits:
  // https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_adjustment_upload_service
  UploadConversionAdjustmentsResponse response =
      conversionUploadServiceClient.uploadConversionAdjustments(
          UploadConversionAdjustmentsRequest.newBuilder()
              .setCustomerId(Long.toString(customerId))
              .addConversionAdjustments(enhancementBuilder)
              // Enables partial failure (must be true).
              .setPartialFailure(true)
              .build());
      

C#‎

// Uploads the enhancement adjustment. Partial failure should always be set to true.
//
// NOTE: This request contains a single adjustment as a demonstration.
// However, if you have multiple adjustments to upload, it's best to upload
// multiple adjustmenst per request instead of sending a separate request per
// adjustment. See the following for per-request limits:
// https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_adjust
UploadConversionAdjustmentsResponse response =
    conversionAdjustmentUploadService.UploadConversionAdjustments(
        new UploadConversionAdjustmentsRequest()
        {
            CustomerId = customerId.ToString(),
            ConversionAdjustments = { enhancement },
            // Enables partial failure (must be true).
            PartialFailure = true,
        });
      

PHP

// Issues a request to upload the conversion enhancement.
$conversionAdjustmentUploadServiceClient =
    $googleAdsClient->getConversionAdjustmentUploadServiceClient();
// NOTE: This request contains a single adjustment as a demonstration. However, if you have
// multiple adjustments to upload, it's best to upload multiple adjustments per request
// instead of sending a separate request per adjustment. See the following for per-request
// limits:
// https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_adjustment_upload_service
$response = $conversionAdjustmentUploadServiceClient->uploadConversionAdjustments(
    // Enables partial failure (must be true).
    UploadConversionAdjustmentsRequest::build($customerId, [$enhancement], true)
);
      

Python

# Creates the conversion adjustment upload service client.
conversion_adjustment_upload_service = client.get_service(
    "ConversionAdjustmentUploadService"
)
# Uploads the enhancement adjustment. Partial failure should always be set
# to true.
# NOTE: This request only uploads a single conversion, but if you have
# multiple conversions to upload, it's still best 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
response = conversion_adjustment_upload_service.upload_conversion_adjustments(
    customer_id=customer_id,
    conversion_adjustments=[conversion_adjustment],
    # Enables partial failure (must be true).
    partial_failure=True,
)
      

Ruby

response = client.service.conversion_adjustment_upload.upload_conversion_adjustments(
  customer_id: customer_id,
  # NOTE: This request only uploads a single conversion, but if you have
  # multiple conversions to upload, it's still best 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
  conversion_adjustments: [enhancement],
  # Partial failure must be set to true.
  partial_failure: true,
)
      

پرل

# Upload the enhancement adjustment. Partial failure should always be set to true.
#
# NOTE: This request contains a single adjustment as a demonstration.
# However, if you have multiple adjustments to upload, it's best to
# upload multiple adjustments per request instead of sending a separate
# request per adjustment. See the following for per-request limits:
# https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_adjustment_upload_service
my $response =
  $api_client->ConversionAdjustmentUploadService()
  ->upload_conversion_adjustments({
    customerId            => $customer_id,
    conversionAdjustments => [$enhancement],
    # Enable partial failure (must be true).
    partialFailure => "true"
  });
      

curl

ساختار درخواست و پاسخ REST

هنگام فراخوانی ConversionAdjustmentUploadService.UploadConversionAdjustments ازطریق REST، درخواست POST را با تنظیم partialFailure روی true ارسال کنید:

POST https://googleads.googleapis.com/v26/customers/{customer_id}:uploadConversionAdjustments
{
  "partialFailure": true,
  "jobId": 2001,
  "conversionAdjustments": [
    {
      "conversionAction": "customers/{customer_id}/conversionActions/{conversion_action_id}",
      "adjustmentType": "ENHANCEMENT",
      "orderId": "ORDER-2026-1001",
      "gclidDateTimePair": {
        "gclid": "EAIaIQobChMI...",
        "conversionDateTime": "2026-06-01 14:30:00-04:00"
      },
      "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
      "userIdentifiers": [
        {
          "userIdentifierSource": "FIRST_PARTY",
          "hashedEmail": "f660ab912ec121d1b1e928a0bb4bc61b15f5ad44d5efdc4e1c92a25e99b8e44a"
        },
        {
          "userIdentifierSource": "FIRST_PARTY",
          "hashedPhoneNumber": "42975f8f9e46c2e13c1a2294957e5cb8d8e6f4f7341a036c6e595bc9f5e24621"
        },
        {
          "userIdentifierSource": "FIRST_PARTY",
          "addressInfo": {
            "hashedFirstName": "a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3",
            "hashedLastName": "b3a8e0e1f9ab1bfe3a36f231f676f78bb30a519d2b21e6c530c0eee8ebb4a5d0",
            "hashedStreetAddress": "35a9e381b1a27567549b5f8a6f783c167ebf809f1c4d6a9e367240484d8ce281",
            "city": "New York",
            "state": "NY",
            "postalCode": "10011",
            "countryCode": "US"
          }
        }
      ]
    },
    {
      "conversionAction": "customers/{customer_id}/conversionActions/{conversion_action_id}",
      "adjustmentType": "ENHANCEMENT",
      "userIdentifiers": [
        {
          "userIdentifierSource": "FIRST_PARTY",
          "hashedEmail": "f660ab912ec121d1b1e928a0bb4bc61b15f5ad44d5efdc4e1c92a25e99b8e44a"
        }
      ]
    }
  ]
}

در این دسته دو اصلاحی که اصلاح دوم orderId را حذف می‌کند، ردیف‌های موفق ورودی‌های پرشده ConversionAdjustmentResult را در results[] برمی‌گردانند، درحالی‌که ردیف‌های ناموفق اشیای خالی {} را در results[] به‌همراه جزئیات خطای سطح ردیف در partialFailureError در UploadConversionAdjustmentsResponse برمی‌گردانند:

{
  "results": [
    {
      "gclidDateTimePair": {
        "gclid": "EAIaIQobChMI...",
        "conversionDateTime": "2026-06-01 14:30:00-04:00"
      },
      "orderId": "ORDER-2026-1001",
      "conversionAction": "customers/{customer_id}/conversionActions/{conversion_action_id}",
      "adjustmentType": "ENHANCEMENT"
    },
    {}
  ],
  "jobId": "2001",
  "partialFailureError": {
    "code": 3,
    "message": "The required field was not present., at conversion_adjustments[1].order_id",
    "details": [
      {
        "@type": "type.googleapis.com/google.ads.googleads.v26.errors.GoogleAdsFailure",
        "errors": [
          {
            "errorCode": {
              "fieldError": "REQUIRED"
            },
            "message": "The required field was not present.",
            "location": {
              "fieldPathElements": [
                {
                  "fieldName": "conversion_adjustments",
                  "index": 1
                },
                {
                  "fieldName": "order_id"
                }
              ]
            }
          }
        ]
      }
    ]
  }
}

مرور موارد واردشده

هم عیب‌یابی میانای کاربر Google Ads و هم عیب‌یابی داده‌های آفلاین را پایش کنید چون هر ابزار مرحله متفاوتی از خط لوله را بررسی می‌کند:

  • گزارش تشخیص خرابی تبدیل‌های بهبودیافته (میانای کاربر Google Ads): مطابقت ناهمگام بین رویدادهای برچسب وب‌سایت و بهبودهای میانای برنامه‌سازی کاربردی را اعتبارسنجی می‌کند. آن را بررسی کنید تا شناسه‌های تراکنش برچسب ناموجود، مقادیر برچسب و میانای برنامه‌سازی کاربردی order_id نامطابق، پوشش بهبود میانای برنامه‌سازی کاربردی پایین، داده‌های کاربر نرمال‌سازی‌نشده، یا فیلدهای address_info ناقص را شناسایی کنید. این مشکلات خطاهای میانای برنامه‌سازی کاربردی را برنمی‌گردانند یا در عیب‌یابی داده‌های آفلاین ظاهر نمی‌شوند. برای مراحل عیب‌یابی، هشدارهای عیب‌یابی میانای کاربر پس‌از بارگذاری موفق میانای برنامه‌سازی کاربردی را ببینید.
  • تشخیص داده‌های آفلاین (Google Ads API): خطاهای اعتبارسنجی و سلامت جذب API در سطح درخواست را ردیابی می‌کند، مانند خطاهای INVALID_USER_IDENTIFIER، CONVERSION_ALREADY_ENHANCED، یا FieldError.REQUIRED. وضعیت EXCELLENT فقط تأیید می‌کند که میانای برنامه‌سازی کاربردی درخواست‌های ENHANCEMENT شما را پذیرفته است، نه اینکه بهبودهای بارگذاری‌شده با رویدادهای برچسب وب‌سایت مطابقت داشته‌اند.

پرس‌وجو کردن عیب‌یابی بارگذاری با GAQL

همچنین می‌توانید با پُرسمان کردن offline_conversion_upload_client_summary دربرابر شناسه مشتری تبدیل، سلامت بارگذاری در سطح حساب، تعداد کارهای اخیر، و هشدارهای خطا را به‌صورت برنامه‌نویسی‌شده بررسی کنید:

SELECT
  customer.id,
  offline_conversion_upload_client_summary.client,
  offline_conversion_upload_client_summary.status,
  offline_conversion_upload_client_summary.total_event_count,
  offline_conversion_upload_client_summary.successful_event_count,
  offline_conversion_upload_client_summary.success_rate,
  offline_conversion_upload_client_summary.pending_event_count,
  offline_conversion_upload_client_summary.pending_rate,
  offline_conversion_upload_client_summary.last_upload_date_time,
  offline_conversion_upload_client_summary.alerts,
  offline_conversion_upload_client_summary.daily_summaries,
  offline_conversion_upload_client_summary.job_summaries
FROM offline_conversion_upload_client_summary

هنگام گزارش‌دهی درباره سنجه‌های تبدیل برای پویش‌هایتان، به نگاشت سنجه‌های میانای کاربر مراجعه کنید تا سنجه‌های میانای کاربر Google Ads را با فیلدهای گزارش‌دهی Google Ads API مرتبط کنید. همچنین می‌توانید منبع conversion_action را جستجو کنید تا تعداد کل تبدیل‌ها و مقدار کل تبدیل را برای یک اقدام تبدیل خاص مشاهده کنید.

روال‌های مطلوب

هنگام پیاده‌سازی تبدیل‌های بهبودیافته برای وب، روال‌های مطلوب زیر را به‌خاطر داشته باشید.

بررسی شناسه مشتری

وقتی تبدیل‌ها را وارد می‌کنید، شناسه مشتری باید روی حسابی تنظیم شود که حاوی کنش تبدیل است و ردگیری تبدیل را انجام می‌دهد. برای بررسی این تنظیم، منبع Google Ads Customer ارائه‌دهنده را برای ConversionTrackingSetting پُرسمان کنید. پُرسمان زیر را با GoogleAdsService.SearchStream صادر کنید تا مقدار customer.conversion_tracking_setting.google_ads_conversion_customer را پیدا کنید.

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

customer_id را روی مقدار google_ads_conversion_customer در درخواست‌هایتان تنظیم کنید تا تبدیل‌ها را وارد کنید.

اگر چند شناسه دارید، همه را اضافه کنید

اگر مقدار gclid را برای تبدیل دارید، آن را در فیلد gclid_date_time_pair علاوه‌بر فیلد user_identifiers برای بهبود عملکرد ارسال کنید. چون پیام GclidDateTimePair فقط فیلد gclid را می‌پذیرد، Google Ads از تبدیل‌های بهبودیافته برای وب پشتیبانی نمی‌کند وقتی کلیک به‌جای پارامتر gclid، پارامتر gbraid یا wbraid را پر می‌کند. اگر بیش‌از یک شیء UserIdentifier برای تبدیل دارید، همه آن‌ها را در همان شیء ConversionAdjustment قرار دهید تا احتمال مطابقت افزایش یابد.

هنگام راه‌اندازی ادغام، خطاهای خرابی جزئی را مرور کنید

وقتی برای اولین‌بار تبدیل‌های بهبودیافته برای ادغام وب را راه‌اندازی می‌کنید، هرگونه خطای جزئی را در فیلد partial_failure_error پاسخ بررسی و برطرف کنید. اگر مشکلی در راه‌اندازی شما وجود دارد، می‌توانید این فیلد را بررسی کنید تا آن‌ها را بررسی و برطرف کنید. برای جزئیات و مثال‌های بیشتر مربوط به رسیدگی به خطای عدم موفقیت جزئی، به راهنمای عدم موفقیت جزئی اختصاصی مراجعه کنید.

پس‌از حل کردن مشکلات در فیلد partial_failure_error و تکمیل ادغام، هر دو ابزار عیب‌یابی را پایش کنید. برای بررسی سلامت جذب میانای برنامه‌سازی کاربردی، عیب‌یابی داده‌های آفلاین را بررسی کنید و برای بررسی سلامت تطابق برچسب با میانای برنامه‌سازی کاربردی، گزارش عیب‌یابی تبدیل‌های بهبودیافته را در میانای کاربر Google Ads بررسی کنید.

چندین اصلاح را در یک درخواست دسته‌بندی کنید

اگر چندین اصلاحیه برای وارد کردن دارید، به‌جای ارسال درخواست وارد کردن برای هر اصلاحیه، عملیات را در یک UploadConversionAdjustmentsRequest دسته‌بندی کنید (حداکثر ۲۰۰۰ اصلاحیه تبدیل در هر درخواست).

برای اطلاع از محدودیت‌های تعداد اصلاحات در هر درخواست، راهنمای سهمیه را بررسی کنید. اگر می‌خواهید عیب‌یابی داده‌های آفلاین مجموعه‌ای از درخواست‌ها را تحت یک کار منطقی گروه‌بندی کند، job_id همه درخواست‌ها را روی یک مقدار تنظیم کنید.

عیب‌یابی

از گزارش تشخیص خرابی تبدیل‌های بهبودیافته در میانای کاربر Google Ads استفاده کنید تا مطمئن شوید تبدیل‌های بهبودیافته برای وب طبق انتظار کار می‌کند. اگر هشدارهای میانای کاربر حتی با وجود موفقیت‌آمیز بودن بارگذاری‌های میانای برنامه‌سازی کاربردی ظاهر می‌شوند، هشدارهای عیب‌یابی میانای کاربر پس‌از بارگذاری موفق میانای برنامه‌سازی کاربردی را ببینید.

اشکال‌زدایی خطاهای رایج

راهنمایی زیر به شما کمک می‌کند خطاهای رایج در تبدیل‌های بهبودیافته برای وب را تشخیص دهید و برطرف کنید.

خطا
CUSTOMER_NOT_ACCEPTED_CUSTOMER_DATA_TERMS شرایط خدمات داده‌های مشتری برای customer_id درخواست پذیرفته نشده است. دستورالعمل‌های مربوط به این کار را در راهنمای پیش‌نیازها پیدا کنید.
CONVERSION_ALREADY_ENHANCED این تبدیل قبلاً تعدیل ENHANCEMENT را با فیلدهای order_id و conversion_action ارائه‌شده دریافت کرده است. حتماً مقدار order_id منحصربه‌فردی برای هر تبدیل ارائه دهید.
CONVERSION_ACTION_NOT_ELIGIBLE_FOR_ENHANCEMENT conversion_action ارائه‌شده واجدشرایط تبدیل‌های بهبودیافته برای وب نیست. در میانای کاربری Google Ads، حتماً چارگوش روشن کردن تبدیل‌های بهبودیافته را در کنش تبدیل ارجاع‌شده در درخواستتان علامت بزنید. دستورالعمل‌های مربوط به این کار را در مرکز راهنمایی پیدا کنید.
INVALID_USER_IDENTIFIER فیلد شناسه کاربر درهم‌سازی‌شده (hashed_email، hashed_phone_number، hashed_first_name، hashed_last_name، یا hashed_street_address) خلاصه SHA-256 شانزده‌شانزدهی ۶۴ نویسه‌ای معتبری نیست. داده‌های ارائه‌شده توسط کاربر را قبل‌از وارد کردن، نرمال‌سازی و درهم‌سازی کنید. برای دستورالعمل‌ها، به نرمال‌سازی و درهم‌سازی کردن داده‌های ارائه‌شده توسط کاربر مراجعه کنید.
CONVERSION_NOT_FOUND

‫Google Ads نتوانست تبدیلی مطابق با فیلد conversion_action و شناسه تبدیل (order_id یا gclid_date_time_pair) ارائه‌شده پیدا کند. این خطا فقط برای اصلاحات RESTATEMENT و RETRACTION اعمال می‌شود. برای جزئیات، الزامات در اصلاحات تبدیل وارداتی را ببینید.

برای اصلاحات ENHANCEMENT، API درخواست را بدون برگرداندن خطای CONVERSION_NOT_FOUND می‌پذیرد و مطابقت برچسب با API order_id را به‌صورت ناهمگام ارزیابی می‌کند. نرخ بالای مقادیر order_id مطابقت‌نیافته باعث فعال شدن هشدار عدم تطابق شناسه سفارش در گزارش عیب‌یابی تبدیل‌های بهبودیافته در میانای کاربر Google Ads می‌شود. برای مراحل عیب‌یابی، هشدارهای عیب‌یابی میانای کاربر پس‌از بارگذاری موفق میانای برنامه‌سازی کاربردی را ببینید.