您可以使用 Google Ads API 將離線轉換匯入 Google Ads,追蹤促成離線銷售 (例如透過電話或業務代表) 的廣告。
為充分發揮匯入轉換資料的效益,建議您導入待開發客戶強化轉換,運用 Google 點擊 ID 和使用者提供的資料,盡可能提升資料準確度和成效。
強化轉換
強化轉換功能會使用電子郵件地址、電話號碼和郵寄地址等第一方轉換資料,補充轉換資料,協助您提升轉換評估的準確度。
強化轉換分為兩種類型。詳情請參閱「關於強化轉換」一文。
以下章節說明如何強化離線轉換,這項功能也稱為待開發客戶強化轉換。
什麼是待開發客戶強化轉換?
待開發客戶強化轉換是升級版的離線轉換匯入,會使用使用者提供的資料 (例如電子郵件地址) 補足匯入的離線轉換資料,進而提升評估準確度和出價成效。匯入離線轉換時,系統會將提供的經雜湊處理顧客數位資料,與您網站上收集的相同資料 (例如待開發客戶表單) 以及與廣告互動的已登入顧客進行比對,藉此將轉換歸因於 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.enablement_setting,
customer.conversion_tracking_setting.effective_enablement_setting
FROM customer
如果 accepted_customer_data_terms 為 false,或 enablement_setting (使用跨帳戶轉換追蹤時為 effective_enablement_setting) 不是 ON,請按照「建立新的轉換動作」中的操作說明完成這些必要條件。
設定代碼
請按照這篇文章的操作說明,設定 Google 代碼,啟用待開發客戶強化轉換。如要使用 Google 代碼管理工具設定待開發客戶強化轉換,請按照這份 Google 代碼管理工具操作說明進行。
API 導入
以下是使用 Google Ads API 匯入待開發客戶強化轉換的整體流程。
將使用者提供的資料正規化並進行雜湊處理,例如電子郵件地址、電話號碼和郵寄地址。
使用經過正規化和雜湊處理的使用者提供資料,填入
ClickConversion物件。使用
ConversionUploadService將ClickConversion物件匯入 Google Ads API。詳情請參閱UploadClickConversions。
Request 和 ClickConversion 結構定義摘要
下表摘要列出待開發客戶強化轉換的 UploadClickConversionsRequest 和 ClickConversion 重要欄位 (如需完整欄位詳細資料,請參閱「填入 ClickConversion 物件」和「建構要求」):
| 欄位路徑 | 規定 | 格式和限制 |
|---|---|---|
customer_id |
必填 | 設為 Google Ads 廣告轉換客戶 ID (customer.conversion_tracking_setting 的 google_ads_conversion_customer),不含連字號。 |
partial_failure |
必填 | 必須設為 true,系統才會匯入有效轉換,並在 partial_failure_error 中傳回資料列層級錯誤。 |
validate_only |
選用 | 如果設為 true,系統會驗證要求,但不會匯入轉換 (在 partial_failure_error 中傳回任何驗證錯誤)。 |
job_id |
選用 | 非負 int32 (0 至 2^31 - 1),用於將多個要求歸入 job_summaries 中的一個邏輯工作。 |
conversions[].conversion_action |
必填 | ENABLED 轉換動作的資源名稱 (customers/{conversion_customer_id}/conversionActions/{action_id}),包含 type = UPLOAD_CLICKS。 |
conversions[].conversion_date_time |
必填 | 必須晚於點擊時間,且包含時區偏移:yyyy-mm-dd hh:mm:ss+|-hh:mm (例如 2026-06-01 14:30:00-04:00)。 |
conversions[].conversion_value和currency_code |
建議 | 轉換價值數值 (double) 和 3 個字元的 ISO 4217 貨幣代碼 (例如 USD)。 |
conversions[].order_id |
建議 | 每項轉換動作都有專屬交易 ID,可避免重複匯入,並支援日後調整。 |
conversions[].gclid/gbraid/wbraid |
建議使用 (如果情況允許) | 從到達網頁網址擷取的點擊 ID。請盡可能與 user_identifiers 一併提供。 |
conversions[].user_identifiers[] |
待開發客戶強化轉換的必要條件 | 每次轉換一到五個 UserIdentifier 物件。設定選用的 user_identifier_source (例如 FIRST_PARTY),以及 hashed_email (移除 gmail.com 和 googlemail.com 的 @ 前面的點和 + 後置字串,並轉換為小寫,SHA-256 十六進位) 或 hashed_phone_number (E.164 格式,SHA-256 十六進位);請參閱「正規化及雜湊處理資料」。不支援 address_info。 |
conversions[].consent.ad_user_data |
建議 | 在 Consent 上設為 GRANTED 或 DENIED。(ad_personalization 僅支援 OfflineUserDataJobService 和 UserDataService)。 |
conversions[].custom_variables和external_attribution_data |
請勿使用 user_identifiers 設定 |
包含 user_identifiers 的轉換不得設定 custom_variables 或 external_attribution_data,否則會遭拒。 |
擷取轉換動作資源名稱
如要上傳轉換,您必須指定在 Google Ads 中設定的 ConversionAction 資源名稱,以便匯入點擊轉換。您可以使用下列 GAQL 查詢,查詢 conversion_action 資源,找出資源名稱:
SELECT
customer.id,
conversion_action.id,
conversion_action.name,
conversion_action.type,
conversion_action.resource_name
FROM conversion_action
WHERE conversion_action.type = 'UPLOAD_CLICKS'
AND conversion_action.status = 'ENABLED'
正規化及雜湊處理使用者提供的資料
基於隱私權考量,請務必使用 SHA-256 雜湊處理,才能匯入下列資料:
- 電子郵件地址
- 電話號碼
- 名字
- 姓氏
- 街道地址
請勿雜湊處理下列資料:
- 國家/地區
- 州/省
- 城市
- 郵遞區號
為標準化雜湊處理結果,在雜湊處理每個值前,請務必:
- 移除開頭和結尾的空白字元。
- 將文字轉換為小寫。
- 根據 E.164 標準設定電話號碼格式。
強化轉換的電子郵件地址格式
為確保強化轉換的媒合率達到最高,請務必按照下列步驟,正確設定電子郵件地址的格式並進行雜湊處理:
套用標準正規化 (所有電子郵件地址):
- 移除開頭和結尾的 ASCII 空白字元。
- 將電子郵件地址中的所有字元改成小寫。
套用特定領域正規化 (僅限
gmail.com和googlemail.com):- 將電子郵件地址轉換為小寫後,請檢查網域 (
@符號後方) 是否為gmail.com或googlemail.com。 - 移除句號 (
.):從使用者名稱部分 (@符號之前) 移除所有句號字元。 - 移除加號後置字串 (
+):從使用者名稱部分,移除第一個加號 (+) 和@符號前的所有後續字元。- 範例:
Jane.Doe+Shopping@googlemail.com會先變成jane.doe+shopping@googlemail.com(小寫),然後變成janedoe@googlemail.com(Gmail 和 Googlemail 規則)。
- 範例:
- 其他網域:如果是
gmail.com或googlemail.com以外的網域,請勿移除使用者名稱中的半形句號或加號後置字串。僅套用標準正規化 (移除空白字元並轉換為小寫)。- 範例:
user.name+NYC@Example.com會正規化為user.name+nyc@example.com。
- 範例:
- 將電子郵件地址轉換為小寫後,請檢查網域 (
雜湊正規化電子郵件地址:
- 將正規化電子郵件字串編碼為 UTF-8 位元組。
- 使用 SHA-256 演算法對 UTF-8 位元組進行雜湊處理。
- 將產生的摘要格式化為小寫十六進位字串 (64 個字元)。
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()
程式碼範例
這個範例說明如何正規化及雜湊處理使用者提供的資料。
Java
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 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); } /** * 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); }
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): 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); }
Python
def normalize_and_hash_email_address(email_address: str) -> str: """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: str = email_address.strip().lower() email_parts: list[str] = 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: str) -> str: """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
Perl
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); }
curl
填入 ClickConversion 物件
UploadClickConversionsRequest 中的 ClickConversion 物件集合代表您要匯入的轉換組合。建立 ClickConversion 物件時,請注意下列事項:
gclidGCLID 是使用者點按廣告並前往網站時,從網址參數擷取的 ID。
gbraidgbraid是網址參數,當使用者在網路上點按廣告並導向您的 iOS 應用程式時,就會出現。wbraidwbraid是網址參數,會在使用者點按 iOS 應用程式中的廣告,並導向您的網頁時顯示。cart_data包含轉換的項目層級詳細資料。您必須填入
cart_data欄位,才能在 Google Ads UI 中回報購物籃資料,例如購買的商品、價格和數量。請參閱CartData物件定義,瞭解必要結構,並參閱「透過購物車資料回報的轉換」一文,瞭解詳情。user_identifiers使用待開發客戶強化轉換時,您必須在
user_identifiers欄位中填入經過正規化和雜湊處理的使用者提供資料。如果您有多個使用者 ID,請為每個 ID 建立個別的UserIdentifier,最多可建立五個 ID。conversion_date_time轉換日期和時間。
值必須指定時區,且格式必須為
yyyy-mm-dd HH:mm:ss+|-HH:mm,例如:2022-01-01 19:32:45-05:00(忽略日光節約時間)。時區可以是任何有效值,不一定要與帳戶時區相符。不過,如果您打算將匯入的轉換資料與 Google Ads 使用者介面中的資料進行比較,建議使用與 Google Ads 帳戶相同的時區,確保轉換次數一致。如需更多詳細資料和範例,請參閱「準備要匯入的資料」一文,並查看「代碼和格式」一節,瞭解有效的時區 ID 清單。
conversion_action離線轉換的
ConversionAction資源名稱。轉換動作的
type必須為UPLOAD_CLICKS,且必須存在於與點擊相關聯的 Google Ads 帳戶的 Google Ads 廣告轉換客戶中。conversion_value轉換價值。
currency_codeconversion_value的貨幣代碼。consent強烈建議您填入
ClickConversion物件的consent欄位。如未設定,轉換可能無法歸因。order_id也稱為轉換的交易 ID。這個欄位為選填欄位,但極力建議您填寫,因為這樣在進行調整時,就能更輕鬆地參照匯入的轉換。如果您在匯入時設定了交易 ID,就必須使用該值進行任何調整。如要進一步瞭解如何使用交易 ID 避免重複計算轉換,請參閱「使用交易 ID 避免重複計算轉換」一文。
custom_variables自訂轉換變數的值。Google Ads 不支援自訂轉換變數與
wbraid或gbraid搭配使用。conversion_environment表示記錄這項轉換的環境。例如
APP或WEB。
session_attributes_encoded和session_attributes_key_value_pairs工作階段屬性代表用於轉換歸因的匯總 ID。除了 Google 點擊 ID、網址參數 (例如 GBRAID) 和使用者提供的資料 (待開發客戶強化轉換的核心) 之外,這些參數也會發揮作用。匯入工作階段屬性的方式有兩種:提供瀏覽器中 JavaScript 程式碼產生的編碼權杖,或為每個 ID 提供個別鍵/值組合。
為盡量提升廣告活動成效,建議您盡可能匯入點擊 ID、使用者提供的資料,以及所有轉換的工作階段屬性。
Java
// Sets one of the sessionAttributesEncoded or sessionAttributesKeyValuePairs if either is // provided. The session attribute fields are only available to allowlisted users. // To include these fields in conversion imports, upgrade to the Data Manager API. 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()); }
C#
// The session attribute fields are only available to allowlisted users. To // include these fields in conversion imports, upgrade to the Data Manager API. 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); }
PHP
// Set one of the sessionAttributesEncoded or // SessionAttributeKeyValuePair fields if either are provided. The session attribute // fields are only available to allowlisted users. To include these fields in conversion // imports, upgrade to the Data Manager API. if (!empty($sessionAttributesEncoded)) { $clickConversion->setSessionAttributesEncoded($sessionAttributesEncoded); } elseif (!empty($sessionAttributesDict)) { // Create a new container object to hold key-value pairs. $sessionAttributesKeyValuePairs = new SessionAttributesKeyValuePairs(); // Initialize an array to hold individual key-value pair messages. $keyValuePairs = []; // Append each key-value pair provided to the $keyValuePairs array foreach ($sessionAttributesDict as $key => $value) { $pair = new SessionAttributeKeyValuePair(); $pair->setSessionAttributeKey($key); $pair->setSessionAttributeValue($value); $keyValuePairs[] = $pair; } // Set the the full list of key-value pairs on the container object. $sessionAttributesKeyValuePairs->setKeyValuePairs($keyValuePairs); // Attach the container of key-value pairs to the ClickConversion object. $clickConversion->setSessionAttributesKeyValuePairs($sessionAttributesKeyValuePairs); }
Python
# Set one of the session_attributes_encoded or # session_attributes_key_value_pairs fields if either are provided. # The session attribute fields are only available to allowlisted users. # To include these fields in conversion imports, upgrade to the Data Manager API. 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: SessionAttributeKeyValuePair = 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 )
小茹
# Set one of the session_attributes_encoded or # session_attributes_key_value_pairs fields if either are provided. # The session attribute fields are only available to allowlisted users. # To include these fields in conversion imports, upgrade to the Data Manager API. 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
Perl
# 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::V26::Services::ConversionUploadService::SessionAttributeKeyValuePair ->new({sessionAttributeKey => $key, sessionAttributeValue => $value}); push @{$click_conversion->{sessionAttributesKeyValuePairs}{keyValuePairs} }, $pair; } }
curl
user_ip_address顧客點按廣告後,在轉換事件發生前,抵達到達網頁時的 IP 位址。這是顧客裝置的 IP 位址,而非廣告主伺服器的 IP 位址。
這個欄位是字串,代表 IPv4 或 IPv6 格式的 IP 位址。例如:
- IPv4:
"192.0.2.0" - IPv6:
"2001:0DB8:1234:5678:9999:1111:0000:0001"
- IPv4:
程式碼範例
以下範例說明如何將正規化和雜湊處理的使用者提供資料,設定到 ClickConversion 物件。
Java
// 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+myalias@gmail.com") // 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("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(normalizeAndHashPhoneNumber(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);
C#
// 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" } });
PHP
// 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, 'sessionAttributesEncoded' => $sessionAttributesEncoded, 'sessionAttributesDict' => $sessionAttributesDict ]; // 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);
Python
# 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: Dict[str, Union[str, float]] = { # 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: ClickConversion = 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: UserIdentifier = 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: UserIdentifier = 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. # The session attribute fields are only available to allowlisted users. # To include these fields in conversion imports, upgrade to the Data Manager API. 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
Perl
# Create an empty click conversion. my $click_conversion = Google::Ads::GoogleAds::V26::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::V26::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::V26::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::V26::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;
curl
這個範例說明如何在 ClickConversion 物件上設定其他必要欄位。
Java
// 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. The session attribute fields are only available to allowlisted users. // To include these fields in conversion imports, upgrade to the Data Manager API. 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();
C#
// 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; } // The session attribute fields are only available to allowlisted users. To // include these fields in conversion imports, upgrade to the Data Manager API. 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); }
PHP
// 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']]) ); } // Set one of the sessionAttributesEncoded or // SessionAttributeKeyValuePair fields if either are provided. The session attribute // fields are only available to allowlisted users. To include these fields in conversion // imports, upgrade to the Data Manager API. if (!empty($sessionAttributesEncoded)) { $clickConversion->setSessionAttributesEncoded($sessionAttributesEncoded); } elseif (!empty($sessionAttributesDict)) { // Create a new container object to hold key-value pairs. $sessionAttributesKeyValuePairs = new SessionAttributesKeyValuePairs(); // Initialize an array to hold individual key-value pair messages. $keyValuePairs = []; // Append each key-value pair provided to the $keyValuePairs array foreach ($sessionAttributesDict as $key => $value) { $pair = new SessionAttributeKeyValuePair(); $pair->setSessionAttributeKey($key); $pair->setSessionAttributeValue($value); $keyValuePairs[] = $pair; } // Set the the full list of key-value pairs on the container object. $sessionAttributesKeyValuePairs->setKeyValuePairs($keyValuePairs); // Attach the container of key-value pairs to the ClickConversion object. $clickConversion->setSessionAttributesKeyValuePairs($sessionAttributesKeyValuePairs); }
Python
# Add details of the conversion. # Gets the conversion action resource name. conversion_action_service: ConversionActionServiceClient = ( 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. # The session attribute fields are only available to allowlisted users. # To include these fields in conversion imports, upgrade to the Data Manager API. 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: SessionAttributeKeyValuePair = 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. # The session attribute fields are only available to allowlisted users. # To include these fields in conversion imports, upgrade to the Data Manager API. 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
Perl
# Add details of the conversion. $click_conversion->{conversionAction} = Google::Ads::GoogleAds::V26::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::V26::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::V26::Services::ConversionUploadService::SessionAttributeKeyValuePair ->new({sessionAttributeKey => $key, sessionAttributeValue => $value}); push @{$click_conversion->{sessionAttributesKeyValuePairs}{keyValuePairs} }, $pair; } }
curl
建構要求
設定 ClickConversion 物件並新增至 UploadClickConversionsRequest 物件的 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)範圍內的值。無論您是否指定值,或讓 Google Ads API 指派值,回應中的
job_id都會包含要求的 工作 ID。partial_failure匯入轉換時,這個欄位必須設為
true。處理回應時,請遵循部分失敗指南。
匯入要求
填入 ClickConversion 物件並建構要求後,即可提交匯入作業。
Java
// 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());
C#
// 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 });
PHP
// 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) );
Python
# Creates the conversion upload service client. conversion_upload_service: ConversionUploadServiceClient = ( 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: UploadClickConversionsResponse = ( 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
Perl
# 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" });
curl
REST 要求和回應結構
透過 REST 呼叫 ConversionUploadService.UploadClickConversions 時,請傳送 POST 要求,並將 partialFailure 設為 true:
POST https://googleads.googleapis.com/v26/customers/{customer_id}:uploadClickConversions
{
"partialFailure": true,
"jobId": 1001,
"conversions": [
{
"conversionAction": "customers/{customer_id}/conversionActions/{conversion_action_id}",
"conversionDateTime": "2026-06-01 14:30:00-04:00",
"conversionValue": 125.50,
"currencyCode": "USD",
"orderId": "ORDER-2026-0001",
"gclid": "EAIaIQobChMI...",
"consent": {
"adUserData": "GRANTED"
},
"userIdentifiers": [
{
"userIdentifierSource": "FIRST_PARTY",
"hashedEmail": "f660ab912ec121d1b1e928a0bb4bc61b15f5ad44d5efdc4e1c92a25e99b8e44a"
},
{
"userIdentifierSource": "FIRST_PARTY",
"hashedPhoneNumber": "42975f8f9e46c2e13c1a2294957e5cb8d8e6f4f7341a036c6e595bc9f5e24621"
}
]
},
{
"conversionAction": "customers/{customer_id}/conversionActions/{conversion_action_id}",
"conversionDateTime": "2026-06-01 14:35:00-04:00",
"conversionValue": 80.00,
"currencyCode": "USD",
"orderId": "ORDER-2026-0002",
"gclid": "EAIaIQobChMI_expired...",
"consent": {
"adUserData": "GRANTED"
}
}
]
}
在這個包含兩筆轉換的批次中,第二個項目失敗,因此成功的資料列會在 results[] 中傳回填入的 ClickConversionResult 項目,而失敗的資料列則會在 results[] 中傳回空白的 {} 物件,並在 UploadClickConversionsResponse 的 partialFailureError 中傳回錯誤詳細資料:
{
"results": [
{
"conversionAction": "customers/{customer_id}/conversionActions/{conversion_action_id}",
"conversionDateTime": "2026-06-01 14:30:00-04:00",
"gclid": "EAIaIQobChMI...",
"userIdentifiers": [
{
"userIdentifierSource": "FIRST_PARTY",
"hashedEmail": "f660ab912ec121d1b1e928a0bb4bc61b15f5ad44d5efdc4e1c92a25e99b8e44a"
},
{
"userIdentifierSource": "FIRST_PARTY",
"hashedPhoneNumber": "42975f8f9e46c2e13c1a2294957e5cb8d8e6f4f7341a036c6e595bc9f5e24621"
}
]
},
{}
],
"jobId": "1001",
"partialFailureError": {
"code": 3,
"message": "The click associated with the given identifier or iOS URL parameter occurred less recently than the maximum lookback window., at conversions[1].gclid",
"details": [
{
"@type": "type.googleapis.com/google.ads.googleads.v26.errors.GoogleAdsFailure",
"errors": [
{
"errorCode": {
"conversionUploadError": "EXPIRED_EVENT"
},
"message": "The click associated with the given identifier or iOS URL parameter occurred less recently than the maximum lookback window.",
"location": {
"fieldPathElements": [
{
"fieldName": "conversions",
"index": 1
},
{
"fieldName": "gclid"
}
]
}
}
]
}
]
}
}
查看匯入內容
請使用待開發客戶強化轉換診斷報告,查看最近匯入資料的整體健康狀態。
使用 GAQL 查詢上傳診斷資料
您也可以透過程式輔助方式,查詢轉換客戶 ID 的 offline_conversion_upload_client_summary,檢查帳戶層級的上傳健康狀態、近期工作數量和錯誤警示:
SELECT
customer.id,
offline_conversion_upload_client_summary.client,
offline_conversion_upload_client_summary.status,
offline_conversion_upload_client_summary.total_event_count,
offline_conversion_upload_client_summary.successful_event_count,
offline_conversion_upload_client_summary.success_rate,
offline_conversion_upload_client_summary.pending_event_count,
offline_conversion_upload_client_summary.pending_rate,
offline_conversion_upload_client_summary.last_upload_date_time,
offline_conversion_upload_client_summary.alerts,
offline_conversion_upload_client_summary.daily_summaries,
offline_conversion_upload_client_summary.job_summaries
FROM offline_conversion_upload_client_summary
匯入的轉換會反映在原始點擊曝光日期的報表中,而非匯入要求的日期或ClickConversion的conversion_date_time日期。
如果是最終點擊歸因,匯入的轉換統計資料最多需要三小時,才會顯示在 Google Ads 帳戶中。其他搜尋歸因模式則可能需要超過三小時。詳情請參閱資料更新間隔指南。
製作廣告活動轉換指標報表時,請參閱「對應使用者介面指標」,將 Google Ads UI 指標與 Google Ads API 報表欄位建立關聯。您也可以查詢 conversion_action 資源,查看特定轉換動作的轉換總數和總轉換價值。
最佳做法
導入待開發客戶強化轉換時,請注意下列最佳做法。
無論完整性如何,一律傳送所有轉換資料
為確保產生完整、準確的轉換報表,請匯入所有可用的離線轉換事件 (包括可能不是來自 Google Ads 的事件),僅包含使用者提供資料的轉換仍有助於 Google Ads 廣告活動最佳化。
如果您為轉換指派 order_id,建議您加入這項資訊。如果您有轉換的 Google 點擊 ID,建議一併傳送該 ID 和 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 不支援使用使用者提供的資料匯入外部已歸因轉換。
不含自訂變數
使用待開發客戶強化轉換時,請勿加入任何 custom_variables。Google Ads 不支援在轉換匯入中使用包含使用者提供資料的自訂變數。如果轉換包含使用者提供的資料,且包含自訂變數,系統會判定這些轉換無效並捨棄。
疑難排解
離線資料診斷功能提供單一資源,可持續查看匯入資料的整體健康狀態。不過,在導入期間,您可以使用本節中的資訊,調查回應的 partial_failure_error 欄位中回報的任何錯誤。
匯入轉換動作時,最常見的錯誤是授權錯誤,例如 USER_PERMISSION_DENIED。請仔細檢查要求中的客戶 ID,是否設為擁有轉換動作的 Google Ads 廣告轉換客戶。如需更多詳細資訊,請參閱授權指南。如需偵錯這些不同錯誤的提示,請參閱常見錯誤指南。
排解常見錯誤
以下指引有助您診斷及修正待開發客戶強化轉換的常見錯誤。
| 錯誤 | |
|---|---|
NO_CONVERSION_ACTION_FOUND
|
指定的轉換動作未啟用,或要求中 如果要求中的 Google 點擊 ID 屬於無權存取要求中指定轉換動作的客戶帳戶,也可能發生這項錯誤。您可以提交依 |
INVALID_CONVERSION_ACTION_TYPE
|
指定的轉換動作類型不適用於待開發客戶強化轉換。請確認上傳要求中指定的 ConversionAction 類型為 UPLOAD_CLICKS。 |
CUSTOMER_NOT_ENABLED_ENHANCED_CONVERSIONS_FOR_LEADS
|
請確認您已在轉換設定中啟用待開發客戶強化轉換。如需操作說明,請參閱必備條件指南。 |
DUPLICATE_ORDER_ID
|
匯入的事件包含具有相同訂單 ID 的多個轉換,因此無法處理。 請確認訂單 ID 並未重複,然後再試一次。 |
CLICK_NOT_FOUND
|
找不到與提供的使用者 ID 相符的點擊。
如果轉換遇到這項警告,Google Ads API 會將其納入離線資料診斷的 如果點擊並非來自 Google Ads 廣告活動,就會發生這項錯誤。例如,可能來自 SA360 或 DV360。其他可能原因如下:
在極少數情況下,如果上傳客戶與 Google Ads 轉換客戶不同,這項錯誤可能表示上傳客戶已接受顧客數位資料條款,但放送客戶尚未接受。 如要確認帳戶是否已接受顧客數位資料條款,請查詢customer 資源,並檢查 customer.conversion_tracking_setting.accepted_customer_data_terms 欄位。 |