향상된 전환

CM360 오프라인 전환 API는 사용자 식별자를 사용하여 웹사이트 태그 기반 전환 향상을 지원합니다.

향상된 전환

  • CM360의 플러드라이트 구성에 대한 향상된 전환 서비스 약관에 동의합니다.
  • 일치 ID로 웹사이트 계측을 사용합니다.
  • 웹사이트에서 발생하는 플러드라이트 전환을 기록합니다. 후속 API 호출에서 필수 필드이므로 다음 내용을 모두 기록해야 합니다.
    • matchId
    • ordinal
    • timestampMicros
    • floodlightActivityId
    • floodlightConfigurationId
    • quantity
    • value
  • 온라인 태그가 전환을 캡처한 후 90분이 지나면 conversions.batchupdate를 호출하여 사용자 식별자로 전환을 개선합니다.
    • 사용자 식별자는 형식을 지정하고 해싱한 후 전환 객체의 userIdentifiers 필드에 추가해야 합니다.
    • 수량과 값을 지정해야 합니다. 동일한 conversions.batchupdate 호출에서 전환의 수량과 가치를 조정하거나 원래 수량과 값을 제공할 수도 있습니다.
    • 각 삽입 및 업데이트 배치에는 성공과 실패가 혼합되어 포함될 수 있습니다. 전환 처리가 평소보다 오래 지연되는 경우 최대 6시간까지 NOT_FOUND 실패를 다시 시도해야 합니다.
    • 온라인 태그로 캡처된 후 24시간 이내에 사용자 식별자를 사용하여 전환을 개선해야 합니다.

정규화 및 해싱

개인 정보 보호를 위해 이메일 주소, 전화번호, 이름, 성, 상세 주소를 업로드하기 전에 SHA-256 알고리즘을 사용하여 해싱해야 합니다. 해시 결과를 표준화하려면 이러한 값 중 하나를 해싱하기 전에 다음을 수행해야 합니다.

  • 선행 또는 후행 공백을 삭제합니다.
  • 텍스트를 소문자로 변환합니다.
  • 전화번호는 E164 표준에 따른 형식으로 작성합니다.
  • gmail.comgooglemail.com 이메일 주소에서 도메인 이름 앞에 있는 모든 마침표 (.)를 삭제합니다.

C#

/// <summary>
/// Normalizes the email address and hashes it. For this use case, Campaign Manager 360
/// 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();
}

Java

private String normalizeAndHash(MessageDigest digest, String s)
    throws UnsupportedEncodingException {
  // Normalizes by removing leading and trailing whitespace and converting all characters to
  // lower case.
  String normalized = s.trim().toLowerCase();
  // 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, Campaign Manager 360
 * requires removal of any '.' characters preceding {@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 {
  String normalizedEmail = emailAddress.toLowerCase();
  String[] emailParts = normalizedEmail.split("@");
  if (emailParts.length > 1 && emailParts[1].matches("^(gmail|googlemail)\\.com\\s*")) {
    // 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("\\.", "");
    normalizedEmail = String.format("%s@%s", emailParts[0], emailParts[1]);
  }
  return normalizeAndHash(digest, normalizedEmail);
}

2,399필리핀

private static function normalizeAndHash(string $hashAlgorithm, string $value): string
{
    return hash($hashAlgorithm, strtolower(trim($value)));
}

/**
  * Returns the result of normalizing and hashing an email address. For this use case, Campaign
  * Manager 360 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);
}

Python

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

    For this use case, Campaign Manager 360 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.lower()
    email_parts = normalized_email.split("@")
    # Checks whether the domain of the email address is either "gmail.com"
    # or "googlemail.com". If this regex does not match then this statement
    # will evaluate to None.
    is_gmail = re.match(r"^(gmail|googlemail)\.com$", email_parts[1])

    # Check that there are at least two segments and the second segment
    # matches the above regex expression validating the email domain name.
    if len(email_parts) > 1 and is_gmail:
        # Removes any '.' characters from the portion of the email address
        # before the domain if the domain is gmail.com or googlemail.com.
        email_parts[0] = email_parts[0].replace(".", "")
        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/7474263

    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/7474263.
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, Campaign Manager 360 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

전환에 사용자 식별자 추가하기

먼저 평소와 같이 업로드 또는 수정Conversion 객체를 준비하고 다음과 같이 사용자 식별자를 첨부합니다.

{
  "matchId": "my-match-id-846513278",
  "ordinal": "my-ordinal-12345678512",
  "quantity": 1,
  "value": 104.23,
  "timestampMicros": 1656950400000000,
  "floodlightConfigurationId": 99999,
  "floodlightActivityId": 8888,
  "userIdentifiers": [
    { "hashedEmail": "0c7e6a405862e402eb76a70f8a26fc732d07c32931e9fae9ab1582911d2e8a3b" },
    { "hashedPhoneNumber": "1fb1f420856780a29719b994c8764b81770d79f97e2e1861ba938a7a5a15dfb9" },
    {
      "addressInfo": {
        "hashedFirstName": "81f8f6dde88365f3928796ec7aa53f72820b06db8664f5fe76a7eb13e24546a2",
        "hashedLastName": "799ef92a11af918e3fb741df42934f3b568ed2d93ac1df74f1b8d41a27932a6f",
        "hashedStreetAddress": "22b7e2d69b91e0ef4a88e81a73d897b92fd9c93ccfbe0a860f77db16c26f662e",
        "city": "seattle",
        "state": "washington",
        "countryCode": "US",
        "postalCode": "98101"
      }
    }
  ]
}

성공적인 응답은 다음과 같습니다.

{
  "hasFailures": false,
  "status": [
    {
      "conversion": {
        "floodlightConfigurationId": 99999,
        "floodlightActivityId": 8888,
        "timestampMicros": 1656950400000000,
        "value": 104.23,
        "quantity": 1,
        "ordinal": "my-ordinal-12345678512",
        "matchId": "my-match-id-846513278",
        "userIdentifiers": [
          { "hashedEmail": "0c7e6a405862e402eb76a70f8a26fc732d07c32931e9fae9ab1582911d2e8a3b" },
          { "hashedPhoneNumber": "1fb1f420856780a29719b994c8764b81770d79f97e2e1861ba938a7a5a15dfb9" },
          {
            "addressInfo": {
              "hashedFirstName": "81f8f6dde88365f3928796ec7aa53f72820b06db8664f5fe76a7eb13e24546a2",
              "hashedLastName": "799ef92a11af918e3fb741df42934f3b568ed2d93ac1df74f1b8d41a27932a6f",
              "hashedStreetAddress": "22b7e2d69b91e0ef4a88e81a73d897b92fd9c93ccfbe0a860f77db16c26f662e",
              "city": "seattle",
              "state": "washington",
              "countryCode": "US",
              "postalCode": "98101"
            }
          }
        ],
        "kind": "dfareporting#conversion"
      },
      "kind": "dfareporting#conversionStatus"
    }
  ]
}

일반적인 실수

다음은 사용자 식별자로 전환을 향상시킬 때 발생할 수 있는 몇 가지 오류입니다.

hash_X 필드가 유효한 SHA-256 해시가 아닙니다.
해시가 접두사로 지정된 모든 필드는 16진수로 인코딩된 SHA-256 해시만 허용합니다.
country_code 필드의 길이가 잘못되었습니다.
country_code은(는) 정확히 2자여야 합니다.
플러드라이트 구성이 향상된 전환 서비스 약관에 서명하지 않았습니다.
요청의 플러드라이트 구성 ID에 대해 향상된 전환 서비스 약관에 동의하지 않았습니다.
user_identifier가 5개를 초과하여 지정되었습니다.
전환에는 최대 5개의 사용자 식별자만 포함할 수 있습니다.

자주 묻는 질문(FAQ)

일치 ID를 사용하는 것이 좋은 이유는 무엇인가요?
클릭 ID 기반 수정은 클릭이 발생하지 않은 전환을 제외하고 향상된 전환 통합의 가치를 제한합니다.
수량과 가치를 기록해야 하는 이유는 무엇인가요?
CM360 오프라인 전환 API를 사용하려면 수량과 값을 지정해야 합니다.
온라인 태그 기반 전환을 수정하려면 Google에서 기록한 정확한 마이크로초 타임스탬프를 가져와야 하나요?
일치 ID 기반 수정의 경우 이제 요청에 제공된 타임스탬프가 Google에서 기록한 타임스탬프에서 1분 이내이면 API가 수정을 허용합니다.
온라인 태그로 전환을 캡처한 후 90분을 기다렸다가 전환을 조정해야 하는 이유는 무엇인가요?
API에서 온라인 전환의 색인을 생성하고 수정할 수 있기까지 최대 90분이 걸릴 수 있습니다.
API 응답에서 주의해야 할 사항은 무엇인가요?
CM360 전환 API가 성공 응답을 반환하더라도 일부 개별 전환은 업로드 또는 업데이트에 실패했을 수 있습니다. 개별 ConversionStatus 필드에 오류가 있는지 검사합니다.
  • 전환 처리가 평소보다 오래 지연되는 경우 NOT_FOUND 실패를 최대 6시간까지 재시도할 수 있으며 다시 시도해야 합니다. NOT_FOUND 오류가 6시간 넘게 지속되는 이유에 관한 FAQ도 참고하세요.
  • INVALID_ARGUMENTPERMISSION_DENIED 오류는 다시 시도해서는 안 됩니다.