Conversion ที่ปรับปรุงแล้วสําหรับโอกาสในการขายช่วยให้คุณเพิ่มความแม่นยําในการวัด Conversion ออฟไลน์ได้โดยการอัปโหลด Conversion การคลิกที่มีตัวระบุผู้ใช้ที่แฮชและรายละเอียดเพิ่มเติมที่ไม่บังคับซึ่งช่วยให้ Google Ads เชื่อมโยง Conversion กับโฆษณาที่ทําให้เกิดโอกาสในการขายได้
โปรดอ่านคําแนะนําเกี่ยวกับการเริ่มต้นใช้งานและติดตั้งใช้งานข้อกําหนดเบื้องต้นสําหรับ Conversion ที่ปรับปรุงแล้วสําหรับโอกาสในการขายก่อนดําเนินการติดตั้งใช้งาน
คุณสามารถอัปโหลด Conversion ที่ปรับปรุงแล้วสําหรับโอกาสในการขายผ่าน UI ของ Google Ads ตามที่อธิบายไว้ในศูนย์ช่วยเหลือ หรือผ่าน Google Ads API ตามที่อธิบายไว้ในคู่มือนี้
ออกแบบการผสานรวม
คุณออกแบบการผสานรวมได้
ขั้นตอนการใช้งาน
ขั้นตอนโดยรวมในการอัปโหลด Conversion ที่ปรับปรุงแล้วสําหรับโอกาสในการขายใน Google Ads API มีดังนี้
ตรวจสอบว่าคุณได้ติดตั้งใช้งานข้อกําหนดเบื้องต้นต่อไปนี้แล้ว
เปิดใช้เครื่องมือวัด Conversion
ยอมรับข้อกําหนดสำหรับข้อมูลลูกค้า
กําหนดค่าการติดแท็กในโฆษณาแบบกรอกฟอร์มบนเว็บไซต์
ดูคำแนะนำโดยละเอียดที่หัวข้อติดตั้งใช้งานข้อกําหนดเบื้องต้น
แปลงและแฮชข้อมูลโอกาสในการขาย เช่น อีเมล หมายเลขโทรศัพท์ และที่อยู่สำหรับจัดส่ง
ใส่ข้อมูลโอกาสในการขายที่แปลงให้เป็นมาตรฐานและแฮชแล้วลงในออบเจ็กต์
ClickConversion
สําหรับClickConversion
แต่ละรายการป้อนข้อมูลผู้มีโอกาสเป็นลูกค้ารูปแบบมาตรฐานที่แฮชแล้วลงใน
user_identifiers
หากคุณมีตัวระบุผู้ใช้หลายรายการ ให้สร้างUserIdentifier
แยกกันสำหรับแต่ละรายการ โดยสร้างได้สูงสุด 5 รายการ(ไม่บังคับแต่แนะนำอย่างยิ่ง) ป้อนข้อมูล
order_id
(ไม่บังคับ) ป้อน
gclid
เพื่อให้การวัดผลแม่นยำที่สุดตรวจสอบว่าคุณป้อนข้อมูลในฟิลด์
consent
ของออบเจ็กต์ClickConversion
ตั้งค่า
conversion_action
เป็นชื่อทรัพยากรของConversionAction
ที่มีtype
ของUPLOAD_CLICKS
ซึ่งควรเป็นชื่อทรัพยากรของConversionAction
ที่คุณสร้างขึ้นเมื่อติดตั้งใช้งานข้อกําหนดเบื้องต้น
อัปโหลดการดำเนินการสร้าง
ClickConversion
ไปยังConversionUploadService
โดยตั้งค่าpartial_failure
เป็นtrue
ตรวจสอบการอัปโหลด
แนวทางปฏิบัติแนะนำ
โปรดคำนึงถึงแนวทางปฏิบัติแนะนำต่อไปนี้เมื่อติดตั้งใช้งาน Conversion ที่ปรับปรุงแล้วสำหรับโอกาสในการขาย
ตรวจสอบตัวระบุลูกค้า
เมื่อคุณอัปโหลด Conversion คุณต้องตั้งค่ารหัสลูกค้าเป็นบัญชีที่มีการกระทำที่ถือเป็น Conversion และทำการวัด Conversion หากต้องการตรวจสอบการตั้งค่านี้ ให้ค้นหาแหล่งข้อมูล Customer
ของ Google Ads ที่แสดงอยู่สําหรับ ConversionTrackingSetting
เรียกใช้การค้นหาต่อไปนี้ด้วย GoogleAdsService.SearchStream
เพื่อค้นหาค่าของ customer.conversion_tracking_setting.google_ads_conversion_customer
ระบุตัวระบุหลายรายการหากมี
หากคุณกําหนด order_id
ให้กับ Conversion เราขอแนะนําอย่างยิ่งให้ใส่ order_id
นั้น
หากคุณมี gclid
สําหรับ Conversion เราขอแนะนําให้ส่ง gclid
นั้นเพิ่มเติมจาก user_identifiers
เพื่อให้ได้ประสิทธิภาพที่ดียิ่งขึ้น นอกจากนี้ หากคุณมี UserIdentifier
มากกว่า 1 รายการสําหรับ Conversion การรวม UserIdentifier
หลายรายการจะเพิ่มโอกาสในการจับคู่ รวมตัวระบุทั้งหมดไว้ในClickConversion
เดียวกัน
ตรวจสอบข้อผิดพลาดที่ดำเนินการไม่สำเร็จบางส่วนเมื่อตั้งค่าการผสานรวม
เมื่อตั้งค่า Conversion ที่ปรับปรุงแล้วสําหรับการผสานรวมโอกาสในการขายเป็นครั้งแรก ให้ตรวจสอบและแก้ไขข้อผิดพลาดบางส่วนในช่อง partial_failure_error
ของคําตอบ หากมีปัญหาในการตั้งค่า คุณจะต้องตรวจสอบช่องนี้เพื่อตรวจสอบและแก้ไขปัญหา ดูรายละเอียดและตัวอย่างเพิ่มเติมเกี่ยวกับการจัดการข้อผิดพลาดที่ดำเนินการไม่สำเร็จบางส่วนได้ที่คู่มือเฉพาะสำหรับการดำเนินการไม่สำเร็จบางส่วน
เมื่อตรวจสอบข้อผิดพลาดที่ดำเนินการสำเร็จบางส่วน โปรดดูตารางข้อผิดพลาดที่พบบ่อยในคู่มือการแก้ปัญหา เมื่อแก้ไขปัญหาที่แสดงในข้อผิดพลาด "บางส่วนไม่สําเร็จ" และผสานรวมเสร็จแล้ว ให้เปลี่ยนไปใช้การวินิจฉัยข้อมูลออฟไลน์เพื่อตรวจสอบประสิทธิภาพของ Conversion เป็นประจํา
ส่ง Conversion หลายรายการพร้อมกันในคําขอเดียว
หากต้องอัปโหลด Conversion หลายรายการ ให้จัดกลุ่มการดำเนินการเป็นกลุ่มเดียวใน UploadClickConversionsRequest
แทนที่จะส่งคำขออัปโหลดต่อ Conversion
โปรดดูคําแนะนําเกี่ยวกับโควต้าเพื่อดูขีดจํากัดของจํานวน Conversion ต่อคําขอ
หากต้องการให้การวินิจฉัยข้อมูลออฟไลน์จัดกลุ่มชุดคําขอไว้ในงานเชิงตรรกะเดียวกัน ให้ตั้งค่า job_id
ของคําขอทั้งหมดเป็นค่าเดียวกัน ซึ่งจะมีประโยชน์หากคุณมีงานหรือกระบวนการเดียวที่อัปโหลด Conversion จํานวนมากโดยใช้คําขอหลายรายการ หากคุณตั้งค่า job_id
ในคําขอแต่ละรายการเป็นค่าเดียวกัน คุณจะดึงข้อมูลรายการเดียวสําหรับงานจาก job_summaries
ได้
หากคุณอนุญาตให้ Google Ads API กําหนดค่าที่ระบบสร้างขึ้นให้กับ job_id
ของคําขอแต่ละรายการแทน job_summaries
จะมีรายการแยกกันสําหรับคําขอแต่ละรายการ ซึ่งอาจทําให้การวิเคราะห์ประสิทธิภาพโดยรวมของงานทํางานได้ยากขึ้น
อัปโหลดเหตุการณ์ Conversion ออฟไลน์ทั้งหมดที่มี
อัปโหลดเหตุการณ์ Conversion ออฟไลน์ทั้งหมดที่มี รวมถึงเหตุการณ์ที่อาจไม่ได้มาจาก Google Ads เพื่อให้การรายงาน Conversion สมบูรณ์และถูกต้อง
การอัปโหลดเหตุการณ์ Conversion ทั้งหมดจะทําให้เหตุการณ์ที่ไม่ใช่จาก Google Ads เกิดข้อผิดพลาด CLICK_NOT_FOUND
เนื่องจากข้อผิดพลาดเหล่านี้เกิดขึ้นได้เมื่ออัปโหลดเหตุการณ์ Conversion ทั้งหมด UploadClickConversionsRequest
จึงมีช่อง debug_enabled
หาก
debug_enabled
เป็นfalse
หรือไม่ได้รับการตั้งค่า Google Ads API จะดำเนินการตรวจสอบอินพุตพื้นฐานเท่านั้น ข้ามการตรวจสอบการอัปโหลดในภายหลัง และแสดงผลสำเร็จแม้ว่าจะไม่พบการคลิกสําหรับuser_identifiers
ที่ระบุซึ่งเป็นค่าเริ่มต้น
หาก
debug_enabled
เป็นtrue
แสดงว่า Google Ads API จะดำเนินการตรวจสอบทั้งหมดและแสดงข้อผิดพลาดCLICK_NOT_FOUND
สําหรับClickConversion
ที่ไม่มี Conversion ของ Google Ads สําหรับuser_identifiers
ที่ระบุ
ในระหว่างการพัฒนาและการทดสอบ คุณสามารถตั้งค่า debug_enabled
เป็น true
เพื่อช่วยระบุปัญหาได้ เช่น หากคุณมีชุด Conversion และ user_identifiers
ที่คุณทราบว่ามาจาก Conversion ของ Google Ads คุณสามารถใช้การตั้งค่า true
เพื่อตรวจสอบว่าการอัปโหลดเหล่านั้นไม่ทําให้เกิดข้อผิดพลาด CLICK_NOT_FOUND
อย่างไรก็ตาม เมื่อคุณพัฒนาและทดสอบเสร็จแล้ว เราขอแนะนำให้ตั้งค่า debug_enabled
เป็น false
เพื่อหลีกเลี่ยงข้อผิดพลาดที่มากเกินไป
อย่าใช้ข้อมูลการระบุแหล่งที่มาภายนอก
อย่าตั้งค่า external_attribution_data
ใน ClickConversion
หรือระบุ conversion_action
ที่ใช้รูปแบบการระบุแหล่งที่มาภายนอก Google Ads ไม่รองรับ Conversion ที่มาจากภายนอกสำหรับการอัปโหลดโดยใช้ตัวระบุ
เตรียมข้อมูลสำหรับการอัปโหลด
ข้อมูลต่อไปนี้ต้องได้รับการแฮชโดยใช้ SHA-256 ก่อนที่จะอัปโหลด เพื่อคำนึงถึงความเป็นส่วนตัว
- อีเมล
- หมายเลขโทรศัพท์
- ชื่อ
- นามสกุล
- ที่อยู่
อย่าแฮชข้อมูลต่อไปนี้
- ประเทศ
- รัฐ
- เมือง
- รหัสไปรษณีย์
ก่อนแฮชค่าใดค่าหนึ่งดังกล่าว คุณต้องทำสิ่งต่อไปนี้เพื่อให้ผลลัพธ์การแฮชเป็นมาตรฐาน
- นําช่องว่างขึ้นต้นและต่อท้ายออก
- แปลงข้อความให้เป็นตัวพิมพ์เล็ก
- จัดรูปแบบหมายเลขโทรศัพท์ตามมาตรฐาน E164
- นําจุด (
.
) ที่อยู่ก่อนชื่อโดเมนในอีเมลgmail.com
และgooglemail.com
ออกทั้งหมด
private String normalizeAndHash(MessageDigest digest, String s)
throws UnsupportedEncodingException {
// Normalizes by first converting all characters to lowercase, then trimming spaces.
String normalized = s.toLowerCase();
// Removes leading, trailing, and intermediate spaces.
normalized = normalized.replaceAll("\\s+", "");
// Hashes the normalized string using the hashing algorithm.
byte[] hash = digest.digest(normalized.getBytes("UTF-8"));
StringBuilder result = new StringBuilder();
for (byte b : hash) {
result.append(String.format("%02x", b));
}
return result.toString();
}
/**
* Returns the result of normalizing and hashing an email address. For this use case, Google Ads
* requires removal of any '.' characters preceding {@code gmail.com} or {@code googlemail.com}.
*
* @param digest the digest to use to hash the normalized string.
* @param emailAddress the email address to normalize and hash.
*/
private String normalizeAndHashEmailAddress(MessageDigest digest, String emailAddress)
throws UnsupportedEncodingException {
String normalizedEmail = emailAddress.toLowerCase();
String[] emailParts = normalizedEmail.split("@");
if (emailParts.length > 1 && emailParts[1].matches("^(gmail|googlemail)\\.com\\s*")) {
// Removes any '.' characters from the portion of the email address before the domain if the
// domain is gmail.com or googlemail.com.
emailParts[0] = emailParts[0].replaceAll("\\.", "");
normalizedEmail = String.format("%s@%s", emailParts[0], emailParts[1]);
}
return normalizeAndHash(digest, normalizedEmail);
}
/// <summary>
/// Normalizes the email address and hashes it. For this use case, Google Ads requires
/// removal of any '.' characters preceding <code>gmail.com</code> or
/// <code>googlemail.com</code>.
/// </summary>
/// <param name="emailAddress">The email address.</param>
/// <returns>The hash code.</returns>
private string NormalizeAndHashEmailAddress(string emailAddress)
{
string normalizedEmail = emailAddress.ToLower();
string[] emailParts = normalizedEmail.Split('@');
if (emailParts.Length > 1 && (emailParts[1] == "gmail.com" ||
emailParts[1] == "googlemail.com"))
{
// Removes any '.' characters from the portion of the email address before
// the domain if the domain is gmail.com or googlemail.com.
emailParts[0] = emailParts[0].Replace(".", "");
normalizedEmail = $"{emailParts[0]}@{emailParts[1]}";
}
return NormalizeAndHash(normalizedEmail);
}
/// <summary>
/// Normalizes and hashes a string value.
/// </summary>
/// <param name="value">The value to normalize and hash.</param>
/// <returns>The normalized and hashed value.</returns>
private static string NormalizeAndHash(string value)
{
return ToSha256String(digest, ToNormalizedValue(value));
}
/// <summary>
/// Hash a string value using SHA-256 hashing algorithm.
/// </summary>
/// <param name="digest">Provides the algorithm for SHA-256.</param>
/// <param name="value">The string value (e.g. an email address) to hash.</param>
/// <returns>The hashed value.</returns>
private static string ToSha256String(SHA256 digest, string value)
{
byte[] digestBytes = digest.ComputeHash(Encoding.UTF8.GetBytes(value));
// Convert the byte array into an unhyphenated hexadecimal string.
return BitConverter.ToString(digestBytes).Replace("-", string.Empty);
}
/// <summary>
/// Removes leading and trailing whitespace and converts all characters to
/// lower case.
/// </summary>
/// <param name="value">The value to normalize.</param>
/// <returns>The normalized value.</returns>
private static string ToNormalizedValue(string value)
{
return value.Trim().ToLower();
}
private static function normalizeAndHash(string $hashAlgorithm, string $value): string
{
// Normalizes by first converting all characters to lowercase, then trimming spaces.
$normalized = strtolower($value);
// Removes leading, trailing, and intermediate spaces.
$normalized = str_replace(' ', '', $normalized);
return hash($hashAlgorithm, strtolower(trim($normalized)));
}
/**
* Returns the result of normalizing and hashing an email address. For this use case, Google
* Ads requires removal of any '.' characters preceding "gmail.com" or "googlemail.com".
*
* @param string $hashAlgorithm the hash algorithm to use
* @param string $emailAddress the email address to normalize and hash
* @return string the normalized and hashed email address
*/
private static function normalizeAndHashEmailAddress(
string $hashAlgorithm,
string $emailAddress
): string {
$normalizedEmail = strtolower($emailAddress);
$emailParts = explode("@", $normalizedEmail);
if (
count($emailParts) > 1
&& preg_match('/^(gmail|googlemail)\.com\s*/', $emailParts[1])
) {
// Removes any '.' characters from the portion of the email address before the domain
// if the domain is gmail.com or googlemail.com.
$emailParts[0] = str_replace(".", "", $emailParts[0]);
$normalizedEmail = sprintf('%s@%s', $emailParts[0], $emailParts[1]);
}
return self::normalizeAndHash($hashAlgorithm, $normalizedEmail);
}
def normalize_and_hash_email_address(email_address):
"""Returns the result of normalizing and hashing an email address.
For this use case, Google Ads requires removal of any '.' characters
preceding "gmail.com" or "googlemail.com"
Args:
email_address: An email address to normalize.
Returns:
A normalized (lowercase, removed whitespace) and SHA-265 hashed string.
"""
normalized_email = email_address.lower()
email_parts = normalized_email.split("@")
# Checks whether the domain of the email address is either "gmail.com"
# or "googlemail.com". If this regex does not match then this statement
# will evaluate to None.
is_gmail = re.match(r"^(gmail|googlemail)\.com$", email_parts[1])
# Check that there are at least two segments and the second segment
# matches the above regex expression validating the email domain name.
if len(email_parts) > 1 and is_gmail:
# Removes any '.' characters from the portion of the email address
# before the domain if the domain is gmail.com or googlemail.com.
email_parts[0] = email_parts[0].replace(".", "")
normalized_email = "@".join(email_parts)
return normalize_and_hash(normalized_email)
def normalize_and_hash(s):
"""Normalizes and hashes a string with SHA-256.
Private customer data must be hashed during upload, as described at:
https://support.google.com/google-ads/answer/7474263
Args:
s: The string to perform this operation on.
Returns:
A normalized (lowercase, removed whitespace) and SHA-256 hashed string.
"""
return hashlib.sha256(s.strip().lower().encode()).hexdigest()
# Returns the result of normalizing and then hashing the string using the
# provided digest. Private customer data must be hashed during upload, as
# described at https://support.google.com/google-ads/answer/7474263.
def normalize_and_hash(str)
# Remove leading and trailing whitespace and ensure all letters are lowercase
# before hasing.
Digest::SHA256.hexdigest(str.strip.downcase)
end
# Returns the result of normalizing and hashing an email address. For this use
# case, Google Ads requires removal of any '.' characters preceding 'gmail.com'
# or 'googlemail.com'.
def normalize_and_hash_email(email)
email_parts = email.downcase.split("@")
# Removes any '.' characters from the portion of the email address before the
# domain if the domain is gmail.com or googlemail.com.
if email_parts.last =~ /^(gmail|googlemail)\.com\s*/
email_parts[0] = email_parts[0].gsub('.', '')
end
normalize_and_hash(email_parts.join('@'))
end
sub normalize_and_hash {
my $value = shift;
# Removes leading, trailing, and intermediate spaces.
$value =~ s/\s+//g;
return sha256_hex(lc $value);
}
# Returns the result of normalizing and hashing an email address. For this use
# case, Google Ads requires removal of any '.' characters preceding 'gmail.com'
# or 'googlemail.com'.
sub normalize_and_hash_email_address {
my $email_address = shift;
my $normalized_email = lc $email_address;
my @email_parts = split('@', $normalized_email);
if (scalar @email_parts > 1
&& $email_parts[1] =~ /^(gmail|googlemail)\.com\s*/)
{
# Remove any '.' characters from the portion of the email address before the
# domain if the domain is 'gmail.com' or 'googlemail.com'.
$email_parts[0] =~ s/\.//g;
$normalized_email = sprintf '%s@%s', $email_parts[0], $email_parts[1];
}
return normalize_and_hash($normalized_email);
}
อัปโหลด Conversion ที่ปรับปรุงแล้ว
ข้อมูลโค้ดต่อไปนี้แสดงวิธีสร้างการอัปโหลด Conversion ที่มีตัวระบุสําหรับอีเมลและหมายเลขโทรศัพท์ โดยมีการใช้มาตรฐานและการแฮชตามต้องการ แนวทางปฏิบัติแนะนำคือใส่ gclid
และ
order_id
ใน Conversion หากมี
เพิ่มตัวระบุผู้ใช้ลงใน ClickConversion
// Creates an empty builder for constructing the click conversion.
ClickConversion.Builder clickConversionBuilder = ClickConversion.newBuilder();
// Extracts user email and phone from the raw data, normalizes and hashes it, then wraps it in
// UserIdentifier objects.
// Creates a separate UserIdentifier object for each. The data in this example is hardcoded, but
// in your application you might read the raw data from an input file.
// IMPORTANT: Since the identifier attribute of UserIdentifier
// (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier) is a
// oneof
// (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must set only ONE of
// hashedEmail, hashedPhoneNumber, mobileId, thirdPartyUserId, or addressInfo. Setting more
// than one of these attributes on the same UserIdentifier will clear all the other members
// of the oneof. For example, the following code is INCORRECT and will result in a
// UserIdentifier with ONLY a hashedPhoneNumber.
//
// UserIdentifier incorrectlyPopulatedUserIdentifier =
// UserIdentifier.newBuilder()
// .setHashedEmail("...")
// .setHashedPhoneNumber("...")
// .build();
ImmutableMap.Builder<String, String> rawRecordBuilder =
ImmutableMap.<String, String>builder()
.put("email", "alex.2@example.com")
// Phone number to be converted to E.164 format, with a leading '+' as required.
.put("phone", "+1 800 5550102")
// This example lets you put conversion details as arguments, but in reality you might
// store this data alongside other user data, so we include it in this sample user
// record.
.put("conversionActionId", Long.toString(conversionActionId))
.put("conversionDateTime", conversionDateTime)
.put("conversionValue", Double.toString(conversionValue))
.put("currencyCode", "USD");
// Adds entries for the optional fields.
if (orderId != null) {
rawRecordBuilder.put("orderId", orderId);
}
if (gclid != null) {
rawRecordBuilder.put("gclid", gclid);
}
if (adUserDataConsent != null) {
rawRecordBuilder.put("adUserDataConsent", adUserDataConsent.name());
}
// Builds the map representing the record.
Map<String, String> rawRecord = rawRecordBuilder.build();
// Creates a SHA256 message digest for hashing user identifiers in a privacy-safe way, as
// described at https://support.google.com/google-ads/answer/9888656.
MessageDigest sha256Digest = MessageDigest.getInstance("SHA-256");
// Creates a list for the user identifiers.
List<UserIdentifier> userIdentifiers = new ArrayList<>();
// Creates a user identifier using the hashed email address, using the normalize and hash method
// specifically for email addresses.
UserIdentifier emailIdentifier =
UserIdentifier.newBuilder()
// Optional: specify the user identifier source.
.setUserIdentifierSource(UserIdentifierSource.FIRST_PARTY)
// Uses the normalize and hash method specifically for email addresses.
.setHashedEmail(normalizeAndHashEmailAddress(sha256Digest, rawRecord.get("email")))
.build();
userIdentifiers.add(emailIdentifier);
// Creates a user identifier using normalized and hashed phone info.
UserIdentifier hashedPhoneNumberIdentifier =
UserIdentifier.newBuilder()
.setHashedPhoneNumber(normalizeAndHash(sha256Digest, rawRecord.get("phone")))
.build();
// Adds the hashed phone number identifier to the UserData object's list.
userIdentifiers.add(hashedPhoneNumberIdentifier);
// Adds the user identifiers to the conversion.
clickConversionBuilder.addAllUserIdentifiers(userIdentifiers);
// Adds a user identifier using the hashed email address, using the normalize
// and hash method specifically for email addresses.
clickConversion.UserIdentifiers.Add(new UserIdentifier()
{
HashedEmail = NormalizeAndHashEmailAddress("alex.2@example.com"),
// Optional: Specifies the user identifier source.
UserIdentifierSource = UserIdentifierSource.FirstParty
});
// Adds a user identifier using normalized and hashed phone info.
clickConversion.UserIdentifiers.Add(new UserIdentifier()
{
HashedPhoneNumber = NormalizeAndHash("+1 800 5550102"),
// Optional: Specifies the user identifier source.
UserIdentifierSource = UserIdentifierSource.FirstParty
});
// Adds a user identifier with all the required mailing address elements.
clickConversion.UserIdentifiers.Add(new UserIdentifier()
{
AddressInfo = new OfflineUserAddressInfo()
{
// FirstName and LastName must be normalized and hashed.
HashedFirstName = NormalizeAndHash("Alex"),
HashedLastName = NormalizeAndHash("Quinn"),
// CountryCode and PostalCode are sent in plain text.
CountryCode = "US",
PostalCode = "94045"
}
});
// Creates a click conversion with the specified attributes.
$clickConversion = new ClickConversion();
// Extract user email and phone from the raw data, normalize and hash it, then wrap it in
// UserIdentifier objects. Creates a separate UserIdentifier object for each.
// The data in this example is hardcoded, but in your application you might read the raw
// data from an input file.
// IMPORTANT: Since the identifier attribute of UserIdentifier
// (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier) is a
// oneof
// (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must set only ONE
// of hashedEmail, hashedPhoneNumber, mobileId, thirdPartyUserId, or addressInfo. Setting
// more than one of these attributes on the same UserIdentifier will clear all the other
// members of the oneof. For example, the following code is INCORRECT and will result in a
// UserIdentifier with ONLY a hashedPhoneNumber.
//
// $incorrectlyPopulatedUserIdentifier = new UserIdentifier([
// 'hashed_email' => '...',
// 'hashed_phone_number' => '...'
// ]);
$rawRecord = [
// Email address that includes a period (.) before the Gmail domain.
'email' => 'alex.2@example.com',
// Phone number to be converted to E.164 format, with a leading '+' as required.
'phone' => '+1 800 5550102',
// This example lets you input conversion details as arguments, but in reality you might
// store this data alongside other user data, so we include it in this sample user
// record.
'orderId' => $orderId,
'gclid' => $gclid,
'conversionActionId' => $conversionActionId,
'conversionDateTime' => $conversionDateTime,
'conversionValue' => $conversionValue,
'currencyCode' => 'USD',
'adUserDataConsent' => $adUserDataConsent
];
// Creates a list for the user identifiers.
$userIdentifiers = [];
// Uses the SHA-256 hash algorithm for hashing user identifiers in a privacy-safe way, as
// described at https://support.google.com/google-ads/answer/9888656.
$hashAlgorithm = "sha256";
// Creates a user identifier using the hashed email address, using the normalize and hash
// method specifically for email addresses.
$emailIdentifier = new UserIdentifier([
// Uses the normalize and hash method specifically for email addresses.
'hashed_email' => self::normalizeAndHashEmailAddress(
$hashAlgorithm,
$rawRecord['email']
),
// Optional: Specifies the user identifier source.
'user_identifier_source' => UserIdentifierSource::FIRST_PARTY
]);
$userIdentifiers[] = $emailIdentifier;
// Checks if the record has a phone number, and if so, adds a UserIdentifier for it.
if (array_key_exists('phone', $rawRecord)) {
$hashedPhoneNumberIdentifier = new UserIdentifier([
'hashed_phone_number' => self::normalizeAndHash(
$hashAlgorithm,
$rawRecord['phone'],
true
)
]);
// Adds the hashed email identifier to the user identifiers list.
$userIdentifiers[] = $hashedPhoneNumberIdentifier;
}
// Adds the user identifiers to the conversion.
$clickConversion->setUserIdentifiers($userIdentifiers);
# Extract user email and phone from the raw data, normalize and hash it,
# then wrap it in UserIdentifier objects. Create a separate UserIdentifier
# object for each. The data in this example is hardcoded, but in your
# application you might read the raw data from an input file.
# IMPORTANT: Since the identifier attribute of UserIdentifier
# (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier)
# is a oneof
# (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must
# set only ONE of hashed_email, hashed_phone_number, mobile_id,
# third_party_user_id, or address_info. Setting more than one of these
# attributes on the same UserIdentifier will clear all the other members of
# the oneof. For example, the following code is INCORRECT and will result in
# a UserIdentifier with ONLY a hashed_phone_number:
#
# incorrectly_populated_user_identifier = client.get_type("UserIdentifier")
# incorrectly_populated_user_identifier.hashed_email = "...""
# incorrectly_populated_user_identifier.hashed_phone_number = "...""
raw_record = {
# Email address that includes a period (.) before the Gmail domain.
"email": "alex.2@example.com",
# Phone number to be converted to E.164 format, with a leading '+' as
# required.
"phone": "+1 800 5550102",
# This example lets you input conversion details as arguments,
# but in reality you might store this data alongside other user data,
# so we include it in this sample user record.
"order_id": order_id,
"gclid": gclid,
"conversion_action_id": conversion_action_id,
"conversion_date_time": conversion_date_time,
"conversion_value": conversion_value,
"currency_code": "USD",
"ad_user_data_consent": ad_user_data_consent,
}
# Constructs the click conversion.
click_conversion = client.get_type("ClickConversion")
# Creates a user identifier using the hashed email address, using the
# normalize and hash method specifically for email addresses.
email_identifier = client.get_type("UserIdentifier")
# Optional: Specifies the user identifier source.
email_identifier.user_identifier_source = (
client.enums.UserIdentifierSourceEnum.FIRST_PARTY
)
# Uses the normalize and hash method specifically for email addresses.
email_identifier.hashed_phone_number = normalize_and_hash_email_address(
raw_record["email"]
)
# Adds the user identifier to the conversion.
click_conversion.user_identifiers.append(email_identifier)
# Checks if the record has a phone number, and if so, adds a UserIdentifier
# for it.
if raw_record.get("phone") is not None:
phone_identifier = client.get_type("UserIdentifier")
phone_identifier.hashed_phone_number = normalize_and_hash(
raw_record["phone"]
)
# Adds the phone identifier to the conversion adjustment.
click_conversion.user_identifiers.append(phone_identifier)
# Extract user email and phone from the raw data, normalize and hash it,
# then wrap it in UserIdentifier objects. Create a separate UserIdentifier
# object for each. The data in this example is hardcoded, but in your
# application you might read the raw data from an input file.
# IMPORTANT: Since the identifier attribute of UserIdentifier
# (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier)
# is a oneof
# (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must
# set only ONE of hashed_email, hashed_phone_number, mobile_id,
# third_party_user_id, or address_info. Setting more than one of these
# attributes on the same UserIdentifier will clear all the other members of
# the oneof. For example, the following code is INCORRECT and will result in
# a UserIdentifier with ONLY a hashed_phone_number:
#
# incorrectly_populated_user_identifier.hashed_email = "...""
# incorrectly_populated_user_identifier.hashed_phone_number = "...""
raw_record = {
# Email address that includes a period (.) before the Gmail domain.
"email" => "alex.2@example.com",
# Phone number to be converted to E.164 format, with a leading '+' as
# required.
"phone" => "+1 800 5550102",
# This example lets you input conversion details as arguments,
# but in reality you might store this data alongside other user data,
# so we include it in this sample user record.
"order_id" => order_id,
"gclid" => gclid,
"conversion_action_id" => conversion_action_id,
"conversion_date_time" => conversion_date_time,
"conversion_value" => conversion_value,
"currency_code" => "USD",
"ad_user_data_consent" => ad_user_data_consent,
}
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
# 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_phone_number = 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_email(raw_record["phone"])
end
end
end
# Create an empty click conversion.
my $click_conversion =
Google::Ads::GoogleAds::V18::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::V18::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::V18::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::V18::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;
เพิ่มรายละเอียด Conversion ลงใน ClickConversion
// Adds details of the conversion.
clickConversionBuilder.setConversionAction(
ResourceNames.conversionAction(
customerId, Long.parseLong(rawRecord.get("conversionActionId"))));
clickConversionBuilder.setConversionDateTime(rawRecord.get("conversionDateTime"));
clickConversionBuilder.setConversionValue(Double.parseDouble(rawRecord.get("conversionValue")));
clickConversionBuilder.setCurrencyCode(rawRecord.get("currencyCode"));
// Sets the order ID if provided.
if (rawRecord.containsKey("orderId")) {
clickConversionBuilder.setOrderId(rawRecord.get("orderId"));
}
// Sets the Google click ID (gclid) if provided.
if (rawRecord.containsKey("gclid")) {
clickConversionBuilder.setGclid(rawRecord.get("gclid"));
}
// Sets the consent information, if provided.
if (rawRecord.containsKey("adUserDataConsent")) {
// Specifies whether user consent was obtained for the data you are uploading. See
// https://www.google.com/about/company/user-consent-policy for details.
clickConversionBuilder.setConsent(
Consent.newBuilder()
.setAdUserData(ConsentStatus.valueOf(rawRecord.get("adUserDataConsent"))));
}
// Calls build to build the conversion.
ClickConversion clickConversion = clickConversionBuilder.build();
// Adds details of the conversion.
clickConversion.ConversionAction =
ResourceNames.ConversionAction(customerId, conversionActionId);
clickConversion.ConversionDateTime = conversionDateTime;
clickConversion.ConversionValue = conversionValue;
clickConversion.CurrencyCode = "USD";
// Sets the order ID if provided.
if (!string.IsNullOrEmpty(orderId))
{
clickConversion.OrderId = orderId;
}
// Sets the Google click ID (gclid) if provided.
if (!string.IsNullOrEmpty(gclid))
{
clickConversion.Gclid = gclid;
}
// Adds details of the conversion.
$clickConversion->setConversionAction(
ResourceNames::forConversionAction($customerId, $rawRecord['conversionActionId'])
);
$clickConversion->setConversionDateTime($rawRecord['conversionDateTime']);
$clickConversion->setConversionValue($rawRecord['conversionValue']);
$clickConversion->setCurrencyCode($rawRecord['currencyCode']);
// Sets the order ID if provided.
if (!empty($rawRecord['orderId'])) {
$clickConversion->setOrderId($rawRecord['orderId']);
}
// Sets the Google click ID (gclid) if provided.
if (!empty($rawRecord['gclid'])) {
$clickConversion->setGclid($rawRecord['gclid']);
}
// Sets the ad user data consent if provided.
if (!empty($rawRecord['adUserDataConsent'])) {
// Specifies whether user consent was obtained for the data you are uploading. See
// https://www.google.com/about/company/user-consent-policy for details.
$clickConversion->setConsent(
new Consent(['ad_user_data' => $rawRecord['adUserDataConsent']])
);
}
# Add details of the conversion.
# Gets the conversion action resource name.
conversion_action_service = client.get_service("ConversionActionService")
click_conversion.conversion_action = (
conversion_action_service.conversion_action_path(
customer_id, raw_record["conversion_action_id"]
)
)
click_conversion.conversion_date_time = raw_record["conversion_date_time"]
click_conversion.conversion_value = raw_record["conversion_value"]
click_conversion.currency_code = raw_record["currency_code"]
# Sets the order ID if provided.
if raw_record.get("order_id"):
click_conversion.order_id = raw_record["order_id"]
# Sets the gclid if provided.
if raw_record.get("gclid"):
click_conversion.gclid = raw_record["gclid"]
# Specifies whether user consent was obtained for the data you are
# uploading. For more details, see:
# https://www.google.com/about/company/user-consent-policy
if raw_record["ad_user_data_consent"]:
click_conversion.consent.ad_user_data = client.enums.ConsentStatusEnum[
raw_record["ad_user_data_consent"]
]
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
# Add details of the conversion.
$click_conversion->{conversionAction} =
Google::Ads::GoogleAds::V18::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::V18::Common::Consent->new({
adUserData => $raw_record->{adUserDataConsent}});
}
อัปโหลด ClickConversion
// Creates the conversion upload service client.
try (ConversionUploadServiceClient conversionUploadServiceClient =
googleAdsClient.getLatestVersion().createConversionUploadServiceClient()) {
// Uploads the click conversion. Partial failure should always be set to true.
// NOTE: This request contains a single conversion as a demonstration. However, if you have
// multiple conversions to upload, it's best to upload multiple conversions per request
// instead of sending a separate request per conversion. See the following for per-request
// limits:
// https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service
UploadClickConversionsResponse response =
conversionUploadServiceClient.uploadClickConversions(
UploadClickConversionsRequest.newBuilder()
.setCustomerId(Long.toString(customerId))
.addConversions(clickConversion)
// Enables partial failure (must be true).
.setPartialFailure(true)
.build());
// Uploads the click conversion. Partial failure should always be set to true.
// NOTE: This request contains a single conversion as a demonstration.
// However, if you have multiple conversions to upload, it's best to upload multiple
// conversions per request instead of sending a separate request per conversion.
// See the following for per-request limits:
// https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload
UploadClickConversionsResponse response =
conversionUploadService.UploadClickConversions(
new UploadClickConversionsRequest()
{
CustomerId = customerId.ToString(),
Conversions = { clickConversion },
// Enables partial failure (must be true).
PartialFailure = true
});
// Issues a request to upload the click conversion.
$conversionUploadServiceClient = $googleAdsClient->getConversionUploadServiceClient();
// NOTE: This request contains a single conversion as a demonstration. However, if you have
// multiple conversions to upload, it's best to upload multiple conversions per request
// instead of sending a separate request per conversion. See the following for per-request
// limits:
// https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service
$response = $conversionUploadServiceClient->uploadClickConversions(
// Enables partial failure (must be true).
UploadClickConversionsRequest::build($customerId, [$clickConversion], true)
);
# Creates the conversion upload service client.
conversion_upload_service = client.get_service("ConversionUploadService")
# Uploads the click conversion. Partial failure should always be set to
# True.
# NOTE: This request only uploads a single conversion, but if you have
# multiple conversions to upload, it's most efficient to upload them in a
# single request. See the following for per-request limits for reference:
# https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service
response = conversion_upload_service.upload_click_conversions(
customer_id=customer_id,
conversions=[click_conversion],
# Enables partial failure (must be true).
partial_failure=True,
)
response = client.service.conversion_upload.upload_click_conversions(
customer_id: customer_id,
conversions: [click_conversion],
# Partial failure must be true.
partial_failure: true,
)
if response.partial_failure_error
puts "Partial failure encountered: #{response.partial_failure_error.message}"
else
result = response.results.first
puts "Uploaded click conversion that happened at #{result.conversion_date_time} " \
"to #{result.conversion_action}."
end
# Upload the click conversion. Partial failure should always be set to true.
#
# NOTE: This request contains a single conversion as a demonstration.
# However, if you have multiple conversions to upload, it's best to
# upload multiple conversions per request instead of sending a separate
# request per conversion. See the following for per-request limits:
# https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service
my $response =
$api_client->ConversionUploadService()->upload_click_conversions({
customerId => $customer_id,
conversions => [$click_conversion],
# Enable partial failure (must be true).
partialFailure => "true"
});
ตรวจสอบการอัปโหลด
ใช้การวินิจฉัยข้อมูลออฟไลน์เพื่อตรวจสอบประสิทธิภาพโดยรวมของการอัปโหลดล่าสุด โปรดทราบว่าการอัปโหลดที่สำเร็จไม่ได้หมายความว่าการอัปโหลดนั้นๆ มีการจับคู่
เมื่อรายงานเมตริก Conversion สําหรับแคมเปญ โปรดดูการแมปเมตริกอินเทอร์เฟซผู้ใช้เพื่อเชื่อมโยงเมตริก UI ของ Google Ads กับช่องการรายงาน Google Ads API นอกจากนี้ คุณยังค้นหาแหล่งข้อมูล conversion_action
เพื่อดูจํานวน Conversion ทั้งหมดและมูลค่า Conversion ทั้งหมดสําหรับการกระทําที่ถือเป็น Conversion หนึ่งๆ ได้ด้วย
ขั้นตอนถัดไป
หากต้องการปรับเปลี่ยน Conversion โปรดดูคำแนะนำอัปโหลดการปรับ Conversion
ดูคําแนะนําในการแก้ปัญหา Conversion ที่ปรับปรุงแล้วสําหรับการผสานรวมโอกาสในการขายต่อในคู่มือการแก้ปัญหา