ה-API של ההמרות אופליין ב-CM360 תומך בשיפור התגים מבוססי האתר המרות עם מזהי משתמשים.
ההגדרה המומלצת
- צריך לאשר את התנאים של התכונה 'המרות משופרות' שירות ל-Floodlight ב-CM360.
- משתמשים במזהה התאמה כדי למנוע את ההצגה של מודעות באתרים שלכם.
- מתעדים המרות של Floodlight שמתרחשות באתר שלכם. חשוב להקליט
את כל השדות הבאים, כי הם שדות חובה בקריאות הבאות ל-API:
matchId
ordinal
timestampMicros
floodlightActivityId
floodlightConfigurationId
quantity
value
- אחרי 90 דקות מאז שהתג אונליין תיעד את ההמרה,
התקשר אל
conversions.batchupdate
כדי לשפר המרות עם מזהי משתמשים.- מזהי משתמשים צריכים להיות בפורמט מגובב (hashed) ולהוסיף אותם אל
השדה
userIdentifiers
באובייקטים של Conversion. - יש לציין כמות וערך.
אפשר גם לשנות את הכמות והערך של ההמרה
אותה קריאה ל-
conversions.batchupdate
, או לספק את הכמות המקורית עם ערך מסוים. - כל אצוות של הוספות ועדכונים יכולה להכיל שילוב של הצלחות
כשלים. צריך לנסות שוב
NOT_FOUND
כשלים למקרה שמשך הזמן ארוך יותר העיכוב הרגיל בעיבוד ההמרות עד 6 שעות. - צריך לשפר את ההמרות באמצעות מזהי משתמשים במהלך 24 השעות שאחרי הם מתועדים באמצעות תגים מקוונים.
- מזהי משתמשים צריכים להיות בפורמט מגובב (hashed) ולהוסיף אותם אל
השדה
נירמול וגיבוב (hashing)
כדי להגן על הפרטיות, כתובות אימייל, מספרי טלפון, שמות פרטיים, השמות של הרחובות צריכים לעבור גיבוב (hashing) של הרחובות באמצעות האלגוריתם SHA-256 לפני בתהליך העלאה. כדי לבצע סטנדרטיזציה של תוצאות הגיבוב, לפני הגיבוב מהערכים האלה, צריך:
- מסירים רווחים לבנים בתחילת הטקסט או בסופו.
- ממירים את הטקסט לאותיות קטנות.
- מזינים מספרי טלפון בפורמט שתואם לתקן E164
מסירים את כל הנקודות (.) שלפני שם הדומיין ב-
gmail.com
ו-googlemail.com
כתובות אימייל.
C#
/// <summary>
/// Normalizes the email address and hashes it. For this use case, Campaign Manager 360
/// requires removal of any '.' characters preceding <code>gmail.com</code> or
/// <code>googlemail.com</code>.
/// </summary>
/// <param name="emailAddress">The email address.</param>
/// <returns>The hash code.</returns>
private string NormalizeAndHashEmailAddress(string emailAddress)
{
string normalizedEmail = emailAddress.ToLower();
string[] emailParts = normalizedEmail.Split('@');
if (emailParts.Length > 1 && (emailParts[1] == "gmail.com" ||
emailParts[1] == "googlemail.com"))
{
// Removes any '.' characters from the portion of the email address before
// the domain if the domain is gmail.com or googlemail.com.
emailParts[0] = emailParts[0].Replace(".", "");
normalizedEmail = $"{emailParts[0]}@{emailParts[1]}";
}
return NormalizeAndHash(normalizedEmail);
}
/// <summary>
/// Normalizes and hashes a string value.
/// </summary>
/// <param name="value">The value to normalize and hash.</param>
/// <returns>The normalized and hashed value.</returns>
private static string NormalizeAndHash(string value)
{
return ToSha256String(digest, ToNormalizedValue(value));
}
/// <summary>
/// Hash a string value using SHA-256 hashing algorithm.
/// </summary>
/// <param name="digest">Provides the algorithm for SHA-256.</param>
/// <param name="value">The string value (e.g. an email address) to hash.</param>
/// <returns>The hashed value.</returns>
private static string ToSha256String(SHA256 digest, string value)
{
byte[] digestBytes = digest.ComputeHash(Encoding.UTF8.GetBytes(value));
// Convert the byte array into an unhyphenated hexadecimal string.
return BitConverter.ToString(digestBytes).Replace("-", string.Empty);
}
/// <summary>
/// Removes leading and trailing whitespace and converts all characters to
/// lower case.
/// </summary>
/// <param name="value">The value to normalize.</param>
/// <returns>The normalized value.</returns>
private static string ToNormalizedValue(string value)
{
return value.Trim().ToLower();
}
Java
private String normalizeAndHash(MessageDigest digest, String s)
throws UnsupportedEncodingException {
// Normalizes by removing leading and trailing whitespace and converting all characters to
// lower case.
String normalized = s.trim().toLowerCase();
// Hashes the normalized string using the hashing algorithm.
byte[] hash = digest.digest(normalized.getBytes("UTF-8"));
StringBuilder result = new StringBuilder();
for (byte b : hash) {
result.append(String.format("%02x", b));
}
return result.toString();
}
/**
* Returns the result of normalizing and hashing an email address. For this use case, Campaign Manager 360
* requires removal of any '.' characters preceding {@code gmail.com} or {@code googlemail.com}.
*
* @param digest the digest to use to hash the normalized string.
* @param emailAddress the email address to normalize and hash.
*/
private String normalizeAndHashEmailAddress(MessageDigest digest, String emailAddress)
throws UnsupportedEncodingException {
String normalizedEmail = emailAddress.toLowerCase();
String[] emailParts = normalizedEmail.split("@");
if (emailParts.length > 1 && emailParts[1].matches("^(gmail|googlemail)\\.com\\s*")) {
// Removes any '.' characters from the portion of the email address before the domain if the
// domain is gmail.com or googlemail.com.
emailParts[0] = emailParts[0].replaceAll("\\.", "");
normalizedEmail = String.format("%s@%s", emailParts[0], emailParts[1]);
}
return normalizeAndHash(digest, normalizedEmail);
}
PHP
private static function normalizeAndHash(string $hashAlgorithm, string $value): string
{
return hash($hashAlgorithm, strtolower(trim($value)));
}
/**
* Returns the result of normalizing and hashing an email address. For this use case, Campaign
* Manager 360 requires removal of any '.' characters preceding "gmail.com" or "googlemail.com".
*
* @param string $hashAlgorithm the hash algorithm to use
* @param string $emailAddress the email address to normalize and hash
* @return string the normalized and hashed email address
*/
private static function normalizeAndHashEmailAddress(
string $hashAlgorithm,
string $emailAddress
): string {
$normalizedEmail = strtolower($emailAddress);
$emailParts = explode("@", $normalizedEmail);
if (
count($emailParts) > 1
&& preg_match('/^(gmail|googlemail)\.com\s*/', $emailParts[1])
) {
// Removes any '.' characters from the portion of the email address before the domain
// if the domain is gmail.com or googlemail.com.
$emailParts[0] = str_replace(".", "", $emailParts[0]);
$normalizedEmail = sprintf('%s@%s', $emailParts[0], $emailParts[1]);
}
return self::normalizeAndHash($hashAlgorithm, $normalizedEmail);
}
Python
def normalize_and_hash_email_address(email_address):
"""Returns the result of normalizing and hashing an email address.
For this use case, Campaign Manager 360 requires removal of any '.'
characters preceding "gmail.com" or "googlemail.com"
Args:
email_address: An email address to normalize.
Returns:
A normalized (lowercase, removed whitespace) and SHA-265 hashed string.
"""
normalized_email = email_address.lower()
email_parts = normalized_email.split("@")
# Checks whether the domain of the email address is either "gmail.com"
# or "googlemail.com". If this regex does not match then this statement
# will evaluate to None.
is_gmail = re.match(r"^(gmail|googlemail)\.com$", email_parts[1])
# Check that there are at least two segments and the second segment
# matches the above regex expression validating the email domain name.
if len(email_parts) > 1 and is_gmail:
# Removes any '.' characters from the portion of the email address
# before the domain if the domain is gmail.com or googlemail.com.
email_parts[0] = email_parts[0].replace(".", "")
normalized_email = "@".join(email_parts)
return normalize_and_hash(normalized_email)
def normalize_and_hash(s):
"""Normalizes and hashes a string with SHA-256.
Private customer data must be hashed during upload, as described at:
https://support.google.com/google-ads/answer/7474263
Args:
s: The string to perform this operation on.
Returns:
A normalized (lowercase, removed whitespace) and SHA-256 hashed string.
"""
return hashlib.sha256(s.strip().lower().encode()).hexdigest()
Ruby
# Returns the result of normalizing and then hashing the string using the
# provided digest. Private customer data must be hashed during upload, as
# described at https://support.google.com/google-ads/answer/7474263.
def normalize_and_hash(str)
# Remove leading and trailing whitespace and ensure all letters are lowercase
# before hasing.
Digest::SHA256.hexdigest(str.strip.downcase)
end
# Returns the result of normalizing and hashing an email address. For this use
# case, Campaign Manager 360 requires removal of any '.' characters preceding
# 'gmail.com' or 'googlemail.com'.
def normalize_and_hash_email(email)
email_parts = email.downcase.split("@")
# Removes any '.' characters from the portion of the email address before the
# domain if the domain is gmail.com or googlemail.com.
if email_parts.last =~ /^(gmail|googlemail)\.com\s*/
email_parts[0] = email_parts[0].gsub('.', '')
end
normalize_and_hash(email_parts.join('@'))
end
הוספה של מזהי משתמשים להמרות
קודם כול צריך להכין אובייקט Conversion
להעלאה או
לערוך כרגיל ואז לצרף מזהה משתמש באופן הבא:
{
"matchId": "my-match-id-846513278",
"ordinal": "my-ordinal-12345678512",
"quantity": 1,
"value": 104.23,
"timestampMicros": 1656950400000000,
"floodlightConfigurationId": 99999,
"floodlightActivityId": 8888,
"userIdentifiers": [
{ "hashedEmail": "0c7e6a405862e402eb76a70f8a26fc732d07c32931e9fae9ab1582911d2e8a3b" },
{ "hashedPhoneNumber": "1fb1f420856780a29719b994c8764b81770d79f97e2e1861ba938a7a5a15dfb9" },
{
"addressInfo": {
"hashedFirstName": "81f8f6dde88365f3928796ec7aa53f72820b06db8664f5fe76a7eb13e24546a2",
"hashedLastName": "799ef92a11af918e3fb741df42934f3b568ed2d93ac1df74f1b8d41a27932a6f",
"hashedStreetAddress": "22b7e2d69b91e0ef4a88e81a73d897b92fd9c93ccfbe0a860f77db16c26f662e",
"city": "seattle",
"state": "washington",
"countryCode": "US",
"postalCode": "98101"
}
}
]
}
תגובה מוצלחת אמורה להיראות כך:
{
"hasFailures": false,
"status": [
{
"conversion": {
"floodlightConfigurationId": 99999,
"floodlightActivityId": 8888,
"timestampMicros": 1656950400000000,
"value": 104.23,
"quantity": 1,
"ordinal": "my-ordinal-12345678512",
"matchId": "my-match-id-846513278",
"userIdentifiers": [
{ "hashedEmail": "0c7e6a405862e402eb76a70f8a26fc732d07c32931e9fae9ab1582911d2e8a3b" },
{ "hashedPhoneNumber": "1fb1f420856780a29719b994c8764b81770d79f97e2e1861ba938a7a5a15dfb9" },
{
"addressInfo": {
"hashedFirstName": "81f8f6dde88365f3928796ec7aa53f72820b06db8664f5fe76a7eb13e24546a2",
"hashedLastName": "799ef92a11af918e3fb741df42934f3b568ed2d93ac1df74f1b8d41a27932a6f",
"hashedStreetAddress": "22b7e2d69b91e0ef4a88e81a73d897b92fd9c93ccfbe0a860f77db16c26f662e",
"city": "seattle",
"state": "washington",
"countryCode": "US",
"postalCode": "98101"
}
}
],
"kind": "dfareporting#conversion"
},
"kind": "dfareporting#conversionStatus"
}
]
}
שגיאות נפוצות
הנה כמה שגיאות שעשויות להופיע במהלך שיפור המרה עם משתמש מזהים:
- השדה hashed_X לא עבר גיבוב (hash) תקין באלגוריתם SHA-256
- כל השדות עם גיבוב (hash) מקבלים רק גיבובי SHA-256 בקידוד הקסדצימליים.
- האורך של שדה המדינה של קוד המדינה (country_code) שגוי
country_code
חייב להיות באורך של 2 אותיות בדיוק.- ההגדרה של Floodlight לא חתמה על התנאים וההגבלות של ההמרות המשופרות
- התנאים וההגבלות של המרות משופרות לא אושרו עבור מזהה ההגדרה ב-Floodlight של הבקשה.
- ציינת יותר מחמישה מזהי user_identifier
- המרה יכולה לכלול עד 5 מזהי משתמש.
שאלות נפוצות
- למה מומלץ להשתמש במזהה התאמה?
- עריכות שמבוססות על מספר הקליק לא כוללות המרות שלא הובילו לקליק ומגבלות את הערך של שילוב המרות משופרות.
- למה צריך לתעד כמות וערך?
- צריך להזין כמות וערך ב-CM360 אופליין Conversions API מוגדר.
- האם צריך לקבל את חותמת הזמן המדויקת של מיקרו-שנייה ש-Google תיעדה כדי לערוך המרה אונליין שמבוססת על תגים?
- לעריכות שמבוססות על מזהה התאמה, ה-API מקבל עכשיו עריכות כל עוד חותמת הזמן שצוינה בבקשה היא דקה אחת לכל היותר מהתאריך ש-Google תיעדה timestamp.
- למה צריך להמתין 90 דקות אחרי שהמרה מתועדת באמצעות תג אונליין כדי לשפר אותה?
- עשויות לחלוף עד 90 דקות לפני שההמרה אונליין תתווסף לאינדקס על ידי API ולהיות זמינים לביצוע עריכות.
- למה כדאי לשים לב בתגובת ה-API?
- גם כש-CM360 Conversion API מחזיר תגובה מוצלחת, חלק
ייתכן שההעלאה או העדכון של המרות בודדות נכשלה. כדאי לבדוק את
שדות
ConversionStatus
בודדים לכשלים:- אפשר לנסות שוב בעוד
NOT_FOUND
כשלים, עד 6 שעות במקרה הצורך יש עיכוב ארוך מהרגיל בעיבוד ההמרות. ראו גם שאלות נפוצות שמסבירות למה שגיאות מסוגNOT_FOUND
יכולות להישאר יותר מ-6 שעות. - אין לנסות שוב לבצע שגיאות מסוג
INVALID_ARGUMENT
ו-PERMISSION_DENIED
.
- אפשר לנסות שוב בעוד