Bạn có thể sử dụng Google Ads API để quản lý lượt chuyển đổi từ lượt nhấp trực tuyến trong Google Ads. Lượt chuyển đổi từ lượt nhấp trực tuyến giúp bạn theo dõi những quảng cáo dẫn đến lượt bán hàng trên mạng, chẳng hạn như thông qua một trang web.
Lượt chuyển đổi trực tuyến được theo dõi bằng thẻ Google, nhưng bạn có thể điều chỉnh hoặc nâng cao lượt chuyển đổi bằng Google Ads API.
Nếu bạn đã thiết lập thẻ Google và muốn điều chỉnh lượt chuyển đổi trực tuyến, hãy xem trang mức điều chỉnh cho lượt chuyển đổi. Nếu bạn đã thiết lập thẻ Google và muốn nâng cao lượt chuyển đổi trực tuyến bằng dữ liệu do người dùng cung cấp (còn gọi là Lượt chuyển đổi nâng cao cho web), hãy tiếp tục đọc.
Lượt chuyển đổi nâng cao cho web
Phần sau đây giải thích cách nâng cao lượt chuyển đổi từ lượt nhấp trực tuyến, còn được gọi là Lượt chuyển đổi nâng cao cho web.
Tính năng lượt chuyển đổi nâng cao cho web yêu cầu bạn thiết lập một thẻ tự động gửi giá trị nhận dạng lượt nhấp (chẳng hạn như GCLID) và mã đơn đặt hàng đến Google Ads khi người dùng chuyển đổi. Bạn có thể thiết lập tính năng lượt chuyển đổi nâng cao thông qua Trình quản lý thẻ của Google, thẻ Google hoặc API Google Ads. Khi sử dụng Google Ads API, bạn có thể gửi dữ liệu lượt chuyển đổi của bên thứ nhất trong vòng 24 giờ kể từ khi sự kiện chuyển đổi xảy ra, thay vì gửi cùng lúc. Điều này giúp bạn xác định vị trí dữ liệu của bên thứ nhất từ nhiều nguồn, chẳng hạn như cơ sở dữ liệu khách hàng hoặc hệ thống CRM.
Cách hoạt động của tính năng lượt chuyển đổi nâng cao cho web
Tính năng lượt chuyển đổi nâng cao cho web trong Google Ads API bổ sung cho bước 3 trong biểu đồ sau. Thay vì gửi thông tin người dùng đã băm khi người dùng chuyển đổi, thẻ chỉ gửi GCLID và mã đơn đặt hàng, còn bạn sẽ gửi thông tin người dùng đã băm sau đó bằng cách nhập mã đơn đặt hàng cùng với dữ liệu đã băm. Để tìm hiểu thêm về tính năng lượt chuyển đổi nâng cao cho web, hãy xem bài viết Giới thiệu về tính năng lượt chuyển đổi nâng cao.
Điều kiện tiên quyết
Bạn phải chấp nhận điều khoản về dữ liệu khách hàng thì mới có thể sử dụng tính năng lượt chuyển đổi nâng cao cho web. Bạn có thể xác minh xem điều khoản dữ liệu khách hàng đã được chấp nhận hay chưa bằng cách đưa ra truy vấn sau cho khách hàng chuyển đổi Google Ads:
SELECT
customer.id,
customer.conversion_tracking_setting.accepted_customer_data_terms
FROM customer
Nếu accepted_customer_data_terms là false, hãy làm theo hướng dẫn trong bài viết Thiết lập tính năng lượt chuyển đổi nâng cao cho web để hoàn tất điều kiện tiên quyết này.
Định cấu hình tính năng gắn thẻ
Bạn có thể định cấu hình tính năng gắn thẻ cho trang web của mình bằng cách làm theo hướng dẫn trong bài viết Thiết lập tính năng lượt chuyển đổi nâng cao cho web bằng Google Ads API. Bạn cũng nên thêm mã giao dịch (mã đơn đặt hàng) vào thẻ theo dõi lượt chuyển đổi để hỗ trợ việc so khớp lượt chuyển đổi.
Triển khai API
Dưới đây là quy trình tổng thể để nhập lượt chuyển đổi nâng cao cho web trong Google Ads API.
Chuẩn hoá và băm dữ liệu do người dùng cung cấp, chẳng hạn như địa chỉ email, số điện thoại và địa chỉ gửi thư.
Điền dữ liệu do người dùng cung cấp đã được chuẩn hoá và băm vào các đối tượng
ConversionAdjustment.Nhập các đối tượng
ConversionAdjustmentvàoConversionAdjustmentUploadService.
Chuẩn hoá và băm dữ liệu do người dùng cung cấp
Để bảo vệ quyền riêng tư, bạn phải băm những dữ liệu sau bằng thuật toán SHA-256 trước khi nhập:
- Địa chỉ email
- Số điện thoại
- Tên
- Họ
- Địa chỉ đường phố
Không băm những dữ liệu sau:
- Quốc gia
- Tiểu bang
- Thành phố
- Mã vùng
Để chuẩn hoá kết quả băm, hãy làm như sau trước khi băm một trong các giá trị này:
- Xoá khoảng trắng ở đầu và cuối.
- Chuyển đổi văn bản thành chữ thường.
- Định dạng số điện thoại theo tiêu chuẩn E.164.
Định dạng địa chỉ email cho tính năng lượt chuyển đổi nâng cao
Để đảm bảo tỷ lệ khớp cao nhất cho tính năng lượt chuyển đổi nâng cao, bạn phải định dạng và băm địa chỉ email đúng cách bằng cách làm theo các bước sau:
Áp dụng quy trình chuẩn hoá tiêu chuẩn (tất cả địa chỉ email):
- Xoá mọi khoảng trắng ASCII ở đầu và cuối.
- Chuyển đổi tất cả ký tự trong địa chỉ email thành chữ thường.
Áp dụng quy tắc chuẩn hoá theo miền cụ thể (chỉ
gmail.comvàgooglemail.com):- Sau khi chuyển địa chỉ email thành chữ thường, hãy kiểm tra xem miền (sau biểu tượng
@) có phải làgmail.comhaygooglemail.comhay không. - Xoá dấu chấm (
.): Xoá tất cả dấu chấm trong phần tên người dùng (trước ký hiệu@). - Xoá hậu tố dấu cộng (
+): Trong phần tên người dùng, hãy xoá dấu cộng đầu tiên (+) và tất cả ký tự tiếp theo cho đến ký hiệu@.- Ví dụ:
Jane.Doe+Shopping@googlemail.comtrước tiên sẽ trở thànhjane.doe+shopping@googlemail.com(chữ thường), sau đó làjanedoe@googlemail.com(các quy tắc của Gmail và Googlemail).
- Ví dụ:
- Các miền khác: Đối với mọi miền ngoài
gmail.comhoặcgooglemail.com, không được xoá dấu chấm hoặc hậu tố dấu cộng khỏi tên người dùng. Chỉ áp dụng quy trình chuẩn hoá tiêu chuẩn (cắt bỏ khoảng trắng và chuyển đổi thành chữ thường).- Ví dụ:
user.name+NYC@Example.comđược chuẩn hoá thànhuser.name+nyc@example.com.
- Ví dụ:
- Sau khi chuyển địa chỉ email thành chữ thường, hãy kiểm tra xem miền (sau biểu tượng
Băm địa chỉ email đã chuẩn hoá:
- Mã hoá chuỗi email đã chuẩn hoá thành byte UTF-8.
- Băm các byte UTF-8 bằng thuật toán SHA-256.
- Định dạng chuỗi băm kết quả dưới dạng chuỗi thập lục phân viết thường (64 ký tự).
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()
Ví dụ về mã
Ví dụ này cho thấy cách chuẩn hoá và băm dữ liệu do người dùng cung cấp.
Java
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
Perl
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
Điền sẵn các đối tượng ConversionAdjustment
Phần sau đây minh hoạ cách tạo một mức điều chỉnh nâng cao có chứa mã đơn đặt hàng, cùng với giá trị nhận dạng cho địa chỉ email, số điện thoại và địa chỉ thực, có áp dụng quy trình chuẩn hoá và băm khi cần. Tốt nhất là bạn nên thêm gclid vào thông tin điều chỉnh (nếu có).
Bước này gần giống với hướng dẫn Nhập mức điều chỉnh cho lượt chuyển đổi, nhưng có một số lưu ý:
- Điền dữ liệu người dùng đã chuẩn hoá và băm vào
user_identifiers. Nếu bạn có nhiều giá trị nhận dạng người dùng, hãy tạo mộtUserIdentifierriêng cho từng giá trị nhận dạng (tối đa 5 giá trị nhận dạng).
Java
// 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
Perl
# 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
- Đặt
order_id,adjustment_type(ENHANCEMENT) vàconversion_action(WEBPAGE), cùng vớigclid_date_time_pairkhông bắt buộc (được định dạng làyyyy-mm-dd HH:mm:ss+|-HH:mm, ví dụ:2022-01-01 19:32:45-05:00(bỏ qua giờ mùa hè) ) vàuser_agent:
Java
// 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
Perl
# 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
Tóm tắt giản đồ Request và ConversionAdjustment
Các bảng sau đây tóm tắt các trường cấp cao nhất trên UploadConversionAdjustmentsRequest và các trường trên mỗi mặt hàng trên ConversionAdjustment (conversion_adjustments[]) khi tải lượt chuyển đổi nâng cao cho web lên bằng ConversionAdjustmentUploadService.UploadConversionAdjustments:
| Trường yêu cầu | Yêu cầu | Định dạng và quy tắc ràng buộc |
|---|---|---|
customer_id |
Bắt buộc | Đặt thành mã khách hàng chuyển đổi Google Ads (google_ads_conversion_customer trên customer.conversion_tracking_setting), không có dấu gạch nối. |
conversion_adjustments[] |
Bắt buộc | Tối đa 2.000 mục ConversionAdjustment cho mỗi yêu cầu (TOO_MANY_ADJUSTMENTS_IN_REQUEST). |
partial_failure |
Bắt buộc | Phải được đặt thành true để các mức điều chỉnh hợp lệ được xử lý và lỗi ở cấp hàng được trả về trong partial_failure_error. |
validate_only |
Không bắt buộc | Khi true, xác thực yêu cầu mà không thực hiện các điều chỉnh. |
job_id |
Không bắt buộc | int32 dương (1 đến 2^31 - 1; 0 là giá trị canh gác chưa đặt và trả về INVALID_JOB_ID nếu được chỉ định) để nhóm nhiều yêu cầu trong một công việc logic duy nhất trong job_summaries. |
Mỗi ConversionAdjustment trong conversion_adjustments[] (tối đa 2.000 mức điều chỉnh cho mỗi yêu cầu) hỗ trợ các trường sau:
ConversionAdjustment trường |
Yêu cầu | Định dạng và quy tắc ràng buộc |
|---|---|---|
adjustment_type |
Bắt buộc | Phải được đặt thành ENHANCEMENT (ConversionAdjustmentType). |
conversion_action |
Bắt buộc | Tên tài nguyên (customers/{conversion_customer_id}/conversionActions/{action_id}) của một ENABLED hành động chuyển đổi được type = WEBPAGE tạo ít nhất 6 giờ trước khi tải lên (TOO_RECENT_CONVERSION_ACTION). |
order_id |
Bắt buộc | Mã giao dịch của lượt chuyển đổi cần nâng cao; phải khớp với mã đơn đặt hàng do thẻ lượt chuyển đổi trên trang web gửi. |
user_identifiers[] |
Bắt buộc | Từ 1 đến 5 đối tượng UserIdentifier cho mỗi điểm cải tiến. Đặt user_identifier_source không bắt buộc (chẳng hạn như FIRST_PARTY) và một giá trị nhận dạng cho mỗi mục nhập:• hashed_email: Chuỗi thập lục phân SHA-256.• hashed_phone_number: Chuỗi thập lục phân SHA-256 E.164.• address_info: OfflineUserAddressInfo có hashed_first_name, hashed_last_name, hashed_street_address được băm bằng thuật toán SHA-256 và city, state, country_code, postal_code không được băm. |
gclid_date_time_pair |
Không bắt buộc (nên dùng) | GclidDateTimePair chứa gclid và conversion_date_time (yyyy-mm-dd HH:mm:ss+|-HH:mm, ví dụ: 2022-01-01 19:32:45-05:00 (bỏ qua giờ mùa hè), ví dụ: 2026-06-01 14:30:00-04:00) của lượt chuyển đổi ban đầu. Bạn không thể điều chỉnh những lượt chuyển đổi đã xảy ra hơn 54 ngày trước (CONVERSION_EXPIRED). |
adjustment_date_time |
Không bắt buộc | Dấu thời gian (yyyy-mm-dd HH:mm:ss+|-HH:mm, ví dụ: 2022-01-01 19:32:45-05:00 (bỏ qua giờ mùa hè)) khi mức điều chỉnh xảy ra; nếu được đặt, phải sau conversion_date_time. |
user_agent |
Không bắt buộc | Chuỗi tiêu đề HTTP User-Agent từ yêu cầu chuyển đổi ban đầu để lượt chuyển đổi và lượt nâng cao có cùng thông tin phân bổ thiết bị (same-device hoặc cross-device). |
restatement_value |
Không đặt vào ENHANCEMENT |
Bỏ qua khi adjustment_type là ENHANCEMENT. Gửi một thao tác riêng biệt bằng adjustment_type = RESTATEMENT để thay đổi giá trị của lượt chuyển đổi. |
Nhập các điểm nâng cao về lượt chuyển đổi
Java
// 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, )
Perl
# 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
Cấu trúc yêu cầu và phản hồi REST
Khi gọi ConversionAdjustmentUploadService.UploadConversionAdjustments qua REST, hãy gửi yêu cầu POST với partialFailure được đặt thành 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"
}
]
}
]
}
Trong lô gồm 2 điều chỉnh này, trong đó điều chỉnh thứ hai bỏ qua orderId, các hàng thành công sẽ trả về các mục ConversionAdjustmentResult được điền sẵn trong results[], trong khi các hàng không thành công sẽ trả về các đối tượng {} trống trong results[] cùng với thông tin chi tiết về lỗi ở cấp hàng trong partialFailureError trên 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"
}
]
}
}
]
}
]
}
}
Xem xét dữ liệu đã nhập
Sử dụng báo cáo chẩn đoán API lượt chuyển đổi nâng cao để xác thực rằng tính năng lượt chuyển đổi nâng cao cho web đang hoạt động hiệu quả và để chẩn đoán các vấn đề trong quá trình thiết lập.
Sử dụng dữ liệu chẩn đoán ngoại tuyến để xem xét tình trạng tổng thể của các dữ liệu nhập gần đây.
Truy vấn thông tin chẩn đoán về lượt tải lên bằng GAQL
Bạn cũng có thể kiểm tra tình trạng tải lên ở cấp tài khoản, số lượng công việc gần đây và cảnh báo lỗi theo cách lập trình bằng cách truy vấn offline_conversion_upload_client_summary dựa trên mã khách hàng chuyển đổi:
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
Khi báo cáo về các chỉ số lượt chuyển đổi cho chiến dịch, hãy tham khảo bài viết Ánh xạ các chỉ số trên giao diện người dùng để liên kết các chỉ số trên giao diện người dùng Google Ads với các trường báo cáo của Google Ads API. Bạn cũng có thể truy vấn tài nguyên conversion_action để xem tổng số lượt chuyển đổi và tổng giá trị lượt chuyển đổi cho một hành động chuyển đổi nhất định.
Các phương pháp hay nhất
Hãy nhớ áp dụng các phương pháp hay nhất sau đây khi triển khai tính năng lượt chuyển đổi nâng cao cho web.
Kiểm tra giá trị nhận dạng khách hàng
Khi bạn nhập lượt chuyển đổi, mã khách hàng phải được đặt cho tài khoản
chứa hành động chuyển đổi và thực hiện việc theo dõi lượt chuyển đổi. Để kiểm tra chế độ cài đặt này, hãy truy vấn tài nguyên Customer của Google Ads đang phân phát cho ConversionTrackingSetting. Đưa ra truy vấn sau đây bằng GoogleAdsService.SearchStream để tìm giá trị của 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
Đặt customer_id thành giá trị google_ads_conversion_customer trong yêu cầu của bạn để nhập lượt chuyển đổi.
Thêm nhiều giá trị nhận dạng nếu bạn có
Nếu có GCLID cho một lượt chuyển đổi, bạn nên gửi GCLID ngoài user_identifiers để cải thiện hiệu suất. Ngoài ra, nếu bạn có nhiều UserIdentifier cho lượt chuyển đổi, thì việc thêm tất cả những thông tin này có thể cải thiện khả năng so khớp. Thêm tất cả giá trị nhận dạng vào cùng một ConversionAdjustment.
Xem xét các lỗi thất bại một phần khi thiết lập chế độ tích hợp
Khi bạn thiết lập tính năng lượt chuyển đổi nâng cao cho web lần đầu tiên, hãy xem xét và giải quyết mọi lỗi một phần trong trường partial_failure_error của phản hồi. Nếu có vấn đề trong chế độ thiết lập, bạn có thể kiểm tra trường này để điều tra và giải quyết vấn đề. Để biết thêm thông tin chi tiết và ví dụ liên quan đến
việc xử lý lỗi không thành công một phần, hãy truy cập vào
hướng dẫn riêng về lỗi không thành công một phần.
Sau khi bạn giải quyết mọi vấn đề xuất hiện trong lỗi không thành công một phần và hoàn tất quá trình tích hợp, hãy chuyển sang sử dụng thông tin chẩn đoán dữ liệu ngoại tuyến để thường xuyên xem xét tình trạng của lượt chuyển đổi.
Gộp nhiều lượt điều chỉnh vào một yêu cầu
Nếu bạn có nhiều mức điều chỉnh cần nhập, hãy gộp các thao tác (tối đa 2.000 mức điều chỉnh cho lượt chuyển đổi mỗi yêu cầu) thành một UploadConversionAdjustmentsRequest, thay vì gửi yêu cầu nhập cho từng mức điều chỉnh.
Xem hướng dẫn về hạn mức để biết giới hạn về số lượng điều chỉnh trên mỗi yêu cầu. Nếu bạn muốn chẩn đoán dữ liệu ngoại tuyến để nhóm một tập hợp
yêu cầu trong cùng một công việc logic, hãy đặt job_id của tất cả
yêu cầu thành cùng một giá trị.
Khắc phục sự cố
Sử dụng báo cáo chẩn đoán API lượt chuyển đổi nâng cao để xác thực rằng tính năng lượt chuyển đổi nâng cao cho web đang hoạt động hiệu quả và để chẩn đoán các vấn đề trong quá trình thiết lập.
Gỡ lỗi thường gặp
Hướng dẫn sau đây giúp bạn chẩn đoán và khắc phục các lỗi thường gặp với tính năng lượt chuyển đổi nâng cao cho web.
| Lỗi | |
|---|---|
CONVERSION_NOT_FOUND
|
Không tìm thấy lượt chuyển đổi cho cặp hành động chuyển đổi và giá trị nhận dạng lượt chuyển đổi được cung cấp hoặc
order_id. Xác minh rằng lượt chuyển đổi là một lượt chuyển đổi từ quảng cáo trên Google Ads cho
khách hàng chuyển đổi trên Google Ads được chỉ định trong customer_id của yêu cầu.Ngoài ra, hãy xác minh rằng lượt chuyển đổi không phải là lượt nhấp mà gbraid
hoặc wbraid được điền sẵn thay vì gclid.
Google Ads không hỗ trợ tính năng lượt chuyển đổi nâng cao cho web đối với những lượt chuyển đổi này.
|
CUSTOMER_NOT_ACCEPTED_CUSTOMER_DATA_TERMS
|
Các điều khoản và điều kiện về dữ liệu khách hàng chưa được chấp nhận cho
customer_id của yêu cầu. Hãy xem hướng dẫn về việc này trong phần
điều kiện tiên quyết.
|
CONVERSION_ALREADY_ENHANCED
|
Lượt chuyển đổi này đã được điều chỉnh bằng order_id và conversion_action đã cho. Hãy nhớ cung cấp
một order_id riêng biệt cho mỗi lượt chuyển đổi.
|
CONVERSION_ACTION_NOT_ELIGIBLE_FOR_ENHANCEMENT
|
conversion_action được cung cấp không đủ điều kiện sử dụng tính năng lượt chuyển đổi nâng cao cho web. Trong giao diện người dùng Google Ads, hãy nhớ đánh dấu vào hộp Bật tính năng lượt chuyển đổi nâng cao trên hành động chuyển đổi được tham chiếu trong yêu cầu của bạn. Tìm hướng dẫn về việc này trong
Trung tâm trợ giúp.
|