Skip to content

Commit 3ca606b

Browse files
authored
Update messaging in AddCustomerMatchUserList example (#357)
* Update messaging in AddCustomerMatchUserList example Change-Id: I9cec5b2a44d3bb4808f552af19fe714a0f382eb7 * Update note Change-Id: I387057f002c96be24f82b8690b48737079b67e43 * Update example to check status Change-Id: Ia6322cf443253e488e2701d8aed72f141e9afd8e * Change to allowlisted Change-Id: I9a3affa7cc8a6bf9fc55554d98bba265562e0ddd
1 parent be8a7ef commit 3ca606b

1 file changed

Lines changed: 92 additions & 57 deletions

File tree

google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/AddCustomerMatchUserList.java

Lines changed: 92 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.google.ads.googleads.v5.common.UserData;
2525
import com.google.ads.googleads.v5.common.UserIdentifier;
2626
import com.google.ads.googleads.v5.enums.CustomerMatchUploadKeyTypeEnum.CustomerMatchUploadKeyType;
27+
import com.google.ads.googleads.v5.enums.OfflineUserDataJobStatusEnum.OfflineUserDataJobStatus;
2728
import com.google.ads.googleads.v5.enums.OfflineUserDataJobTypeEnum.OfflineUserDataJobType;
2829
import com.google.ads.googleads.v5.errors.GoogleAdsError;
2930
import com.google.ads.googleads.v5.errors.GoogleAdsException;
@@ -41,11 +42,9 @@
4142
import com.google.ads.googleads.v5.services.SearchGoogleAdsStreamResponse;
4243
import com.google.ads.googleads.v5.services.UserListOperation;
4344
import com.google.ads.googleads.v5.services.UserListServiceClient;
44-
import com.google.api.gax.longrunning.OperationFuture;
4545
import com.google.api.gax.rpc.ServerStream;
4646
import com.google.common.collect.ImmutableList;
4747
import com.google.protobuf.BoolValue;
48-
import com.google.protobuf.Empty;
4948
import com.google.protobuf.Int64Value;
5049
import com.google.protobuf.StringValue;
5150
import java.io.FileNotFoundException;
@@ -56,17 +55,14 @@
5655
import java.util.ArrayList;
5756
import java.util.Arrays;
5857
import java.util.List;
59-
import java.util.concurrent.ExecutionException;
60-
import java.util.concurrent.TimeUnit;
61-
import java.util.concurrent.TimeoutException;
6258

6359
/**
6460
* Creates a user list (a.k.a. audience) and uploads members to populate the list.
6561
*
6662
* <p><em>Notes:</em>
6763
*
6864
* <ul>
69-
* <li>This feature is only available to whitelisted accounts. See
65+
* <li>This feature is only available to allowlisted accounts. See
7066
* https://support.google.com/adspolicy/answer/6299717 for more details.
7167
* <li>It may take up to several hours for the list to be populated with members.
7268
* <li>Email addresses must be associated with a Google account.
@@ -76,17 +72,14 @@
7672
*/
7773
public class AddCustomerMatchUserList {
7874

79-
private static final long MAX_TOTAL_POLL_INTERVAL_SECONDS = 60L;
80-
8175
private static class AddCustomerMatchUserListParams extends CodeSampleParams {
8276

8377
@Parameter(names = ArgumentNames.CUSTOMER_ID, required = true)
8478
private Long customerId;
8579
}
8680

8781
public static void main(String[] args)
88-
throws InterruptedException, ExecutionException, TimeoutException,
89-
UnsupportedEncodingException {
82+
throws UnsupportedEncodingException {
9083
AddCustomerMatchUserListParams params = new AddCustomerMatchUserListParams();
9184
if (!params.parseArguments(args)) {
9285

@@ -133,16 +126,12 @@ public static void main(String[] args)
133126
* @throws GoogleAdsException if an API request failed with one or more service errors.
134127
*/
135128
private void runExample(GoogleAdsClient googleAdsClient, long customerId)
136-
throws InterruptedException, ExecutionException, TimeoutException,
137-
UnsupportedEncodingException {
129+
throws UnsupportedEncodingException {
138130
// Creates a Customer Match user list.
139131
String userListResourceName = createCustomerMatchUserList(googleAdsClient, customerId);
140132

141133
// Adds members to the user list.
142134
addUsersToCustomerMatchUserList(googleAdsClient, customerId, userListResourceName);
143-
144-
// Prints information about the user list.
145-
printCustomerMatchUserListInfo(googleAdsClient, customerId, userListResourceName);
146135
}
147136

148137
/**
@@ -193,13 +182,12 @@ private String createCustomerMatchUserList(GoogleAdsClient googleAdsClient, long
193182
*
194183
* @param googleAdsClient the Google Ads API client.
195184
* @param customerId the client customer ID.
196-
* @param userListResourceName the resource name of the Customer Match user list to add members
185+
* @param userListResourceName the resource name of the Customer Match user list to add members.
197186
* to.
198187
*/
199188
private void addUsersToCustomerMatchUserList(
200189
GoogleAdsClient googleAdsClient, long customerId, String userListResourceName)
201-
throws InterruptedException, ExecutionException, TimeoutException,
202-
UnsupportedEncodingException {
190+
throws UnsupportedEncodingException {
203191
try (OfflineUserDataJobServiceClient offlineUserDataJobServiceClient =
204192
googleAdsClient.getLatestVersion().createOfflineUserDataJobServiceClient()) {
205193
// Creates a new offline user data job.
@@ -245,21 +233,14 @@ private void addUsersToCustomerMatchUserList(
245233
System.out.printf(
246234
"Successfully added %d operations to the offline user data job.%n",
247235
userDataJobOperations.size());
248-
}
249-
250-
// Issues an asynchronous request to run the offline user data job for executing all added
251-
// operations.
252-
OperationFuture<Empty, Empty> runFuture =
253-
offlineUserDataJobServiceClient.runOfflineUserDataJobAsync(
254-
offlineUserDataJobResourceName);
255-
System.out.println("Asynchronous request to execute the added operations started.");
256-
System.out.println("Waiting until operation completes.");
257236

258-
// The polling future implements a default back-off policy for retrying.
259-
runFuture.getPollingFuture().get(MAX_TOTAL_POLL_INTERVAL_SECONDS, TimeUnit.SECONDS);
260-
System.out.printf(
261-
"Offline user data job with resource name '%s' has finished.%n",
262-
offlineUserDataJobResourceName);
237+
// Offline user data jobs may take up to 24 hours to complete, so instead of waiting for the
238+
// job to complete, retrieves and displays the job status once. If the job is completed
239+
// successfully, prints information about the user list. Otherwise, prints the query to use
240+
// to check the job again later.
241+
checkJobStatus(
242+
googleAdsClient, customerId, offlineUserDataJobResourceName, userListResourceName);
243+
}
263244
}
264245
}
265246

@@ -310,6 +291,85 @@ private List<OfflineUserDataJobOperation> buildOfflineUserDataJobOperations()
310291
return operations;
311292
}
312293

294+
/**
295+
* Returns the result of normalizing and then hashing the string using the provided digest.
296+
* Private customer data must be hashed during upload, as described at
297+
* https://support.google.com/google-ads/answer/7474263.
298+
*
299+
* @param digest the digest to use to hash the normalized string.
300+
* @param s the string to normalize and hash.
301+
*/
302+
private String normalizeAndHash(MessageDigest digest, String s)
303+
throws UnsupportedEncodingException {
304+
// Normalizes by removing leading and trailing whitespace and converting all characters to
305+
// lower case.
306+
String normalized = s.trim().toLowerCase();
307+
// Hashes the normalized string using the hashing algorithm.
308+
byte[] hash = digest.digest(normalized.getBytes("UTF-8"));
309+
StringBuilder result = new StringBuilder();
310+
for (byte b : hash) {
311+
result.append(String.format("%02x", b));
312+
}
313+
314+
return result.toString();
315+
}
316+
317+
/**
318+
* Retrieves, checks, and prints the status of the offline user data job.
319+
*
320+
* @param googleAdsClient the Google Ads API client.
321+
* @param customerId the client customer ID.
322+
* @param offlineUserDataJobResourceName the resource name of the OfflineUserDataJob to get the
323+
* status for.
324+
* @param userListResourceName the resource name of the Customer Match user list.
325+
*/
326+
private void checkJobStatus(
327+
GoogleAdsClient googleAdsClient,
328+
long customerId,
329+
String offlineUserDataJobResourceName,
330+
String userListResourceName) {
331+
try (GoogleAdsServiceClient googleAdsServiceClient =
332+
googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
333+
String query =
334+
String.format(
335+
"SELECT offline_user_data_job.resource_name, "
336+
+ "offline_user_data_job.id, "
337+
+ "offline_user_data_job.status, "
338+
+ "offline_user_data_job.type, "
339+
+ "offline_user_data_job.failure_reason "
340+
+ "FROM offline_user_data_job "
341+
+ "WHERE offline_user_data_job.resource_name = '%s'",
342+
offlineUserDataJobResourceName);
343+
// Issues the query and gets the GoogleAdsRow containing the job from the response.
344+
GoogleAdsRow googleAdsRow =
345+
googleAdsServiceClient
346+
.search(Long.toString(customerId), query)
347+
.iterateAll()
348+
.iterator()
349+
.next();
350+
OfflineUserDataJob offlineUserDataJob = googleAdsRow.getOfflineUserDataJob();
351+
System.out.printf(
352+
"Offline user data job ID %d with type '%s' has status: %s%n",
353+
offlineUserDataJob.getId().getValue(),
354+
offlineUserDataJob.getType(),
355+
offlineUserDataJob.getStatus());
356+
OfflineUserDataJobStatus jobStatus = offlineUserDataJob.getStatus();
357+
if (OfflineUserDataJobStatus.SUCCESS == jobStatus) {
358+
// Prints information about the user list.
359+
printCustomerMatchUserListInfo(googleAdsClient, customerId, userListResourceName);
360+
} else if (OfflineUserDataJobStatus.FAILED == jobStatus) {
361+
System.out.printf(" Failure reason: %s%n", offlineUserDataJob.getFailureReason());
362+
} else if (OfflineUserDataJobStatus.PENDING == jobStatus
363+
|| OfflineUserDataJobStatus.RUNNING == jobStatus) {
364+
System.out.println();
365+
System.out.printf(
366+
"To check the status of the job periodically, use the following GAQL query with"
367+
+ " GoogleAdsService.search:%n%s%n",
368+
query);
369+
}
370+
}
371+
}
372+
313373
/**
314374
* Prints information about the Customer Match user list.
315375
*
@@ -348,31 +408,6 @@ private void printCustomerMatchUserListInfo(
348408
userList.getResourceName(),
349409
userList.getSizeForDisplay().getValue(),
350410
userList.getSizeForSearch().getValue());
351-
System.out.println(
352-
"Reminder: It may take several hours for the user list to be populated with the users.");
353411
}
354412
}
355-
356-
/**
357-
* Returns the result of normalizing and then hashing the string using the provided digest.
358-
* Private customer data must be hashed during upload, as described at
359-
* https://support.google.com/google-ads/answer/7474263.
360-
*
361-
* @param digest the digest to use to hash the normalized string.
362-
* @param s the string to normalize and hash.
363-
*/
364-
private String normalizeAndHash(MessageDigest digest, String s)
365-
throws UnsupportedEncodingException {
366-
// Normalizes by removing leading and trailing whitespace and converting all characters to
367-
// lower case.
368-
String normalized = s.trim().toLowerCase();
369-
// Hashes the normalized string using the hashing algorithm.
370-
byte[] hash = digest.digest(normalized.getBytes("UTF-8"));
371-
StringBuilder result = new StringBuilder();
372-
for (byte b : hash) {
373-
result.append(String.format("%02x", b));
374-
}
375-
376-
return result.toString();
377-
}
378413
}

0 commit comments

Comments
 (0)