Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@
* https://support.google.com/adspolicy/answer/6299717.
* <li>It may take up to several hours for the list to be populated with members.
* <li>Email addresses must be associated with a Google account.
* <li>For privacy purposes, the user list size will show as zero until the list has at least
* 100 members. After that, the size will be rounded to the two most significant digits.
* <li>For privacy purposes, the user list size will show as zero until the list has at least 100
* members. After that, the size will be rounded to the two most significant digits.
* </ul>
*/
public class AddCustomerMatchUserList {
Expand Down Expand Up @@ -423,22 +423,22 @@ private List<OfflineUserDataJobOperation> buildOfflineUserDataJobOperations()
ImmutableMap.<String, String>builder()
.put("email", "dana@example.com")
// Phone number to be converted to E.164 format, with a leading '+' as required. This
// includes whitespace that will be removed later.
.put("phone", "+1 800 5550101")
// includes whitespace, dashes, and parentheses that will be removed later.
.put("phone", "+1 (800) 555-0101")
.build();
// The second user data has an email address, a mailing address, and a phone number.
Map<String, String> rawRecord2 =
ImmutableMap.<String, String>builder()
// Email address that includes a period (.) before the domain.
.put("email", "alex.2@example.com")
// Email address that includes a period (.) and plus (+) suffix before the Gmail domain.
.put("email", "alex.2+myalias@gmail.com")
// Address that includes all four required elements: first name, last name, country
// code, and postal code.
.put("firstName", "Alex")
.put("lastName", "Quinn")
.put("countryCode", "US")
.put("postalCode", "94045")
// Phone number to be converted to E.164 format, with a leading '+' as required.
.put("phone", "+1 800 5550102")
.put("phone", "+1 800-555-0102")
.build();
// The third user data only has an email address.
Map<String, String> rawRecord3 =
Expand Down Expand Up @@ -479,7 +479,7 @@ private List<OfflineUserDataJobOperation> buildOfflineUserDataJobOperations()
if (rawRecord.containsKey("email")) {
UserIdentifier hashedEmailIdentifier =
UserIdentifier.newBuilder()
.setHashedEmail(normalizeAndHash(sha256Digest, rawRecord.get("email"), true))
.setHashedEmail(normalizeAndHashEmailAddress(sha256Digest, rawRecord.get("email")))
.build();
// Adds the hashed email identifier to the UserData object's list.
userDataBuilder.addUserIdentifiers(hashedEmailIdentifier);
Expand All @@ -489,7 +489,8 @@ private List<OfflineUserDataJobOperation> buildOfflineUserDataJobOperations()
if (rawRecord.containsKey("phone")) {
UserIdentifier hashedPhoneNumberIdentifier =
UserIdentifier.newBuilder()
.setHashedPhoneNumber(normalizeAndHash(sha256Digest, rawRecord.get("phone"), true))
.setHashedPhoneNumber(
normalizeAndHashPhoneNumber(sha256Digest, rawRecord.get("phone")))
.build();
// Adds the hashed phone number identifier to the UserData object's list.
userDataBuilder.addUserIdentifiers(hashedPhoneNumberIdentifier);
Expand Down Expand Up @@ -578,6 +579,50 @@ private String normalizeAndHash(MessageDigest digest, String s, boolean trimInte
return result.toString();
}

/**
* Returns the result of normalizing and hashing an email address. For this use case, Google Ads
* requires removal of any '.' characters or trailing '+' and characters that follow it from the
* username portion of the email address if the domain is {@code gmail.com} or {@code
* googlemail.com}.
*
* @param digest the digest to use to hash the normalized string.
* @param emailAddress the email address to normalize and hash.
*/
private String normalizeAndHashEmailAddress(MessageDigest digest, String emailAddress)
throws UnsupportedEncodingException {
// Removes all whitespace (leading, trailing, and intermediate) from the email address.
String normalizedEmail = emailAddress.toLowerCase().replaceAll("\\s+", "");
String[] emailParts = normalizedEmail.split("@", 2);
if (emailParts.length == 2 && emailParts[1].matches("^(gmail|googlemail)\\.com$")) {
// Removes any '.' characters from the portion of the email address before the domain if the
// domain is gmail.com or googlemail.com.
emailParts[0] = emailParts[0].replaceAll("\\.", "");
// Removes any '+' and all characters that follow it from the portion of the email address
// before the domain if the domain is gmail.com or googlemail.com.
emailParts[0] = emailParts[0].replaceAll("\\+.*", "");
normalizedEmail = String.format("%s@%s", emailParts[0], emailParts[1]);
}
return normalizeAndHash(digest, normalizedEmail, true);
}

/**
* Returns the result of normalizing and hashing a phone number. For this use case, Google Ads
* requires phone numbers to be in E.164 format.
*
* @param digest the digest to use to hash the normalized string.
* @param phoneNumber the phone number to normalize and hash.
*/
private String normalizeAndHashPhoneNumber(MessageDigest digest, String phoneNumber)
throws UnsupportedEncodingException {
// Removes non-digit characters and prepends a leading '+' sign.
String digitsOnly = phoneNumber.replaceAll("[^0-9]", "");
String formattedPhone = "+" + digitsOnly;
if (!formattedPhone.matches("^\\+[1-9]\\d{6,14}$")) {
throw new IllegalArgumentException("Phone number must be in E.164 format: " + phoneNumber);
}
return normalizeAndHash(digest, formattedPhone, true);
}

/**
* Retrieves, checks, and prints the status of the offline user data job.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,18 +86,17 @@ private static class UploadEnhancedConversionsForLeadsParams extends CodeSampleP
names = ArgumentNames.SESSION_ATTRIBUTES_ENCODED,
required = false,
description =
"A session attributes token. Only one of sessionAttributesEncoded or sessionAttributesMap"
+ " should be passed.")
"A session attributes token. Only one of sessionAttributesEncoded or"
+ " sessionAttributesMap should be passed.")
private String sessionAttributesEncoded;

@Parameter(
names = ArgumentNames.SESSION_ATTRIBUTES_MAP,
required = false,
description =
"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'. Only "
+ "one of sessionAttributesEncoded or sessionAttributesMap should be passed.")
"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'."
+ " Only one of sessionAttributesEncoded or sessionAttributesMap should be passed.")
private String sessionAttributesMap;
}

Expand Down Expand Up @@ -217,9 +216,9 @@ private void runExample(

ImmutableMap.Builder<String, String> rawRecordBuilder =
ImmutableMap.<String, String>builder()
.put("email", "alex.2@example.com")
.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 5550102")
.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.
Expand Down Expand Up @@ -269,7 +268,7 @@ private void runExample(
// Creates a user identifier using normalized and hashed phone info.
UserIdentifier hashedPhoneNumberIdentifier =
UserIdentifier.newBuilder()
.setHashedPhoneNumber(normalizeAndHash(sha256Digest, rawRecord.get("phone")))
.setHashedPhoneNumber(normalizeAndHashPhoneNumber(sha256Digest, rawRecord.get("phone")))
.build();
// Adds the hashed phone number identifier to the UserData object's list.
userIdentifiers.add(hashedPhoneNumberIdentifier);
Expand Down Expand Up @@ -324,9 +323,10 @@ private void runExample(
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'");
"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()
Expand Down Expand Up @@ -409,22 +409,46 @@ private String normalizeAndHash(MessageDigest digest, String s)

/**
* 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}.
* 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 {
String normalizedEmail = emailAddress.toLowerCase();
String[] emailParts = normalizedEmail.split("@");
if (emailParts.length > 1 && emailParts[1].matches("^(gmail|googlemail)\\.com\\s*")) {
// 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);
}
// [END normalize_and_hash]
}
Original file line number Diff line number Diff line change
Expand Up @@ -171,17 +171,16 @@ private void runExample(

ImmutableMap.Builder<String, String> rawRecordBuilder =
ImmutableMap.<String, String>builder()
.put("email", "alex.2@example.com")
// Email address that includes a period (.) before the Gmail domain.
.put("email", "alex.2@example.com")
// Email address that includes a period (.) and plus (+) suffix before the Gmail domain.
.put("email", "alex.2+myalias@gmail.com")
// Address that includes all four required elements: first name, last name, country
// code, and postal code.
.put("firstName", "Alex")
.put("lastName", "Quinn")
.put("countryCode", "US")
.put("postalCode", "94045")
// Phone number to be converted to E.164 format, with a leading '+' as required.
.put("phone", "+1 800 5550102")
.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.
Expand Down Expand Up @@ -222,7 +221,8 @@ private void runExample(
if (rawRecord.containsKey("phone")) {
UserIdentifier hashedPhoneNumberIdentifier =
UserIdentifier.newBuilder()
.setHashedPhoneNumber(normalizeAndHash(sha256Digest, rawRecord.get("phone"), true))
.setHashedPhoneNumber(
normalizeAndHashPhoneNumber(sha256Digest, rawRecord.get("phone")))
.build();
// Adds the hashed phone number identifier to the UserData object's list.
userIdentifiers.add(hashedPhoneNumberIdentifier);
Expand Down Expand Up @@ -363,22 +363,46 @@ private String normalizeAndHash(MessageDigest digest, String s, boolean trimInte

/**
* 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}.
* 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 {
String normalizedEmail = emailAddress.toLowerCase();
String[] emailParts = normalizedEmail.split("@");
if (emailParts.length > 1 && emailParts[1].matches("^(gmail|googlemail)\\.com\\s*")) {
// Removes all whitespace (leading, trailing, and intermediate) from the email address.
String normalizedEmail = emailAddress.toLowerCase().replaceAll("\\s+", "");
String[] emailParts = normalizedEmail.split("@", 2);
if (emailParts.length == 2 && emailParts[1].matches("^(gmail|googlemail)\\.com$")) {
// Removes any '.' characters from the portion of the email address before the domain if the
// domain is gmail.com or googlemail.com.
emailParts[0] = emailParts[0].replaceAll("\\.", "");
// Removes any '+' and all characters that follow it from the portion of the email address
// before the domain if the domain is gmail.com or googlemail.com.
emailParts[0] = emailParts[0].replaceAll("\\+.*", "");
normalizedEmail = String.format("%s@%s", emailParts[0], emailParts[1]);
}
return normalizeAndHash(digest, normalizedEmail, true);
}

/**
* Returns the result of normalizing and hashing a phone number. For this use case, Google Ads
* requires phone numbers to be in E.164 format.
*
* @param digest the digest to use to hash the normalized string.
* @param phoneNumber the phone number to normalize and hash.
*/
private String normalizeAndHashPhoneNumber(MessageDigest digest, String phoneNumber)
throws UnsupportedEncodingException {
// Removes non-digit characters and prepends a leading '+' sign.
String digitsOnly = phoneNumber.replaceAll("[^0-9]", "");
String formattedPhone = "+" + digitsOnly;
if (!formattedPhone.matches("^\\+[1-9]\\d{6,14}$")) {
throw new IllegalArgumentException("Phone number must be in E.164 format: " + phoneNumber);
}
return normalizeAndHash(digest, formattedPhone, true);
}
// [END normalize_and_hash]
}
Loading