Google Ads API를 사용하여 오프라인 전환을 Google Ads로 가져와 전화 또는 영업사원을 통해 오프라인에서 판매로 이어진 광고를 추적할 수 있습니다.
전환 데이터 가져오기의 이점을 최대한 활용하려면 GCLID 및 사용자 제공 데이터를 활용하여 내구성과 실적을 극대화하는 리드 확보용 향상된 전환을 구현하는 것이 좋습니다.
향상된 전환
향상된 전환을 사용하면 이메일 주소, 이름, 집 주소, 전화번호와 같은 퍼스트 파티 전환 데이터로 전환을 보완하여 전환 측정의 정확성을 개선할 수 있습니다.
향상된 전환에는 두 가지 유형이 있습니다. 자세한 내용은 향상된 전환 정보 고객센터 도움말을 참고하세요.
다음 섹션에서는 리드 확보용 향상된 전환이라고도 하는 오프라인 전환을 개선하는 방법을 설명합니다.
리드 확보용 향상된 전환이란 무엇인가요?
리드 확보용 향상된 전환은 오프라인 전환 가져오기의 업그레이드 버전으로, 이메일 주소와 같은 사용자 제공 데이터를 사용하여 가져온 오프라인 전환 데이터를 보완하여 정확성과 입찰 실적을 개선합니다. 오프라인 전환을 가져올 때 제공된 해싱된 고객 데이터는 웹사이트에서 수집된 동일한 데이터(예: 리드 양식) 및 광고에 참여한 로그인한 고객과 매칭하여 Google Ads 캠페인의 기여도를 분석하는 데 다시 사용됩니다. 리드 확보용 향상된 전환의 작동 방식에 관한 자세한 내용은 리드 확보용 향상된 전환에 대한 정보 도움말을 참고하세요.
Google 태그를 사용하여 웹페이지에서 양식 제출 이벤트를 추적하는지에 따라 리드 확보용 향상된 전환을 구현하는 방법에는 두 가지가 있습니다. 최상의 성능과 내구성을 위해 리드 확보를 위한 향상된 전환에 Google 태그를 사용하는 것이 좋습니다.
- 처음부터 시작하는 경우 요구사항 섹션부터 시작하세요.
- 이미 오프라인 전환 가져오기를 설정했고 리드 확보용 향상된 전환으로 업그레이드하려면 태그 지정 구성 섹션부터 시작하는 것이 좋습니다.
- 이미 Google 태그를 설정했거나 Google 태그를 사용하지 않을 계획이며 Google Ads API 통합 작업을 시작하는 경우 API 구현 섹션으로 이동하세요.
- 사용자 제공 데이터를 가져올 수 없거나 전환에 외부 기여 분석을 사용해야 하는 경우 기존 오프라인 전환 가져오기 가이드를 참고하세요.
기본 요건
먼저 시작하기 섹션의 단계를 완료했는지 확인하세요.
리드 확보용 향상된 전환을 사용하려면 리드 확보용 향상된 전환을 선택하고 고객 데이터 약관에 동의해야 합니다. Google Ads 전환 고객에게 다음 쿼리를 실행하여 이러한 기본 요건이 이미 충족되었는지 확인할 수 있습니다.
SELECT
customer.id,
customer.conversion_tracking_setting.accepted_customer_data_terms,
customer.conversion_tracking_setting.enhanced_conversions_for_leads_enabled
FROM customer
accepted_customer_data_terms
또는 enhanced_conversions_for_leads_enabled
가 false
인 경우 고객센터의 안내에 따라 기본 요건을 완료하세요.
태그 지정 구성
고객센터의 안내에 따라 리드 확보용 향상된 전환을 사용 설정하도록 Google 태그를 구성합니다. Google 태그 관리자로 리드 확보용 향상된 전환을 설정하려면 다음 안내를 따르세요.
API 구현
다음은 Google Ads API를 사용하여 리드 확보용 향상된 전환을 가져오는 전반적인 흐름입니다.
이메일 주소, 전화번호, 우편 주소와 같은 사용자 제공 데이터를 정규화하고 해싱합니다.
정규화되고 해싱된 사용자 제공 데이터로
ClickConversion
객체를 채웁니다.ConversionUploadService
를 사용하여 Google Ads API에ClickConversion
객체를 가져옵니다.
사용자 제공 데이터 정규화 및 해싱
개인 정보 보호를 위해 다음 데이터는 가져오기 전에 SHA-256을 사용하여 해싱해야 합니다.
- 이메일 주소
- 전화번호
- 이름
- 성
- 상세 주소
해싱 결과를 표준화하려면 이러한 값을 해싱하기 전에 다음을 실행해야 합니다.
- 선행 및 후행 공백을 삭제합니다.
- 텍스트를 소문자로 변환합니다.
- 전화번호는 E164 표준에 따른 형식으로 작성합니다.
gmail.com
및googlemail.com
이메일 주소의 도메인 이름 앞에 있는 모든 마침표 (.
)를 삭제합니다.
다음 데이터는 해싱하지 마세요.
- 국가
- 주
- 도시
- 우편번호
코드 예
이 예에서는 사용자 제공 데이터를 정규화하고 해싱하는 방법을 보여줍니다.
private String normalizeAndHash(MessageDigest digest, String s) throws UnsupportedEncodingException { // Normalizes by first converting all characters to lowercase, then trimming spaces. String normalized = s.toLowerCase(); // Removes leading, trailing, and intermediate spaces. normalized = normalized.replaceAll("\\s+", ""); // 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 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); }
/// <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(); }
private static function normalizeAndHash(string $hashAlgorithm, string $value): string { // Normalizes by first converting all characters to lowercase, then trimming spaces. $normalized = strtolower($value); // Removes leading, trailing, and intermediate spaces. $normalized = str_replace(' ', '', $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); }
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: # 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. if re.match(r"^(gmail|googlemail)\.com$", email_parts[1]): # 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()
# 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 hashing. 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; # Removes leading, trailing, and intermediate spaces. $value =~ 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); }
ClickConversion 객체 채우기
UploadClickConversionRequest
의 ClickConversion
객체 모음은 가져오려는 전환 집합을 나타냅니다. ClickConversion
객체를 만들 때는 다음 세부정보에 유의하세요.
gclid
GCLID는 사용자가 광고를 클릭하고 웹사이트로 이동할 때 URL 매개변수에서 캡처되는 클릭 식별자입니다.
user_identifiers
리드 확보용 향상된 전환을 사용하는 경우
user_identifiers
필드를 정규화되고 해싱된 사용자 제공 데이터로 채워야 합니다. 사용 가능한 사용자 식별자가 여러 개인 경우 각 식별자(최대 5개)에 대해 별도의UserIdentifier
를 만듭니다.conversion_date_time
전환 날짜 및 시간입니다.
값에는 시간대가 지정되어야 하며 형식은
yyyy-mm-dd HH:mm:ss+|-HH:mm
여야 합니다(예:2022-01-01 19:32:45-05:00
(일광 절약 시간 무시)).시간대는 유효한 값이면 무엇이든 될 수 있습니다. 계정의 시간대와 일치할 필요는 없습니다. 하지만 가져온 전환 데이터를 Google Ads UI의 전환 데이터와 비교하려는 경우 전환 수가 일치하도록 Google Ads 계정과 동일한 시간대를 사용하는 것이 좋습니다. 자세한 내용과 예시는 고객센터를 참고하고 유효한 시간대 ID 목록은 코드 및 형식을 확인하세요.
conversion_action
오프라인 전환의
ConversionAction
리소스 이름입니다.전환 액션의
type
는UPLOAD_CLICKS
여야 하며 클릭과 연결된 Google Ads 계정의 Google Ads 전환 고객에 있어야 합니다.conversion_value
전환의 가치입니다.
currency_code
conversion_value
의 통화 코드입니다.consent
ClickConversion
객체의consent
필드를 채우는 것이 매우 좋습니다. 설정하지 않으면 전환 기여도를 부여할 수 없습니다.order_id
전환의 거래 ID라고도 합니다. 이 입력란은 선택사항이지만 조정 시 가져온 전환을 더 쉽게 참조할 수 있으므로 적극 권장됩니다. 가져오는 동안 설정하는 경우 조정 시 이를 사용해야 합니다. 거래 ID를 사용하여 중복 전환을 최소화하는 방법을 자세히 알아보려면 이 고객센터 도움말을 참고하세요.
custom_variables
맞춤 전환 변수의 값입니다.
Google Ads에서는
wbraid
또는gbraid
와 함께 맞춤 전환 변수를 지원하지 않습니다.conversion_environment
이 전환이 기록된 환경을 나타냅니다. 예를 들면
APP
또는WEB
입니다.session_attributes_encoded
및session_attributes_key_value_pairs
세션 속성은 전환 기여 분석에 사용되는 집계된 식별자를 나타냅니다. 이는 클릭 식별자(예: GCLID 및 GBRAID) 및 리드 확보용 향상된 전환의 핵심인 사용자 제공 데이터와 함께 작동합니다. 세션 속성을 가져오는 방법에는 두 가지가 있습니다. 브라우저에서 JavaScript 코드로 생성된 인코딩된 토큰을 제공하거나 각 식별자에 개별 키-값 쌍을 제공하는 것입니다.
캠페인 실적을 극대화하려면 가능하면 모든 전환과 함께 클릭 식별자, 사용자 제공 데이터, 세션 속성을 가져오는 것이 좋습니다.
This example is not yet available in Java; you can take a look at the other languages.
if (!string.IsNullOrEmpty(sessionAttributesEncoded)) { clickConversion.SessionAttributesEncoded = ByteString.CopyFrom(sessionAttributesEncoded, Encoding.Unicode); } else if (!string.IsNullOrEmpty(sessionAttributes)) { IEnumerable<SessionAttributeKeyValuePair> parsedSessionAttributes = sessionAttributes.Split(';').Select(pair => { string[] split = pair.Split('='); return new SessionAttributeKeyValuePair() { SessionAttributeKey = split[0], SessionAttributeValue = split[1] }; }); clickConversion.SessionAttributesKeyValuePairs = new SessionAttributesKeyValuePairs(); clickConversion.SessionAttributesKeyValuePairs.KeyValuePairs .AddRange(parsedSessionAttributes); }
This example is not yet available in PHP; you can take a look at the other languages.
# Set one of the session_attributes_encoded or # session_attributes_key_value_pairs fields if either are provided. if session_attributes_encoded: click_conversion.session_attributes_encoded = session_attributes_encoded elif session_attributes_dict: for key, value in session_attributes_dict.items(): pair = client.get_type("SessionAttributeKeyValuePair") pair.session_attribute_key = key pair.session_attribute_value = value click_conversion.session_attributes_key_value_pairs.key_value_pairs.append( pair )
This example is not yet available in Ruby; you can take a look at the other languages.
# Set one of the session_attributes_encoded or session_attributes_key_value_pairs # fields if either are provided. if (defined $session_attributes_encoded) { $click_conversion->{sessionAttributesEncoded} = $session_attributes_encoded; } elsif (defined $session_attributes_hash) { while (my ($key, $value) = each %$session_attributes_hash) { my $pair = Google::Ads::GoogleAds::V19::Services::ConversionUploadService::SessionAttributeKeyValuePair ->new({sessionAttributeKey => $key, sessionAttributeValue => $value}); push @{$click_conversion->{sessionAttributesKeyValuePairs}{keyValuePairs} }, $pair; } }
코드 예
이 예에서는 정규화되고 해싱된 사용자 제공 데이터를 ClickConversion
객체에 설정하는 방법을 보여줍니다.
// Creates an empty builder for constructing the click conversion. ClickConversion.Builder clickConversionBuilder = ClickConversion.newBuilder(); // Extracts user email and phone 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() .put("email", "alex.2@example.com") // Phone number to be converted to E.164 format, with a leading '+' as required. .put("phone", "+1 800 5550102") // 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("conversionActionId", Long.toString(conversionActionId)) .put("conversionDateTime", conversionDateTime) .put("conversionValue", Double.toString(conversionValue)) .put("currencyCode", "USD"); // Adds entries for the optional fields. if (orderId != null) { rawRecordBuilder.put("orderId", orderId); } if (gclid != null) { rawRecordBuilder.put("gclid", gclid); } if (adUserDataConsent != null) { rawRecordBuilder.put("adUserDataConsent", adUserDataConsent.name()); } if (sessionAttributesEncoded != null) { rawRecordBuilder.put("sessionAttributesEncoded", sessionAttributesEncoded); } if (sessionAttributesMap != null) { rawRecordBuilder.put("sessionAttributesMap", sessionAttributesMap); } // 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); // Creates a user identifier using normalized and hashed phone info. UserIdentifier hashedPhoneNumberIdentifier = UserIdentifier.newBuilder() .setHashedPhoneNumber(normalizeAndHash(sha256Digest, rawRecord.get("phone"))) .build(); // Adds the hashed phone number identifier to the UserData object's list. userIdentifiers.add(hashedPhoneNumberIdentifier); // Adds the user identifiers to the conversion. clickConversionBuilder.addAllUserIdentifiers(userIdentifiers);
// Adds a user identifier using the hashed email address, using the normalize // and hash method specifically for email addresses. clickConversion.UserIdentifiers.Add(new UserIdentifier() { HashedEmail = NormalizeAndHashEmailAddress("alex.2@example.com"), // Optional: Specifies the user identifier source. UserIdentifierSource = UserIdentifierSource.FirstParty }); // Adds a user identifier using normalized and hashed phone info. clickConversion.UserIdentifiers.Add(new UserIdentifier() { HashedPhoneNumber = NormalizeAndHash("+1 800 5550102"), // Optional: Specifies the user identifier source. UserIdentifierSource = UserIdentifierSource.FirstParty }); // Adds a user identifier with all the required mailing address elements. clickConversion.UserIdentifiers.Add(new UserIdentifier() { AddressInfo = new OfflineUserAddressInfo() { // FirstName and LastName must be normalized and hashed. HashedFirstName = NormalizeAndHash("Alex"), HashedLastName = NormalizeAndHash("Quinn"), // CountryCode and PostalCode are sent in plain text. CountryCode = "US", PostalCode = "94045" } });
// Creates a click conversion with the specified attributes. $clickConversion = new ClickConversion(); // Extract user email and phone from the raw data, normalize and hash it, then wrap 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', // 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, 'gclid' => $gclid, 'conversionActionId' => $conversionActionId, 'conversionDateTime' => $conversionDateTime, 'conversionValue' => $conversionValue, 'currencyCode' => 'USD', 'adUserDataConsent' => $adUserDataConsent ]; // 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; } // Adds the user identifiers to the conversion. $clickConversion->setUserIdentifiers($userIdentifiers);
# Extract user email and phone 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: # # 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", # 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, "gclid": gclid, "conversion_action_id": conversion_action_id, "conversion_date_time": conversion_date_time, "conversion_value": conversion_value, "currency_code": "USD", "ad_user_data_consent": ad_user_data_consent, } # Constructs the click conversion. click_conversion = client.get_type("ClickConversion") # 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 user identifier to the conversion. click_conversion.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. click_conversion.user_identifiers.append(phone_identifier)
# Extract user email and phone 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: # # 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", # 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, "gclid" => gclid, "conversion_action_id" => conversion_action_id, "conversion_date_time" => conversion_date_time, "conversion_value" => conversion_value, "currency_code" => "USD", "ad_user_data_consent" => ad_user_data_consent, "session_attributes_encoded" => session_attributes_encoded, "session_attributes_hash" => session_attributes_hash } click_conversion = client.resource.click_conversion do |cc| cc.conversion_action = client.path.conversion_action(customer_id, conversion_action_id) cc.conversion_date_time = conversion_date_time cc.conversion_value = conversion_value.to_f cc.currency_code = 'USD' unless order_id.nil? cc.order_id = order_id end unless raw_record["gclid"].nil? cc.gclid = gclid end # 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 unless raw_record["ad_user_data_consent"].nil? cc.consent = client.resource.consent do |c| c.ad_user_data = ad_user_data_consent end end # Set one of the session_attributes_encoded or # session_attributes_key_value_pairs fields if either are provided. if session_attributes_encoded != nil cc.class.module_eval { attr_accessor :session_attributes_encoded} cc.session_attributes_encoded = session_attributes_encoded elsif session_attributes_hash != nil # Add new attribute to click conversion object cc.class.module_eval { attr_accessor :session_attributes_key_value_pairs} cc.session_attributes_key_value_pairs = ::Google::Ads::GoogleAds::V19::Services::SessionAttributesKeyValuePairs.new # Loop thru inputted session_attributes_hash to populate session_attributes_key_value_pairs session_attributes_hash.each do |key, value| pair = ::Google::Ads::GoogleAds::V19::Services::SessionAttributeKeyValuePair.new pair.session_attribute_key = key pair.session_attribute_value = value cc.session_attributes_key_value_pairs.key_value_pairs << pair end end # Creates a user identifier using the hashed email address, using the # normalize and hash method specifically for email addresses. # If using a phone number, use the normalize_and_hash method instead. cc.user_identifiers << client.resource.user_identifier do |ui| 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? cc.user_identifiers << client.resource.user_identifier do |ui| ui.hashed_phone_number = normalize_and_hash(raw_record["phone"]) end end end
# Create an empty click conversion. my $click_conversion = Google::Ads::GoogleAds::V19::Services::ConversionUploadService::ClickConversion ->new({}); # Extract user email and phone 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::V19::Common::UserIdentifier->new({ # hashedEmail => '...', # hashedPhoneNumber => '...', # }); my $raw_record = { # Email address that includes a period (.) before the Gmail domain. email => 'alex.2@example.com', # 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, gclid => $gclid, conversionActionId => $conversion_action_id, conversionDateTime => $conversion_date_time, conversionValue => $conversion_value, currencyCode => "USD", adUserDataConsent => $ad_user_data_consent }; 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::V19::Common::UserIdentifier->new({ hashedEmail => $hashed_email, # Optional: Specify the user identifier source. userIdentifierSource => FIRST_PARTY })); # Create a user identifier using normalized and hashed phone info. my $hashed_phone = normalize_and_hash($raw_record->{phone}); push( @$user_identifiers, Google::Ads::GoogleAds::V19::Common::UserIdentifier->new({ hashedPhone => $hashed_phone, # Optional: Specify the user identifier source. userIdentifierSource => FIRST_PARTY })); # Add the user identifiers to the conversion. $click_conversion->{userIdentifiers} = $user_identifiers;
이 예에서는 ClickConversion
객체에 필요한 다른 필드를 설정하는 방법을 보여줍니다.
// Adds details of the conversion. clickConversionBuilder.setConversionAction( ResourceNames.conversionAction( customerId, Long.parseLong(rawRecord.get("conversionActionId")))); clickConversionBuilder.setConversionDateTime(rawRecord.get("conversionDateTime")); clickConversionBuilder.setConversionValue(Double.parseDouble(rawRecord.get("conversionValue"))); clickConversionBuilder.setCurrencyCode(rawRecord.get("currencyCode")); // Sets the order ID if provided. if (rawRecord.containsKey("orderId")) { clickConversionBuilder.setOrderId(rawRecord.get("orderId")); } // Sets the Google click ID (gclid) if provided. if (rawRecord.containsKey("gclid")) { clickConversionBuilder.setGclid(rawRecord.get("gclid")); } // Sets the consent information, if provided. if (rawRecord.containsKey("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. clickConversionBuilder.setConsent( Consent.newBuilder() .setAdUserData(ConsentStatus.valueOf(rawRecord.get("adUserDataConsent")))); } // Sets one of the sessionAttributesEncoded or sessionAttributesKeyValuePairs if either is // provided. if (rawRecord.containsKey("sessionAttributesEncoded")) { clickConversionBuilder.setSessionAttributesEncoded( ByteString.copyFromUtf8(rawRecord.get("sessionAttributesEncoded"))); } else if (rawRecord.containsKey("sessionAttributesMap")) { List<String> pairings = Arrays.stream(rawRecord.get("sessionAttributesMap").split(" ")) .map(String::trim) .collect(Collectors.toList()); SessionAttributesKeyValuePairs.Builder sessionAttributePairs = SessionAttributesKeyValuePairs.newBuilder(); for (String pair : pairings) { String[] parts = pair.split("=", 2); if (parts.length != 2) { throw new IllegalArgumentException( "Failed to read the sessionAttributesMap. SessionAttributesMap must use a " + "space-delimited list of session attribute key value pairs. Each pair should be" + " separated by an equal sign, for example: 'gad_campaignid=12345 gad_source=1'"); } sessionAttributePairs.addKeyValuePairs( SessionAttributeKeyValuePair.newBuilder() .setSessionAttributeKey(parts[0]) .setSessionAttributeValue(parts[1]) .build()); } clickConversionBuilder.setSessionAttributesKeyValuePairs(sessionAttributePairs.build()); } // Calls build to build the conversion. ClickConversion clickConversion = clickConversionBuilder.build();
// Adds details of the conversion. clickConversion.ConversionAction = ResourceNames.ConversionAction(customerId, conversionActionId); clickConversion.ConversionDateTime = conversionDateTime; clickConversion.ConversionValue = conversionValue; clickConversion.CurrencyCode = "USD"; // Sets the order ID if provided. if (!string.IsNullOrEmpty(orderId)) { clickConversion.OrderId = orderId; } // Sets the Google click ID (gclid) if provided. if (!string.IsNullOrEmpty(gclid)) { clickConversion.Gclid = gclid; } if (!string.IsNullOrEmpty(sessionAttributesEncoded)) { clickConversion.SessionAttributesEncoded = ByteString.CopyFrom(sessionAttributesEncoded, Encoding.Unicode); } else if (!string.IsNullOrEmpty(sessionAttributes)) { IEnumerable<SessionAttributeKeyValuePair> parsedSessionAttributes = sessionAttributes.Split(';').Select(pair => { string[] split = pair.Split('='); return new SessionAttributeKeyValuePair() { SessionAttributeKey = split[0], SessionAttributeValue = split[1] }; }); clickConversion.SessionAttributesKeyValuePairs = new SessionAttributesKeyValuePairs(); clickConversion.SessionAttributesKeyValuePairs.KeyValuePairs .AddRange(parsedSessionAttributes); }
// Adds details of the conversion. $clickConversion->setConversionAction( ResourceNames::forConversionAction($customerId, $rawRecord['conversionActionId']) ); $clickConversion->setConversionDateTime($rawRecord['conversionDateTime']); $clickConversion->setConversionValue($rawRecord['conversionValue']); $clickConversion->setCurrencyCode($rawRecord['currencyCode']); // Sets the order ID if provided. if (!empty($rawRecord['orderId'])) { $clickConversion->setOrderId($rawRecord['orderId']); } // Sets the Google click ID (gclid) if provided. if (!empty($rawRecord['gclid'])) { $clickConversion->setGclid($rawRecord['gclid']); } // Sets the ad user data consent if provided. if (!empty($rawRecord['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' => $rawRecord['adUserDataConsent']]) ); }
# Add details of the conversion. # Gets the conversion action resource name. conversion_action_service = client.get_service("ConversionActionService") click_conversion.conversion_action = ( conversion_action_service.conversion_action_path( customer_id, raw_record["conversion_action_id"] ) ) click_conversion.conversion_date_time = raw_record["conversion_date_time"] click_conversion.conversion_value = raw_record["conversion_value"] click_conversion.currency_code = raw_record["currency_code"] # Sets the order ID if provided. if raw_record.get("order_id"): click_conversion.order_id = raw_record["order_id"] # Sets the gclid if provided. if raw_record.get("gclid"): click_conversion.gclid = raw_record["gclid"] # 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 if raw_record["ad_user_data_consent"]: click_conversion.consent.ad_user_data = client.enums.ConsentStatusEnum[ raw_record["ad_user_data_consent"] ] # Set one of the session_attributes_encoded or # session_attributes_key_value_pairs fields if either are provided. if session_attributes_encoded: click_conversion.session_attributes_encoded = session_attributes_encoded elif session_attributes_dict: for key, value in session_attributes_dict.items(): pair = client.get_type("SessionAttributeKeyValuePair") pair.session_attribute_key = key pair.session_attribute_value = value click_conversion.session_attributes_key_value_pairs.key_value_pairs.append( pair )
cc.conversion_action = client.path.conversion_action(customer_id, conversion_action_id) cc.conversion_date_time = conversion_date_time cc.conversion_value = conversion_value.to_f cc.currency_code = 'USD' unless order_id.nil? cc.order_id = order_id end unless raw_record["gclid"].nil? cc.gclid = gclid end # 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 unless raw_record["ad_user_data_consent"].nil? cc.consent = client.resource.consent do |c| c.ad_user_data = ad_user_data_consent end end # Set one of the session_attributes_encoded or # session_attributes_key_value_pairs fields if either are provided. if session_attributes_encoded != nil cc.class.module_eval { attr_accessor :session_attributes_encoded} cc.session_attributes_encoded = session_attributes_encoded elsif session_attributes_hash != nil # Add new attribute to click conversion object cc.class.module_eval { attr_accessor :session_attributes_key_value_pairs} cc.session_attributes_key_value_pairs = ::Google::Ads::GoogleAds::V19::Services::SessionAttributesKeyValuePairs.new # Loop thru inputted session_attributes_hash to populate session_attributes_key_value_pairs session_attributes_hash.each do |key, value| pair = ::Google::Ads::GoogleAds::V19::Services::SessionAttributeKeyValuePair.new pair.session_attribute_key = key pair.session_attribute_value = value cc.session_attributes_key_value_pairs.key_value_pairs << pair end end
# Add details of the conversion. $click_conversion->{conversionAction} = Google::Ads::GoogleAds::V19::Utils::ResourceNames::conversion_action( $customer_id, $raw_record->{conversionActionId}); $click_conversion->{conversionDateTime} = $raw_record->{conversionDateTime}; $click_conversion->{conversionValue} = $raw_record->{conversionValue}; $click_conversion->{currencyCode} = $raw_record->{currencyCode}; # Set the order ID if provided. if (defined $raw_record->{orderId}) { $click_conversion->{orderId} = $raw_record->{orderId}; } # Set the Google click ID (gclid) if provided. if (defined $raw_record->{gclid}) { $click_conversion->{gclid} = $raw_record->{gclid}; } # Set the consent information, if provided. if (defined $raw_record->{adUserDataConsent}) { $click_conversion->{consent} = Google::Ads::GoogleAds::V19::Common::Consent->new({ adUserData => $raw_record->{adUserDataConsent}}); } # Set one of the session_attributes_encoded or session_attributes_key_value_pairs # fields if either are provided. if (defined $session_attributes_encoded) { $click_conversion->{sessionAttributesEncoded} = $session_attributes_encoded; } elsif (defined $session_attributes_hash) { while (my ($key, $value) = each %$session_attributes_hash) { my $pair = Google::Ads::GoogleAds::V19::Services::ConversionUploadService::SessionAttributeKeyValuePair ->new({sessionAttributeKey => $key, sessionAttributeValue => $value}); push @{$click_conversion->{sessionAttributesKeyValuePairs}{keyValuePairs} }, $pair; } }
요청 구성
ClickConversion
객체가 구성되고 UploadClickConversionRequest
객체의 conversions
필드에 추가되면 다음 필드를 설정하고 요청을 ConversionUploadService
의 UploadClickConversions
메서드에 전달합니다.
customer_id
- 클릭 소스인 계정의 Google Ads 전환 고객으로 설정합니다. 어떤 계정이 올바른 계정인지 모르겠다면 시작하기 섹션의 샘플 쿼리에서
customer.conversion_tracking_setting.google_ads_conversion_customer
필드를 참고하세요. job_id
가져오기 요청을 오프라인 데이터 진단의 작업별 정보와 연결하는 메커니즘을 제공합니다.
이 필드를 설정하지 않으면 Google Ads API는 각 요청에
[2^31, 2^63)
범위의 고유한 값을 할당합니다. 여러 요청을 단일 논리 작업으로 그룹화하려면 작업의 모든 요청에서 이 필드를[0, 2^31)
범위의 동일한 값으로 설정하세요.응답의
job_id
에는 값을 지정했는지 또는 Google Ads API가 값을 할당했는지와 관계없이 요청의 작업 ID가 포함됩니다.partial_failure
전환을 가져올 때 이 필드는
true
로 설정해야 합니다. 응답을 처리할 때는 부분 실패 가이드라인을 따르세요.
요청 가져오기
ClickConversion
객체를 채우고 요청을 구성한 후 가져오기를 제출할 수 있습니다.
// 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());
// 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 UploadClickConversionsResponse response = conversionUploadService.UploadClickConversions( new UploadClickConversionsRequest() { CustomerId = customerId.ToString(), Conversions = { clickConversion }, // Enables partial failure (must be true). PartialFailure = true });
// Issues a request to upload the click conversion. $conversionUploadServiceClient = $googleAdsClient->getConversionUploadServiceClient(); // 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( // Enables partial failure (must be true). UploadClickConversionsRequest::build($customerId, [$clickConversion], true) );
# Creates the conversion upload service client. conversion_upload_service = client.get_service("ConversionUploadService") # Uploads the click conversion. 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 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 response = conversion_upload_service.upload_click_conversions( customer_id=customer_id, conversions=[click_conversion], # Enables partial failure (must be true). partial_failure=True, )
response = client.service.conversion_upload.upload_click_conversions( customer_id: customer_id, conversions: [click_conversion], # Partial failure must be true. partial_failure: true, ) if response.partial_failure_error puts "Partial failure encountered: #{response.partial_failure_error.message}" else result = response.results.first puts "Uploaded click conversion that happened at #{result.conversion_date_time} " \ "to #{result.conversion_action}." end
# 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 $response = $api_client->ConversionUploadService()->upload_click_conversions({ customerId => $customer_id, conversions => [$click_conversion], # Enable partial failure (must be true). partialFailure => "true" });
가져온 항목 검토하기
리드 확보용 향상된 전환 진단 보고서를 사용하여 최근 가져온 데이터의 전반적인 상태를 검토합니다.
가져온 전환은 가져오기 요청 날짜 또는 ClickConversion
의 conversion_date_time
날짜가 아니라 원래 클릭의 노출 날짜의 보고서에 반영됩니다.
가져온 전환 통계가 마지막 클릭 기여 분석을 위해 Google Ads 계정에 표시되기까지 최대 3시간이 걸립니다. 다른 검색 기여 분석 모델의 경우 3시간 넘게 걸릴 수 있습니다. 자세한 내용은 데이터 업데이트 가이드를 참고하세요.
캠페인의 전환 측정항목을 보고할 때는 사용자 인터페이스 측정항목 매핑을 참고하여 Google Ads UI 측정항목을 Google Ads API 보고 필드와 연결하세요. conversion_action
리소스를 쿼리하여 특정 전환 액션의 총 전환수 및 총 전환 가치를 확인할 수도 있습니다.
권장사항
리드 확보를 위한 향상된 전환을 구현할 때는 다음 권장사항을 염두에 두세요.
완전성 여부와 관계없이 모든 전환 데이터 전송
완전하고 정확한 전환 보고를 하려면 Google Ads에서 발생하지 않았을 수도 있는 전환 이벤트를 포함하여 사용 가능한 모든 오프라인 전환 이벤트를 가져오세요. 사용자 제공 데이터만 포함된 전환도 유용하며 Google Ads 캠페인 최적화에 긍정적인 영향을 줄 수 있습니다.
전환에 order_id
를 할당하는 경우 포함하는 것이 좋습니다.
전환의 GCLID가 있는 경우 성능을 개선하기 위해 user_identifiers
와 함께 전송하는 것이 좋습니다. 또한 전환에 UserIdentifier
가 두 개 이상 있는 경우 일치 가능성을 높이기 위해 ClickConversion
객체에 모두 포함합니다.
단일 요청으로 여러 전환 일괄 처리
가져올 전환이 여러 개인 경우 전환별로 가져오기 요청을 전송하는 대신 전환을 하나의 UploadClickConversionsRequest
로 일괄 처리합니다.
요청당 전환 수 한도는 할당량 가이드를 참고하세요.
오프라인 데이터 진단이 동일한 로직 작업 아래에 요청 집합을 그룹화하도록 하려면 모든 요청의 job_id
를 동일한 값으로 설정하세요. 이는 여러 요청을 사용하여 대량의 전환을 가져오는 단일 작업 또는 프로세스가 있는 경우에 유용할 수 있습니다. 각 요청에서 job_id
를 동일한 값으로 설정하면 job_summaries
에서 작업의 단일 항목을 검색할 수 있습니다.
대신 Google Ads API가 각 요청의 job_id
에 시스템 생성 값을 할당하도록 허용하면 job_summaries
에 각 요청에 대한 별도의 항목이 포함되므로 작업의 전반적인 상태를 분석하기가 더 어려워질 수 있습니다.
외부 기여 분석 데이터를 사용하지 않음
리드 확보용 향상된 전환을 사용할 때는 ClickConversion
에 external_attribution_data
를 설정하거나 외부 기여 분석 모델을 사용하는 conversion_action
를 지정하지 마세요. Google Ads에서는 사용자 제공 데이터를 사용하여 가져올 때 외부 기여 분석 전환을 지원하지 않습니다.
문제 해결
오프라인 데이터 진단은 지속적으로 가져오기의 전반적인 상태를 검토할 수 있는 단일 리소스를 제공합니다. 그러나 구현 중에 이 섹션의 정보를 사용하여 응답의 partial_failure_error
필드에 보고된 오류를 조사할 수 있습니다.
전환 액션을 가져올 때 가장 일반적인 오류는 USER_PERMISSION_DENIED
와 같은 승인 오류입니다. 요청의 고객 ID가 전환 액션을 소유한 Google Ads 전환 고객으로 설정되어 있는지 다시 확인합니다. 자세한 내용은 승인 가이드를 참고하고 다양한 오류를 디버그하는 방법에 관한 도움말은 일반 오류 가이드를 참고하세요.
일반적인 오류 디버그
오류 | |
---|---|
NO_CONVERSION_ACTION_FOUND
|
지정된 전환 액션이 사용 설정되지 않았거나 요청의 `client_id` 필드에 지정된 고객 계정에서 액세스할 수 없습니다. 업로드의 전환 액션이 사용 설정되어 있고 업로드 요청을 전송하는 고객이 소유하고 있는지 확인합니다. 요청의 GCLID가 요청에 지정된 전환 액션에 액세스할 수 없는 고객 계정에 속하는 경우에도 이 오류가 발생할 수 있습니다. |
INVALID_CONVERSION_ACTION_TYPE
|
지정된 전환 액션의 유형이 리드 확보용 향상된 전환에 유효하지 않습니다. 업로드 요청에 지정된 ConversionAction 의 유형이 UPLOAD_CLICKS 인지 확인합니다.
|
CUSTOMER_NOT_ENABLED_ENHANCED_CONVERSIONS_FOR_LEADS
|
전환 설정에서 리드 확보용 향상된 전환을 사용 설정했는지 확인합니다. 기본 요건 가이드에서 이에 관한 안내를 확인하세요. |
DUPLICATE_ORDER_ID
|
가져온 이벤트에 주문 ID가 동일한 전환이 여러 개 포함되어 있어 처리되지 않았습니다. 주문 ID가 고유한지 확인한 후 다시 시도해 주세요. |
CLICK_NOT_FOUND
|
제공된 사용자 식별자와 일치하는 클릭이 없습니다. Google Ads API는 UploadClickConversionsRequest 에서 debug_enabled 이 true 인 경우에만 이 오류를 반환합니다.
전환에서 이 경고가 발생하면 Google Ads API는 오프라인 데이터 진단의 클릭이 Google Ads 캠페인에서 발생하지 않은 경우 이 오류가 발생할 수 있습니다. 예를 들어 SA360 또는 DV360에서 가져올 수 있습니다. 그 밖의 가능한 원인은 다음과 같습니다.
업로드 고객이 Google Ads 전환 고객과 다른 드문 경우 이 오류는 업로드 고객이 고객 데이터 약관에 동의했지만 게재 고객이 동의하지 않았음을 의미할 수 있습니다. customer 리소스를 쿼리하고 customer.offline_conversion_tracking_info.accepted_customer_data_terms 필드를 확인하여 계정이 고객 데이터 약관에 동의했는지 확인할 수 있습니다.
|